77.Combinations

題目連接:https://leetcode.com/problems/combinations/description/ide

題目大意:組合問題,給出一個數n以及要組合的數的個數k,輸出全部組合數。優化

法一(借鑑):雖然前面作了排列的題,惋惜仍是不會作這個組合題。代碼以下(耗時76ms):spa

 1     public List<List<Integer>> combine(int n, int k) {
 2         List<List<Integer>> res = new ArrayList<List<Integer>>();
 3         List<Integer> tmp = new ArrayList<Integer>();
 4         dfs(res, tmp, n, k, 1);
 5         return res;
 6     }
 7     public static void dfs(List<List<Integer>> res, List<Integer> tmp, int n, int k, int start) {
 8     //    System.out.println(tmp);
 9         if(tmp.size() == k) {
10             res.add(new ArrayList<Integer>(tmp));
11             return;
12         }
13         for(int i = start; i <= n; i++) {
14             tmp.add(i);
15             dfs(res, tmp, n, k, i + 1);
16             tmp.remove(tmp.size() - 1);//回溯刪除
17         }
18     }
View Code

當n=4,k=2時的運行結果:.net

[]
[1]
[1, 2]--->return執行i++ -> add
[1, 3]--->return執行i++ -> add
[1, 4]--->return執行i++ -> add
[2]--->return到1dfs後執行remove操做,再i++ -> add
[2, 3]
[2, 4]
[3]
[3, 4]
[4]
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

優化剪枝:http://blog.csdn.net/wys2011101169/article/details/72887512 code

根據這個博客剪枝,緣由可見博客。代碼以下(耗時4ms):blog

 1     public List<List<Integer>> combine(int n, int k) {
 2         List<List<Integer>> res = new ArrayList<List<Integer>>();
 3         List<Integer> tmp = new ArrayList<Integer>();
 4         dfs(res, tmp, n, k, 1);
 5         return res;
 6     }
 7     public static void dfs(List<List<Integer>> res, List<Integer> tmp, int n, int k, int start) {
 8         if(tmp.size() == k) {
 9             res.add(new ArrayList<Integer>(tmp));
10             return;
11         }
12         for(int i = start; i <= (n - (k - tmp.size()) + 1); i++) {
13             //i <= (n - (k - tmp.size()) + 1)剪枝,當可選的數已經不夠時,直接剪枝
14             tmp.add(i);
15             dfs(res, tmp, n, k, i + 1);
16             tmp.remove(tmp.size() - 1);//回溯刪除
17         }
18     }
View Code

法二(借鑑):作完78題,回頭用78題的非遞歸代碼,發現超時了,按理說這個辦法應該是能夠過的,可是應該須要合理的剪枝吧。代碼以下:遞歸

 1     public List<List<Integer>> combine(int n, int k) {
 2         List<List<Integer>> res = new ArrayList<List<Integer>>();
 3         res.add(new ArrayList<Integer>());
 4         for(int i = 1; i <= n; i++) {
 5             List<List<Integer>> tmp = new ArrayList<List<Integer>>();
 6             for(List<Integer> r : res) {
 7                 List<Integer> a = new ArrayList<Integer>(r);
 8                 a.add(i);
 9                 tmp.add(a);
10             }
11             res.addAll(tmp);
12         }
13         //從全部集合中拿到個數是k的子集合加到結果集中
14         List<List<Integer>> list = new ArrayList<List<Integer>>();
15         for(List<Integer> r : res) {
16             if(r.size() == k) {
17                 list.add(r);
18             }
19         }
20         return list;
21     }
View Code
相關文章
相關標籤/搜索