leetcode-剑指 Offer 57 - II. 和为s的连续正数序列
输入一个正整数 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
解题思路:
方法一:根据求二次方程的数学公式推导:
x,x+1,x+2,x+3…,x+k。
等差数列求和公式:(x+x+k)*(k+1)/2=target;
x是已知的范围[1,target-1];
然后解方程求k.
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> ans;
for(int i=1;i<target;i++)
{
double dlt=4.0*i*i-4*i+1+8*target; //判别式
//cnt代表连续序列的个数,所以只能是正根,舍掉负根
double cnt=1.0*(sqrt(dlt)-(2*i+1))/2;
vector<int> tmp;
if(dlt>=0) //有根
{
int k=cnt;
if((2*i+k)*(k+1)==2*target) //k满足的条件
{
for(int j=0;j<=k;j++)
tmp.push_back(i+j);
ans.push_back(tmp);
}
}
}
return ans;
}
};
方法二:滑动窗口:
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> ans;
int left=1,right=1;
int sum=0;
while(left<=target/2)
{
vector<int> tmp;
if(sum<target)
{
sum+=right;
right++;
}
else if(sum==target)
{
for(int j=left;j<right;j++)
tmp.push_back(j);
ans.push_back(tmp);
sum-=left;
left++;
}
else
{
sum-=left;
left++;
}
}
return ans;
}
};