题目
题目连接
输入一个正整数 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
解题思路1
没啥技巧纯暴力但超时
class Solution {
public int[][] findContinuousSequence(int target) {
List<List<Integer>> ans = new ArrayList<>();
for (int i = 1; i < target; i++) {
List<Integer> temp = new ArrayList<>();
temp.add(i);
int sum = i;
for (int j = i + 1; j < target; j++) {
temp.add(j);
sum += j;
if (sum == target) {
ans.add(temp);
break;
}
}
}
int[][] result = new int[ans.size()][];
for (int i = 0; i < result.length; i++) {
result[i] = new int[ans.get(i).size()];
for (int j = 0; j < ans.get(i).size(); j++) {
result[i][j] = ans.get(i).get(j);
}
}
return result;
}
}
解题思路2
滑动窗口问题
- 当窗口中的每个元素的和小于 target 的时候,窗口的和需要增加,所以要扩大窗口,窗口的右边界向右移动
- 当窗口中的每个元素的和大于 target 的时候,窗口的和需要减少,所以要缩小窗口,窗口的左边界向右移动
- 当窗口中的每个元素的和等于target 的时候,记录从i到j的每一个元素装进结果集中,并且左右边界都有要右移
需要注意的是:左边界右移会缩小窗口和大小,所以记得减去左边界右移之前的值
代码详细流程:
class Solution {
public int[][] findContinuousSequence(int target) {
if (target <= 2) {
return new int[0][0];
}
//结果集
List<List<Integer>> ans = new ArrayList<>();
int left = 1;
int right = 2;
int sum = left + right;
while (left < right && right < target) {
//如果sum==target说明找到一组正数序列,加入结果集后,准备下次寻找
if (sum == target) {
List<Integer> list = new ArrayList<>();
for (int n = left; n <= right; n++) {
list.add(n);
}
ans.add(list);
sum -= left;
left++;
right++;
sum += right;
//sum>target right再往后移也大于target所以将left++
} else if (sum > target) {
sum -= left;
left++;
}
//sum<target right应该后移
else {
right++;
sum += right;
}
}
//处理结果 将list转化为数组
int[][] result = new int[ans.size()][];
for(int i = 0;i < result.length;i++){
result[i] = new int[ans.get(i).size()];
for(int j = 0;j < ans.get(i).size();j++){
result[i][j] = ans.get(i).get(j);
}
}
return result;
}
}