思路一:直接遍历左边界和右边界,使用数学的方法来计算这一段连续序列的和,如果和为给定值则保存下来,并且放入答案中。
import java.util.*; public class Solution { public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> list = new ArrayList<>(); for(int l = 1; l <= (sum + 1) / 2; ++ l) { //左边界 for(int r = l + 1; r <= (sum + 1) / 2; ++ r) {//右边界 int _sum = (r - l + 1) * (l + r) / 2; if(_sum == sum) { ArrayList<Integer> temp = new ArrayList<>(); for(int i = l; i <= r; ++ i) { temp.add(i); } list.add(temp); } } } return list; } }
思路二:双指针,类似于滑动窗口,首先一开始我们先固定一个长度为 2 的一个区间,如果这个区间和小于给定值我们就可以让右指针后移一位,重复这种操作直到区间和不小于给定值,接着如果区间和小于给定值,那么我们就让左指针后移一位,直到区间和不大于给定值,此时的区间和有可能等于给定值,那么我们判断,如果等于给定值则保存答案,此时将左指针后移一位以便于统计后面符合条件的区间。
import java.util.*; public class Solution { public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> list = new ArrayList<>(); int l = 1, r = 2, _sum = 3; while(r <= (sum + 1) / 2) { //右指针不越界 while(r <= (sum + 1) / 2 && _sum < sum) {//不断的添加数字 ++ r; _sum += r; } while(l <= r && _sum > sum) {//如果和比较大则不断的删除数字 _sum -= l; ++ l; } if(r >= l + 1 && _sum == sum) {//找到答案,并且保证区间最小为二 ArrayList<Integer> temp = new ArrayList<>(); for(int i = l; i <= r; ++ i) { temp.add(i); } list.add(temp); _sum -= l; ++ l;//可能不止一个答案,删除小的数字继续找一个合适的区间 } } return list; } }