ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

(真)n选m排列算法next_permutation() 非递归版本

2019-09-22 21:42:44  阅读:188  来源: 互联网

标签:loc 递归 int lis System next permutation println out


/**
 *@auther 皇阿玛
 *2019/9/16 13:51
 */

package courseOne;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;


class Permutation{//递归方法,要找一个非递归的方法
	int total;
	static int count=0;
//	private int[] people;
	public Permutation(){}
	public Permutation(int total,int SelectPeople){
//		this.people = new int[SelectPeople];
		this.total = total;
	}
	public boolean next(List<Integer> lis,int start){
		if(start >= lis.size() ){
			System.out.println(lis);
			count++;
			return true;
		}
		for(int i=1;i<=total;i++){
			if( !lis.contains(i) ){
				lis.set(start, i);
			}else{
				continue;
			}
			next(lis,start+1);
			lis.set(start, -1);
		}
		return true;
	}
	public boolean next2(List<Integer> lis){//非递归写出来
		int flag = 0;//用来判断初始list是否全为0,则需要赋初值1,2,3...
		int ChangeFlag = 0;//用来判断是否已经对list进行更新了,若已更新,则直接退出并返回true
		for(int i=0;i<lis.size();i++){
			flag += lis.get(i);
		}
		if(flag == 0){//初始化
			for(int j=0;j<lis.size();j++){
				lis.set(j, j); //lis.set(index, element)
			}
			ChangeFlag = 1;
		}else{
			for(int k=lis.size()-1;k>=0;k--){
//				System.out.println("1.k = "+k);/////////////////////////////
				if(!IsMaxOrNot(lis,k) && ChangeFlag == 0){//最后一位不是最大值的话,就进行最小增值
					if( LittleIncrease(lis,k) )
						ChangeFlag = 1;
					//break;
					//若最后一位是最大值,则  k 进入下一层for循环,即把lis中的搜索位置前移
					//若更新的位置k不是最后一位,则需要对k位之后的数据进行从小到大更新!
					if(1 == ChangeFlag ){//如果最小更新的元素位置是k的话=>&& k < lis.size()
//						System.out.println("I'm complemening!!!,k = "+k+" lis = "+lis);
						Complement(lis,k);//对k之后的元素进行按顺序补全
					}
					break;
				}	
			}
		}
		if(1 == ChangeFlag)
			return true;
		else
			return false;
	}
	
	public boolean IsMaxOrNot(List<Integer> lis,int loc){//loc从0开始计数
		int[] tem = new int[total];//初值为0;
		Arrays.fill(tem, 0);	    //对数组用某个数进行填充
		int flag = 1;				//判断标志,默认是最大值,则flag=1,若不是最大值,则令flag=0;
		
		for(int i=0;i<lis.size() && i<loc;i++){//对loc之前&&已用过的 元素进行标记
			tem[lis.get(i)] = 1;
		}
		for(int j=0;j<total;j++){  //未用过的元素中去比较查找是否有更大的元素
			if(tem[j] != 1 && j>lis.get(loc))//数值 j 没用过,而且 j 比lis第loc位的数值要大。
				flag = 0;		   //说明list.get(loc)不是最大值,还有更大的数值可选
		}
		if(0==flag) 
			return false;
		else
			return true;
	}
	public boolean LittleIncrease(List<Integer> lis,int loc){//当某个位置的数值不是最大值时,进行最小限度地增加
		int[] tem = new int[total];//初值为0;
		Arrays.fill(tem, 0);	    //对数组用某个数进行填充
		int flag = 0;				//判断标志,默认是最大值,则flag=1,若不是最大值,则令flag=0;
		
		for(int i=0;i<lis.size() && i<loc;i++){//对loc之前&&已用过的 元素进行标记
			tem[lis.get(i)] = 1;
		}
		for(int j=0;j<total;j++){  //未用过的元素中去比较查找是否有更大的元素
//			System.out.println("2.lis.get(loc) = "+lis.get(loc)+" loc = "+loc);
			if(tem[j] != 1 && j>lis.get(loc)){//数值 j 没用过,而且 j 比lis第loc位的数值要大。
				lis.set(loc, j);   //把loc位置的数值增加为j;!!!!!!!!!!!!
				flag = 1;		   //完成增值工作
//				System.out.println("3.list = "+lis);
				break;
			}
		}
		if(0==flag){
//			System.out.println("false");
			return false;
		}
			
		else{
//			System.out.println("true");
			return true;
		}
			
	}
	public boolean Complement(List<Integer> lis,int loc){//loc是中间更新的位置下标(index) <=> k
		//当处理完的最小增值位置不是在最后一位时,需要对 后面 元素进行补全,按照剩余元素,从小到大处理;当前的 loc 位置  不用改动 !!!!!
		int[] tem = new int[total];//初值为0;
		Arrays.fill(tem, 0);	    //对数组用某个数进行填充
		//int flag = 1;				//判断标志,
//		System.out.println("4.in Complement,loc = "+loc+", lis = "+lis);
		for(int i=0;i<=loc;i++){//对loc之前&&已用过的 元素进行标记(loc就是下标,直接带入index)  :i<lis.size() && 
			tem[lis.get(i)] = 1;				//这里loc要记得取等号
		}
		
		for(int j=loc+1;j<lis.size();j++){//j:每个待修正的位置坐标!!!对loc之后的元素进行重新洗牌,坐标从(loc+1)开始走
			int ChangeFlag = 0;//修补过程,已进行到的 位置 下标!!!
			for(int k=0;k<total && ChangeFlag == 0;k++){
				if(tem[k]!=1){
					lis.set(j, k);
					ChangeFlag = 1;
					//ChangeFlag++;
					tem[k] = 1;
//					System.out.println("5.lis = "+lis+", k = "+k+", loc = "+loc+", Changeflag="+ChangeFlag);
				}
			}
		}
		return true;
	}
	
}


public class PermutationExample {
	public static void main(String[] args){
		
		int sum = 0;
		int total = 5;
		int need = 3;// n <=> SelectPeople
		List<Integer> lis = new ArrayList<Integer>();
		List<String> lis2 = new ArrayList<String>();
//		lis2.add("q");
//		lis2.get(0);
//		System.out.println("ss");
		for(int i = 0 ; i < need;i++) {
			lis.add(0);
		}
		Permutation perm = new Permutation(total,need);
		
		
		while(perm.next2(lis)){
			System.out.println(lis);
			sum++;
		}
		System.out.println("The num of permutations is "+sum+" !!!");
//		while(sum>0){
//			perm.next2(lis);
//			System.out.println(lis);
//			sum--;
//		}
	}
}
		/**
		 * 
		 
		List<Integer> lis = new ArrayList<Integer>();
		for(int i = 0 ; i < need;i++) {
			lis.add(-1);
		}
		
		Permutation per = new Permutation(total,need);
		per.next(lis, 0);
//		int sum = 60;
//		while( sum>0 ){
//			per.next(lis, 0);
//			System.out.println(lis);
//			sum--;
//		}
		System.out.println("all of the number:"+per.count); 
		*/

 

标签:loc,递归,int,lis,System,next,permutation,println,out
来源: https://blog.csdn.net/Lukelluke/article/details/101173078

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有