力扣77. 組合
阿新 • • 發佈:2022-04-20
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(); //這步很關鍵 } } } };
以上內容參考自公眾號:程式碼隨想錄