滑动窗口求解。
规律:一个有序排列的数组,求两个数的和,可以考虑使用两个指针在两端,向中间移动。如果两个指针的和大于目标数,说明两下标之间的任意数与右下标数的和一定大于目标数,那么就淘汰右下标的数,即右指针向左移动一位。再进行比较,同理,如果两个指针的数之和小于目标数,就将左标向右移动一位,再进行比较。结束条件是left≥right。 如:1,3,5,6,7,8 target=10;
一个有序排列的数组,求很多连续数字的和。可以使用两个指针(left,right)都从左边第一个数开始向右移动。创建一个数sum记录当前左右下标之间的数之和是多少,初始sum=left。
*如果sum<target 说明两下标之间的元素和不够大,将right标向右移动一位,sum=sum+right;
*如果sum>target,说明两下标之间的元素和太大了,先将sum=sum-left ,left标向右移动一位。
*如果等于的话就记录下标之间的元素。
如:1 2 3 4 5 6 , target=9. 当left=1,right=4时,sum已经到了10;太大了,这时应该将left移到2,。等于放弃了left=1,right=5,6的可能。是合理的,因为1-4 相加大于9了,那么1-5,1-6 相加更大于9.所以放弃1是合理的。
这两个思路可以考虑到所有情况。适用于排好序的数组的计算。
class Solution {
public static int[][] findContinuousSequence(int target) {
//由题意可知,滑动窗口求解
if(target<=0){
return new int[0][0];
}
List<int[]> list = new ArrayList<>();
int last = target/2+1;
int left=1;
int right=1;
int sum=1;
while(right<=last){
if(sum<target){
right++;
sum+=right;
}else if(sum>target){
sum-=left;
left++;
}else{
int[] arr = new int[right-left+1];
for(int i =left;i<=right;i++){
arr[i-left]=i;
}
list.add(arr);
sum-=left;
left++;
}
}
return list.toArray(new int[list.size()][]);
}
}