美文网首页
面试题57 - II. 和为s的连续正数序列

面试题57 - II. 和为s的连续正数序列

作者: 阿星啊阿星 | 来源:发表于2020-02-15 16:43 被阅读0次

    和为s的连续正数序列

    题目描述

    输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。

    序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。


    示例:

    输入:target = 9
    输出:[[2,3,4],[4,5]]

    输入:target = 15
    输出:[[1,2,3,4,5],[4,5,6],[7,8]]


    提示:
    1 <= target <= 10^5

    转载来源:力扣(LeetCode)


    题目分析

    一开始想这题是关于数组的求和,很有可能是和动态规划有关,考点就是通过动态规划来存放中间计算量,来达到加速效果,不然会卡时间超限,嗯我真是天才,一看题目什么都知道了;


    动态规划

    然后就秒想出状态转移方程sum[i][j] = sum[i-1][j-1] + j,时空都是O(N^2),然后再天才的千方百计将空间复杂度下降到O(N),并添加一些提前结束计算循环的剪枝,再按照题目要求输出,才提交上去,果然AC了!只不过...


    Kotlin提交
    我真是天才,超越Kotlin100%的用户,但是感觉不太对劲啊,怎么花了差不多四秒才执行完,遂用Java重新写了一遍,提交上去,啊哦~
    Java提交

    我真是个弟弟,然后我就重新想,这道题的第I部分是前后夹击,但是这道题这样做不行,因为要求是连续和,不能前后计算,因为连续和为target的几个数(两个以上),最大的只能是target/2,所以就从target/2往前推,一开始设置尾指针tail为target/2,头指针head为target/2-1,长度len为2,和sum为head+tail,就开始下面的循环

    • sum为target,就将从head开始,包装出一个长度为len的步长为1的单增数组,并添加到答案,重点来了,因为从head到tail的和为target,那么,tail就肯定不能出现在长度len更长的其他答案里面(反证法,如果在,和就肯定比target大),tail就需要往前推,tail往前推了,head+tail肯定就小于target了,所以head也往前推,sum就比原来小了len那么多

    • sum比target大,那tail肯定要排除在后面的答案序列里面,举个例子,2+3+4比8要大,我们是从后往前的,如果不把4踢掉,那么连续序列肯定比(2+3+4)要长,肯定不符合答案,所以这种情况下前后指针都往前推,sum就比原来小了len那么多

    • sum比target小,这种情况只能head往前推,不能head和tail都往前推,因为head to tail比target小,都往前推的话还是比target小,没意义,只能通过增长序列来求解,所以这种情况head往前推,sum+=head,len++

    ArrayList<int[]> ans = new ArrayList<>();
            int tail = (target % 2 == 0) ? target / 2 : target / 2 + 1;
            int head = tail - 1;
            int len = 2;
            int sum = tail + head;
            while(head != 0){
                if(sum == target){
                    int[] tmp = new int[len];
                    for (int i = 0; i < tmp.length; i++) {
                        tmp[i] = head + i;
                    }
                    ans.add(tmp);
                    tail--;
                    head--;
                    sum -= len;
                }else if(sum > target){
                    head--;
                    tail--;
                    sum -= 2;
                }else{
                    head--;
                    len++;
                    sum += head;
                }
            }
            int[][] ret = new int[ans.size()][];
            for (int i = 0; i < ans.size(); i++) {
                ret[i] = ans.get(ans.size() - i - 1);
            }
            return ret;
    

    代码文件,kotlin的为DP算法,Java为指针算法


    相关文章

      网友评论

          本文标题:面试题57 - II. 和为s的连续正数序列

          本文链接:https://www.haomeiwen.com/subject/driefhtx.html