求递增正数数组的子数组之和等于给定值

问题:

1. 给定一个数组其每个元素都是正数,和一个给定值M,求所有连续的子数组其和等于M。

2. 给定一个正数N,求所有和为N的连续正数序列。


这类求子数组之和的问题与编程之美2.12——快速寻找满足条件的两个数或三个数问题的求解思路相似,都是可用双指针法在O(n)的时间内解决。

1.解法:

我们让两个指针i,j都从数组的第一个元素开始,记变量sum初始化为第一个元素的值,sum表示子数组[i,j]的元素之和。在每步操作中,若sum的值小于等于M,则j增加1,并且让sum加上元素A[j];若sum的值大于M,则先让sum减去元素A[i],再i增加1。

[cpp]  view plain copy
  1. // 求连续子序列和等于m  
  2. void FindSumK(int *A, int n, unsigned int m)  
  3. {  
  4.     int i, j;  
  5.     i = j = 0;  
  6.     int sum = A[0]; // 表示子数组[i,j]的元素之和  
  7.     // 当j==n时,说明当前子数组之和sum小于m,而增加i只会让sum更加小于m,  
  8.     // 所以不用使i再增加到n  
  9.     while (i<=j && j<n)   
  10.     {  
  11.         // sum大于m,增加i,以减小sum  
  12.         if (sum >= m)  
  13.         {  
  14.             if (sum == m) printf("%d-%d\n",i,j);  
  15.             sum -= A[i];  
  16.             ++i;  
  17.         }  
  18.         // sum小于m,增加j,以增大sum  
  19.         else  
  20.         {  
  21.             ++j;  
  22.             sum += A[j];  
  23.         }  
  24.     }  
  25. }  

2.解法:

让我们先举个例子,例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续的序列1-5,4-6和7-8。

同样是计算子数组之和,同样使用双指针法,具体分析同上。唯一需要注意下它的边界条件,由于子数组至少要有两个数字,所以较小的指针的位置遍历到n/2就结束。

[cpp]  view plain copy
  1. // 求所有和为n的连续正数序列  
  2. void FindSumN(int n)  
  3. {  
  4.     int i, j;  
  5.     i = j = 1;  
  6.     int sum = 1;  
  7.     while(i<=n/2)  
  8.     {  
  9.         if (sum <= n)   
  10.         {  
  11.             if (sum == n) printf("%d-%d\n",i,j);  
  12.             ++j;  
  13.             sum += j;  
  14.         }  
  15.         else  
  16.         {  
  17.             sum -= i;  
  18.             ++i;  
  19.         }  
  20.     }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值