最小删除子数组以使数组等于目标

Posted

技术标签:

【中文标题】最小删除子数组以使数组等于目标【英文标题】:Minimum removal of subarrays to make array equal to target 【发布时间】:2022-01-22 04:08:18 【问题描述】:

假设我们有一个数组 [5, 4, -2, 4, -3],我们希望所有元素都等于 0。子数组可用于加或减 1。例如,我可以加 1从索引 0 到 3,然后列表为 [5 + 1, 4 + 1, -2 + 1, 4 + 1, -3 + 1]。这算作一招。如何最小化移动次数? 我的方法虽然可能很慢,但还是遍历列表,如果一个数字是正数,则继续向右延伸,直到达到 0 或负数。反之亦然。然后,如果该窗口大于 0,则将该范围内的所有数字减去到目前为止的最小值。否则,如果该窗口小于 0,则将该范围内的所有数字相加到 abs(minimum) 为止。例如:

[5, 4, -2, -5, -3]
5 is start, 4 is end since we reach end of positives. Minimum so far is 4. 
[5 - 4, 4 - 4, -2, -5, -3] = [1, 0, -2, -5, -3]

[1, 0, -2, 4, -3] 1 is start, 1 is end. minimum so far is 1.
[1 - 1, 0, -2, -5, -3] = [0, 0, -2, -5, -3]

We go to 0, but we skip it 
[0, 0, -2, -5, -3]  -2 is start, -3 is end. abs(-2) is minimum so far
[0, 0, 0, -3, -1] -3 is start, -1 is end. abs(-1) is minimum so far
[0, 0, 0, -3 + 1, -1 + 1] = [0, 0, 0, -2, 0]

[0, 0, 0, -2, 0] -2 is start, -2 is end. abs(-2) is minimum so far
[0, 0, 0, -2 + 2, 0] = [0, 0, 0, 0, 0]

总共需要 4 + 1 + abs(-2) + abs(-1) + abs(-2) 移动。

有没有更高效的算法?另外,我的方法正确吗?

【问题讨论】:

【参考方案1】:

您的算法的描述似乎朝着正确的方向发展,但它不完整,因此很难确定它是否正确。

您可以通过将列表分成连续的正值、负值和零值组来解决此问题。对于每个组,您可以使整个子范围的所有数字更接近零,其量与最小绝对值相对应。这将为您留下一个新的组分布,您可以在这些组上重复该过程,直到所有元素都为零。

from itertools import groupby

def incdec(A):
    count  = 0
    while any(A):
        groups = (list(g) for _,g in groupby(A,lambda n:(n>0)-(n<0)))
        A = []
        for group in groups:
            moves = min(group,key=abs)
            count += abs(moves)
            A.extend(n-moves for n in group)
    return count

输出:

print(incdec([5, 4, -2, -5, -3]))  # 10
print(incdec([5, 4, -2, 4, -3]))   # 14             
print(incdec([5, 3, 4, 2, 3, 0, 1, 1 , -2, -4, -3])) # 12

# sample process expansion:
#
# [5, 3, 4, 2, 3, 0, 1, 1 , -2, -4, -3]
# [5, 3, 4, 2, 3], [0], [1, 1],[-2, -4, -3]
#  -2                    -1     +2                5 moves
# [3, 1, 2, 0, 1, 0, 0, 0 , 0, -2, -1]
# [3, 1, 2], [0], [1], [0, 0, 0 , 0], [-2, -1]
#  -1             -1                   +1         3 moves
# [2, 0, 1, 0, 0, 0, 0, 0 , 0, -1, 0]
# [2], [0], [1], [0, 0, 0, 0, 0 , 0], [-1], [0]
# -2        -1                         +1         4 moves
#                                                ---------
#                                                12 moves

【讨论】:

以上是关于最小删除子数组以使数组等于目标的主要内容,如果未能解决你的问题,请参考以下文章

最大值减去最小值小于或等于 num 的子数组数量问题

栈和队列----最大值减去最小值小于等于num的子数组的数量

最大值减去最小值小于或等于num的子数组数量

1.10 最大值减去最小值小于或等于num的子数组数量

队列最大值减去最小值小于等于num的子数组数量

和等于 0 的最大子数组