【问题标题】:Subarray Sum Solution子数组和解
【发布时间】:2019-09-21 16:12:45
【问题描述】:

我最近遇到了一个带有两个指针的子数组和问题的解决方案,我不太确定该算法的正确性。子数组和问题包括找到一个子数组,其和等于某个目标值。我已经使用哈希表看到了这个问题的解决方案,但我质疑这个其他解决方案的正确性。让我给你们举一个算法的例子。

假设你有一个数组 [1,3,2,5,1,1,2,3] 和一个目标值 x = 8。

使用左右指针指示子数组的开始和结束。在每一步中,左指针向前移动一步,而右指针向前移动,只要子数组和最多为 x。这就是上述数组的算法将如何进行。

[1,3,2,5,1,1,2,3]
l    r

[1,3,2,5,1,1,2,3] ##The right pointer doesn't move because the next element would make the sum larger than x
   l r

[1,3,2,5,1,1,2,3]
     l   r

总和现在等于目标,算法停止。对我来说,该算法似乎不适用于边缘情况。但它看起来适合我给它的每个测试用例,它运行 O(n)。有人可以给我一个正确的证明吗?

谢谢

edit - 为了论证起见,假设为正整数。

【问题讨论】:

  • 如果您对正确性证明感兴趣。请让社区知道您尝试了什么。要求完整的正确性证明听起来很宽泛。
  • To me the algorithm doesn't seem to be valid for edge cases. 那些边缘情况是什么?

标签: algorithm


【解决方案1】:

令 LEN(i) 为从索引 i 开始且总和最多为 X 的最长子数组的长度

如果有一个总和为 X 的子数组从索引 i 开始,则 LEN(i) 将是这样一个子数组的长度(可能有多个这样的数组,后面有 0)。由于数组中只有正整数,所有从 i 开始的较长数组的和都会更大,而所有较短的数组的和都会相等或较小。

所以我们需要做的就是找到每个索引的 LEN(i) 和相应子数组的总和。如果这些总和之一是 X,那么您就有答案了。

考虑任何索引的 LEN(i) 子数组。如果它是非空的并且我们删除了第一项,那么从 i+1 开始的结果子数组将具有较小的相等和。 因此 LEN(i+1) >= max(LEN(i-1),0)。

我们可以将其重写为 LEN(i+1) >= max(LEN(i),1)-1,这就是双指针算法用来实现 O(n) 时间的事实。

我们首先将左右指针设置为 0 处的 max(LEN(0),1) 子数组的开始和结束,并检查其总和。然后我们把左指针上移,从上面的方程我们知道右指针只能向前移动,所以我们把它移到 max(LEN(1),1) 子数组的末尾,并检查它的和。

我们继续检查从每个索引开始的相应子数组的总和。

【讨论】:

  • 这样的东西正是我想要的!很好的解释。非常感谢。
【解决方案2】:

如果数组中存在负整数,则双指针方法不适用于此问题。

反例:

[-15, 2, 4, 8, -9, 5, 10, 23] 和目标值 = 15

仅考虑使用正整数。

以下几点帮助我们证明该算法有效:

  1. 算法终止: 只要子数组和不大于目标值,右指针就一直向右移动。

一个。如果未找到 sum = 目标值的子数组,则右指针索引变为 = 数组大小,算法终止。

b.如果找到 sum = 目标值的子数组,我们报告它并且算法终止。

  1. 算法不会错过检测 sum = 目标值的子数组(如果存在)。

假设有一个子数组 [i, j],其总和 = 目标值。为了矛盾起见,假设我们的算法没有检测到这样的子阵列。

一个。如果是这种情况,那么右指针要么继续移动到索引j 的右侧,这是不可能的,因为如果子数组总和 > 目标值,我们的算法不允许右指针向右移动。

b.其他可能的情况是右指针停在j,但左指针超过i。这是不可能的,因为在左指针的每个增量中,我们都会检查子数组总和是否 = 目标值。

因此,通过矛盾的证明,我们知道该算法将始终检测 sum = 目标值的子数组(如果存在于数组中)。

  1. 证明算法不报告误报很简单,因为算法报告仅当 sum = 目标值时才找到子数组。

因此,证明。它不是一种形式或数学证明,而是一种足够清晰的直观证明,足以证明其正确性。

【讨论】:

  • 没想到。如果只存在正整数怎么办?那么为什么算法一定是正确的呢?
  • 现在您已经编辑了问题以添加排除负数的假设,问题的范围发生了变化。
  • 我知道。我想这是我从一开始就想包括但没想过要写的假设。感谢您指出!
  • @EmanuelA:用简单易懂的正确性证明更新了帖子。
猜你喜欢
  • 1970-01-01
  • 2020-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-18
  • 1970-01-01
  • 2017-11-29
  • 2016-11-17
相关资源
最近更新 更多