题目描述
把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
直接去使用遍历循环是不可以的,其时间太久,通过观察一个丑数必定是由另外一个丑数得来。
使用一个数组,里面放都是丑数,数组后面的数必定是前面的数乘以2,3,5得来的,关键就是确保数组里的丑数是有序的,
以下是构建有序丑数序列的算法:
我们把现有的最大丑数记做M。现在我们来生成下一个丑数,该丑数肯定是前面某一个丑数乘以2、3或者5的结果。
我们考虑记录2、3、5的对所求数组位置的元素的乘积,把已有的每个丑数乘以2、3、5。由于我们是按照顺序生成的,小于或者等于M肯定已经在数组中了,我们不需再次考虑;我们还会得到若干个大于M的结果,但我们只需要第一个大于M的结果,因为我们希望丑数是按从小到大顺序生成的,其他更大的结果我们以后再说。我们把得到的第一个乘以2后大于M的结果,记为M2。
同样我们把已有的每一个丑数乘以3和5,能得到第一个大于M的结果M3和M5。那么下一个丑数应该是M2、M3和M5三个数的最小者。
细节处理: 1、注意从一开始,对数组下标和具体数的对应关系;
2、注意对丑数进行确定后,像6=3*2,6=2*3这种的处理,这里需要同时对2和3的要乘的数组的元素后移;
3、但是需要在起初初始化一个很大的数组,空间换取了时间的效率;
扫描二维码关注公众号,回复:
1692629 查看本文章
import java.util.*; public class Solution { public int GetUglyNumber_Solution(int index) { if(index<=0) return 0; int[] result = new int[index]; int count = 0; int i2 = 0; int i3 = 0; int i5 = 0; result[0] = 1; int tmp = 0; while (count < index-1) { tmp = min(result[i2] * 2, min(result[i3] * 3, result[i5] * 5)); if(tmp==result[i2] * 2) i2++;//三条if防止值是一样的,不要改成else的 if(tmp==result[i3] * 3) i3++;//这里的必须有这个判断,否则重复记录 if(tmp==result[i5] * 5) i5++; result[++count]=tmp; } return result[index - 1]; } private int min(int a, int b) { return (a > b) ? b : a; } }