[Lc]面试题57_II和为s的连续正数序列
Contents
题目
题解
1. 暴力法
挨个计算所有数组的和,时间复杂度太高
- 时间复杂度: $O(n^{2})$
- 空间复杂度: $O(1)$
2. 滑动窗口法
看注释吧,不太难,证明可以看题解
- 时间复杂度: $O(n)$
- 空间复杂度: $O(1)$
class Solution {//三个方法。1.滑动窗口
public:
vector<vector<int>> findContinuousSequence(int target) {
//左闭右开区间,起初sum为0
int left = 1, right = 1;
int sum = 0;
vector<vector<int>> res;
//!!注意这个终止条件
while(right <= target / 2 + 2){
//sum小于target右边界右移
if(sum < target){
sum += right;
right++;
//sum大于target左边界右移
}else if(sum > target){
sum -= left;
left++;
//sum等于target存结果,并左边界左移
}else{
vector<int> arr;
for(int i = left; i < right; ++i) arr.push_back(i);
res.push_back(arr);
sum -= left;
left++;
}
}
return res;
}
};
3. 等差数列通项公式法
来自erick_chen。这个方法很牛逼,理解起来更容易一点
注意几个点:
- n从2开始,因为题目要求数组至少有两个数
- 借鉴题解2,其实n到不了target+1,在分子小于0的时候循环就停止了
- 随着n增加,tmp和a1都递减
- 只有tmp/n为正整数的时候,该结果才有效
- 注意res要从前面插入结果,否则其数列顺序和结果是相反的
- 时间复杂度: $O(n)$
- 空间复杂度: $O(1)$
class Solution {//三个方法。2.等差数列通项公式法
public:
vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> res;
for(int n=2; n < target + 1; ++n){
int tmp = target - n * (n - 1) / 2;
if(tmp < 1) break;
if(tmp % n == 0){
int a1 = tmp / n;
vector<int> arr;
for(int i = a1; i <= a1 + n - 1; ++i) arr.push_back(i);
res.insert(res.begin(), arr);
}
}
return res;
}
};
4. 求根公式法
和3的思路类似,也是用等差数列的思想,但是是用求根公式求解,而且会有复数情况,个人感觉理解起来比较困难
- 时间复杂度: $O(n)$
- 空间复杂度: $O(1)$
占坑
Author ChrisHRZ
LastMod 2020-06-26