Arrays 可被k整除的子阵列数
在一次采访中,我提出了以下问题,尽管我给出了一个有效的实现,但效率还不够 数组A的一个切片是任何一对整数(p,Q),使得0≤ P≤ QArrays 可被k整除的子阵列数,arrays,algorithm,subset-sum,Arrays,Algorithm,Subset Sum,在一次采访中,我提出了以下问题,尽管我给出了一个有效的实现,但效率还不够 数组A的一个切片是任何一对整数(p,Q),使得0≤ P≤ Q
A = {4, 5, 0, -2, -3, 1}, K = 5
Function must return 7, because there are 7 subarrays which sums are divisible by 5
{4, 5, 0, -2, -3, 1}
{5}
{5, 0}
{5, 0, -2, -3}
{0}
{0, -2, -3}
{-2, -3}
因为你只对可被K整除的数感兴趣,所以你可以做K模的所有计算。 考虑累积和数组S,使得<代码> s [i]=S〔0〕+S〔1〕+…+S[i]。然后(P,Q)是一个可被K整除的切片,iff
S[P]=S[Q]
(记住我们所有的计算都是以K为模)。因此,您只需计算[0,…,K-1]的每个可能值在S中出现的次数
下面是一些伪代码:
B = new array( K )
B[0]++
s = 0
for i = 0 to N - 1
s = ( s + A[i] ) % K
B[s]++
ans = 0
for i = 0 to K - 1
ans = ans + B[i] * ( B[i] - 1 ) / 2
一旦知道它们是S中的x个值为i的单元格,就要计算从值为i的单元格开始到值为i的单元格结束的切片数,这个数字是x(x-1)/2
。为了解决边缘问题,我们添加一个值为0的单元格
x(x-1)/2
代表什么:假设我们的数组是[4,5,0],4作为前缀和的频率是x,在本例中是3。现在我们可以从x的值得出结论,至少有x-1个数可以被k整除或者mod k等于0。现在,这些x-1数字中可能的子阵列总数为1+2+3…+(x-1)是((x-1)*((x-1)+1)/2
(从1到N求和的标准公式,其中N代表(x-1)。公共类子数组可分
{
公共静态void main(字符串[]args)
{
int[]A={4,5,0,-2,-3,1};
SubrayDivisible obj=新的SubrayDivisible();
对象子数组(A,5);
}
私有void getsubarray(int[]A,int K)
{
整数计数=0,s=0;
对于(int i=0;iprivate int getsubrayscont(int[]A,int K)
{
int N=A.长度;
int[]B=新的int[K];
for(int i=0;istaticvoidmain(string[]args)
{
int[]A=新的int[]{4,5,0,-2,-3,1};
整数和=0;
int i,j;
整数计数=0;
对于(i=0;i
这里是@Thomash提出的解决方案的Java实现
第二个循环是不必要的,因为我们可以直接增加当前值的答案,然后增加它
为了避免负数组索引,我们还必须调整模块计算
public static int countSubarrays(int[] nums, int k) {
int[] cache = new int[k];
cache[0]++;
int s = 0, counter = 0;
for (int i = 0; i < nums.length; i++) {
s = ((s + nums[i]) % k + k) % k;
counter += cache[s];
cache[s]++;
}
return counter;
}
公共静态int countsubarray(int[]nums,int k){
int[]缓存=新的int[k];
缓存[0]++;
int s=0,计数器=0;
对于(int i=0;i
示例:-
输入数组
int [] nums = {4,3,1,2,1,5,2};
K是3
连续和
4,7,8,10,11,16,18
将上述连续和数组除以3
1,1,2,1,2,1,0
我们有四个1,两个2,一个0
因此,总计数将为(4*3)/2+(2*1)/2+(2*1)/2=8
(4*3)/2来自从四个中选择任意两个1,即nC2=n(n-1)/2
这是节目
4,7,8,10,11,16,18
公共静态长计数子raydivbyk(int k,int[]nums){
Map moduleuscountmap=newhashmap();
int[]concessum=新的int[nums.length];
求和[0]=nums[0];
对于(inti=1;i谢谢,@damluar,但是它非常整洁!我只想添加一些评论
输出应该是7,而不是6。因为我们有7个子数组可以被k整除,如下所示,添加res+=storedArray[0];
来修复它
{4,5,0,-2,-3,1};{5};{5,0};{5,0,-2,-3};{0};{0,-2,-3};{-2,-3};{-2,-3}
初始化代码> Cache [0 ]++;取决于语言,如果使用C++,则需要,但对于java [].<
代码:
公共类HelloWorld{
公共静态void main(字符串[]args){
int[]A=新的int[]{4,5,0,-2,-3,1};
int k=5;
int ans=0;
System.out.println(countSubArray(A,k));//输出=7
}
公共静态int countSubArray(int[]nums,int k){
int[]storedArray=新的int[k];
int sum=0,res=0;
对于(inti=0;iIt不会改变任何东西,我的解决方案仍然有效。B[0]++和B[S]是什么++意味着?@Thomash从理论的角度来看,模仅为正数定义。对于负数,模没有定义的值。如果你声称你的解决方案适用于负数,你应该定义模如何适用于负数。B[0]++
的值是多少?ans=ans+B[i]*(B[i]-1)/2
我想向其他任何不明白的人澄清这一点:B包含nu
1,1,2,1,2,1,0
Map<Integer, Integer> modulusCountMap = new HashMap<Integer, Integer>();
int [] consecSum = new int[nums.length];
consecSum[0]=nums[0];
for(int i=1;i<nums.length;i++){
consecSum[i]= consecSum[i-1] +nums[i];
}
for(int i=0;i<nums.length;i++){
consecSum[i]= consecSum[i]%k;
if(consecSum[i]==0 && modulusCountMap.get(consecSum[i])==null){
modulusCountMap.put(consecSum[i], 2);
}else{
modulusCountMap.put(consecSum[i], modulusCountMap.get(consecSum[i])==null ? 1 : modulusCountMap.get(consecSum[i])+1);
}
}
int count = 0;
for (Integer val : modulusCountMap.values()) {
count = count + (val*(val-1))/2;
}
return count;
}
static long customOptimizedCountSubArrayDivByK(int k, int[] nums) {
Map<Integer, Integer> modulusCountMap = new HashMap<Integer, Integer>();
int [] quotient = new int[nums.length];
quotient[0]=nums[0]%3;
if(quotient[0]==0){
modulusCountMap.put(quotient[0], 2);
}else{
modulusCountMap.put(quotient[0], 1);
}
for(int i=1;i<nums.length;i++){
quotient[i]= (quotient[i-1] + nums[i])%3;
if(quotient[i]==0 && modulusCountMap.get(quotient[i])==null){
modulusCountMap.put(quotient[i], 2);
}else{
modulusCountMap.put(quotient[i], modulusCountMap.get(quotient[i])==null ? 1 : modulusCountMap.get(quotient[i])+1);
}
}
int count = 0;
for (Integer val : modulusCountMap.values()) {
count = count + (val*(val-1))/2;
}
return count;
}
public class HelloWorld{
public static void main(String []args){
int [] A = new int[] {4,5,0,-2,-3,1};
int k = 5;
int ans=0;
System.out.println(countSubArray(A, k)); // output = 7
}
public static int countSubArray(int [] nums, int k){
int [] storedArray = new int[k];
int sum=0, res=0;
for(int i=0; i<nums.length; i++){
sum = (((sum + nums[i]) % k) + k) % k;
res += storedArray[sum];
storedArray[sum]++;
}
res += storedArray[0];
return res;
}
}