确定排序数组是否包含总计N的连续序列

时间:2013-05-14 20:43:54

标签: algorithm contiguous

我正在尝试编写一个算法,该算法将返回True/False 排序数组中仅包含正整数的连续序列,可以总计为N

例如:

Array = {  1, 2, 3, 4 };
6 is good! 1 + 2 + 3 = 6
8 is not good! 1 + 3 + 4 = 8, but it's not contiguous, since we skipped the 2.

这就是我试图做的事情:

int[] arr = ...;
int headIndex = 1, tailIndex = 0, sum = arr[0];

while (sum != n)
{
    if (sum < n)
    {
        sum += arr[headIndex++];
    }

    if (sum > n)
    {
        sum -= arr[tailIndex++];
    }
}

return sum == n;

显然上面的内容不起作用(在某些情况下,它可能会陷入无限循环)。有什么建议吗?

我之前没有提到的一件事,非常重要 - 算法的复杂性必须尽可能低。

5 个答案:

答案 0 :(得分:8)

这只是一幅草图:

  1. 从左向右循环,找到k n1 + ... + nk <= target的最大sum = n1 + ... + nk,设置sum == target。如果数组总和小于目标,则返回false。
  2. 如果S,我们就完成了。如果不是,那么总和为target的任何子数组S.length < k将具有sum -= n1,并且将从大于第一个的元素开始。因此,我们从总和中取出第一个:leftEnd++k。现在我们可以回到第1步,但不需要从头开始计算{{1}}。
  3. 由于左端最多移动N次,右端移动最多N次,因此该算法具有时间复杂度O(N)和恒定空间要求。

答案 1 :(得分:0)

简单地:

for i = 1 to n - 1:
   j = 0
   while (j < i):
      sm = 0
      for k = j to i:
        sm = sm + array[k]
      if sm == N:
        return True
      j = j + 1
return False

这适用于 O(n ^ 3)时间。

答案 2 :(得分:0)

var i = 0;
while(i != arr.Length)
{
    var remembre = i;
    var tmp = 0;
    for(; tmp < N && i < arr.Length; ++i)
        tmp += arr[i];
    if(N == tmp)
        return true;
    i = remembre + 1;
}
return false;

我相信这应该有用。

答案 3 :(得分:0)

这是代码中的解决方案。它受到了@Ziyao Wei的草图的极大影响,它简化了我的原始方法(特别是,没有必要回溯并添加小数字,只是按照我的想法将它们取下来。)

public static bool HasConsecutiveSum(IList<int> list, int requiredSum)
{
    int start = 0;
    int sum = 0;

    for (int end = 0; end < list.Count; end++)
    {
        sum += list[end];

        while (sum > requiredSum)
        {
            sum -= list[start++];
            if (start > end)
            {
                return false;
            }
        }

        if (sum == requiredSum)
        {
            return true;
        }        
    }

    return false;
}

答案 4 :(得分:0)

我认为最优化的算法适用于在列表上移动的窗口。窗口的值(WV)是窗口内元素的总和。如果WV小于N,则移动头部并将适合窗口的新值添加到WV,如果该值大于N,则将尾部向上移动一个并从WV中减去窗口下降的值。当WV等于N,或者尾部移动到头部之外,或者头部位于列表的末尾,并且WV仍然为低时,算法停止。

这将以线性时间运行:列表中的每个元素都被添加一次,最多减去一次。

写下一些代码来说明这个想法(python一样),但没有经过测试

WV = list[0]
L = len(list)
tail = 0
head = 0

while WV != N
  if WV < N
    head += 1
    if head < L
       WV += list[head]
    else
      return false // beyond end of list
  elif WV > N
    if tail < head
       WV -= list[tail]
       tail += 1
    else
      return false // single element bigger then N, and list is sorted

return true