和为S的连续正数序列

1.本题知识点
   知识迁移能力
2. 题目描述
   小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
   输出描述:
   输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
3. 思路
   这题曾经被面试官问到过,因为之前从来没刷过算法,应试场景下后果可想而知,撕心裂肺的经历告诫我,一定要刷算法!!!
   主要思路:滑动窗口和等差数列的求和公式。采用双指针,一个高位指针,一个低位指针。计算2指针之间数的和(窗口大小),通过与目标值sum的比较来改变2个指针的位置。
   具体思路:
   ① 由于是连续正序列,所以首先设置初始指针大小1和2。然后我们就把1~2看成是一个滑动的窗口。
   ② 如果窗口size大于目标sum,此时我们要缩小窗口size,低位指针就往前走一步。
   ③ 如果窗口size小于目标sum,此时我们要放大窗口size,高位指针就往前走一步。
   ④ 如果窗口size等于目标sum,此时我们找到了连续序列,输出,然后低位指针往前走一步寻找下一个正确的窗口。
   ⑤ 终止条件为:高位指针等于sum,因为连续序列至少2个值,如果高位指针等于sum,就成了1个值的和等于sum,不符合条件。高位指针大于sum就更不合理了,所以高位指针最高能走到 sum-1处。
   Java 版:
import java.util.ArrayList;
public class Solution {
    private ArrayList<ArrayList<Integer>> result = new ArrayList<>();
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
       //高低位指针初始化
        int high = 2,low = 1;
        //终止条件:高位指针等于sum
        while(high < sum){
            //等差数列求和公式,求得当前连续序列的和
            int curSum = (high + low)*(high - low + 1)/2;
            //当前序列和等于目标sum
            if(curSum == sum){
                ArrayList<Integer> temp = new ArrayList<>();
                //保存当前序列
                for(int i = low; i <= high;i++)
                    temp.add(i);
                result.add(temp);
                low++;//继续寻找
            }
            else if(curSum < sum){
                high++;
            }
            else{
                low++;
            }
        }
        return result;
    }
}
   更简单更好理解的版本:
import java.util.ArrayList;
public class Solution {
    private ArrayList<ArrayList<Integer> > result = new ArrayList<>();
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int n) {
       int start = 1,end = 2;
       int sum = start+end;
        //思路:先固定左指针,移动右指针。遍历完右指针后,再移动左指针
        while(start < (n+1)>>1)
        {
            if(sum == n) {
                result.add(FinaNums(start,end));
            }
            while(sum < n){
                end++;
                sum+=end;
                if(sum == n) 
                {
                    result.add(FinaNums(start,end));
                }
            }
            
            //然后移动左指针
			sum-=start;
			start++;
        }
        
        return result;
    }
    
    ArrayList<Integer> FinaNums(int start,int end)
    {
        ArrayList<Integer> temp = new ArrayList<>();
        for(int i = start;i<=end;i++){
            temp.add(i);
        }
        
        return temp;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值