传统的两和问题(我的下面的参考实现)是,对于排序的数组,找到所有数字对,其总和值等于给定的目标值。传统实现从数组的两端进行扫描,如果当前总和小于目标值,则增加低索引指针,如果当前总和大于目标值,则减少高索引指针。
我的问题是,是否有证据证明此算法的正确性,表明它不会错过一对?
顺便说一句,如果我的代码有问题,请随时指出。def twoSum(numbers, skipIndex, targetValue):
i = 0
j = len(numbers) - 1
result = []
while i < j:
if i in skipIndex:
i+=1
if j in skipIndex:
j+=1
if numbers[i] + numbers[j] == targetValue:
result.append((numbers[i], numbers[j]))
i += 1
j -= 1
elif numbers[i] + numbers[j] > targetValue:
j -= 1
else:
i += 1
return result
if __name__ == "__main__":
numbers = [1,2,4,5,6,7,9,10]
print twoSum(numbers, [1], 11) # output, [(1, 10), (4, 7), (5, 6)]
print twoSum(numbers, [], 11) # output, [(1, 10), (2, 9), (4, 7), (5, 6)]
答案 0 :(得分:0)
让我们简化问题以找到第一个这样的对,而不是所有对(将其扩展到加在一起targetValue
的所有对中很简单)。
每当增加左指针i
时,您就不再考虑相应的元素,因为与数组中的 any 其他元素相加时,总和仍然太小。因此它是不可用的。对于递减右指针j
,也有类似的论点,但要进行调整,即总和太大而不是太小。
另一种查看方式是,如果您认为修改指针与修改(排序的)列表相同,因为实际上与删除最小和最大的元素相同。
最后,如果指针越过,这与列表变得太小(<2个元素)而无法继续搜索是一样的。
我上面描述的是针对搜索符合targetValue
的第一对的情况。要找到所有这样的对,只要指针不交叉就可以继续搜索(而不是从当前的成对和中找到targetValue
时返回)。您已经完成了while i < j
条件的操作(尽管对我个人而言,i != j
更容易理解)。
我不确定skipIndex
的实用程序在您的实现中是什么(调试代码?),但是j += 1
对我来说感觉很可疑。
为进一步阅读,我写了一篇博客文章:https://funloop.org/post/2020-12-05-twosum-problem-explained.html。我不擅长数学,所以这不是一个数学解释。