解密系列 - 找到连续整数序列的数量,使得它们的和为零

时间:2014-06-03 08:47:42

标签: php algorithm performance sequences

以下是编程任务。

您将获得一系列N个整数。任务是找到连续的整数序列的数量,使它们的和为零。

例如,如果序列是: 2,-2,6,-6,8 有3个这样的序列:

  • '2,-2'
  • '6,-6'
  • '2,-2,6,-6'

我已经有用PHP编写的以下程序,它读取STDIN的输入(第一行包含后面的整数。)

<?php

$n = fgets(STDIN) * 1;
$seq = array();

for ($i = 0; $i < $n; $i++) {
    $seq[] = fgets( STDIN ) * 1;
}

$count = 0;
for( $i = 0; $i < $n; $i++)
{
    $number = 0;
    for( $j = $i; $j < $n; $j++)
    {
        $number += $seq[$j];
        if( $number == 0 )
            $count++;
    }
}

echo 'count: ' . $count . PHP_EOL;

输入示例

5
2
-2
6
-6
8

这适用于较小的序列,但其效率为O(n ^ 2)。

对于包含100.000个整数的序列,什么算法是合适的 - 可能是O(n)效率?

2 个答案:

答案 0 :(得分:7)

假设您的数据存储在一个数组中,并让它为arr。 创建一个数组sum,例如:

sum[i] = arr[0] + arr[1] + ... + arr[i]

另外,在开头的一个条目为0(处理从开头开始并总和为零的子数组)

现在,很容易看出,对于i,ji<j这两个索引sum[i]=sum[j],连续序列arr[i+1]+arr[i+2]+...+arr[j] = 0

通过创建此数组sum,您只需要找到有多少重复项。这不能在O(n) 1 (这是element distinctness problem)中完成,但可以使用排序在O(nlogn)中解决,然后迭代和计数,这仍然是非常快速的100,000个条目。

请注意,如果数组n中的数字k存在sum个重复项,则会为这些重复项生成Choose(n,2) = n(n-1)/2个连续子序列。

示例:

arr = [1,2,-2,5,6,-6,-5,8]
sum = [0,1,3,1,6,12,6,1,9]
sorted(sum) = [0,1,1,1,3,6,6,9,12]

有3个重复的1个和2个重复的6个,所以总共有:

Choose(3,2) + Choose(2,2) = 3*2/2 + 2/2 = 3+1 = 4

确实匹配4个子序列:

2,-2
2,-2,5,6,-6,-5
6,-6
5,6,-6,-5

(1)没有散列,然后你会衰减到O(n ^ 2)最坏的情况,但会从O(n)平均情况中受益,代价为O(n)额外空间。

答案 1 :(得分:0)

由于我无法回复评论,这是对amit答案的回复。 也许我有些不对劲,但在将您的方法应用于原始测试用例时,我们无法得到正确的答案:

input = [2, -2, 6, -6, 8]
sum = [2, 0, 6, 0, 8]
sorted(sum) = [0, 0, 2, 6, 8]

由于数字0有两个重复,这给我们(2 * 1)/ 2 = 1,这是不正确的(正确的答案是3)。 我错过了什么?感谢