排列与组合算法



组合算法:比如从集合m中选取n个元素,记为{n|m} 算法思路: 1. 创建一个数组,每个数组元素对应一个m中元素,该数组元素值为1,代表其对应m中的元素已被选中,否则没被选中 2. 初始化数组前面n个元素成1,代表第一种组合 3. 从左往右扫描“10”组合,并将首次发现该组合,该成“01” 4. 将该组合前面的所有1,遇到最左端 5. 回到第三步,直到找不到“10”组合为主,每次交换“10”组合就是一种可能性 例如求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 代码如下:
import java.io.*;class test  {	
<span style="white-space:pre">	</span>public static void main (String[] args) throws java.lang.Exception	{
        int[] m={1,2,3,4,5};//集合m
        byte[] b={0,0,0,0,0};//标识数组
        for(int i=0;i<3;++i) b[i]=1;//从集合m中选取n
        print(m,b);//第一种组合情况 
        boolean status=true;//ture标识找到10组合
        while(status){
            status=false;
            for(int i=0;i<b.length-1;++i){
                if(b[i]==1&&b[i+1]==0){ //找到“10”组合
                    b[i]=0;b[i+1]=1;//交换成“01”组合
                    int s=i-1;
                    for(int j=s;j>=0;--j){//将1全部移到最左端
                        if(b[j]==0){
                            for(int k=j;k<s;++k)b[k]=1;
                            b[s]=0;--s;
                        }
                    }
                    status=true;
                    print(m,b);
                    break;
                }
            }
        }
	}
	//打印	public static void print(int[] m,byte[] b){
	    for(byte j:b)System.out.print(j+" ");
	    System.out.print("//");
	    for(int i=0;i<b.length;++i)
	        if(b[i]==1)System.out.print(m[i]+" ");
	    System.out.println();	}
}

执行结果:

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

全排列算法:将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。

算法思路:以{1, 2, 3, 4, 5}为例 

1. 首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。由于一个数的全排列就是其本身,从而得到以上结果。 

2. 再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.从而可以推断,设一组数p= {r1, r2, r3, ... ,rn}, 全排列为perm(p),pn = p - {rn}。 因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。当n = 1时perm(p} = r1。为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列。

代码如下:

import java.io.*;
import java.util.*;
class test  {
	public static void main (String[] args) throws java.lang.Exception	{
        Queue<String> p = new LinkedList<>();//集合p
        String[] element = {"1","2","3","4","5"};//元素
        Collections.addAll(p,element);
        for(int i=1;i<element.length;++i){//将集合p中的元素,与element中的元素结合成一个新的排列,可以通过修改element.length实现,从集合中选取m个元素排序
            int size=p.size();
            for(int j=0;j<size;++j){
                String pre=p.poll();//移除上一种排列
                for(String ele:element){//如果某个元素还不存在该排列中,则组合成新的排列方式,并加入到排列集合p中
                    if(pre.indexOf(ele)==-1) p.offer(pre+ele);
                }
            }
        }
        int i=0;
        for(String d:p){
            System.out.print(d+" ");
            if(++i%10==0) System.out.println();
        }
	}
}

结果如下: 12345 12354 12435 12453 12534 12543 13245 13254 13425 13452 13524 13542 14235 14253 14325 14352 14523 14532 15234 15243 15324 15342 15423 15432 21345 21354 21435 21453 21534 21543 23145 23154 23415 23451 23514 23541 24135 24153 24315 24351 24513 24531 25134 25143 25314 25341 25413 25431 31245 31254 31425 31452 31524 31542 32145 32154 32415 32451 32514 32541 34125 34152 34215 34251 34512 34521 35124 35142 35214 35241 35412 35421 41235 41253 41325 41352 41523 41532 42135 42153 42315 42351 42513 42531 43125 43152 43215 43251 43512 43521 45123 45132 45213 45231 45312 45321 51234 51243 51324 51342 51423 51432 52134 52143 52314 52341 52413 52431 53124 53142 53214 53241 53412 53421 54123 54132 54213 54231 54312 54321 

排列元素中含有重复元素解决方案: 

1. 添加用来标识重复次数数组 

2. 每次构建新序列时,检查该元素是否已超过规定重复元素个数,不超过,该序列为新的排序 代码如下:

import java.io.*;

import java.util.*;

class test { public static void main (String[] args) throws java.lang.Exception {

Queue<String> p = new LinkedList<>();//集合p

String[] element = {"1","2","3","4","5"};//元素

int[] repeat = {1,1,2,1,1};//标识元素重复数次

Collections.addAll(p,element);

for(int i=1;i<sum(repeat);++i){//将集合p中的元素,与element中的元素结合成一个新的排列,可以通过sum(repeat)修改实现,从集合中选取m个元素排序

int size=p.size();

for(int j=0;j<size;++j){

String pre=p.poll();//移除上一种排列

for(int l=0;l<element.length;++l){//如果某个元素还不存在该排列中或存在个数小于重复次数,则组合成新的排列方式,并加入到排列集合p中

int count = 0;

int index=0;

while(pre.indexOf(element[l],index)!=-1){

++index;count++;

}

if(count<repeat[l]) p.offer(pre+element[l]);

}

}

}

int i=0;

for(String d:p){

System.out.print(d+" ");

if(++i%10==0) System.out.println();

}

}

public static int sum(int[] s){

int rt=0;

for(int d:s)rt += d;

return rt; }

}

结果如下:312345 312354 312435 312453 312534 312543 313245 313254 313425 313452 313524 313542 314235 314253 314325 314352 314523 314532 315234 315243 315324 315342 315423 315432 321345 321354 321435 321453 321534 321543 323145 323154 323415 323451 323514 323541 324135 324153 324315 324351 324513 324531 325134 325143 325314 325341 325413 325431 331245 331254 331425 331452 331524 331542 332145 332154 332415 332451 332514 332541 334125 334152 334215 334251 334512 334521 335124 335142 335214 335241 335412 335421 341235 341253 341325 341352 341523 341532 342135 342153 342315 342351 342513 342531 343125 343152 343215 343251 343512 343521 345123 345132 345213 345231 345312 345321 351234 351243 351324 351342 351423 351432 352134 352143 352314 352341 352413 352431 353124 353142 353214 353241 353412 353421 354123 354132 354213 354231 354312 354321


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值