问题描述
设计一个算法,找出只含素因子2,3,5 的第 n 小的数。
符合条件的数如:1, 2, 3, 4, 5, 6, 8, 9, 10, 12…
如果n = 9, 返回 10
丑数
- 介绍: 只包含因子2,3,5的正整数被称作丑数,比如4,10,12都是丑数,而7,23,111则不是丑数。
- 判断方法:
1. 首先除2,直到不能整除为止;
2. 然后除5到不能整除为止;
3. 然后除3直到不能整除为止;
4. 最终判断剩余的数字是否为1,如果是1则为丑数,否则不是丑数。 -
解法一 (过于复杂)
根据丑数的判断方法,以第n个丑数为循环条件,依次判断。如果n比较大的情况下,时间复杂度不满足要求。代码如下:
int n = 9; // 第n个丑数 int temp; int result; int lastNo = 0; int i = 0; //丑数 个数 int j = 0; // 循环数 while(i < n){ j++; result = j; temp = j; while(temp % 2 == 0) { temp = temp / 2; } while(temp % 5 == 0) { temp = temp / 5; } while(temp % 3 == 0) { temp = temp / 3; } if (temp == 1) { //System.out.print(result + " "); i ++ ; if (i == n) { lastNo = result; } } }
解法二 (正解)
参考链接:http://blog.csdn.net/leex_brave/article/details/51766194
总结规律发现,后一个丑数都可以由之前的丑数乘(2,3,5)所得到,提取第一个大于现有最大丑数的数,变为最新的丑数。
最终代码如下:import java.util.ArrayList; public class Solution { /** * @param n: An integer * @return: the nth prime number as description. */ public int nthUglyNumber(int n) { // write your code here if(n<=0){ return 0; } ArrayList<Integer> list = new ArrayList<Integer>(); list.add(1); int i2=0, i3=0, i5=0; while(list.size() < n){ int m2 = list.get(i2) * 2; int m3 = list.get(i3) * 3; int m5 = list.get(i5) * 5; int min = Math.min(m2, Math.min(m3,m5)); list.add(min); if(min == m2) i2++; if(min == m3) i3++; if(min == m5) i5++; } return list.get(n-1); } }