我需要用O(n)时间复杂度完成练习,但是,我只能用O(n ^ 2)解决方案来解决它。
你有一个数组,你需要计算最长的连续序列,使得它的总和可以被分成3而没有任何余数。例如,对于array {1,2,3,-4,-1)
,函数将返回4,因为其sum(0)
可以划分为3
的最长序列为{2,3,-4,-1}
。
我的解决方案O(n ^ 2)基于 arithmetic progression
。有没有办法用O(n)复杂度做到这一点?
拜托,我只想要一个线索或理论解释。请不要写完整的解决方案:)
答案 0 :(得分:15)
让我们来看看前缀总和。当且仅当[L, R]
时,prefixSum[L - 1] mod 3 = prefixSum[R] mod 3
子阵列才会被3除。这个观察给出了一个非常简单的线性解(因为前缀sum mod 3只有3个可能的值,我们可以简单地找到第一个和最后一个)。
例如,如果输入数组是{1,2,3,-4,-1},则前缀和为{0,1,0,0,2,1}。 (由于前缀为空,因此有n + 1个前缀和)。现在,您可以查看第一个和最后一个出现的0,1和2。
答案 1 :(得分:3)
作为非CS人,这很有趣。我的第一种方法就是计算运行总和mod 3.你会得到一个{0,1,2}的序列。现在查找第一个和最后一个0,第一个和最后一个1以及第一个和最后一个2,并比较它们各自的距离......
答案 2 :(得分:3)
遍历数组,总结你的总数。记录模数和为0
的第一个位置的位置。另外,记录模数和1
的第一个位置的位置。最后,记录模数总和为2
的第一个位置的位置。
同样向后做同样的事情,记录模数总和为0
,1
和2
的最后位置。这为最长的序列提供了三种可能性 - 您只需检查哪一对距离最远。
答案 3 :(得分:2)
您应用动态编程。 对于每个位置,您计算3个值:
因此,给定位置i的这个值,您可以轻松计算位置i + 1的新值。