思路一:暴力破解,双指针
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)