Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当所有的值都是非负值时,我们真的能避免额外的空间吗?_C++_Algorithm_Memory_Space Complexity - Fatal编程技术网

C++ 当所有的值都是非负值时,我们真的能避免额外的空间吗?

C++ 当所有的值都是非负值时,我们真的能避免额外的空间吗?,c++,algorithm,memory,space-complexity,C++,Algorithm,Memory,Space Complexity,这个问题是我不久前提出的后续问题: 我们已经得到了一个整数数组和另一个数字k,我们需要找到其和等于k的连续子数组的总数。例如,对于输入:[1,1,1]和k=2,预期输出为2 在报告中说: PS:顺便说一句,如果所有值都是非负的,则有更好的算法。它不需要额外的内存 虽然当时我没怎么想,但现在我对它很好奇。嗯,我们需要额外的内存。如果所有的输入值都是非负的,我们的运行(前缀)和将继续增加,因此,当然,我们不需要一个无序映射来存储特定和的频率。但是,我们仍然需要额外的内存(可能是一个无序集)来存储正在

这个问题是我不久前提出的后续问题:

我们已经得到了一个整数数组和另一个数字k,我们需要找到其和等于k的连续子数组的总数。例如,对于输入:
[1,1,1]
k=2
,预期输出为
2

在报告中说:

PS:顺便说一句,如果所有值都是非负的,则有更好的算法。它不需要额外的内存

虽然当时我没怎么想,但现在我对它很好奇。嗯,我们需要额外的内存。如果所有的输入值都是非负的,我们的运行(前缀)和将继续增加,因此,当然,我们不需要一个
无序映射来存储特定和的频率。但是,我们仍然需要额外的内存(可能是一个
无序集
)来存储正在运行的(前缀)和。这显然与所说的相矛盾

有人能确认一下我们是否真的需要额外的内存,或者它是否可以避免


谢谢

我认为这个算法可以使用
O(1)
空间

我们维护两个指向当前子序列开始和结束的指针,以及当前子序列的总和。最初,两个指针都指向
array[0]
,并且总和显然设置为
array[0]


向前移动结束指针(从而将子序列向右扩展),并按其指向的值增加总和,直到总和超过
k
。然后向前移动开始指针(从而从左侧收缩子序列),并减小和,直到和低于
k
。继续执行此操作,直到结束指针到达数组的末尾。跟踪求和的精确次数
k

让我们从一个稍微简单的问题开始:所有值都是正的(没有零)。在这种情况下,子阵列可以重叠,但不能相互包含

即:arr=
21512
,Sum=
8

2 1 5 1 1 5 1 2
|---|
  |-----|
      |-----|
          |---|
但这种情况永远不会发生:

* * * * * * *
  |-------|
    |---|
考虑到这一点,有一种算法不需要额外的空间(嗯..
O(1)
space),并且具有
O(n)
时间复杂度。ideea应具有左右索引,指示当前序列和当前序列的总和

  • 如果总和为
    k
    递增计数器,则向前推进
  • 如果总和小于
    k
    ,则前进
    right
  • else advance<代码>左侧

现在,如果有零,区间可以互相包含,但前提是零位于区间的边距上

要适应非负数,请执行以下操作:

执行上述操作,但以下情况除外:

  • 向左推进
    时跳过零
  • 如果总和为
    k
    • right
      的右侧计算连续的零,比如说
      zero\u right\u count
    • 左侧
      的左侧连续计算零。比如说
      zero\u left\u count
    • 不要像以前那样增加计数,而是将计数器增加:
      (零左计数+1)*(零右计数+1)
例如:

... 7 0 0 5  1  2 0 0 0 9 ...
          ^     ^
          left  right         
这里有两个零在左边,三个零在右边。这使得
(2+1)*(3+1)=12个序列的和
8
如下:

5 1 2
5 1 2 0
5 1 2 0 0 
5 1 2 0 0 0

0 5 1 2 
0 5 1 2 0
0 5 1 2 0 0 
0 5 1 2 0 0 0

0 0 5 1 2
0 0 5 1 2 0
0 0 5 1 2 0 0 
0 0 5 1 2 0 0 0

因为这些值仅仅是非负的,而不是严格意义上的正的,所以您需要解释零。@EricPostChil我们将此作为练习留给读者。我记得我以前见过这个问题,所以这一定是重复的。有人能找到它吗?