這個題很經典,我只會兩種做法,然後在網上看了別的大佬的新穎解法(我想不到的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;
}
};