Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.
X. DFS
Code from http://blog.csdn.net/u010500263/article/details/18435495
http://blog.csdn.net/linhuanmars/article/details/21260217
https://jiajiewu.wordpress.com/2014/08/19/leetcode-combinations/
Good naming -> subResult
http://www.programcreek.com/2014/03/leetcode-combinations-java/
Use List as stack - Stack class is deprecated in java.
X. Iterative Version
https://leetcode.com/discuss/24600/iterative-java-solution
http://www.sigmainfy.com/blog/leetcode-combinations.html
https://leetcode.com/discuss/67405/java-my-iterative-13ms-and-recursive-7ms-solutions
from http://gongxuns.blogspot.com/2012/12/leetcodecombinations.html
Use iterations to generate different levels of solutions. The first level solution is the set of all first numbers in the final solution is {1,2,...,n-k+1}. To avoid duplicates, for the next level, always add a larger number to the element in current level.
https://leetcode.com/discuss/37021/1-liner-3-liner-4-liner
http://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given-array-of-size-n/
1) The element is included in current combination (We put the element in data[] and increment next available index in data[])
2) The element is excluded in current combination (We do not put the element and do not change index)
Read full article from [leet code] Combinations - 伪技回忆录 - 博客频道 - CSDN.NET
For example,
If n = 4 and k = 2, a solution is:
If n = 4 and k = 2, a solution is:
[ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]For choosing number in a specific layer, we can use a iteration, e.g. in the first layer, we try 1-5. While for step in another layer, we can use recursive call. Parameters we need for a recursive call are the current combination, the combination result set, the n, the k, and the start point of iteration (e.g. if we chose 1 for the first position, start point of 2nd position is 2; while if we chose 2 for the first position, start point of second position is 3).
X. DFS
Code from http://blog.csdn.net/u010500263/article/details/18435495
Code from http://www.darrensunny.me/leetcode-combinations/From this example, we can see that in the first position of the resulting combinations we can chose number 1-5. Assume that we chose 1 for the 1 position of the combination, then we can choose 2-5 for the second position. Till we chosen numbers for all position, we can have one possible combination.However, when we chose 3 for the first position and 5 for the second position, we don't have any other number to choose for the 3rd position. (former number must be smaller than the following number).Now we have the rules of this problem, and we can try to implement these rules. For choosing number in a specific layer, we can use a iteration, e.g. in the first layer, we try 1-5. While for step in another layer, we can use recursive call. Parameters we need for a recursive call are the current combination, the combination result set, the n, the k, and the start point of iteration (e.g. if we chose 1 for the first position, start point of 2nd position is 2; while if we chose 2 for the first position, start point of second position is 3).public ArrayList<ArrayList<Integer>> combine(int n, int k) {ArrayList<ArrayList<Integer>> combSet = new ArrayList<ArrayList<Integer>>();ArrayList<Integer> comb = new ArrayList<Integer>();if(n<k) return combSet;helper(n, k, combSet, comb, 1);return combSet;}public void helper(int n, int k, ArrayList<ArrayList<Integer>> combSet, ArrayList<Integer> comb, int start){// one possible combinition constructuredif(comb.size() == k){combSet.add(new ArrayList<Integer> (comb));return;}else{for(int i=start; i<=n; i++){// try each possibility number in current positioncomb.add(i);helper(n, k, combSet, comb, i+1); // after selecting number for current position, process next positioncomb.remove(comb.size()-1); // clear the current position to try next possible number}}}
http://blog.csdn.net/linhuanmars/article/details/21260217
https://jiajiewu.wordpress.com/2014/08/19/leetcode-combinations/
Good naming -> subResult
public
ArrayList<ArrayList<Integer>> combine(
int
n,
int
k) {
if
(n<=
0
||k<=
0
){
return
null
;
}
ArrayList<ArrayList<Integer>> result=
new
ArrayList<ArrayList<Integer>>();
int
st=
1
;
int
num=
0
;
ArrayList<Integer> subResult=
new
ArrayList<Integer>();
buildResult(st, num, k, n, subResult, result);
return
result;
}
private
void
buildResult(
int
start,
int
currentNum,
int
k,
int
n, ArrayList<Integer> subResult, ArrayList<ArrayList<Integer>> result)
{
if
(currentNum==k){
ArrayList<Integer> temp=
new
ArrayList<Integer>(subResult);
result.add(temp);
return
;
}
for
(
int
i=start; i<=n; i++){
subResult.add(i);
buildResult(i+
1
, currentNum+
1
, k, n, subResult, result);
subResult.remove(subResult.size()-
1
);
}
}
Use List as stack - Stack class is deprecated in java.
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> ans = new LinkedList<List<Integer>>();
combineHelper(ans, new LinkedList<Integer>(), n, k, 1);
return ans;
}
private void combineHelper(List<List<Integer>> ans, List<Integer> current,
int n, int k, int start) {
if (current.size() == k) {
ans.add(current);
return;
}
for (int i = start; i <= n; i++) {
List<Integer> newCurrent = new LinkedList<Integer>(current);//
newCurrent.add(i);//\\
combineHelper(ans, newCurrent, n, k, i + 1);
}
}
X. Use int[]
[leetcode] Combinations | 给数字n和k,求所有由1~n组成的长度为k的combination
这个题和上两道相比简单了不少,因为是固定长度所以不用stack了,用int[]加一个position variable。每次在这个pos上一个一个试数,每确定一个就在下一个pos处recurse。
public ArrayList<ArrayList<Integer>> combine(int n, int k) { ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(); if (k <= 0 || n < 1) return result; populateResult(1, n, 0, result, new int[k]); return result; } private void populateResult(int startNum, int endNum, int pos, ArrayList<ArrayList<Integer>> result, int[] path) { if (pos == path.length) { ArrayList<Integer> combination = new ArrayList<Integer>(); convertArrayToList(path, combination); result.add(combination); return; } for (int i = startNum; i <= endNum; i++) { //i is using which number path[pos] = i; populateResult(i + 1, endNum, pos + 1, result, path); //use next //number on next position //as i++, use next number on same position } }
X.
Basically, this solution follows the idea of the mathematical formula C(n,k)=C(n-1,k-1)+C(n-1,k).
Here C(n,k) is divided into two situations. Situation one, number n is selected, so we only need to select k-1 from n-1 next. Situation two, number n is not selected, and the rest job is selecting k from n-1.
public List<List<Integer>> combine(int n, int k) {
if (k == n || k == 0) {
List<Integer> row = new LinkedList<>();
for (int i = 1; i <= k; ++i) {
row.add(i);
}
return new LinkedList<>(Arrays.asList(row));//? why not new LinkedList<>(row)
}
List<List<Integer>> result = this.combine(n - 1, k - 1);
result.forEach(e -> e.add(n));
result.addAll(this.combine(n - 1, k));
return result;
}
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
if (k > n || k < 0) {
return result;
}
if (k == 0) {
result.add(new ArrayList<Integer>());
return result;
}
result = combine(n - 1, k - 1);
for (List<Integer> list : result) {
list.add(n);
}
result.addAll(combine(n - 1, k));
return result;
}
public List<List<Integer>> combine(int n, int k) {
return combine(n,1,k);
}
public List<List<Integer>> combine(int n,int current,int k){
List<List<Integer>> result = new LinkedList<List<Integer>>();
if(k==0) {
result.add(new LinkedList<Integer>());
return result;
}
if(current>n) return result;
for(List<Integer> res:combine(n,current+1,k)){
result.add(res);
}
for(List<Integer> res:combine(n,current+1,k-1)){
res.add(0,current);
result.add(res);
}
return result;
}
X. Iterative Version
https://leetcode.com/discuss/24600/iterative-java-solution
The idea is to iteratively generate combinations for all lengths from 1 to k. We start with a list of all numbers <= n as combinations for k == 1. When we have all combinations of length k-1, we can get the new ones for a length k with trying to add to each one all elements that are <= n and greater than the last element of a current combination.
public List<List<Integer>> combine(int n, int k) {
if (k == 0 || n == 0 || k > n) return Collections.emptyList();
List<List<Integer>> combs = new ArrayList<>();
for (int i = 1; i <= n; i++) combs.add(Arrays.asList(i));
for (int i = 2; i <= k; i++) {
List<List<Integer>> newCombs = new ArrayList<>();
for (int j = i; j <= n; j++) {
for (List<Integer> comb : combs) {
if (comb.get(comb.size()-1) < j) {
List<Integer> newComb = new ArrayList<>(comb);
newComb.add(j);
newCombs.add(newComb);
}
}
}
combs = newCombs;
}
return combs;
}
TODO: http://www.sigmainfy.com/blog/leetcode-combinations.html
https://leetcode.com/discuss/67405/java-my-iterative-13ms-and-recursive-7ms-solutions
https://leetcode.com/discuss/14645/iterative-versionpublic List<List<Integer>> combine(int n, int k) { List<List<Integer>> list = new ArrayList<List<Integer>>(); List<Integer> kind = new ArrayList<Integer>(); int i = 1; while(i<=n || kind.size()!=0){ if(kind.size()==k){ list.add(new ArrayList(kind)); } if(i>n||kind.size()==k){ i = kind.get(kind.size()-1)+1; kind.remove(kind.size()-1); } else{ kind.add(i); i++; } } return list; }
from http://gongxuns.blogspot.com/2012/12/leetcodecombinations.html
Use iterations to generate different levels of solutions. The first level solution is the set of all first numbers in the final solution is {1,2,...,n-k+1}. To avoid duplicates, for the next level, always add a larger number to the element in current level.
public ArrayList<ArrayList<Integer>> combine(int n, int k) { ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>(); if(k==0) return res; res.add(new ArrayList<Integer>()); for(int i=0;i<k;i++){ ArrayList<ArrayList<Integer>> prev = new ArrayList<ArrayList<Integer>>(); for(ArrayList<Integer> temp:res){ int a=0; if(temp.size()>0) a=temp.get(temp.size()-1); for(int j=a+1;j<=n-k+1+i;j++){ ArrayList<Integer> b= new ArrayList<Integer>(temp); b.add(j); prev.add(b); } } res = new ArrayList<ArrayList<Integer>>(prev); } return res; }
https://leetcode.com/discuss/37021/1-liner-3-liner-4-liner
http://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given-array-of-size-n/
Method 1 (Fix Elements and Recur)
We create a temporary array ‘data[]‘ which stores all outputs one by one. The idea is to start from first index (index = 0) in data[], one by one fix elements at this index and recur for remaining indexes. Let the input array be {1, 2, 3, 4, 5} and r be 3. We first fix 1 at index 0 in data[], then recur for remaining indexes, then we fix 2 at index 0 and recur. Finally, we fix 3 and recur for remaining indexes. When number of elements in data[] becomes equal to r (size of a combination), we print data[].
void
printCombination(
int
arr[],
int
n,
int
r)
{
// A temporary array to store all combination one by one
int
data[r];
// Print all combination using temprary array 'data[]'
combinationUtil(arr, data, 0, n-1, 0, r);
}
/* arr[] ---> Input Array
data[] ---> Temporary array to store current combination
start & end ---> Staring and Ending indexes in arr[]
index ---> Current index in data[]
r ---> Size of a combination to be printed */
void
combinationUtil(
int
arr[],
int
data[],
int
start,
int
end,
int
index,
int
r)
{
// Current combination is ready to be printed, print it
if
(index == r)
{
for
(
int
j=0; j<r; j++)
printf
(
"%d "
, data[j]);
printf
(
"\n"
);
return
;
}
// replace index with all possible elements. The condition
// "end-i+1 >= r-index" makes sure that including one element
// at index will make a combination with remaining elements
// at remaining positions
for
(
int
i=start; i<=end && end-i+1 >= r-index; i++)
{
data[index] = arr[i];
combinationUtil(arr, data, i+1, end, index+1, r);
}
}
How to handle duplicates?
Note that the above method doesn’t handle duplicates. For example, if input array is {1, 2, 1} and r is 2, then the program prints {1, 2} and {2, 1} as two different combinations. We can avoid duplicates by adding following two additional things to above code.
1) Add code to sort the array before calling combinationUtil() in printCombination()
2) Add following lines at the end of for loop in combinationUtil()
Note that the above method doesn’t handle duplicates. For example, if input array is {1, 2, 1} and r is 2, then the program prints {1, 2} and {2, 1} as two different combinations. We can avoid duplicates by adding following two additional things to above code.
1) Add code to sort the array before calling combinationUtil() in printCombination()
2) Add following lines at the end of for loop in combinationUtil()
// Since the elements are sorted, all occurrences of an element // must be together while (arr[i] == arr[i+1]) i++;
See this for an implementation that handles duplicates.
Method 2 (Include and Exclude every element)1) The element is included in current combination (We put the element in data[] and increment next available index in data[])
2) The element is excluded in current combination (We do not put the element and do not change index)
This method is mainly based on Pascal’s Identity, i.e. ncr = n-1cr + n-1cr-1
oid
printCombination(
int
arr[],
int
n,
int
r)
{
// A temporary array to store all combination one by one
int
data[r];
// Print all combination using temprary array 'data[]'
combinationUtil(arr, n, r, 0, data, 0);
}
/* arr[] ---> Input Array
n ---> Size of input array
r ---> Size of a combination to be printed
index ---> Current index in data[]
data[] ---> Temporary array to store current combination
i ---> index of current element in arr[] */
void
combinationUtil(
int
arr[],
int
n,
int
r,
int
index,
int
data[],
int
i)
{
// Current cobination is ready, print it
if
(index == r)
{
for
(
int
j=0; j<r; j++)
printf
(
"%d "
,data[j]);
printf
(
"\n"
);
return
;
}
// When no more elements are there to put in data[]
if
(i >= n)
return
;
// current is included, put next at next location
data[index] = arr[i];
combinationUtil(arr, n, r, index+1, data, i+1);
// current is excluded, replace it with next (Note that
// i+1 is passed, but index is not changed)
combinationUtil(arr, n, r, index, data, i+1);
}