最小删除子数组以使数组等于目标
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
【讨论】:
以上是关于最小删除子数组以使数组等于目标的主要内容,如果未能解决你的问题,请参考以下文章