声明:本片文章为阅读何海涛网易日志后,自己用java实现后的学习总结。
何海涛日志:http://zhedahht.blog.163.com/blog/static/2541117420094245366965/
题目:我们把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第1500个丑数。
思路:我们本能的想到何海涛日志中提到的第一种方法,虽然我们也知道这种方法确实效率很低,而且也想到是不是可以直接new一个int[1500]的数组存储排过序丑数,但是这个数组怎么生成呢?我甚至还将前面十几个丑数列出来,试图找出规律,也曾想过,知道前n个丑数,那么第n+1个丑数无非就是前面n个丑数中的一个乘以2或者3或者5生成的,但到底是哪个数乘以几生成的,其实如果把这个问题解决了,整个问题就迎刃而解,但是思考到这里却有点不知道怎么去解决。直到看到何海涛下面的思路,真是醍醐灌顶。
分别用t2、t3、t5表示前n个数中乘以2、3、5大于nums[n]的最小的下标。也就是说nums[n+1]就是从nums[t2]*2、nums[t3]*3、nums[t5]*5中产生的,而且是这三个数中最小的一个。
仅差一步。。。
代码:
/**
* 题目:我们把只包含因子2、3和5的数称作丑数(Ugly Number)。
* 例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第1500个丑数。
* @author hongbin.gao
*
*/
public class GetUglyNumber {
public static void main(String[] args){
int n= 1500;
int result = getUglyNumber_1(n);
System.out.println(result);
}
public static int getUglyNumber_1(int number){
if(number <= 5) //如果number则直接返回结果。
return number;
int[] nums = new int[number];
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
nums[3] = 4;
nums[4] = 5;
int sum = 5;
int t2 = 2; //t2表示:nums[t2]是最小的大于nums[sum]的下标
int t3 = 1;
int t5 = 2;
int temp = 0;
while(sum<number){
temp = nums[t2]*2; //在t2,t3,t5三个中选出一个得到nums[sum]的下标。
if(temp > nums[t3]*3)
temp = nums[t3]*3;
if(temp > nums[t5] *5)
temp = nums[t5]*5;
nums[sum] = temp; //对nums[sum]进行修改
while(nums[t2]*2 <= nums[sum])
t2++;
while(nums[t3]*3 <= nums[sum])
t3++;
while(nums[t5]*5 <= nums[sum])
t5++;
sum++;
}
return nums[number-1];
}
}