给出两个整数n和k,求在1...n这n个数字中选出k个数字的所有组合。
n = 4 , k = 2
[ [1 ,2], [1 ,3], [1 ,4], [2 ,3], [2 ,4], [3 ,4], ]
使用回溯算法求解组合问题
package com.haobi;
import java.util.ArrayList;
import java.util.List;
public class Combinations {
// res数组用来存储所有结果
private static List res = new ArrayList<>();
public static void main(String[] args) {
List list = combine(4, 2);
for(String s : list) {
System.out.print(s+" ");
}
}
/**
* 递归函数
* 求解C(n,k),当前已经找到的组合存储在c中,需要从start开始搜索新的元素
* @param n 示例:4
* @param k 示例:2
* @param statr 从start开始搜索
* @param c
*/
private static void generateCombinations(int n, int k, int start, ArrayList c) {
if(c.size() == k) {//递归终止条件:向下递归调用直至c中有k个元素
res.add(c.toString());
return;
}
//将当前遍历的i加入数组c中
for(int i=start;i<=n;i++) {
//将当前元素放入c中
c.add(i);
//下一层递归寻找i+1及其之后的
generateCombinations(n, k, i+1, c);
//每次删除c中最后一个元素
c.remove(c.size()-1);
}
return;
}
/**
*
* @param n 1到n这n个数字内
* @param k 将结果存进List并返回
* @return
*/
public static List combine(int n, int k){
res.clear();
if( n<=0 || k<=0 || k>n ) {
return res;
}
// c用来存储递归过程中的所有组合的元素
ArrayList c = new ArrayList();
generateCombinations(n, k, 1, c);
return res;
}
}
程序输出结果如下:
[1, 2] [1, 3] [1, 4] [2, 3] [2, 4] [3, 4]
优化方法一,进行剪枝操作,将不需要考虑的可能性去掉。
package com.haobi;
import java.util.ArrayList;
import java.util.List;
public class Combinations1 {
// res数组用来存储所有结果
private static List res = new ArrayList<>();
public static void main(String[] args) {
List list = combine(4, 2);
for(String s : list) {
System.out.print(s+" ");
}
}
/**
* 递归函数
* 求解C(n,k),当前已经找到的组合存储在c中,需要从start开始搜索新的元素
* @param n 示例:4
* @param k 示例:2
* @param statr 从start开始搜索
* @param c
*/
private static void generateCombinations(int n, int k, int start, ArrayList c) {
if(c.size() == k) {//递归终止条件:向下递归调用直至c中有k个元素
res.add(c.toString());
return;
}
//将当前遍历的i加入数组c中
//当前还有k-c.size()个空位,所以,[i...n]中至少要有k-c.size()个元素
//i最多为 n-(k-c.size())+1
for(int i=start;i<=n-(k-c.size())+1;i++) {
//将当前元素放入c中
c.add(i);
//下一层递归寻找i+1及其之后的
generateCombinations(n, k, i+1, c);
//每次删除c中最后一个元素
c.remove(c.size()-1);
}
return;
}
/**
*
* @param n 1到n这n个数字内
* @param k 将结果存进List并返回
* @return
*/
public static List combine(int n, int k){
res.clear();
if( n<=0 || k<=0 || k>n ) {
return res;
}
// c用来存储递归过程中的所有组合的元素
ArrayList c = new ArrayList();
generateCombinations(n, k, 1, c);
return res;
}
}
程序输出结果如下:
[1, 2] [1, 3] [1, 4] [2, 3] [2, 4] [3, 4]