每日刷题第10天 2021.1.5
和为s的连续正数序列
- 难度:简单
- 双指针、滑动窗口
题目
- 输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
- 序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例
输入: target = 9
输出: [[2,3,4],[4,5]]
输入: target = 15
输出: [[1,2,3,4,5],[4,5,6],[7,8]]
限制
1 <= target <= 10^5
解法
/**
* @param {number} target
* @return {number[][]}
*/
var findContinuousSequence = function(target) {
// 开始指针
let start = 1;
// 结束指针
let end = 1;
// 记录加和结果
let ans = 0;
// 记录结果
let map = new Map();
// 记录长度
let len = 0;
while (end < target) {
ans += end;
if (ans >= target) {
if (ans == target) {
len = end - start + 1;
map.set(start, len);
}
// 打破循环
while(ans >= target) {
ans -= start;
start++;
if (ans == target) {
len = end - start + 1;
map.set(start, len);
}
}
}
end++;
}
// 需要返回:一个二维数组
// map的key 就是开始的数字,map的value就是包含开始数字的长度
let lenM = map.size;
let arr = new Array(lenM);
// 存储获取的结果数组
let arr2 = [...map];
// [ [ 2, 3 ], [ 4, 2 ] ]
for (let i = 0; i < lenM; i++) {
arr[i] = new Array(arr2[i][1]);
arr[i][0] = arr2[i][0];
for (let j = 1; j < arr2[i][1]; j++) {
arr[i][j] = arr[i][0] + j;
}
}
return arr;
};
优化
var findContinuousSequence = function(target) {
......处理数据
while (end < target) {
ans += end;
// 优化后的代码
while(ans >= target) {
if (ans == target) {
len = end - start + 1;
map.set(start, len);
}
ans -= start;
start++;
}
end++;
}
......转换数据
return arr;
附录
- 出错原因:end++不应该只在
ans<target的时候进行++- 遗漏掉的情况: 在
while循环start进行打破后,也需要end++ - 因此
end++应该写在最后面,不需要任何的判断条件,直接++即可。
- 遗漏掉的情况: 在
// 错误写法:
// 只有ans最终结果,小于target的时候,才end++
else {
end++;
}
// 正确写法:
end++;