0
点赞
收藏
分享

微信扫一扫

两种方法解LeetCode和为s的连续正数序列


题目描述

两种方法解LeetCode和为s的连续正数序列_滑动窗口

方法一:数学方法

头一次自己想的方法不仅能通过,而且效率还挺高,先看一下数学方法的提交结果

两种方法解LeetCode和为s的连续正数序列_i++_02


其实思路也很简单:分析题目可知得到的序列为等差数列,那我们只要知道每个序列的起始值以及序列的长度,我们就可以构造出整个序列,然后用一个临时的vector保存此序列,最后将临时的vector加入二维数组(vector<vector> res)即可

  • 首先确定序列的大小,序列的大小为[2,sqrt(2*target)]
  • 因为当序列起始值为1时构造序列,序列长度最长,由等差数列公式可知此时长度就是sqrt(2*target)
  • 有了序列的长度n,又有了等差数列的和target,现在就可以求得数列的起始值,然后构造数列了。起始值s,数列长度n,目标值target三者满足如下关系才可构造数列
  • 此时要想完美地求得数列的起始值,我们需要

附上代码:

vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> res;
for(int n=(int)sqrt((double)target*2); n>=2; n--){
if(2*target%n==0 && (2*target/n+1-n)%2==0){
int s = (2*target/n+1-n)/2;//s表示数列起始值
if(s < 1) continue;//起始值必须为正整数
vector<int> temp;
int len = n;
while(len-- > 0){
temp.push_back(s++);
}
res.push_back(temp);
}
}
return res;
}

方法二:滑动窗口

也挺好理解的,我就不写分析过程了,参考题解:​​滑动窗口​​

int getSum(int left , int right){
int res = 0;
for(int i=left; i<=right; i++){
res += i;
}
return res;
}
vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> res;
int left = 1;
int right = left + 1;
while( left <= target/2 ){
int sum = getSum(left, right);
if(sum < target){
right++;
continue;
}else if(sum > target){
left++;
continue;
}else{
vector<int> temp;
for(int i=left; i<=right; i++){
temp.push_back(i);
}
res.push_back(temp);
left++;
right++;
}
}
return res;
}

不用每次调用getsum函数的代码

vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> res;
int left = 1;
int right = left + 1;
int sum = getSum(left, right);
while( left <= target/2 ){
if(sum < target){
//先移动右侧窗口再修改sum值
right++;
sum += right;//此时的区间和
}else if(sum > target){
//先修改sum值,再移动左侧窗口
sum -= left;
left++;
}else{
vector<int> temp;
for(int i=left; i<=right; i++){
temp.push_back(i);
}
res.push_back(temp);
sum -= left;
left++;//窗口左边界向右移动
right++;//由于左边界移动了,显然右边界也要向右移动
sum += right;
}
}
return res;
}


举报

相关推荐

0 条评论