題目連接: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 }
當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 }
法二(借鑑):作完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 }