数字总和可被 K 整除的子数组的数量
Posted
技术标签:
【中文标题】数字总和可被 K 整除的子数组的数量【英文标题】:number of subarrays where sum of numbers is divisible by K 【发布时间】:2012-07-31 02:39:07 【问题描述】:给定一个数组,找出有多少这样的子序列(不需要是连续的),其中该子数组中的元素之和可以被 K 整除。
我知道一种复杂度为 2^n 的方法,如下所示。这就像找到 i=[0,n] 的所有 nCi 并验证 sum 是否可被 K 整除。 请提供类似线性/二次或 n^3 的伪代码。
static int numways = 0;
void findNumOfSubArrays(int [] arr,int index, int sum, int K)
if(index==arr.length)
if(sum%k==0) numways++;
else
findNumOfSubArrays(arr, index+1, sum, K);
findNumOfSubArrays(arr, index+1, sum+arr[index], K);
【问题讨论】:
你提到的这种方法看起来更像是蛮力而不是分而治之,只是说 将原数组取模缩小到[0 .. (k-1)]的范围内,然后用动态规划计算组合的个数(一维是取模,另一维是您总结的元素数量)。 【参考方案1】:输入 - 数组 A,长度为 n,自然数为 k。
算法:
构造数组 B:对于每个 1现在我们可以使用动态规划了:
我们定义 D[i,j] = - B[i..n] 的最大子数组数,其元素的模 k 之和等于 j。
1
D[n,0] = if (b[n] == 0), 2. 否则为 1.
如果 j > 0:
D[n,j] = if (B[n] modulo k) == j, 大于 1。否则为 0。
对于 i
D[i,j] = maxD[i+1,j], 1 + D[i+1, D[i+1,(jB[i]+k) 模 k)]。
构造 D.
返回 D[1,0]。
整体运行时间:O(n*k)
【讨论】:
D[i,j] = maximum number of sub-arrays of - B[j..n] that the sum of its elements = j
j
之一是i
,不是吗?
我不明白你的问题 - i 代表起始子数组,j 代表我们想要的子数组的总和(当然是模 k)。
那不是台风吗?不应该是 B[i..n] 吗? :\
对不起伙计们..我的意思只是子序列..这对子序列有用吗?
以上算法是针对子序列的。【参考方案2】:
实际上,如果 K 的范围和数组中的数字范围未知,我认为这个问题不可能在 O(n^3) 甚至多项式时间内解决。这是我的想法:
考虑以下情况:arr 中的 N 个数字类似于
[1,2,4,8,16,32,...,2^(N-1)]
,
这样,arr 的 2^N 个“子数组”(不需要连续)的总和正好是 [0,2^N) 中的所有整数
问其中有多少能被K整除,相当于问[0, 2^N)中有多少整数能被K整除。
我知道在上述情况下,答案可以像 (2^N-1)/K(或其他东西)一样直接计算出来。但是,如果我们只是随机更改 arr 中的几个(可能是 3?4?)数字,以在完美连续整数范围 [0,2^N)中“挖一些随机洞”,这看起来不可能无需遍历 [0,2^N) 中的几乎所有数字即可计算答案。
好吧,只是一些愚蠢的想法......可能是完全错误的。
【讨论】:
n 这里是数组的长度。他要求 n 的多项式时间,而不是你提到的任何其他事情 我的意思是:这个问题不能在 n 的多项式时间内解决 作为参考,可以看到上面barak提供的DP方案需要O(n*k),也就是说算法取决于K的大小。这是Pseudo-polynomial time的一个例子,不是 n 的多项式时间内的算法。 你是对的,但是如果你假设 k 是常数,并且 n 是数组的长度,那么上面的算法就是 O(n)。如果将n定义为输入的大小,则上述算法不是多项式的。【参考方案3】:使用辅助数组A
1) 在接受输入时,将当前总计存储在相应的索引中(这在O(n)
中执行):
int sum = 0;
for (int i = 0; i < n; i++)
cin >> arr[i];
sum += arr[i];
A[i] = sum;
2) 现在,
for (int i = 0; i < n; i++)
for (int j = i; j < n; j++)
check that (A[j] - A[i] + arr[i]) is divisible by k
你去:O(n^2)
...
【讨论】:
子数组不一定像 OP 提到的那样连续。 所以你是说在 2^n 个子数组中不超过 n^2 个子数组可以被 k 整除? 我告诉了 Subarray 的解决方案...你们所说的 abt 是 Subsequence,所以您需要以更好的方式提出问题。 也许他用错了术语,但他写了“不需要连续”。以上是关于数字总和可被 K 整除的子数组的数量的主要内容,如果未能解决你的问题,请参考以下文章
[LeetCode] 974. 和可被 K 整除的子数组 !!!