Medium!php
題目描述:數組
給定兩個整數 n 和 k,返回 1 ... n 中全部可能的 k 個數的組合。markdown
示例:spa
輸入: n = 4, k = 2 輸出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
解題思路:.net
這道題讓求1到n共n個數字裏k個數的組合數的全部狀況,仍是要用深度優先搜索DFS來解,根據以往的經驗,像這種要求出全部結果的集合,通常都是用DFS調用遞歸來解。那麼咱們創建一個保存最終結果的大集合res,還要定義一個保存每個組合的小集合out,每次放一個數到out裏,若是out裏數個數到了k個,則把out保存到最終結果中,不然在下一層中繼續調用遞歸。https://blog.csdn.net/u010500263/article/details/18435495中有一張圖很好的說明了遞歸調用的順序。code
C++解法一:blog
1 class Solution { 2 public: 3 vector<vector<int>> combine(int n, int k) { 4 vector<vector<int>> res; 5 vector<int> out; 6 helper(n, k, 1, out, res); 7 return res; 8 } 9 void helper(int n, int k, int level, vector<int>& out, vector<vector<int>>& res) { 10 if (out.size() == k) res.push_back(out); 11 for (int i = level; i <= n; ++i) { 12 out.push_back(i); 13 helper(n, k, i + 1, out, res); 14 out.pop_back(); 15 } 16 } 17 };
對於n = 5, k = 3, 處理的結果以下:遞歸
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5it
咱們再來看一種迭代的寫法,也是一種比較巧妙的方法。這裏每次先遞增最右邊的數字,存入結果res中,當右邊的數字超過了n,則增長其左邊的數字,而後將當前數組賦值爲左邊的數字,再逐個遞增,直到最左邊的數字也超過了n,中止循環。對於n=4, k=2時,遍歷的順序以下所示:io
0 0 #initialization 1 0 1 1 #push_back 1 2 #push_back 1 3 #push_back 1 4 #push_back 1 5 2 5 2 2 #push_back 2 3 #push_back 2 4 #push_back ... 3 4 #push_back 3 5 4 5 4 4 4 5 5 5 #stop
C++解法二:
1 class Solution { 2 public: 3 vector<vector<int>> combine(int n, int k) { 4 vector<vector<int>> res; 5 vector<int> out(k, 0); 6 int i = 0; 7 while (i >= 0) { 8 ++out[i]; 9 if (out[i] > n) --i; 10 else if (i == k - 1) res.push_back(out); 11 else { 12 ++i; 13 out[i] = out[i - 1]; 14 } 15 } 16 return res; 17 } 18 };