我有一个由十进制数字组成的数组。基本上,我必须查询在给定范围内,当被视为十进制数时,有多少连续子数组可被3整除。
我使用的基本事实是,如果数字的总和可以被3整除,则数字可以被3整除。因此,感觉就像是一个修正形式的范围而不是一个总和即分段树问题。我正在使用自下而上的方法来构建段树,在该树中我在每个节点中放置了所需子阵列的计数器。但是,我遇到了导致零的问题。
任何人都可以帮助我。
答案 0 :(得分:1)
可以在O(N)运行时复杂度中实现。我用Python编写了算法,看看代码:
s = [0, 0, 0]
arr = [0, 3, 0, 3]
count_map = [0]*(len(arr)+1)
for i,n in enumerate(arr):
r = n % 3
s = [s[(3 + (j - r))%3] for j in [0, 1, 2]]
s[r] += (0 if n == 0 else 1)
count_map[i+1] = count_map[i] + s[0]
print(count_map[len(arr)])
上面的算法打印4.要获得范围[i,j](包含i和j)的计数,请执行:count_map[j+1] - count_map[i]
这是JsFiddle试用它的链接。 http://jsfiddle.net/Lt7aP/179/
对于可被3整除的数字;所有数字的总和必须可以被三整除。因此,我们可以应用基本模数学和映射变量来查找可被3整除的所有子数组。更多细节:
a = [1, 5]
m = [1 % 3, 5 % 3] = [1, 2]
Therefore [1, 5] ie. 15 is divisible as summations of its modulus [1, 2] is divisible by 3
想法是将数字的总和打破为剩余部分的总和3.上述算法中的s
跟踪在当前的for-loop迭代中产生余数0,1,2的连续子数组的数量。
例如:在i = 3时,s [0]是范围(0,i-1)内的连续子阵列的数量,使得其3的余数为0(基本上可被3整除)。重要的更新步骤是:
s = [s[(3 + (j - r))%3] for j in [0, 1, 2]]
基本上,如果在当前迭代中,元素的余数为2
,那么我可以使用具有余数1
的连续子数组来生成具有余数0
的子数组,依此类推。如果当前元素为0,那么我们可以忽略s [0]计数的更新或仅保留先前的计数。
答案 1 :(得分:0)
您可以通过动态编程解决此问题,并忽略前导零的数字,如下所示。令A(n,0),A(n,1),A(n,2)为在位置n结束的数字的计数,其不具有前导零,其中A(n,j)计数的数量这样的数字在除以3时给出j的余数。在给定A(n-1,j)的值的情况下,看到如何根据增加的n按递增顺序计算A(n,j)是相当简单的,因为除以3时数字的余数与其数字之和的余数相同。那么所有n的所有A(n,0)的总和就会给出你的答案。如果您想了解更多详情,请与我们联系。