编程题:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序。
一开始只想到了最粗暴的穷举解法:因为S/2后,数字相加一定大于S,所以循环只到S/2为止:
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > res=new ArrayList<ArrayList<Integer> >();
if(sum<3)return res;
int halfSum=sum/2+1;
int i=1;
while(i<=halfSum){
ArrayList<Integer> temp=new ArrayList<>();
int curSum=0;
for(int j=i;j<halfSum+1;j++){
curSum+=j;
temp.add(j);
if(curSum==sum){
res.add(temp);
// i=j-1;
break;
}
else if(curSum>sum){
break;
}
}
i++;
}
return res;
}
学习用双指针方法也就是滑动窗口解决:
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > res=new ArrayList<ArrayList<Integer> >();
if(sum<3)return res;
//滑动窗口的两边,确定窗口的位置和大小
int left=1,right=2;
//当左指针大于等于右指针时,说明窗口数字之和永远大于指定值,结束循环
while(left<right){
//计算当前窗口的和
int curSum=((left+right)*(right-left+1))/2;
//如果与指定数字相等,则将窗口中数字添加到结果中,并将窗口右移
if(curSum==sum){
ArrayList<Integer> temp=new ArrayList<>();
for(int i=left;i<=right;i++){
temp.add(i);
}
res.add(temp);
left++;
}
//如果小于指定值,则右边右移
else if(curSum<sum){
right++;
}
//如果大于,则左边右移
else{
left++;
}
}
return res;
}