ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

剑指41.和为S的连续正数序列

2020-08-25 18:34:20  阅读:214  来源: 互联网

标签:int big ArrayList 41 small 序列 正数 sum


题目描述

小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!  

输出描述:

输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序  

思路

思路1:滑动窗口法(区间连续,双指针同向移动)。用两个数small和big分别表示序列的最小值和最大值,首先把small初始化为1,big初始化为2.如果从small到big的序列的和大于s,则从序列中去掉较小的值,也就是增大small的值。如果从small到big的序列的和小于s,则可以增大big,让这个序列包含更多的数字。因为这个序列至少要有两个数字,我们一直增加small到(1+s)/2为止。

 

思路2:还可以尝试数学分析法。

 

解法1

import java.util.ArrayList;
public class Solution {
    // 版本1
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
        ArrayList<ArrayList<Integer> >  res = new ArrayList<>();
        int small = 1, big = 2;  //两个起点,相当于动态窗口的两边
        while (small < big){ // small < (sum + 1) / 2  也能通过
            int tempSum = (small + big)*(big - small + 1) / 2;
            if (tempSum == sum){
                ArrayList<Integer> list = new ArrayList<>(); // 每次用的时候new一个,这样就不需要用完list.clear()了
                for (int i = small; i <= big; i++) {
                    list.add(i);
                }
                res.add(list);
                big++;
            }else if (tempSum > sum){  //如果当前窗口内的值之和大于sum,那么左边窗口右移一下
                small++;
            }else{  //如果当前窗口内的值之和小于sum,那么右边窗口右移一下
                big++;
            }
        }
        return res;
    }
    // 版本2
    // 与版本1相比不同之处:求连续序列的和,因此可以在前一个序列和的基础上求操作之后的序列的和。
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
        ArrayList<ArrayList<Integer> >  res = new ArrayList<>();
        int small = 1, big = 2;  //两个起点,相当于动态窗口的两边
        int tempSum = small + big;
        while (small < big){ // small < (sum + 1) / 2  也能通过
            if (tempSum == sum){
                ArrayList<Integer> list = new ArrayList<>();
                for (int i = small; i <= big; i++) {
                    list.add(i);
                }
                res.add(list);
                big++;
                tempSum += big;
            }else if (tempSum > sum){  //如果当前窗口内的值之和大于sum,那么左边窗口右移一下
                tempSum -= small;
                small++;
            }else{  //如果当前窗口内的值之和小于sum,那么右边窗口右移一下
                big++;
                tempSum += big;
            }
        }
        return res;
    }
}

 

解法2

M一下,以后再做可以试试用数学的思路解一下。

 

自己写的暴力遍历法

import java.util.ArrayList;
public class Solution {
    // 思路就是根据等差数列求和公式(count*(a1+an))/2,遍历起始位置a1,然后遍历count,看是否满足题意
    // 测试用例,输入15;输出1~5 、4~6 、7~8
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
        ArrayList<ArrayList<Integer> > res = new ArrayList<>();
        ArrayList<Integer> list = new ArrayList<>();
        for (int i = 1; i <= sum / 2 + 1; i++) {
            int num = i;
            int counts = sum / 2 + 1;
            while (counts >= 2){
                if (counts*(num+num+counts-1)/2 == sum){  // 核心
                    for (int j = num; j <=num+counts-1;j++)
                        list.add(j);
                    res.add(new ArrayList<>(list));
                    list.clear();
                    break;
                }
                counts--;
            }
        }
        return res;
    }
}

 

收获

如果需要多次使用ArrayList添加数据,可以在每次用的时候new一个新的,这样就不用共用一个,用完list.clear()了。

 

标签:int,big,ArrayList,41,small,序列,正数,sum
来源: https://www.cnblogs.com/HuangYJ/p/13559983.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有