一.利用二进制状态法求排列组合,此种方法比较容易懂,但是运行效率不高,小数据排列组合可以使用
import java.util.Arrays;
//利用二进制算法进行全排列
//count1:170187
//count2:291656
public class test {
public static void main(String[] args) {
long start=System.currentTimeMillis();
count2();
long end=System.currentTimeMillis();
System.out.println(end-start);
}
private static void count2(){
int[] num=new int []{1,2,3,4,5,6,7,8,9};
for(int i=1;i<Math.pow(9, 9);i++){
String str=Integer.toString(i,9);
int sz=str.length();
for(int j=0;j<9-sz;j++){
str="0"+str;
}
char[] temp=str.toCharArray();
Arrays.sort(temp);
String gl=new String(temp);
if(!gl.equals("012345678")){
continue;
}
String result="";
for(int m=0;m<str.length();m++){
result+=num[Integer.parseInt(str.charAt(m)+"")];
</pre><pre name="code" class="java"> }
System.out.println(result);
}
}
public static void count1(){
int[] num=new int []{1,2,3,4,5,6,7,8,9};
int[] ss=new int []{0,1,2,3,4,5,6,7,8};
int[] temp=new int[9];
while(temp[0]<9){
temp[temp.length-1]++;
for(int i=temp.length-1;i>0;i--){
if(temp[i]==9){
temp[i]=0;
temp[i-1]++;
}
}
int []tt=temp.clone();
Arrays.sort(tt);
if(!Arrays.equals(tt,ss)){
continue;
}
String result="";
for(int i=0;i<num.length;i++){
result+=num[temp[i]];
}
System.out.println(result);
}
}
}
二.用递归的思想来求排列跟组合,代码量比较大
package practice;
import java.util.ArrayList;
import java.util.List;
public class Test1 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Object[] tmp={1,2,3,4,5,6};
// ArrayList<Object[]> rs=RandomC(tmp);
ArrayList<Object[]> rs=cmn(tmp,3);
for(int i=0;i<rs.size();i++)
{
// System.out.print(i+"=");
for(int j=0;j<rs.get(i).length;j++)
{
System.out.print(rs.get(i)[j]+",");
}
System.out.println();
}
}
// 求一个数组的任意组合
static ArrayList<Object[]> RandomC(Object[] source)
{
ArrayList<Object[]> result=new ArrayList<Object[]>();
if(source.length==1)
{
result.add(source);
}
else
{
Object[] psource=new Object[source.length-1];
for(int i=0;i<psource.length;i++)
{
psource[i]=source[i];
}
result=RandomC(psource);
int len=result.size();//fn组合的长度
result.add((new Object[]{source[source.length-1]}));
for(int i=0;i<len;i++)
{
Object[] tmp=new Object[result.get(i).length+1];
for(int j=0;j<tmp.length-1;j++)
{
tmp[j]=result.get(i)[j];
}
tmp[tmp.length-1]=source[source.length-1];
result.add(tmp);
}
}
return result;
}
static ArrayList<Object[]> cmn(Object[] source,int n)
{
ArrayList<Object[]> result=new ArrayList<Object[]>();
if(n==1)
{
for(int i=0;i<source.length;i++)
{
result.add(new Object[]{source[i]});
}
}
else if(source.length==n)
{
result.add(source);
}
else
{
Object[] psource=new Object[source.length-1];
for(int i=0;i<psource.length;i++)
{
psource[i]=source[i];
}
result=cmn(psource,n);
ArrayList<Object[]> tmp=cmn(psource,n-1);
for(int i=0;i<tmp.size();i++)
{
Object[] rs=new Object[n];
for(int j=0;j<n-1;j++)
{
rs[j]=tmp.get(i)[j];
}
rs[n-1]=source[source.length-1];
result.add(rs);
}
}
return result;
}
}
三.利用动态规划的思想求排列和组合
package Acm;
//强大的求组合数
public class MainApp {
public static void main(String[] args) {
int[] num=new int[]{1,2,3,4,5};
String str="";
//求3个数的组合个数
// count(0,str,num,3);
// 求1-n个数的组合个数
count1(0,str,num);
}
private static void count1(int i, String str, int[] num) {
if(i==num.length){
System.out.println(str);
return;
}
count1(i+1,str,num);
count1(i+1,str+num[i]+",",num);
}
private static void count(int i, String str, int[] num,int n) {
if(n==0){
System.out.println(str);
return;
}
if(i==num.length){
return;
}
count(i+1,str+num[i]+",",num,n-1);
count(i+1,str,num,n);
}
}
下面是求排列
package Acm;
//求排列,求各种排列或组合后排列
import java.util.Arrays;
import java.util.Scanner;
public class Demo19 {
private static boolean f[];
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int sz=sc.nextInt();
for(int i=0;i<sz;i++){
int sum=sc.nextInt();
f=new boolean[sum];
Arrays.fill(f, true);
int[] num=new int[sum];
for(int j=0;j<sum;j++){
num[j]=j+1;
}
int nn=sc.nextInt();
String str="";
count(num,str,nn);
}
}
/**
*
* @param num 表示要排列的数组
* @param str 以排列好的字符串
* @param nn 剩下需要排列的个数,如果需要全排列,则nn为数组长度
*/
private static void count(int[] num, String str, int nn) {
if(nn==0){
System.out.println(str);
return;
}
for(int i=0;i<num.length;i++){
if(!f[i]){
continue;
}
f[i]=false;
count(num,str+num[i],nn-1);
f[i]=true;
}
}
}
字符串的组合:
给一个字符串,比如ABC, 把所有的组合,即:A, B, C, AB, AC, BC, ABC, 都找出来。
解题思路:
假设我们想在长度为n的字符串中求m个字符的组合。我们先从头扫描字符串的第一个字符。针对第一个字符,我们有两种选择:一是把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符;二是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。这两种选择都很容易用递归实现。
字符串的排列:
public static void combiantion(char chs[]){
if(chs.length == 0) return ;
Stack<Character> stack = new Stack<Character>();
for(int i = 1; i <= chs.length; i++){
combine(chs, 0, i, stack);
}
}
//从字符数组中第begin个字符开始挑选number个字符加入list中
public static void combine(char []chs, int begin, int number, Stack<Character> stack){
if(number == 0){
System.out.println(stack.toString());
return ;
}
if(begin == chs.length){
return;
}
stack.push(chs[begin]);
combine(chs, begin + 1, number - 1, stack);
stack.pop();
combine(chs, begin + 1, number, stack);
}
另一种实现方法:
package BeanUtil;
import java.util.ArrayList;
import java.util.List;
import com.work.core.exception.OurException;
/**
* 统计任三出现的最多的几率的组合
*
* @author wangmingjie
* @date 2009-1-1下午01:22:19
*/
public class Copy_2_of_StatisAnyThree {
// 组合算法
// 本程序的思路是开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标
// 代表的数被选中,为0则没选中。
// 首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。
// 然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为
// “01”组合,同时将其左边的所有“1”全部移动到数组的最左端。
// 当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得
// 到了最后一个组合。
// 例如求5中选3的组合:
// 1 1 1 0 0 //1,2,3
// 1 1 0 1 0 //1,2,4
// 1 0 1 1 0 //1,3,4
// 0 1 1 1 0 //2,3,4
// 1 1 0 0 1 //1,2,5
// 1 0 1 0 1 //1,3,5
// 0 1 1 0 1 //2,3,5
// 1 0 0 1 1 //1,4,5
// 0 1 0 1 1 //2,4,5
// 0 0 1 1 1 //3,4,5
public static void main(String[] args) {
Copy_2_of_StatisAnyThree s = new Copy_2_of_StatisAnyThree();
s.printAnyThree();
}
/**
*
*/
public void printAnyThree(){
int[] num = new int[]{1,2,3,4,5,6};
print(combine(num,3));
}
/**
* 从n个数字中选择m个数字
* @param a
* @param m
* @return
*/
public List combine(int[] a,int m){
int n = a.length;
if(m>n){
throw new OurException("错误!数组a中只有"+n+"个元素。"+m+"大于"+2+"!!!");
}
List result = new ArrayList();
int[] bs = new int[n];
for(int i=0;i<n;i++){
bs[i]=0;
}
//初始化
for(int i=0;i<m;i++){
bs[i]=1;
}
boolean flag = true;
boolean tempFlag = false;
int pos = 0;
int sum = 0;
//首先找到第一个10组合,然后变成01,同时将左边所有的1移动到数组的最左边
do{
sum = 0;
pos = 0;
tempFlag = true;
result.add(print(bs,a,m));
for(int i=0;i<n-1;i++){
if(bs[i]==1 && bs[i+1]==0 ){
bs[i]=0;
bs[i+1]=1;
pos = i;
break;
}
}
//将左边的1全部移动到数组的最左边
for(int i=0;i<pos;i++){
if(bs[i]==1){
sum++;
}
}
for(int i=0;i<pos;i++){
if(i<sum){
bs[i]=1;
}else{
bs[i]=0;
}
}
//检查是否所有的1都移动到了最右边
for(int i= n-m;i<n;i++){
if(bs[i]==0){
tempFlag = false;
break;
}
}
if(tempFlag==false){
flag = true;
}else{
flag = false;
}
}while(flag);
result.add(print(bs,a,m));
return result;
}
private int[] print(int[] bs,int[] a,int m){
int[] result = new int[m];
int pos= 0;
for(int i=0;i<bs.length;i++){
if(bs[i]==1){
result[pos]=a[i];
pos++;
}
}
return result ;
}
private void print(List l){
for(int i=0;i<l.size();i++){
int[] a = (int[])l.get(i);
for(int j=0;j<a.length;j++){
System.out.print(a[j]+"/t");
}
System.out.println();
}
}
}