算法题-和为S的数字

和为S的数字

题目描述

给定正整数n,求所有和为n的连续序列,如n = 100,则9,10,11,12,13,14,15,16是他的一个连续序列。(剑指Offer 57题)

解题思路

1.利用序列为连续的特性求解

由于这个序列是连续的那么设这个序列为(a1,a2,…an-1,an),其和Sn的值为k,那么当k < n时为了增大k得到n,在序列中加入an+1,反之当 k > n时取出当前序列中最小的元素a1,当n == k时则为一个符合要求的解。为了寻找下一个解则继续在序列后加入下一个数。

由于和为n且序列为连续序列,当n为偶数时序列结尾肯定小于等于n/2,因为(n / 2) + (n / 2) + 1 > n,当n为奇数时(n / 2) * 2 + 1 == n 所以结尾肯定小于等于(n / 2) + 1 综上序列搜索的结尾为Math.ceil(n/2)

综上所述,我们可以从(1,2)序列开始往后搜索直到结尾数为Math.ceil(n/2)

代码如下

    /**
     * 
     * @param sum 序列和
     * @return 所有符合要求的序列的集合
     */
    public static List<List<Integer>> solve(int sum){
        if(sum < 1)
            throw new IllegalArgumentException("sum must greater than zero");
        List<List<Integer>> result = new ArrayList<>();
        if(sum < 3)//和小于3时不存在符合序列
            return result;
        //从1,2序列开始遍历所有可能
        //end最大为sum一半的上取整,因为(sum / 2) + (sum / 2) == sum
        //sum为偶数则(sum / 2) + (sum / 2) + 1 > sum
        //sum为奇数时2 * (sum / 2 + 1) > sum
        //now用来记录当前序列和防止每次重复计算
        int beg = 1, end = 2, now = 3, half = (int) Math.ceil((double)sum/2);
        while(end <= half && beg < end){
            if(now == sum){
                List<Integer> list = new ArrayList<>();
                for(int i = beg;i <= end;i++)
                    list.add(i);
                result.add(list);
                /*
                * 找到后末尾添加下一个元素继续搜索
                * 设添加前首元素为a1,末尾为an-1,和为n
                * 那么n + an - a1 > n,所以beg+=2
                */
                end++;beg+=2;
                now += end - (2 * beg -3);
            }else if(now < sum){
  
  //序列过小末尾增加下一个
                end++;
                now += end;//计算当前总和值
            }
            else{
  
  //序列过大前面减少一个
                now -= beg;
                beg++;
            }
        }
        return result;
    }
2.利用数学公式求解

设这个序列为(a1,a2,…an-1,an),那么其和有公式如下

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值