JZ41 和为S的连续正数序列

 思路一:暴力破解,双指针

import java.util.ArrayList;
public class Solution {
    ArrayList<ArrayList<Integer>> list = new ArrayList<>();
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
        if(sum<=2)
            return list;
        for(int i=1;i<=sum;i++)
        {
            ArrayList tempList = new ArrayList<>();
            int total=sum;
            for(int j=i;j<=sum;j++)
            {
                total-=j;
                if(total>0)
                {
                   tempList.add(j);
                }
                else if(total<0)
                {
                    break;
                }
                else
                {
                	tempList.add(j);
                    if(tempList.size()>1)
                    list.add(tempList);
                    break;
                }
            }
        }
        return list;
    }
}

思路一的优化:由于和的序列最少为2个,所以遍历的上界为sum/2,sum/2+(sum+1)/2已经超过sum了。由于是向上取整所以上界为(sum+1)/2;

也可以通过举例子来找规律

import java.util.ArrayList;
public class Solution {
    ArrayList<ArrayList<Integer>> list = new ArrayList<>();
    public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
        if(sum<=2)
            return list;
        for(int i=1;i<=(sum+1)/2;i++)
        {
            ArrayList tempList = new ArrayList<>();
            int total=sum;
            for(int j=i;j<=(sum+1)/2;j++)
            {
                total-=j;
                if(total>0)
                {
                   tempList.add(j);
                }
                else if(total<0)
                {
                    break;
                }
                else
                {
                	tempList.add(j);
                    list.add(tempList);
                    break;
                }
            }
        }
        return list;
    }
}

时间复杂度是n根号n,为什么是根号n?leetcode题解有这一块的证明,额外空间复杂度是O(1)

我随便举了两个数来看内循环的复杂度,这当然不够严谨

思路二:滑动窗口【解决定长问题】

import java.util.ArrayList;
public class Solution {
    ArrayList<ArrayList<Integer>> list=new ArrayList<>();
    public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
        int left=1;
        int right=1;
        ArrayList tempList = new ArrayList<>();
        int total=0;
        while(left<=sum/2)
        {
            if(total<sum)
            {
                total+=right;
                tempList.add(right);
                right++;
            }
            else if(total>sum)
            {
                total-=left;
                tempList.remove(0);
                left++;
            }
            else
            {
                list.add(new ArrayList<>(tempList));
                total-=left;
                tempList.remove(0);
                left++;
            }
        }
        return list;
    }
}

复杂度:这种方式在移除集合左边元素的时候,集合会整体左移,时间复杂度还可以优化下

思路二优化:滑动窗口【解决定长问题,通用解法】,考虑到解的稀疏性【满足的序列个数相对于遍历长度很小】,因此构建序列复杂度简化为O(1),参考K神

import java.util.ArrayList;
public class Solution {
    public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
        int left=1;
        int right=1;
        int curSum=0;
        ArrayList<ArrayList<Integer>> list=new ArrayList<>();
        if(sum<3)
            return list;
        while(right<=sum)
        {
            if(curSum>sum)
            {
                curSum-=left;
                left++;
            }
            else if(curSum<sum)
            {
                curSum+=right;
                right++;
            }
            else if(curSum==sum)
            {
                ArrayList tempList = new ArrayList<>();
                for(int i=left;i<right;i++)
                {
                    tempList.add(i);
                }
                list.add(tempList);
                curSum-=left;
                left++;
            }
        }
        return list;
}
}

时间复杂度O(N),空间复杂度仅使用几个常量为O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_40396568

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值