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

问题:

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。

// 求连续子序列和等于m
void FindSumK(int *A, int n, unsigned int m)
{
	int i, j;
	i = j = 0;
	int sum = A[0];	// 表示子数组[i,j]的元素之和
	// 当j==n时,说明当前子数组之和sum小于m,而增加i只会让sum更加小于m,
	// 所以不用使i再增加到n
	while (i<=j && j<n) 
	{
		// sum大于m,增加i,以减小sum
		if (sum >= m)
		{
			if (sum == m) printf("%d-%d\n",i,j);
			sum -= A[i];
			++i;
		}
		// sum小于m,增加j,以增大sum
		else
		{
			++j;
			sum += A[j];
		}
	}
}

2.解法:

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

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

// 求所有和为n的连续正数序列
void FindSumN(int n)
{
	int i, j;
	i = j = 1;
	int sum = 1;
	while(i<=n/2)
	{
		if (sum <= n) 
		{
			if (sum == n) printf("%d-%d\n",i,j);
			++j;
			sum += j;
		}
		else
		{
			sum -= i;
			++i;
		}
	}
}

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 4

打赏作者

linyunzju

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值