题目:
Write a program to find the n
-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5
. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12
is the sequence of the first 10
ugly numbers.
Note that 1
is typically treated as an ugly number, and n does not exceed 1690.
大意:
情给出第n个丑数,丑数是因数只有2,3,5的数,从小到大排列,1,2,3,4,5,6,8,9,10,12是前10个丑陋数字的序列。其中1被定义为丑数。
分析:
丑数的因数只能是2,3,5,所以我这样可以得到
1、丑数是丑数*丑数得到的,一开始的丑数是1、2、3、5。
2、每个丑数刚好可以获得三个丑数,分别乘以2、3、5得到。
3、由于丑数都是整数所以,第n个丑数*2<第n个丑数*3<第n个丑数*5
然后我为了分析起来方便定义了一个名词,通过某个丑数*2、*3、*5获得另一个丑数,这样的过程中某个丑数被我称为底丑数。
4、所以第3条可以增加为相同的底丑数*2获得的丑数最小,不同的不一定。
根据这4个规律我们可以这样,
建立一个数组存储丑数,第一个丑数为1,索引为0。
然后设定3个变量记录底丑数在数组中的索引,所以a=0(*2)、b=0(*3)、c=0(*5)指定1为底丑数。
对比1*2,1*3,1*5可得第二关丑数是2,因为这是是*2获得的,那么将a++,因为这个丑数已经获得过了。这是底丑数分别为2,1,1。
对比2*2,1*3,1*5可得第三个丑数是3,因为这是是*3获得的,那么将b++,因为这个丑数已经获得过了。这是底丑数分别为2,2,1。
对比2*2,2*3,1*5可得第三个丑数是4,因为这是是*2获得的,那么将a++,因为这个丑数已经获得过了。这是底丑数分别为3,2,1。
对比3*2,2*3,1*5可得第三个丑数是5,因为这是是*5获得的,那么将c++,因为这个丑数已经获得过了。这是底丑数分别为3,2,2。
对比3*2,2*3,2*5可得第三个丑数是6,因为这是是*2和*3都可获得的,那么将a++,b++,因为这两个相等的丑数已经获得过了。这是底丑数分别为4,3,2。
对比4*2,3*3,2*5可得第三个丑数是8,因为这是是*2获得的,那么将a++,因为这个丑数已经获得过了。这是底丑数分别为5,2,2。
。。。。。。
总结为代码就是:
public static int nthUglyNumber(int n) { if(n <= 0){ return 0; } List<Integer> result = new ArrayList<Integer>(); result.add(1); int a = 0, b = 0, c = 0; while (result.size() < n){ int next = min(result.get(a) * 2,min(result.get(b)*3, result.get(c)*5)); result.add(next); if(result.get(a) * 2 == next) a++; if(result.get(b) * 3 == next) b++; if(result.get(c) * 5 == next) c++; } return result.get(n - 1); } static int min(int n,int m) { if(n >= m){ n =m; } return n; }