输入一个正整数 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
分析:
方法:滑动窗口
拿 target = 9 举例,我们列举出从 1 到 9 的所有数字:
- 1 2 3 4 5 6 7 8 9
那么 target 的数组就是其中的几个区域,我们可以将求区域的过程不断移动收缩的过程,从 1,2 开始:
- 1 2 3 4 5 6 7 8 9 区域和 = 3 < target,扩大区域
- 1 2 3 4 5 6 7 8 9 区域和 = 6 < target,扩大区域
- 1 2 3 4 5 6 7 8 9 区域和 = 10 > target,缩小区域
- 1 2 3 4 5 6 7 8 9 区域和 = 9 == target,记录区域,向右移动
- 1 2 3 4 5 6 7 8 9 区域和 = 12 > target,缩小区域
- 1 2 3 4 5 6 7 8 9 区域和 = 9 == target,记录区域,向右移动
- 1 2 3 4 5 6 7 8 9 区域和 = 11 > target,缩小区域
- 1 2 3 4 5 6 7 8 9 区域长度变为1,不满足至少两个数,停止遍历
我们可以定义双制针 i ,j 来实现:
- 区域和小于 target,j++
- 区域和大于 target,i++
- 区域和等于 target,记录该区域,i++,j++
- 两指针重合,停止遍历
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public int[][] findContinuousSequence(int target) {
//定义双指针,滑块和
int i = 1, j = 2, sum = 3;
//定义List集合存储每个数组
List<int[]> res = new ArrayList<>();
//遍历
while(i < j){
//滑块和等于target,存储数组
if(sum == target){
//创建数组并存储对应数字
int[] nums = new int[j - i + 1];
int index = 0;
for(int k = i; k <= j; ++k){
nums[index] = k;
index++;
}
res.add(nums);
//移动滑块
j++;
sum += j - i;
i++;
}
//滑块和小于target,扩大滑块
else if(sum < target){
j++;
sum += j;
}
//滑块和大于target,缩小滑块
else{
sum -= i;
i++;
}
}
return res.toArray(new int[0][]);
}
}
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof