[LeetCode] Ugly Number II

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.

 

分析:根据丑数的定义,丑数应该是另一个丑数乘以2、3和或者5的结果(1除外)。因此我们可以创建一个数组,里面的数字是排好序的丑数,每一个丑数都是前面的丑数乘以2、3或者5得到的。

     这种思路的关键在于怎样确保数组里面的丑数是排好序的。假设数组中已经有若干个丑数排好序后存放在数组中,并且把已有的最大的丑数记作M,接下来分析如何生成最大的丑数。该丑数肯定是前面某一个丑数乘以2,3或者5的结果,所以我们首先考虑把已经有的每个丑数乘以2。在乘以2的时候,能得到若干个小于或者等于M的结果。由于是按照顺序生成的,小于或者等于M肯定已经在数组中了,我们不需再次考虑;还会得到若干个大于M的结果,但我们只需要第一个大于M的结果,因为我们希望丑数是按照从小到大的顺序生成的,其他更大的结果以后再说。我们把得到的第一个乘以2后大于M的结果记为M2.同样,,我们把已有的每个丑数乘以3和5能得到第一个大于M的结果M3和M5.那么下一个丑数应该是M2,M3和M5这3个数字最小者。

     前面分析的时候,提到把已有的每个丑数分别乘以2、3和5.事实上这不是必须的,因为已有的丑数是按顺序存放在数组中的。对乘以2而言,肯定存在某一个丑数T2,排在它之前的每一个丑数乘以2得到的结果都会太大。我们只需记下这个丑数的位置,同时每次生成新的丑数的时候,去更新这个T2。对乘以3和5而言,也存在着同样的T3和T5.

相关题目:《剑指offer》面试题34

 

 1 class Solution {
 2 public:
 3     int nthUglyNumber(int n) {
 4         if (n <= 0) return -1;
 5         vector<int> nums(n, 1);
 6         int i2 = 0, i3 = 0, i5 = 0;
 7         for (int i = 1; i < n; i++) {
 8             nums[i] = min(nums[i2] * 2, min(nums[i3] * 3, nums[i5] * 5));
 9             
10             if (nums[i2] * 2 <= nums[i])
11                 i2++;
12             if (nums[i3] * 3 <= nums[i])
13                 i3++;
14             if (nums[i5] * 5 <= nums[i])
15                 i5++;
16         }
17         
18         return nums[n-1];
19     }
20 };

 

posted @ 2015-09-20 08:55  vincently  阅读(184)  评论(0编辑  收藏  举报