题目分析:[[EVD]] - 剑指 Offer 57 - II. 和为s的连续正数序列https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/
简单描述:
- 输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
- 序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
限制🚫
- 1 <= target <= 10^5
示例:
输入:target = 9
输出:[[2,3,4],[4,5]]
解题思路:
思路:
- #数学 反推数学求和公式,枚举左边界,结合公式和target预估右边界,判断是否符合
- #双指针 #滑动窗口 从头开始,根据target滑动窗口
效率:
- 时间复杂度
- 空间复杂度
代码:
- 1.数学反推
class Solution
{
public:
/*枚举左边界,根据数学求和公式和target反推右边界*/
vector<vector<int> > findContinuousSequence(int target)
{
vector<vector<int> > res;
int l = 1;
double r = target / 2 + 1;
while (l < r)
{
r = (-1 + sqrt(1 + 4 * (2 * target + (long)l * l - l))) / 2;
if (l < r && r == (int)r)
{
vector<int> tmp;
for (int i = l; i <= (int)r; i++)
tmp.push_back(i);
res.push_back(tmp);
tmp.clear();
}
l++;
}
return res;
}
};
- 2.双指针、滑动窗口
class Solution
{
public:
/*双指针枚举左右边界*/
vector<vector<int> > findContinuousSequence(int target)
{
int i = 1, j = 2;
vector<vector<int> > res;
while (i < j)
{
int s = (i + j) * (j - i + 1) / 2; //求和公式
if (s == target)
{
vector<int> ans;
for (int k = i; k <= j; k++)
ans.push_back(k);
res.push_back(ans);
}
if (s >= target) //序列和>目标,左边界移动,降低序列所含数字个数
i++;
else
j++;
}
return res;
}
};