57_ContinuousSquenceWithSum

package pers.lyt.java;

import java.util.ArrayList;
import java.util.List;

//题目
//	输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如输入15,
//由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5、4~6和7~8。
//思路:指针法
//	类似(57-1) 和为s的两个数字的方法,用两个指针small和big分别代表序列的最大值和最小值。
//令small从1开始,big从2开始。
//当从small到big的序列的和小于s时,增加big,使序列包含更多数字;(记得更新序列之和)
//当从small到big的序列的和大于s时,增加small,使序列去掉较小的数字;(记得更新序列之和)
//当从small到big的序列的和等于s时,此时得到一个满足题目要求的序列,输出,然后继续将
//small增大,往后面找新的序列。
//序列最少两个数字,因此,当small到了s/2时,就可以结束判断了。
//数学分析法: 参考自牛客网,丁满历险记的答案。
//对于一个长度为n的连续序列,如果它们的和等于s,有:
//1)当n为奇数时,s/n恰好是连续序列最中间的数字,即n满足 (n&1)==1 && s%n==0
//2)当n为偶数时,s/n恰好是连续序列中间两个数字的平均值,小数部分为0.5,即n满足
//(s%n)*2==n (判断条件中包含了n为偶数的判断)
//得到满足条件的n后,相当于得到了序列的中间数字s/n,所以可以得到第一个数字为
//(s / n) - (n - 1) / 2,结合长度n可以得到所有数字。
//此外,在什么范围内找n呢?我们知道n至少等于2,那至多等于多少?n最大时,序列从1开始,
//根据等差数列的求和公式根据等差数列的求和公式:S = (1 + n) * n / 2,可以得到n应该
//小于sqrt(2s),所以只需要从n=2到sqrt(2s)来判断满足条件的n,继而输出序列。
public class Offer57_ContinuousSquenceWithSum {
	// 方法一:采用两个指针的方法
	public List<List<Integer>> FindContinuousSequence1(int sum) {
		List<List<Integer>> sequenceList = new ArrayList<>();
		if (sum <= 0)
			return sequenceList;

		int small = 1;
		int big = 2;
		int curSum = small + big;
		while (small <= sum / 2) {
			if (curSum == sum) {
				List<Integer> sequence = new ArrayList<Integer>();
				for (int i = small; i <= big; i++)
					sequence.add(i);
				sequenceList.add(sequence);
				curSum -= small;
				small++; // 这两行位置先后要注意
			}
			if (curSum < sum) {
				big++;
				curSum += big;
			}
			if (curSum > sum) {
				curSum -= small;
				small++;
			}
		}
		return sequenceList;
	}

	// 方法二:数学分析法
	public List<List<Integer>> FindContinuousSequence2(int sum) {
		List<List<Integer>> sequenceList = new ArrayList<>();
		if (sum <= 0)
			return sequenceList;

		for (int n = (int) Math.sqrt(2 * sum); n >= 2; n--) {
			if (((n & 1) == 1 && sum % n == 0) || ((n & 1) == 0 && (sum % n) * 2 == n)) {
				ArrayList<Integer> sequence = new ArrayList<>();
				for (int j = 0, k = (sum / n) - (n - 1) / 2; j < n; j++, k++) {
					sequence.add(k);
				}
				sequenceList.add(sequence);
			}
		}
		return sequenceList;
	}

	public static void main(String[] args) {
		Offer57_ContinuousSquenceWithSum demo = new Offer57_ContinuousSquenceWithSum();
		List<List<Integer>> sequence1 = demo.FindContinuousSequence1(15);
		for (List<Integer> list : sequence1) {
			System.out.println(list);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值