秒杀排列组合(下)————组合篇
2014-08-17 20:23
155 查看
首先为什么要写排列组合?因为排列组合在数学中占有重要的地位,其与概率论也有密切关系;并且排列组合问题在求职的笔试,面试出现的概率特别高,而我在网上又没有搜到比较全面题型的文章;同时,我觉得编写排列组合程序对学习递归也是很有帮助的;当然,最重要的原因是排列组合本身就很有趣!所以就总结下排列组合的各种问法,分两篇写:上篇写排列,下篇写组合。
组合篇
排列篇地址:http://blog.csdn.net/nash_/article/details/8351611
首先从各大IT公司的题中总结出排列组合的对象都是整形数组或字符数组,而且绝大部分组合问题都是无重复数字或者字符的;所以组合问题可以按输入数据分为两大类:输入数据有重复和无重复,又可以按输出数据分为两大类:输出数据有重复和无重复。
由于侧重点在输入数据无重复,所以先看输入数据无重复类型:
算法思想:按递增顺序输出,如12,13,14,15.....23.24.25........34,35.............用一个变量begin遍历的第一个数
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int[] a, int n) {
if(null == a || a.length == 0 || n <= 0 || n > a.length)
return;
int[] b = new int
;//辅助空间,保存待输出组合数
getCombination(a, n , 0, b, 0);
}
private void getCombination(int[] a, int n, int begin, int[] b, int index) {
if(n == 0){//如果够n个数了,输出b数组
for(int i = 0; i < index; i++){
System.out.print(b[i] + " ");
}
System.out.println();
return;
}
for(int i = begin; i < a.length; i++){
b[index] = a[i];
getCombination(a, n-1, i+1, b, index+1);
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,3,4};
int n = 2;
robot.combine(a,n);
}
}
算法思想:首先对数组a排序,再利用1的算法,把i=begin,改成i=0,让它每次从0开始遍历,但每个组合都是升序排列,所以为了去重加上升序的判断
代码清单:
[java]
view plaincopyprint?
import java.util.Arrays;
public class ZuHe {
public void combine(int[] a, int n) {
if(null == a || a.length == 0 || n <= 0 || n > a.length)
return;
Arrays.sort(a);
int[] b = new int
;//辅助空间,保存待输出组合数
getCombination(a, n , 0, b, 0);
}
private void getCombination(int[] a, int n, int begin, int[] b, int index) {
if(n == 0){//如果够n个数了,输出b数组
for(int i = 0; i < index; i++){
System.out.print(b[i] + " ");
}
System.out.println();
return;
}
for(int i = 0; i < a.length; i++){
if(index == 0 || a[i] >= b[index-1]){
b[index] = a[i];
getCombination(a, n-1, i+1, b, index+1);
}
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,3,4};
int n = 3;
robot.combine(a,n);
}
}
3.输入两个整数 n 和 m,从数列1,2,3.......n
如m =5,n=4 输出14,23
这种问法是典型01背包问题,因为要求是输出所有组合,所以我们不用DP,而用回溯
算法思想:从最大数n开始尝试装包,输出所有情况,再尝试n不装包,输出所有情况。
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int m, int n) {
if(m < 1 || n < 1)
return;
if(n > m)//如果n>m,把n>m的数去掉
n = m;
boolean[] b = new boolean[n+1];//保存是否装包
getCombination(m, n, b);
}
public void getCombination(int m, int n, boolean[] b){
if(m < 1 || n < 1)//递归出口
return;
if(m == n){//输出组合
b
= true;
for(int i = 1; i < b.length; i++){
if(b[i] == true)
System.out.print(i + " ");
}
System.out.println();
b
= false;
}
b
= true;//装包
getCombination(m-n, n-1, b);
b
= false;//不装包
getCombination(m, n-1, b);
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,3,4};
int n = 3;
robot.combine(10,12);
}
}
4.输入两个整数 n 和 m,从数列1,2,3.......n
如m =3,n=2 输出111,12
算法思想:由于组合元素个数未知,所以改用集合存储,使集合内元素有序为了去重,当m=0时候输出结果。
代码清单:
[java]
view plaincopyprint?
import java.util.ArrayList;
public class ZuHe {
public void combine(int m,int n) {
if(m < 1 || n < 1)
return;
if(m > n)
n = m;
ArrayList<Integer> arr = new ArrayList<Integer>();
getCombination(m,n, arr);
}
public void getCombination(int m, int n,ArrayList<Integer> arr) {
if(m < 0)
return;
if (m == 0 && arr.size() > 1) {
for (int i = 0; i < arr.size(); i++) {
System.out.print(arr.get(i) + " ");
}
System.out.println();
return;
}
for (Integer i = 1; i <= n; i++) {
if (!arr.isEmpty() && i < arr.get(arr.size() - 1))//使集合内元素递增,防止重复
continue;
arr.add(i);
getCombination(m - i, n, arr);
arr.remove(i);
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
robot.combine(3,2);
}
}
输出113,122
算法思想:按递增序列递归求解,如果
n==0 && m==0 输出结果,如果n==0,m!=0,返回
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int m, int n) {
if(m < 1 || n < 1)
return;
int[] b = new int
;
getCombination(m, n, b, 0, 1);
}
private void getCombination(int m, int n,int b[], int index,int begin) {
// TODO Auto-generated method stub
if(n == 0 && m == 0){
for(int i = 0; i < b.length; i++)
System.out.print(b[i] + " ");
System.out.println();
}
if(n == 0)
return;
for(int i = begin; i <= m; i++){
b[index] = i;
getCombination(m-i,n-1,b ,index+1,i);
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
robot.combine(5,3);
}
}
算法思想:按递增序列递归求解,如果 n==0 && m==0 输出结果,如果n==0,m!=0,返回,将递归调用设置成i+1
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int m, int n) {
if(m < 1 || n < 1)
return;
int[] b = new int
;
getCombination(m, n, b, 0, 1);
}
private void getCombination(int m, int n,int b[], int index,int begin) {
// TODO Auto-generated method stub
if(n == 0 && m == 0){
for(int i = 0; i < b.length; i++)
System.out.print(b[i] + " ");
System.out.println();
}
if(n == 0)
return;
for(int i = begin; i <= m; i++){
b[index] = i;
getCombination(m-i,n-1,b ,index+1,i+1);
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
robot.combine(5,3);
}
}
输出111,12,3
算法思想(与算法4相同):由于组合元素个数未知,所以改用集合存储,使集合内元素有序为了去重,当m=0时候输出结果
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int m) {
if(m < 1 )
return;
ArrayList<Integer> arr = new ArrayList<Integer>();
getCombination(m, arr);
}
public void getCombination(int m, ArrayList<Integer> arr) {
if (m == 0 && arr.size() > 1) {
for (int i = 0; i < arr.size(); i++) {
System.out.print(arr.get(i) + " ");
}
System.out.println();
return;
}
for (Integer i = 1; i <= m; i++) {
if (!arr.isEmpty() && i < arr.get(arr.size() - 1))//使集合内元素递增,防止重复
continue;
arr.add(i);
getCombination(m - i, arr);
arr.remove(i);
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
robot.combine(5);
}
}
算法思想:我们把输出顺序重新排列:1,12,123,13,2,23,3可以看出规律以1开头加上以非1开头的所有组合就构成了以1开头的所有组合,2,3同理,用一个参数index控制输出范围。
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int[] a) {
if(null == a || a.length == 0)
return;
int[] b = new int[a.length];
getCombination(a, 0, b, 0);
}
private void getCombination(int[] a, int begin, int b[], int index) {
if(index >= a.length)
return;
for(int i = begin; i < a.length; i++){
b[index] = a[i];
printArray(b,index);
getCombination(a, i+1, b, index+1);
}
}
private void printArray(int[] b, int index) {
for(int i = 0; i < index+1; i++){
System.out.print(b[i] + " ");
}
System.out.println();
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,3};
robot.combine(a);
}
}
算法思想:我们把输出顺序重新排列:1,12,123,13,2,23,3可以看出规律以1开头加上以非1开头的所有组合就构成了以1开头的所有组合,2,3同理,用一个参数index控制输出范围,去掉begin参数,保持序列递增有序。
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int[] a) {
if(null == a || a.length == 0)
return;
int[] b = new int[a.length];
getCombination(a, b, 0);
}
private void getCombination(int[] a, int b[], int index) {
if(index >= a.length)
return;
for(int i = 0; i < a.length; i++){
if(index == 0 || a[i] >= b[index-1]){
b[index] = a[i];
printArray(b,index);
getCombination(a, b, index+1);
}
}
}
private void printArray(int[] b, int index) {
for(int i = 0; i < index+1; i++){
System.out.print(b[i] + " ");
}
System.out.println();
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,3};
robot.combine(a);
}
}
输入数据有重复类型:
这类如a={1,3,2,3},这种问题相对较少,博主可以没有什么特别好的想法,只想到了两种通用的思路:
思路一:每次添加一个序列时,判断此序列是否已添加过。
思路二:添加所有的序列,最后去重。
两种思路解法差不多,但由于判断的是一个序列存不存在,所以不能直接用Hash,博主按思路一写了一题的解法供参考:
算法思想:在判断序列是否已添加之前,排序该序列,再验证;如果不存在,拷贝该序列添加到集合中。
代码清单:
[java]
view plaincopyprint?
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ZuHe {
/*保存序列集合*/
ArrayList<List<Integer>> _arr = new ArrayList<List<Integer>>();
public void combine(int[] a) {
if(null == a || a.length == 0)
return;
List<Integer> b = new ArrayList<Integer>();//序列存储空间
getCombination(a,b);
printArr();//输出所有组合
}
public void getCombination(int[] a, List<Integer> b){
if(a.length == b.size()){
/*自定义按List中升序排序*/
Collections.sort(b, new Comparator() {
public int compare(Object o1, Object o2) {
return (Integer)o1 - (Integer)o2;
}
});
if(!haveArray(b)){//如果序列b不存在
/*拷贝一个序列b*/
List<Integer> new_list = new ArrayList<Integer>();
for(int i = 0; i < b.size(); i++){
new_list.add(b.get(i));
}
_arr.add(new_list);//加入集合中
}
return;
}
for(int i = 0; i < a.length; i++){
Integer num = a[i];
b.add(num);
getCombination(a, b);
b.remove(num);
}
}
private boolean haveArray(List<Integer> b) {
for(int i = 0; i < _arr.size(); i++){
List<Integer> temp = _arr.get(i);
int j;
for(j = 0; j < temp.size(); j++){
if(temp.get(j) != b.get(j))
break;
}
if(j >= temp.size())
return true;
}
return false;
}
public void printArr(){
for(int i = 0; i < _arr.size(); i++){
List<Integer> temp = _arr.get(i);
for(int j = 0; j < temp.size(); j++)
System.out.print(temp.get(j) + " ");
System.out.println();
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,2};
robot.combine(a);
}
}
以上组合问题如果您有好的建议或者有其他的组合问题,请您留言,谢谢!
==================================================================================================
作者:nash_ 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:http://blog.csdn.net/nash_/article/details/8315418
===================================================================================================
组合篇
排列篇地址:http://blog.csdn.net/nash_/article/details/8351611
首先从各大IT公司的题中总结出排列组合的对象都是整形数组或字符数组,而且绝大部分组合问题都是无重复数字或者字符的;所以组合问题可以按输入数据分为两大类:输入数据有重复和无重复,又可以按输出数据分为两大类:输出数据有重复和无重复。
由于侧重点在输入数据无重复,所以先看输入数据无重复类型:
1. 从数组a中,取出n个数的所有组合(不可重复取)
如a={1,2,3}。当n=2时候的所有组合数为12,13,23算法思想:按递增顺序输出,如12,13,14,15.....23.24.25........34,35.............用一个变量begin遍历的第一个数
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int[] a, int n) {
if(null == a || a.length == 0 || n <= 0 || n > a.length)
return;
int[] b = new int
;//辅助空间,保存待输出组合数
getCombination(a, n , 0, b, 0);
}
private void getCombination(int[] a, int n, int begin, int[] b, int index) {
if(n == 0){//如果够n个数了,输出b数组
for(int i = 0; i < index; i++){
System.out.print(b[i] + " ");
}
System.out.println();
return;
}
for(int i = begin; i < a.length; i++){
b[index] = a[i];
getCombination(a, n-1, i+1, b, index+1);
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,3,4};
int n = 2;
robot.combine(a,n);
}
}
public class ZuHe { public void combine(int[] a, int n) { if(null == a || a.length == 0 || n <= 0 || n > a.length) return; int[] b = new int ;//辅助空间,保存待输出组合数 getCombination(a, n , 0, b, 0); } private void getCombination(int[] a, int n, int begin, int[] b, int index) { if(n == 0){//如果够n个数了,输出b数组 for(int i = 0; i < index; i++){ System.out.print(b[i] + " "); } System.out.println(); return; } for(int i = begin; i < a.length; i++){ b[index] = a[i]; getCombination(a, n-1, i+1, b, index+1); } } public static void main(String[] args){ ZuHe robot = new ZuHe(); int[] a = {1,2,3,4}; int n = 2; robot.combine(a,n); } }
2.从数组a中,取出n个数的所有组合(可重复取)
如a={1,2,3}。当n=2时候的所有组合数为11,12,13,22,23,33算法思想:首先对数组a排序,再利用1的算法,把i=begin,改成i=0,让它每次从0开始遍历,但每个组合都是升序排列,所以为了去重加上升序的判断
代码清单:
[java]
view plaincopyprint?
import java.util.Arrays;
public class ZuHe {
public void combine(int[] a, int n) {
if(null == a || a.length == 0 || n <= 0 || n > a.length)
return;
Arrays.sort(a);
int[] b = new int
;//辅助空间,保存待输出组合数
getCombination(a, n , 0, b, 0);
}
private void getCombination(int[] a, int n, int begin, int[] b, int index) {
if(n == 0){//如果够n个数了,输出b数组
for(int i = 0; i < index; i++){
System.out.print(b[i] + " ");
}
System.out.println();
return;
}
for(int i = 0; i < a.length; i++){
if(index == 0 || a[i] >= b[index-1]){
b[index] = a[i];
getCombination(a, n-1, i+1, b, index+1);
}
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,3,4};
int n = 3;
robot.combine(a,n);
}
}
import java.util.Arrays; public class ZuHe { public void combine(int[] a, int n) { if(null == a || a.length == 0 || n <= 0 || n > a.length) return; Arrays.sort(a); int[] b = new int ;//辅助空间,保存待输出组合数 getCombination(a, n , 0, b, 0); } private void getCombination(int[] a, int n, int begin, int[] b, int index) { if(n == 0){//如果够n个数了,输出b数组 for(int i = 0; i < index; i++){ System.out.print(b[i] + " "); } System.out.println(); return; } for(int i = 0; i < a.length; i++){ if(index == 0 || a[i] >= b[index-1]){ b[index] = a[i]; getCombination(a, n-1, i+1, b, index+1); } } } public static void main(String[] args){ ZuHe robot = new ZuHe(); int[] a = {1,2,3,4}; int n = 3; robot.combine(a,n); } }
3.输入两个整数 n 和 m,从数列1,2,3.......n
中 随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来(不可重复取)
如m =5,n=4 输出14,23这种问法是典型01背包问题,因为要求是输出所有组合,所以我们不用DP,而用回溯
算法思想:从最大数n开始尝试装包,输出所有情况,再尝试n不装包,输出所有情况。
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int m, int n) {
if(m < 1 || n < 1)
return;
if(n > m)//如果n>m,把n>m的数去掉
n = m;
boolean[] b = new boolean[n+1];//保存是否装包
getCombination(m, n, b);
}
public void getCombination(int m, int n, boolean[] b){
if(m < 1 || n < 1)//递归出口
return;
if(m == n){//输出组合
b
= true;
for(int i = 1; i < b.length; i++){
if(b[i] == true)
System.out.print(i + " ");
}
System.out.println();
b
= false;
}
b
= true;//装包
getCombination(m-n, n-1, b);
b
= false;//不装包
getCombination(m, n-1, b);
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,3,4};
int n = 3;
robot.combine(10,12);
}
}
public class ZuHe { public void combine(int m, int n) { if(m < 1 || n < 1) return; if(n > m)//如果n>m,把n>m的数去掉 n = m; boolean[] b = new boolean[n+1];//保存是否装包 getCombination(m, n, b); } public void getCombination(int m, int n, boolean[] b){ if(m < 1 || n < 1)//递归出口 return; if(m == n){//输出组合 b = true; for(int i = 1; i < b.length; i++){ if(b[i] == true) System.out.print(i + " "); } System.out.println(); b = false; } b = true;//装包 getCombination(m-n, n-1, b); b = false;//不装包 getCombination(m, n-1, b); } public static void main(String[] args){ ZuHe robot = new ZuHe(); int[] a = {1,2,3,4}; int n = 3; robot.combine(10,12); } }
4.输入两个整数 n 和 m,从数列1,2,3.......n
中 随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来(可重复取)
如m =3,n=2 输出111,12算法思想:由于组合元素个数未知,所以改用集合存储,使集合内元素有序为了去重,当m=0时候输出结果。
代码清单:
[java]
view plaincopyprint?
import java.util.ArrayList;
public class ZuHe {
public void combine(int m,int n) {
if(m < 1 || n < 1)
return;
if(m > n)
n = m;
ArrayList<Integer> arr = new ArrayList<Integer>();
getCombination(m,n, arr);
}
public void getCombination(int m, int n,ArrayList<Integer> arr) {
if(m < 0)
return;
if (m == 0 && arr.size() > 1) {
for (int i = 0; i < arr.size(); i++) {
System.out.print(arr.get(i) + " ");
}
System.out.println();
return;
}
for (Integer i = 1; i <= n; i++) {
if (!arr.isEmpty() && i < arr.get(arr.size() - 1))//使集合内元素递增,防止重复
continue;
arr.add(i);
getCombination(m - i, n, arr);
arr.remove(i);
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
robot.combine(3,2);
}
}
import java.util.ArrayList; public class ZuHe { public void combine(int m,int n) { if(m < 1 || n < 1) return; if(m > n) n = m; ArrayList<Integer> arr = new ArrayList<Integer>(); getCombination(m,n, arr); } public void getCombination(int m, int n,ArrayList<Integer> arr) { if(m < 0) return; if (m == 0 && arr.size() > 1) { for (int i = 0; i < arr.size(); i++) { System.out.print(arr.get(i) + " "); } System.out.println(); return; } for (Integer i = 1; i <= n; i++) { if (!arr.isEmpty() && i < arr.get(arr.size() - 1))//使集合内元素递增,防止重复 continue; arr.add(i); getCombination(m - i, n, arr); arr.remove(i); } } public static void main(String[] args){ ZuHe robot = new ZuHe(); robot.combine(3,2); } }
5.求将m分解成n个正整数相加之和的所有组合(可重复取)
如m=5,n=3输出113,122
算法思想:按递增序列递归求解,如果
n==0 && m==0 输出结果,如果n==0,m!=0,返回
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int m, int n) {
if(m < 1 || n < 1)
return;
int[] b = new int
;
getCombination(m, n, b, 0, 1);
}
private void getCombination(int m, int n,int b[], int index,int begin) {
// TODO Auto-generated method stub
if(n == 0 && m == 0){
for(int i = 0; i < b.length; i++)
System.out.print(b[i] + " ");
System.out.println();
}
if(n == 0)
return;
for(int i = begin; i <= m; i++){
b[index] = i;
getCombination(m-i,n-1,b ,index+1,i);
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
robot.combine(5,3);
}
}
public class ZuHe { public void combine(int m, int n) { if(m < 1 || n < 1) return; int[] b = new int ; getCombination(m, n, b, 0, 1); } private void getCombination(int m, int n,int b[], int index,int begin) { // TODO Auto-generated method stub if(n == 0 && m == 0){ for(int i = 0; i < b.length; i++) System.out.print(b[i] + " "); System.out.println(); } if(n == 0) return; for(int i = begin; i <= m; i++){ b[index] = i; getCombination(m-i,n-1,b ,index+1,i); } } public static void main(String[] args){ ZuHe robot = new ZuHe(); robot.combine(5,3); } }
6.求将m分解成n个正整数相加之和的所有组合(不可重复取)
如m=6,n=3 输出123算法思想:按递增序列递归求解,如果 n==0 && m==0 输出结果,如果n==0,m!=0,返回,将递归调用设置成i+1
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int m, int n) {
if(m < 1 || n < 1)
return;
int[] b = new int
;
getCombination(m, n, b, 0, 1);
}
private void getCombination(int m, int n,int b[], int index,int begin) {
// TODO Auto-generated method stub
if(n == 0 && m == 0){
for(int i = 0; i < b.length; i++)
System.out.print(b[i] + " ");
System.out.println();
}
if(n == 0)
return;
for(int i = begin; i <= m; i++){
b[index] = i;
getCombination(m-i,n-1,b ,index+1,i+1);
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
robot.combine(5,3);
}
}
public class ZuHe { public void combine(int m, int n) { if(m < 1 || n < 1) return; int[] b = new int ; getCombination(m, n, b, 0, 1); } private void getCombination(int m, int n,int b[], int index,int begin) { // TODO Auto-generated method stub if(n == 0 && m == 0){ for(int i = 0; i < b.length; i++) System.out.print(b[i] + " "); System.out.println(); } if(n == 0) return; for(int i = begin; i <= m; i++){ b[index] = i; getCombination(m-i,n-1,b ,index+1,i+1); } } public static void main(String[] args){ ZuHe robot = new ZuHe(); robot.combine(5,3); } }
7.求将m分解成任意个正整数相加之和的所有组合
如m=3输出111,12,3
算法思想(与算法4相同):由于组合元素个数未知,所以改用集合存储,使集合内元素有序为了去重,当m=0时候输出结果
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int m) {
if(m < 1 )
return;
ArrayList<Integer> arr = new ArrayList<Integer>();
getCombination(m, arr);
}
public void getCombination(int m, ArrayList<Integer> arr) {
if (m == 0 && arr.size() > 1) {
for (int i = 0; i < arr.size(); i++) {
System.out.print(arr.get(i) + " ");
}
System.out.println();
return;
}
for (Integer i = 1; i <= m; i++) {
if (!arr.isEmpty() && i < arr.get(arr.size() - 1))//使集合内元素递增,防止重复
continue;
arr.add(i);
getCombination(m - i, arr);
arr.remove(i);
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
robot.combine(5);
}
}
public class ZuHe { public void combine(int m) { if(m < 1 ) return; ArrayList<Integer> arr = new ArrayList<Integer>(); getCombination(m, arr); } public void getCombination(int m, ArrayList<Integer> arr) { if (m == 0 && arr.size() > 1) { for (int i = 0; i < arr.size(); i++) { System.out.print(arr.get(i) + " "); } System.out.println(); return; } for (Integer i = 1; i <= m; i++) { if (!arr.isEmpty() && i < arr.get(arr.size() - 1))//使集合内元素递增,防止重复 continue; arr.add(i); getCombination(m - i, arr); arr.remove(i); } } public static void main(String[] args){ ZuHe robot = new ZuHe(); robot.combine(5); } }
8.输出数组a的所有组合(不可重复取)
如a={1,2,3}输出1,2,3,12,13,23,123算法思想:我们把输出顺序重新排列:1,12,123,13,2,23,3可以看出规律以1开头加上以非1开头的所有组合就构成了以1开头的所有组合,2,3同理,用一个参数index控制输出范围。
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int[] a) {
if(null == a || a.length == 0)
return;
int[] b = new int[a.length];
getCombination(a, 0, b, 0);
}
private void getCombination(int[] a, int begin, int b[], int index) {
if(index >= a.length)
return;
for(int i = begin; i < a.length; i++){
b[index] = a[i];
printArray(b,index);
getCombination(a, i+1, b, index+1);
}
}
private void printArray(int[] b, int index) {
for(int i = 0; i < index+1; i++){
System.out.print(b[i] + " ");
}
System.out.println();
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,3};
robot.combine(a);
}
}
public class ZuHe { public void combine(int[] a) { if(null == a || a.length == 0) return; int[] b = new int[a.length]; getCombination(a, 0, b, 0); } private void getCombination(int[] a, int begin, int b[], int index) { if(index >= a.length) return; for(int i = begin; i < a.length; i++){ b[index] = a[i]; printArray(b,index); getCombination(a, i+1, b, index+1); } } private void printArray(int[] b, int index) { for(int i = 0; i < index+1; i++){ System.out.print(b[i] + " "); } System.out.println(); } public static void main(String[] args){ ZuHe robot = new ZuHe(); int[] a = {1,2,3}; robot.combine(a); } }
9.输出数组a的所有组合(可重复取)
如a={1,2}输出1,11,12,2,22算法思想:我们把输出顺序重新排列:1,12,123,13,2,23,3可以看出规律以1开头加上以非1开头的所有组合就构成了以1开头的所有组合,2,3同理,用一个参数index控制输出范围,去掉begin参数,保持序列递增有序。
代码清单:
[java]
view plaincopyprint?
public class ZuHe {
public void combine(int[] a) {
if(null == a || a.length == 0)
return;
int[] b = new int[a.length];
getCombination(a, b, 0);
}
private void getCombination(int[] a, int b[], int index) {
if(index >= a.length)
return;
for(int i = 0; i < a.length; i++){
if(index == 0 || a[i] >= b[index-1]){
b[index] = a[i];
printArray(b,index);
getCombination(a, b, index+1);
}
}
}
private void printArray(int[] b, int index) {
for(int i = 0; i < index+1; i++){
System.out.print(b[i] + " ");
}
System.out.println();
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,3};
robot.combine(a);
}
}
public class ZuHe { public void combine(int[] a) { if(null == a || a.length == 0) return; int[] b = new int[a.length]; getCombination(a, b, 0); } private void getCombination(int[] a, int b[], int index) { if(index >= a.length) return; for(int i = 0; i < a.length; i++){ if(index == 0 || a[i] >= b[index-1]){ b[index] = a[i]; printArray(b,index); getCombination(a, b, index+1); } } } private void printArray(int[] b, int index) { for(int i = 0; i < index+1; i++){ System.out.print(b[i] + " "); } System.out.println(); } public static void main(String[] args){ ZuHe robot = new ZuHe(); int[] a = {1,2,3}; robot.combine(a); } }
输入数据有重复类型:
这类如a={1,3,2,3},这种问题相对较少,博主可以没有什么特别好的想法,只想到了两种通用的思路:
思路一:每次添加一个序列时,判断此序列是否已添加过。
思路二:添加所有的序列,最后去重。
两种思路解法差不多,但由于判断的是一个序列存不存在,所以不能直接用Hash,博主按思路一写了一题的解法供参考:
题目:输出数组a的所有数的所有组合
如a={1,2,2}输出111,112,122,222算法思想:在判断序列是否已添加之前,排序该序列,再验证;如果不存在,拷贝该序列添加到集合中。
代码清单:
[java]
view plaincopyprint?
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class ZuHe {
/*保存序列集合*/
ArrayList<List<Integer>> _arr = new ArrayList<List<Integer>>();
public void combine(int[] a) {
if(null == a || a.length == 0)
return;
List<Integer> b = new ArrayList<Integer>();//序列存储空间
getCombination(a,b);
printArr();//输出所有组合
}
public void getCombination(int[] a, List<Integer> b){
if(a.length == b.size()){
/*自定义按List中升序排序*/
Collections.sort(b, new Comparator() {
public int compare(Object o1, Object o2) {
return (Integer)o1 - (Integer)o2;
}
});
if(!haveArray(b)){//如果序列b不存在
/*拷贝一个序列b*/
List<Integer> new_list = new ArrayList<Integer>();
for(int i = 0; i < b.size(); i++){
new_list.add(b.get(i));
}
_arr.add(new_list);//加入集合中
}
return;
}
for(int i = 0; i < a.length; i++){
Integer num = a[i];
b.add(num);
getCombination(a, b);
b.remove(num);
}
}
private boolean haveArray(List<Integer> b) {
for(int i = 0; i < _arr.size(); i++){
List<Integer> temp = _arr.get(i);
int j;
for(j = 0; j < temp.size(); j++){
if(temp.get(j) != b.get(j))
break;
}
if(j >= temp.size())
return true;
}
return false;
}
public void printArr(){
for(int i = 0; i < _arr.size(); i++){
List<Integer> temp = _arr.get(i);
for(int j = 0; j < temp.size(); j++)
System.out.print(temp.get(j) + " ");
System.out.println();
}
}
public static void main(String[] args){
ZuHe robot = new ZuHe();
int[] a = {1,2,2};
robot.combine(a);
}
}
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class ZuHe { /*保存序列集合*/ ArrayList<List<Integer>> _arr = new ArrayList<List<Integer>>(); public void combine(int[] a) { if(null == a || a.length == 0) return; List<Integer> b = new ArrayList<Integer>();//序列存储空间 getCombination(a,b); printArr();//输出所有组合 } public void getCombination(int[] a, List<Integer> b){ if(a.length == b.size()){ /*自定义按List中升序排序*/ Collections.sort(b, new Comparator() { public int compare(Object o1, Object o2) { return (Integer)o1 - (Integer)o2; } }); if(!haveArray(b)){//如果序列b不存在 /*拷贝一个序列b*/ List<Integer> new_list = new ArrayList<Integer>(); for(int i = 0; i < b.size(); i++){ new_list.add(b.get(i)); } _arr.add(new_list);//加入集合中 } return; } for(int i = 0; i < a.length; i++){ Integer num = a[i]; b.add(num); getCombination(a, b); b.remove(num); } } private boolean haveArray(List<Integer> b) { for(int i = 0; i < _arr.size(); i++){ List<Integer> temp = _arr.get(i); int j; for(j = 0; j < temp.size(); j++){ if(temp.get(j) != b.get(j)) break; } if(j >= temp.size()) return true; } return false; } public void printArr(){ for(int i = 0; i < _arr.size(); i++){ List<Integer> temp = _arr.get(i); for(int j = 0; j < temp.size(); j++) System.out.print(temp.get(j) + " "); System.out.println(); } } public static void main(String[] args){ ZuHe robot = new ZuHe(); int[] a = {1,2,2}; robot.combine(a); } }
以上组合问题如果您有好的建议或者有其他的组合问题,请您留言,谢谢!
==================================================================================================
作者:nash_ 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:http://blog.csdn.net/nash_/article/details/8315418
===================================================================================================
相关文章推荐
- 秒杀排列组合(下)————组合篇
- 秒杀排列组合(下)————组合篇
- 秒杀排列组合(上)————排列篇
- EularProject 24: 排列组合的序数问题
- HDOJ热身赛1004--复习下排列组合公式
- 排列组合问题
- Java中的排列组合(二)
- bzoj 3505: [Cqoi2014]数三角形 排列组合+数学
- python下实现字符串的排列和组合
- python 排列组合 解决实际问题
- iOS多线程中,队列和执行的排列组合结果分析
- [经典面试题]排列组合专题
- CodeForces 630I:Parking Lot【排列组合】
- 生成排列和组合
- hdu 4451 Dressing 排列组合/水题
- 字母表的特殊排列组合
- 排列与组合的实现
- 字符串排列组合2
- 递归 求全排列与全组合
- 排列组合