`
mwei
  • 浏览: 124220 次
  • 性别: Icon_minigender_1
  • 来自: 抽象空间
社区版块
存档分类
最新评论

将一个自然数拆分为若干不重复自然数之和(OO实现)

    博客分类:
  • java
阅读更多
原题出处:http://www.iteye.com/topic/927532
使用OO的方式实现会占用更多的内存,在递归调用的时候需要保存每次参数,对性能大打折扣,加大JVM参数到256M后,使用1000测试都会宕掉,然而这里演示的是一种解题思路。

初步结构分析:
/**
 * 将一个自然数拆分为若干不重复自然数之和。
 * 以10为例:	
 * 1+9		--对原数据(10)的初次拆分(拆为m+n)应该很容易
 *   |_2+7	--对9拆分为x+y,x应该大于1,这样就避免了因子重复
 *       |_3+4  --对7拆分为i+j,i应该大于2,以此规律持续下去
 *   |_3+6	--此处依然对9拆分	
 *   |_4+5
 * 2+8
 *   |_3+5
 * 3+7		--7,在此处无法拆分,否则导致重复
 * 4+6	
 */

java代码如下:
import java.util.ArrayList;
import java.util.List;

public class SplitNumber {
	public static void main(String[] args) {
		SplitNumber.split(30);
		System.out.println("=>DONE...");
	}
	public static void split(int number){
		if(number<3){
			System.out.println(number+"=>can not split...");
			return;
		}
		List<Splitor> outer=new ArrayList<Splitor>(); 
		int half=(number+1) >> 1; //+1 计算奇数与偶数的一半
		Splitor s=null;
		for(int i=1;i<half;i++){ //for-loop:初次拆分为m+n
			s=new Splitor();
			s.smaller=i; //
			s.bigger=number-i;
			outer.add(s);
			s.splitCenter(s); //是对m+n中的n进行深度拆分
		} // end for		
		for(Splitor t:outer){ //上面拆分完毕后输出
			showRetHelper(t.splitors,t);
		}
	}
	/**
	 * 这个递归很恶心:它要把保存每次传入的参数
	 * @param sps 按照顺序保存传入的参数
	 */
	private static void showRetHelper(List<Splitor> splitors,Splitor... sps){
		int len=sps.length;
		for(int i=0;i<len;i++){ //每次递归前都要先输出各个因子
			if(len==1){ //只有一个就输出 smaller+bigger
				System.out.print(sps[0]+" ");	
				break;
			}
			if(i==len-1){ //最后一个同样输出 smaller+bigger
				System.out.print(sps[i]+" ");	
			}else {
				System.out.print(sps[i].smaller+"+");	//不是最后一个就输出小的那个数
			}
		}
		System.out.println(""); //换行
		for(Splitor s:splitors){
			showRetHelper(s.splitors,copyArray(sps,s)); //保存每次的参数,递归
		}
	}
	private static Splitor[] copyArray(Splitor[] src, Splitor s){ //不多说
		if(src==null || src.length==0){
			return new Splitor[]{s};
		}else{
			int srcLength=src.length;
			Splitor[] dest=new Splitor[srcLength+1];
			System.arraycopy(src, 0, dest, 0, srcLength);
			dest[srcLength]=s;
			return dest;
		}
	}
	
	//内部类:对数据的包装
	private static class Splitor{
		private int smaller;
		private int bigger;
		private List<Splitor> splitors=new ArrayList<Splitor>(); //作用:构造树
		
		private void add(Splitor s){
			this.splitors.add(s);
		}
		public void splitCenter(Splitor s){
			int half=(s.bigger+1) >>1; //+1 计算奇数与偶数的一半,用于for里的小于
			int small=s.smaller+1; //+1 防止重复
			if(small>=half) return;
			Splitor s2=null;
			for(int i=small;i<half;i++){
				s2=new Splitor();
				s2.smaller=i;
				s2.bigger=s.bigger-i;
				s.add(s2); //s指向s.bigger被拆分的结果集
				splitCenter(s2); //recursively 持续拆分
			}
		}
		@Override
		public String toString(){
			return smaller+"+"+bigger;
		}
	}
}

30测试结果如下:
1+29 
1+2+27 
1+2+3+24 
1+2+3+4+20 
1+2+3+4+5+15 
1+2+3+4+5+6+9 
1+2+3+4+5+7+8 
1+2+3+4+6+14 
1+2+3+4+7+13 
1+2+3+4+8+12 
1+2+3+4+9+11 
1+2+3+5+19 
1+2+3+5+6+13 
1+2+3+5+7+12 
1+2+3+5+8+11 
1+2+3+5+9+10 
1+2+3+6+18 
1+2+3+6+7+11 
1+2+3+6+8+10 
1+2+3+7+17 
1+2+3+7+8+9 
1+2+3+8+16 
1+2+3+9+15 
1+2+3+10+14 
1+2+3+11+13 
1+2+4+23 
1+2+4+5+18 
1+2+4+5+6+12 
1+2+4+5+7+11 
1+2+4+5+8+10 
1+2+4+6+17 
1+2+4+6+7+10 
1+2+4+6+8+9 
1+2+4+7+16 
1+2+4+8+15 
1+2+4+9+14 
1+2+4+10+13 
1+2+4+11+12 
1+2+5+22 
1+2+5+6+16 
1+2+5+6+7+9 
1+2+5+7+15 
1+2+5+8+14 
1+2+5+9+13 
1+2+5+10+12 
1+2+6+21 
1+2+6+7+14 
1+2+6+8+13 
1+2+6+9+12 
1+2+6+10+11 
1+2+7+20 
1+2+7+8+12 
1+2+7+9+11 
1+2+8+19 
1+2+8+9+10 
1+2+9+18 
1+2+10+17 
1+2+11+16 
1+2+12+15 
1+2+13+14 
1+3+26 
1+3+4+22 
1+3+4+5+17 
1+3+4+5+6+11 
1+3+4+5+7+10 
1+3+4+5+8+9 
1+3+4+6+16 
1+3+4+6+7+9 
1+3+4+7+15 
1+3+4+8+14 
1+3+4+9+13 
1+3+4+10+12 
1+3+5+21 
1+3+5+6+15 
1+3+5+6+7+8 
1+3+5+7+14 
1+3+5+8+13 
1+3+5+9+12 
1+3+5+10+11 
1+3+6+20 
1+3+6+7+13 
1+3+6+8+12 
1+3+6+9+11 
1+3+7+19 
1+3+7+8+11 
1+3+7+9+10 
1+3+8+18 
1+3+9+17 
1+3+10+16 
1+3+11+15 
1+3+12+14 
1+4+25 
1+4+5+20 
1+4+5+6+14 
1+4+5+7+13 
1+4+5+8+12 
1+4+5+9+11 
1+4+6+19 
1+4+6+7+12 
1+4+6+8+11 
1+4+6+9+10 
1+4+7+18 
1+4+7+8+10 
1+4+8+17 
1+4+9+16 
1+4+10+15 
1+4+11+14 
1+4+12+13 
1+5+24 
1+5+6+18 
1+5+6+7+11 
1+5+6+8+10 
1+5+7+17 
1+5+7+8+9 
1+5+8+16 
1+5+9+15 
1+5+10+14 
1+5+11+13 
1+6+23 
1+6+7+16 
1+6+8+15 
1+6+9+14 
1+6+10+13 
1+6+11+12 
1+7+22 
1+7+8+14 
1+7+9+13 
1+7+10+12 
1+8+21 
1+8+9+12 
1+8+10+11 
1+9+20 
1+10+19 
1+11+18 
1+12+17 
1+13+16 
1+14+15 
2+28 
2+3+25 
2+3+4+21 
2+3+4+5+16 
2+3+4+5+6+10 
2+3+4+5+7+9 
2+3+4+6+15 
2+3+4+6+7+8 
2+3+4+7+14 
2+3+4+8+13 
2+3+4+9+12 
2+3+4+10+11 
2+3+5+20 
2+3+5+6+14 
2+3+5+7+13 
2+3+5+8+12 
2+3+5+9+11 
2+3+6+19 
2+3+6+7+12 
2+3+6+8+11 
2+3+6+9+10 
2+3+7+18 
2+3+7+8+10 
2+3+8+17 
2+3+9+16 
2+3+10+15 
2+3+11+14 
2+3+12+13 
2+4+24 
2+4+5+19 
2+4+5+6+13 
2+4+5+7+12 
2+4+5+8+11 
2+4+5+9+10 
2+4+6+18 
2+4+6+7+11 
2+4+6+8+10 
2+4+7+17 
2+4+7+8+9 
2+4+8+16 
2+4+9+15 
2+4+10+14 
2+4+11+13 
2+5+23 
2+5+6+17 
2+5+6+7+10 
2+5+6+8+9 
2+5+7+16 
2+5+8+15 
2+5+9+14 
2+5+10+13 
2+5+11+12 
2+6+22 
2+6+7+15 
2+6+8+14 
2+6+9+13 
2+6+10+12 
2+7+21 
2+7+8+13 
2+7+9+12 
2+7+10+11 
2+8+20 
2+8+9+11 
2+9+19 
2+10+18 
2+11+17 
2+12+16 
2+13+15 
3+27 
3+4+23 
3+4+5+18 
3+4+5+6+12 
3+4+5+7+11 
3+4+5+8+10 
3+4+6+17 
3+4+6+7+10 
3+4+6+8+9 
3+4+7+16 
3+4+8+15 
3+4+9+14 
3+4+10+13 
3+4+11+12 
3+5+22 
3+5+6+16 
3+5+6+7+9 
3+5+7+15 
3+5+8+14 
3+5+9+13 
3+5+10+12 
3+6+21 
3+6+7+14 
3+6+8+13 
3+6+9+12 
3+6+10+11 
3+7+20 
3+7+8+12 
3+7+9+11 
3+8+19 
3+8+9+10 
3+9+18 
3+10+17 
3+11+16 
3+12+15 
3+13+14 
4+26 
4+5+21 
4+5+6+15 
4+5+6+7+8 
4+5+7+14 
4+5+8+13 
4+5+9+12 
4+5+10+11 
4+6+20 
4+6+7+13 
4+6+8+12 
4+6+9+11 
4+7+19 
4+7+8+11 
4+7+9+10 
4+8+18 
4+9+17 
4+10+16 
4+11+15 
4+12+14 
5+25 
5+6+19 
5+6+7+12 
5+6+8+11 
5+6+9+10 
5+7+18 
5+7+8+10 
5+8+17 
5+9+16 
5+10+15 
5+11+14 
5+12+13 
6+24 
6+7+17 
6+7+8+9 
6+8+16 
6+9+15 
6+10+14 
6+11+13 
7+23 
7+8+15 
7+9+14 
7+10+13 
7+11+12 
8+22 
8+9+13 
8+10+12 
9+21 
9+10+11 
10+20 
11+19 
12+18 
13+17 
14+16 
=>DONE...


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics