1. 程式人生 > 其它 >力扣77. 組合

力扣77. 組合

77. 組合

77. 組合

難度:中等

給定兩個整數 n 和 k,返回範圍 [1, n] 中所有可能的 k 個數的組合。

你可以按 任何順序 返回答案。

示例 1:

輸入:n = 4, k = 2
輸出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
示例 2:

輸入:n = 1, k = 1
輸出:[[1]]

回溯法解題思路:

回溯法,一般可以解決如下幾種問題:

組合問題:N個數裡面按一定規則找出k個數的集合
切割問題:一個字串按一定規則有幾種切割方式
子集問題:一個N個數的集合裡有多少符合條件的子集
排列問題:N個數按一定規則全排列,有幾種排列方式
棋盤問題:N皇后,解數獨等等

另外,會有一些同學可能分不清什麼是組合,什麼是排列?

組合是不強調元素順序的,排列是強調元素順序。

例如:{1, 2} 和 {2, 1} 在組合上,就是一個集合,因為不強調順序,而要是排列的話,{1, 2} 和 {2, 1} 就是兩個集合了。

記住組合無序,排列有序,就可以了。

回溯法解決的問題都可以抽象為樹形結構,是的,我指的是所有回溯法的問題都可以抽象為樹形結構!

因為回溯法解決的都是在集合中遞迴查詢子集,集合的大小就構成了樹的寬度,遞迴的深度,都構成的樹的深度。

回溯演算法模板框架如下:

//這份模板很重要,後面做回溯法的題目都靠它了!
void backtracking(引數) {
    if (終止條件) {
        存放結果;
        return;
    }

    for (選擇:本層集合中元素(樹中節點孩子的數量就是集合的大小)) {
        處理節點;
        backtracking(路徑,選擇列表); // 遞迴
        回溯,撤銷處理結果
    }
}
class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>>res;
        vector<int>tem;
        backtracking(n,k,1,tem,res);
        return res;
    }
//回溯演算法
    void backtracking(int n,int k,int startindex,vector<int>& tem,vector<vector<int>>& res)
    {
         //比如1,2已經滿足條件則加入res,遞迴返回
        if (tem.size()==k)
        {
            res.push_back(tem);
            return;
        }
        else
        {
            for(int i=startindex;i<=n;i++)
            {
                tem.push_back(i);
                backtracking(n,k,i+1,tem,res);
                tem.pop_back();    //這步很關鍵
            }
        }
    }
};

以上內容參考自公眾號:程式碼隨想錄