题目链接:leetcode.
没把题看清楚就做,(但终于一次写出一个回溯了!!!
要求连续的正整数序列,回溯得到的根本不连续鸭
class Solution {
public:
vector<vector<int>> ans;
vector<int> tmp;
void dfs(int target, int sum, int index)
{
if(sum > target)
{
return;
}
if(sum == target)
{
ans.push_back(tmp);
return;
}
while(index < target)
{
tmp.push_back(index);
dfs(target, sum + index, index + 1);
tmp.pop_back();
index++;
}
}
vector<vector<int>> findContinuousSequence(int target) {
dfs(target, 0, 1);
return ans;
}
};
一、暴力枚举:
/*
执行用时:316 ms, 在所有 C++ 提交中击败了7.27%的用户
内存消耗:96 MB, 在所有 C++ 提交中击败了5.30%的用户
*/
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
if(target < 3)
return {};
vector<vector<int>> ans;
for(int i = 1;i + i + 1 < target;++i)
{
vector<int> tmp;
tmp.push_back(i);
tmp.push_back(i + 1);
int t = i + i + 1;
for(int j = i + 2;t < target;++j)
{
t += j;
tmp.push_back(j);
if(t == target)
{
ans.push_back(tmp);
break;
}
}
}
return ans;
}
};
很好,我很蠢,竟然只想到了暴力,没有利用上题中的条件
二、连续也一定有序,双指针滑动窗口,时间复杂度只有O(n)
/*
执行用时:4 ms, 在所有 C++ 提交中击败了64.50%的用户
内存消耗:6.4 MB, 在所有 C++ 提交中击败了94.39%的用户
*/
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> ans;
int limit = target / 2 + 1;
int i = 1, j = 2;
int windows = i + j;
while(i < j && j <= limit)
{
if(windows == target)
{
vector<int> tmp;
for(int k = i;k <= j;++k)
{
tmp.emplace_back(k);
}
ans.push_back(tmp);
windows -= i;
i++;
}
else if(windows < target)
{
j++;
windows += j;
}
else
{
windows -= i;
i++;
}
}
return ans;
}
};
第三种方法,所求子数列是一个等差数列,可以用数学方法直接得出其和sum = (i + j) * (j - i + 1) / 2;
当sum == target时,把子数列记录起来,其实是对第一种方法的优化,O(n),O(1)
对于每一个
i,不必循环计数求有没有满足条件的j,而是直接用一元二次求根公式算出满足条件的j,看其是否存在(是否为整数)
j^2 + j + (i - i^2 - 2 * target) = 0;
因为x = (-b ±√(b^2 - 4 * b * c) ) / (2 * a);
故解j = (-1 ±√(1 - 4 * (i - i^2 - 2 * target)) ) / 2;
j一定为正数,所以不取负解
可以通过计算出double类型的j,比较j == (int)j判断是否为整数
也可以通过观察,发现判别式Δ= (b^2 - 4 * b * c)开根号一定是整数 ,且-1 + √Δ一定是偶数
另外:求取i^2过程中可能会导致溢出,所以要使用long型
/*
执行用时:8 ms, 在所有 C++ 提交中击败了28.48%的用户
内存消耗:6.6 MB, 在所有 C++ 提交中击败了57.78%的用户
*/
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
vector<vector<int>> ans;
int limit = target / 2 + 1;
for(long i = 1;i < target;++i)
{
double j = (-1 + sqrt(1 - 4 * (i * (1 - i) - 2 * target)) ) / 2;
if(j == (int) j)
{
vector<int> tmp;
for(int k = i;k <= j;++k)
{
tmp.emplace_back(k);
}
ans.emplace_back(tmp);
}
}
return ans;
}
};
该博客主要讨论了LeetCode的一道题目,关于找到和为s的连续正数序列。博主首先反思了暴力枚举的不足,然后提出使用双指针滑动窗口的方法降低时间复杂度到O(n)。接着,博主指出所求序列是等差数列,并介绍了如何利用一元二次方程求根公式直接计算,优化了空间复杂度。博客中还提到了避免溢出的计算策略,并强调了解的正数性质。
366

被折叠的 条评论
为什么被折叠?



