多位水仙花数算法

多位水仙花数算法

1.递归(用时16-20s;写起来非常方便,非常爽):

import java.math.BigInteger;
import java.util.ArrayList;

/**
 * 三位的水仙花数共有4个:153,370,371,407;  
	四位的水仙花数共有3个:1634,8208,9474;   
	五位的水仙花数共有3个:54748,92727,93084;   
	六位的水仙花数只有1个:548834;   
	七位的水仙花数共有4个:1741725,4210818,9800817,9926315;   
	八位的水仙花数共有3个:24678050,24678051,88593477 
 * @author Administrator
 *ps : 把new BigInteger(),改为BigInteger.valueof(); 把运行时间从35秒减低到20秒
 */
public class FlowerNumber_simple {
	private int size;
	private ArrayList resultLists;
	private int[] base_num_count;
	private BigInteger[] subResult;
	
	public FlowerNumber_simple(int size){
		this.size = size;
		resultLists = new ArrayList();
		base_num_count = new int[10];
		subResult = new BigInteger[10];
		
		/*for(int i=0;i<10;i++){
			subResult[i] = new BigInteger(i+"").pow(size);
		}*/
		for(int i = 0; i < 10; ++i){
			//subResult[i] = BigInteger.valueOf(i).pow(this.level);
			subResult[i] = BigInteger.ONE;
			for(int j = 0; j < size; ++j){
				subResult[i] = subResult[i].multiply(BigInteger.valueOf(i));
			}
		}
		
		
	}
	
	
	public static void main(String[] args) {
		FlowerNumber_simple fn = new FlowerNumber_simple(21);
		long start = System.currentTimeMillis();
		fn.backTracking(0, 0);
		for(BigInteger b : fn.resultLists){
			System.out.println(b);
		}
		long times = System.currentTimeMillis()-start;
		System.out.println(times/1000+"秒");
	}
	
	private void backTracking(int level,int current_index){
		if(level>=size){
			getresult();
			return ;
		}
		for(int i=current_index;i < 10;i++){
			base_num_count[i] ++;
			backTracking(level+1, i);
			base_num_count[i] --;
		}
		
	}

	private void getresult() {
		
		BigInteger result = BigInteger.ZERO;
		for(int i=0;i<10;i++){
			if(base_num_count[i]!=0){
				//result = result.add(subResult[i].multiply(new BigInteger(base_num_count[i]+""))  );
				result = result.add(subResult[i].multiply(BigInteger.valueOf(base_num_count[i])));
			}
		}
		String result_str = result.toString();
		if(result_str.length()== size){
			int[] same_num_count = new int[10];
			for(int i =0 ;i



2.栈回溯(用时1s-3s;极速):

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;


/**
 * 寻找水仙花数问题
 * @author lixinji
 * 从三方面优化循环
*0.把常用的大数都缓存在数组。(21位水仙花数,缓存和不缓存时间相差10s到30s之间)
 * 1.循环对象优化:利用组合来穷举,例如0个9,1个9....9个9循环所有的可能性。只要这个组合不符合,那么可以排除很多数
 * 2.上下限优化:在特定的组合下,计算最小值,最大值,然后和最小值常量,最大值常量比较,如果超出那么立马排除
 * 3.组合违背优化: 在特定的组合下,比较最小值和最大值高位相同的部分,如果出现与特定组合的情况,排除。(例如组合假定只有2个9,而最小大值高位相同部分计算结果有3个,很明显不符合)
 */
public class FlowerNumber {
	private int size; 			//位数
	private  BigInteger MIN_CONSTANT; 	//最小数常量
	private  BigInteger MAX_CONSTANT;	//最大数常量
	private Hashtable ht;  //存放常用的大数,用hashtable是未了提高效率
	private Set resultsets = new HashSet(); //存放结果集合
	private int index;//索引,其中9-index代表基数
	private int[] base_num_count;		// base_num_count[index] 表示当前基数的组合个数
	private int[] sum_num_count;		//sum_num_count[index] 表示当前循环总基数的组合个数
	private BigInteger[] totalResult;	//sum_num_count[index]  代表当前循环基数的总结果
	
	


	public FlowerNumber(int size) {
		this.size = size;
		int s = size<10?10:size;
		base_num_count = new int[s];
		sum_num_count = new int[s];
		totalResult = new BigInteger[s];
		ht = new Hashtable();
		
		for(int i=0;i<=s;i++){ //存放基数,位数的大数字
			ht.put("n_"+i, new BigInteger(i+""));
		}
		for(int i=0;i<=10;i++){ //存放基数的size次方结果
			ht.put("p_"+i, new BigInteger(i+"").pow(size));
		}
		MIN_CONSTANT=N(10).pow(size-1);
		MAX_CONSTANT=P(10).subtract(N(1));
	}
	private BigInteger N(int i){
		return ht.get("n_"+i);
	}
	private BigInteger P(int i){
		return ht.get("p_"+i);
	}
	
	public static void main(String[] args) {
		
		FlowerNumber fn =new FlowerNumber(21); //这里更改位数
		int s = fn.MAX_CONSTANT.divide(fn.P(9)).intValue();//求出P(9)的除数
		for(int i=0;i<=s;i++){
			fn.find(i);
		}
		BigInteger[] results =new BigInteger[fn.resultsets.size()];
		fn.resultsets.toArray(results);
		Arrays.sort(results);
		for(BigInteger bi : results){
			System.out.println(bi);
		}
		
	}
	// 检查组合是否合格,如果组合位数未满,或者组合匹配正确返回真;不合格,返回假。
	private boolean checkCombination(){
		BigInteger minVal = totalResult[index];
		BigInteger maxVal = totalResult[index].add(P(9-index).multiply(N(size-sum_num_count[index])));
		
		//检查是否违反上下限
		if(minVal.compareTo(MAX_CONSTANT)>0) return false;
		if(maxVal.compareTo(MIN_CONSTANT)<0) return false;
		String minStr = minVal.toString();
		String maxStr = maxVal.toString();
		
		char c;
		int sameCount[] = new int[10];
		for(int i=0;i 0)
					index --;
				else 
					return true;
			}
		}
		//如果当前基数不是9,那么当前基数数目减1,设回原来的值
		if(index >0){
			setValue(base_num_count[index]-1);
			return false;
		}else{
			return true;
		}
		
	}
	
	private boolean checkEnd(){
		for(int i=0;i<=9;i++){
			if(base_num_count[i] !=0)
				return false;
		}
		return true;
	}
	
	
}



你可能感兴趣的:(算法)