一.题目描述
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例 1:
输入:target = 9
输出:[[2,3,4],[4,5]]
示例 2:
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
限制:
1 <= target <= 10^5
二.题目解析
public int[][] findContinuousSequence(int target) {
/*滑动窗口(窗口的左边界和右边界永远只能向右移动),时间复杂度O(n)
* */
if(target <= 0){
return null;
}
int left = 1;
int right = 0;//滑动窗口包含元素[left,right],初始滑动窗口大小是0
int sum = 0;
List<List<Integer>> resList = new ArrayList<>();
//滑动窗口的左边界最大是(target - 1) / 2
while (left <= (target - 1) / 2){
//当窗口的和小于 target 的时候,窗口的和需要增加,
// 所以要扩大窗口,窗口的右边界向右移动
if(sum < target){
//顺序不能颠倒
right++;
sum = sum + right;
}else if(sum > target){
//sum > target说明left不可能是连续正数序列的第一个数,
// 于是缩小窗口,左边界向右移动,从下一个开始找
sum = sum - left;
left++;
}else{
//记录结果
List<Integer> curList = new ArrayList<>();
//注意这里不能直接使用left递增,会改变left值
for (int i = left;i <= right;i++) {
curList.add(i);
}
resList.add(curList);
//找到以left开头的连续正数序列满足,那么下次寻找从left+1开始寻找,于是左边界向右移动
sum = sum - left;//顺序不能颠倒
left++;
}
}
//链表转为二维数组
int[][] res = new int[resList.size()][];
for (int i = 0; i < resList.size(); i++) {
int length = resList.get(i).size();
res[i] = new int[length];
for (int j = 0; j < length; j++) {
res[i][j] = resList.get(i).get(j);
}
}
return res;
}