Problem14

题目:The following iterative sequence is defined for the set of positive integers:

n → n/2 (n is even)
n → 3n + 1 (n is odd)

Using the rule above and starting with 13, we generate the following sequence:

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1

It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.

Which starting number, under one million, produces the longest chain?

(克拉茨问题,求一百万内的一个数,使其经过克拉茨问题的运算后得到的序列最长)

 

 

public class Problem14 {
	private int[] counts;
	private int num;
	
	public Problem14(int num){
		this.num = num;
		counts = new int[num];
	}
	
	public static void main(String[] args) {
		int range = 1000000;
		Problem14 p = new Problem14(range);
		int cmp1 = 0;
		int cmp2 = 0;
		int r = 0;
		int tmp = 0;
		
		long st1 = System.nanoTime();
		for(int i = 1; i<=range; i++){
			tmp = p.comlen(i);
			if(tmp>cmp1){
				cmp1 = tmp;
				r = i;
			}

		}
		
		long et1= System.nanoTime();
		System.out.println(r);
		
		/*
		long st2 = System.nanoTime();
		for(int i = 1; i<=range; i++){
			tmp = p.len(i);
			if(tmp>cmp2){
				cmp2 = tmp;
				r = i;
			}		
		}
		
		long et2= System.nanoTime();
		System.out.println(r);
		*/
		//System.out.println(p.getCounts(1000000));
		System.out.println(et1-st1);
		//System.out.println(et2-st2);
		
		
	}

	public int len(int n){
		long copy = n;
		int len = 1;
		while(copy != 1){
			if(copy%2==0){
				
				copy /= 2;
				if(copy<=num){
					int flag = (int)copy;
					if(counts[flag-1] != 0){
						len += counts[flag-1];
						break;
					}
				}
				len++;
			}else{
				
				copy = 3*copy+1;
				if(copy<=num){
					int flag = (int)copy;
					if(counts[flag-1] != 0){
						len += counts[flag-1];
						break;
					}
				}
				len++;
			}	
		}
		counts[n-1] = len;
		return len;	
	}
	/*
	public int comlen(int n){
		long copy = n;
		int len  = 1;
		while(copy != 1){
			if(copy%2==0)
				copy /= 2;
			else
				copy = 3*copy+1;
			len++;
		}
		return len;
	}
	*/

}
 

我的想法是这样的:

 

按照常规做法,只需计算一百万内各个自然数的Collatz数列,然后比较即可。但这样其实重复了一些过程,比如题中例子:

 

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1

 

自然数从13到20的运算是是之前没出现过的,但到了自然数10,不难发现在计算13之前是计算过10的Collatz数列的长度

 

的,所以这个数列计算到10其实可以不必计算了,只需把预先存储起来10的Collatz数列的长度加上13到20这过程中产生

 

自然数个数就可以了。

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值