双指针算法。
法1:直接枚举,从头到尾枚举区间,记录出某段区间的值,如果值==sum,把这段区间的值加入res中。
时间复杂度为On√n(n根号n)。因为内层判断不会超过√n次(1+2+3+…+√n > n)。因此空间复杂度为O√n。
vector<vector<int> > FindContinuousSequence(int sum) {
// write code here
if(sum == 0 || sum == 1 || sum == 2) return{};
vector<vector<int>> res;
vector<int> temp;
for(int i = 1; i < sum; i++){
int curSum = 0;
for(int j =i; ; j++){
curSum += j;
if(curSum > sum){
break;
}else if(curSum == sum){
temp.clear();
for(int k = i; k <= j; k++){
temp.emplace_back(k);
}
res.emplace_back(temp);
}
}
}
return res;
}
法2:滑动窗口 能够实现On的复杂度。
思路:从某一个数字开始的连续序列和等于目标数如果有,只能有一个,于是我们可以用这个性质来使区间滑动。
两个指针l、r指向区间首和区间尾,公式(l+r)∗(r−l+1)/2计算区间内部的序列和,如果这个和刚好等于目标数,说明以该区间首开始的序列找到了,记录下区间内的序列,同时以左边开始的起点就没有序列了,于是左区间收缩;如果区间和大于目标数,说明该区间过长需要收缩,只能收缩左边;如果该区间和小于目标数,说明该区间过短需要扩大,只能向右扩大,移动区间尾。
vector<vector<int> > FindContinuousSequence(int sum) {
// write code here
if(sum == 0 || sum == 1 || sum == 2) return{};
vector<vector<int>> res;
vector<int> temp;
int l = 1;
int r = 2;
int up = sum / 2 + 1;
while(l < r && r <= up){
int curSum = (l + r) * (r - l + 1) / 2;
if(curSum == sum){
temp.clear();
for(int i = l; i <= r; i++){
temp.emplace_back(i);
}
res.emplace_back(temp);
l++; // 记得等于条件下,左边界也要收缩
} else if(curSum < sum){ // 说明序列和小了 r往右边去点
r++;
}else{
l++;
}
}
return res;
}
剑指offerNo42:为S的两个数字
双指针算法,和41差不多思路
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
if(array.size() == 0 || sum < array.front()) return {};
int l = 0;
int r = array.size() - 1;
int curSum = 0;
while(l < r){
curSum = array[l] + array[r];
if(curSum == sum){
return {array[l], array[r]};
}else if(curSum < sum){
l++;
}else{
r--;
}
}
return {};
}