77. Combinations

时间:2024-03-27 20:36:08

题目:

Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.

For example,
If n = 4 and k = 2, a solution is:

[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
Hide Tags

Backtracking 

链接:  http://leetcode.com/problems/combinations/

题解:

求组合数。依然是使用recursive + backtracking,当所传list的大小等于k时,将list加入到result里。使用控制位置的变量pos根据题目要求从1开始,本体依然假定无重复数字。

Time Complexity - O(2n), Space Complexity - O(n)。                         --复杂度有点糊涂,还需要重新计算

public class Solution {
public ArrayList<ArrayList<Integer>> combine(int n, int k) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
if(n < 0 || k < 0)
return result;
ArrayList<Integer> list = new ArrayList<Integer>();
helper(result, list, n, k, 1);
return result;
} private void helper(ArrayList<ArrayList<Integer>> result, ArrayList<Integer> list, int n, int k, int pos){
if(list.size() == k){
result.add(new ArrayList<Integer>(list));
return;
} for(int i = pos; i <= n; i++){
list.add(pos);
helper(result, list, n, k, ++pos);
list.remove(list.size() - 1);
}
}
}

Update:

public class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res = new ArrayList<>();
if(n < 0 || k < 0)
return res;
ArrayList<Integer> list = new ArrayList<Integer>();
dfs(res, list, n, k, 1);
return res;
} private void dfs(List<List<Integer>> res, ArrayList<Integer> list, int n, int k, int position) { // from 1 to n
if(list.size() == k) {
res.add(new ArrayList<Integer>(list));
return;
} for(int i = position; i <= n; i++) {
list.add(i);
dfs(res, list, n, k, i + 1);
list.remove(list.size() - 1);
}
}
}

二刷

有关这一类排列组合题目有不少题型,一定要好好思考总结融会贯通。

依然是跟1刷类似的方法,使用DFS + Backtracking。要注意的是最后的结果是(1, 2), (1, 3), (1, 4), (2, 3), (2, 4)这类一定是升序的组合,所以我们构建辅助函数的时候只要pass in 一个position来控制就可以了。递归的时候传入 combine(res, list, k, n, i + 1)这样就能简单避免掉i,只丛i后面的数字继续遍历。

这里branching factor是n, depth是k。 所以其实时间复杂度是 O(n! / k!) 约等于 O(n!)

Time Complexity - O(n!), Space Complexity - O(nk)

Java:

public class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
combine(res, list, n, k, 1);
return res;
} private void combine(List<List<Integer>> res, List<Integer> list, int n, int k, int pos) {
if (list.size() == k) {
res.add(new ArrayList<Integer>(list));
return;
}
for (int i = pos; i <= n; i++) {
list.add(i);
combine(res, list, n, k, i + 1);
list.remove(list.size() - 1);
}
}
}

三刷:

方法跟二刷一样。也是构造递归求解的辅助方法来解决。注意这里我们也需要一个保存position的int pos。

有机会要再算一算复杂度。

Java:

public class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res = new ArrayList<>();
if (n < 0 || k < 0 || n < k) return res;
getCombinations(res, new ArrayList<Integer>(), n, k, 1);
return res;
} private void getCombinations(List<List<Integer>> res, List<Integer> list, int n, int k, int pos) {
if (list.size() == k) {
res.add(new ArrayList<>(list));
return;
}
for (int i = pos; i <= n; i++) {
list.add(i);
getCombinations(res, list, n, k, i + 1);
list.remove(list.size() - 1);
}
}
}

Reference:

http://www.1point3acres.com/bbs/thread-117602-1-1.html

http://codeganker.blogspot.com/2014/03/combinations-leetcode.html

http://www.cnblogs.com/zhuli19901106/p/3485751.html

http://www.1point3acres.com/bbs/thread-117602-1-1.html

https://leetcode.com/discuss/42034/java-solution-easy-understood

https://leetcode.com/discuss/30221/dfs-recursive-java-solution

https://leetcode.com/discuss/61607/ac-python-backtracking-iterative-solution-60-ms

https://leetcode.com/discuss/37021/1-liner-3-liner-4-liner

https://leetcode.com/discuss/24600/iterative-java-solution

https://leetcode.com/discuss/12915/my-shortest-c-solution-using-dfs

https://leetcode.com/discuss/31250/backtracking-solution-java

http://rangerway.com/way/algorithm-permutation-combination-subset/

http://www.1point3acres.com/bbs/thread-117602-1-1.html

http://www.cnblogs.com/zhuli19901106/p/3492515.html