剑指offer第二版——面试题49(java)

面试题: 丑数

题目:

我们把只包含因子2、3和5的数称作丑数(Ugly Number)。

求按从小到大的顺序的第1500个丑数。

例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做第一个丑数

思路:

参考:https://blog.csdn.net/Tianzez/article/details/80385144

“以空间换时间”

根据丑数的定义,一个丑数肯定是另一个丑数乘以2、3或5的结果(丑数1除外)。

创建一个数组,里面存放的是已经排序好的丑数,每个丑数是前面某个丑数乘以2、3或5放入结果。把数组中现有的最大丑数记做M

要得到的下一个丑数,肯定是前面某一个丑数乘以2、3或者5(定义)

1. 首先考虑把已有的每个丑数乘以2。在乘以2的时候,能得到若干个结果:

    对于小于或者等于M的值,此时肯定已经在数组中了,不再考虑;

    对于大于M的结果,只需要第一个大于M的结果,因为生成时是按从小到大顺序生成的,更大的结果以后再考虑

    把得到的第一个乘以2后大于M的结果,记为M2,同样把已有的每一个丑数乘以3和5,能得到第一个大于M的结果M3和M5,下一个丑数应该是M2、M3和M5三个数的最小者

 

2. 实际时,并不需要把已有的每个丑数分别乘以2、3和5,因为已有的丑数是按顺序存放在数组中的。

    对于乘以2而言,M前面一定存在某个丑数x,x前面的所有丑数乘以2的结果都小于M;x后面的所有丑数乘以2的结果都大于M。只要记住x这个丑数的位置,同时每次生成新的丑数时再去更新x的位置即可。对于3、5而言同理。

    每次更新现有最大丑数M后,对2、3、5的每个记录位置m2loc,m3loc,m5loc分别更新:对m2loc位置的丑数×2,如果小于当前M,则将m2loc++,移动到下一个更大的丑数位置,再计算m2loc位置的丑数×2,直到其结果超过M为止;更新m3loc和m5loc同理

代码:

public class Q49 {
	public static void main(String[] args) {
		System.out.print(amethod(1500));
	}
	
	public static int amethod(int x) {
		if(x<1) 
			return 0;
		
		if(x==1) 
			return 1;
		
		int[] list = new int[x];
		list[0]=1;
		int count = 1;
		int m2loc = 0;
		int m3loc = 0;
		int m5loc = 0;
		while(count<x) {
			list[count] = min(list[m2loc]*2,list[m3loc]*3,list[m5loc]*5);
			
			while(list[m2loc]*2<=list[count]) 
				m2loc++;
			
			while(list[m3loc]*3<=list[count]) 
				m3loc++;
			
			while(list[m5loc]*5<=list[count]) 
				m5loc++;
			
			System.out.printf("count:%d\t%d\n",count,list[count]);
			count++;	
		}
		return list[x-1];
	}
	
	public static int min(int a,int b,int c) {
		int temp =  (b<c)?b:c;
		int re = (temp<a)?temp:a;
		return re;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值