和为S的连续正数序列

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

解法,刚开始直接用的暴力解法,解题思路是通过遍历在100/i附近对数字进行拼接,如果100%i==0,那连续正数数列肯定在100/i处附近对称,如果100%i!=0,那肯定左边或者右边会多出一个数,解法如下:

import java.util.*;
public class Solution {
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
       ArrayList<ArrayList<Integer>> resultlist = new ArrayList<ArrayList<Integer>>();
       int midnum = sum/2;
       if(sum==3){
           ArrayList<Integer> templist = new ArrayList<Integer>();
           templist.add(1);
           templist.add(2);
           resultlist.add(templist);
           return resultlist;
       }
       for(int i=2;i<midnum;i++){
           int middle = sum/i;
           if(sum%i==0){
               int temp = 0;
               for(int j=middle-i/2;j<=middle+i/2&&j>0;j++){
                   temp = temp+j;
               }
               if(temp==sum){
                   ArrayList<Integer> templist = new ArrayList<Integer>();
                   for(int j=middle-i/2;j<=middle+i/2;j++){
                    templist.add(j);
                   }
                   resultlist.add(templist);
               }
           }else{
               int modNum = sum%i;
               int max = sum - middle*(i-1);
               int temp = 0;
               if(max==modNum+middle&&middle+i/2==max){
                   ArrayList<Integer> templist = new ArrayList<Integer>();
                   for(int j=middle-i/2+1;j<=middle+i/2&&j>0;j++){
                    templist.add(j);
                    temp = temp + j;
                   }
                   if(templist!=null&&templist.size()!=0&&temp==sum){
                       resultlist.add(templist);
                   }
               }

           }
       }
       Collections.sort(resultlist,new MyComparator());
       return resultlist;
    }
    class MyComparator implements Comparator{
        public int compare(Object object1, Object object2) {// 实现接口中的方法  
            ArrayList<Integer> p1 = (ArrayList<Integer>) object1; // 强制转换  
            ArrayList<Integer> p2 = (ArrayList<Integer>) object2;  
            if(p1.get(0)>=p2.get(0)){
                return 1;
            }else{
                return -1;
            }
        }  
    }
}

后来看了一下网友的解法,觉得更加巧妙,贴上来:

思路:
    由,求和为s的的两个数得到的启发。
    由于是要求连续的。所以我们就从左开始走。
    当连续数组和小于sum时,我们肯定得再多加一点。那么就再加上后一个数字。(i++)
    当所加和大于sum时,那么我们肯定得减小一点。舍弃第一个数字。
    当所加和等于时,listAll添加一个新的list。然后list删去head,count减去head。
import java.util.ArrayList;
public class Solution {
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
        ArrayList<ArrayList<Integer>> listALL = new ArrayList<>();
        ArrayList<Integer> list = new ArrayList<>();

        if (sum < 1) {
            return listALL;
        }

        int count = 0;
        int head = 0;
        // 最多就到sum/2
        for (int i = 1; i <= sum;) {
            if (count < sum) {
                count += i;
                list.add(i);
                i++;
            } else if (count > sum) {
                head = list.remove(0);
                count -= head;
            } else {
                listALL.add(new ArrayList(list));
                head = list.remove(0);
                count -= head;
            }
        }
        return listALL;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值