力扣题目地址:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/
首先看题目:
输入一个正整数 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
解决思路:
这道题目的解决方法其实有很多,但是我很喜欢官方题解中的双指针法(也可以叫滑动窗口法);今天就给大家讲一讲我的如何实现双指针法的吧。
既然是双指针法,那么我们肯定有两个指针,一个是左指针 left,一个是右指针 right。主要思路是这样的:我们指定 left 和 right 的一个区间,利用正整数列求和公式:sum = (left+right)*(right-left+1)*2 我们可以算出当前区间的sum值。如果 sum 等于 target 说明当前区间是我们需要的数组,再去把这个区间保存为一个数组,同时左指针右移一位(因为当前左指针和为target值的区间已被找到);如果 sum 小于 target 说明当前区间太小,需要将右指针右移一位,扩大区间;如果 sum 大于 target 说明当前区间太大,需要将左指针右移一位,减小区间。
开始我们的解题之旅:
- 计算当前区间sum值
- 如果相等,遍历区间每个值放入数组,并将左指针右移一位
- 如果sum小于target 右指针右移一位
- 如果sum大于target 左指针右移一位
代码实现:
/**
* https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/
* @param target
* @author GeYuxuan 2020-03-06 23:41:56
* @return int[][]
*/
public int[][] findContinuousSequence(int target) {
List<int []> result = new ArrayList<>();
//遍历区间
for(int l = 1,r = 2; l < r;) {
//1.计算当前区间sum值
int sum = (l+r)*(r-l+1)/2;
//2.如果相等,遍历区间每个值放入数组,并将左指针右移一位
if(sum == target){
int[] a = new int[r-l+1];
//遍历区间值,放入数组
for(int i = l; i <= r; ++i) {
a[i-l] = i;
}
result.add(a);
//左指针右移一位
l++;
}
//3.如果sum小于target 右指针右移一位
else if(sum < target){
r++;
}
//4.如果sum大于target 左指针右移一位
else{
l++;
}
}
return result.toArray(new int[0][]);
}
这个活动窗口法其实也是暴力法的一种,但是他能够通过题目的特性排除一大部分的穷举区间,所以也是一种比较好的方法。
不忘初心,砥砺前行。