这个题很经典,我只会两种做法,然后在网上看了别的大佬的新颖解法(我想不到的0.0),也算作是个学习吧。
题目描述:
输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。
例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5、4~6和7~8。
样例:
输入:15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
方法一:暴力DFS(我的笨解法,没有什么值得注意的地方)
class Solution {
public:
void dfs(vector<vector<int>>& vv,vector<int> v, int target, int sum)
{
if(target <= sum)
{
if(target == sum)
{
vv.push_back(v);
}
return;
}
for(int i = 1; i < target; i++)
{
if(v.empty() || (!v.empty() && i == v.back() + 1))
{
v.push_back(i);
dfs(vv,v,target,sum + i);
v.pop_back();
}
}
}
vector<vector<int> > findContinuousSequence(int sum) {
vector<vector<int>> vv;
vector<int> v;
if(sum == 0)
return vv;
dfs(vv,v,sum,0);
return vv;
}
};
方法二 暴力枚举 (我的O(N*N)的笨方法)
思路:
设置两个指针i和j,j再去遍历数组后面的数字,看是否能加到sum, j和 j + n分别指向连续正数序列的起始和终止
用s表示当前连续正数序列的和,即s=j+(j+1)+…+j + n <= sum ?
看是否能凑出sum的值。
时间复杂度:O(N*N)
空间复杂度:O(N)
class Solution {
public:
vector<vector<int> > findContinuousSequence(int sum) {
vector<vector<int> > ans;
for(int i = 1; i < sum; i++) {
int res = 0;
vector<int> tmp;
for(int j = i; j < sum; j++) {
tmp.push_back(j);
res += j;
if(res >= sum) break;
}
if(res == sum) ans.push_back(tmp);
}
return ans;
}
};
方法三: 利用求和公式
思路:利用连续数组求和公式,Sn = (首项 + 尾项)*项数 / 2 。所以利用双指针i,j 求的解。
class Solution {
public:
vector<vector<int> > findContinuousSequence(int sum) {
vector<vector<int>> res;
vector<int> path;
for(int i = 1, j = 2; j < sum && i < j; j) {
int ans = (i + j) * (j - i + 1) / 2;
if ( ans == sum){ //如果相同就加入。
int k = i;
while(k <= j)
path.push_back(k++);
res.push_back(path);
path.clear();
i ++, j ++;//两个指针同时往后移。
}
else if ( ans < sum) {//如果比较小,j就往后移动。
j ++;
}
else
i ++;//否则i往后移动
}
return res;
}
};
方法四:双指针
思路:
设置两个指针i和j,分别指向连续正数序列的起始和终止
用s表示当前连续正数序列的和,即s=i+(i+1)+…+js=i+(i+1)+…+j
以i递增的方式遍历整个序列(1到n),代表查找以i开头的时候结尾j应该是多少。当s<sums<sum说明j应该往后移动,当s=sums=sum说明满足题意,当s>sums>sum说明向后走即可。
注意上述遍历过程中,s=sums=sum的情况下不需要把j往前移动,原因是当进入下一个循环前s−=is−=i,即(i+1)到j的和肯定小于sum。
class Solution {
public:
vector<vector<int> > findContinuousSequence(int sum) {
vector<vector<int>> res;
for (int i = 1, j = 1, s = 1; i <= sum; i ++ )
{
while (s < sum) j ++, s += j;
if (s == sum && j > i)
{
vector<int> line;
for (int k = i; k <= j; k ++ ) line.push_back(k);
res.push_back(line);
}
s -= i;
}
return res;
}
};