您的位置:首页 > 编程语言 > C语言/C++

【LeetCode从零单刷】Ugly Number I, II & Super Ugly Number

2015-10-11 10:17 477 查看
I 题目:

Write a program to check whether a given number is an ugly number.

Ugly numbers are positive numbers whose prime factors only include 
2, 3, 5
. For example, 
6,
8
 are ugly while 
14
 is not ugly since it includes another prime factor 
7
.

Note that 
1
 is typically treated as an ugly number.
解答:

如果某个数是丑数,那么它一定可以不断被 2 或者 3 或者 5 整除,然后除以之后的结果依然满足丑数的条件

不断循环,直到这个数不再变化。此时如果是 1 则是丑数,否则不是。

class Solution {
public:
bool isUgly(int num) {
if(num == 1 || num == 2 || num == 3 || num == 5)    return true;

int tmp = 0;
while(tmp != num)
{
tmp = num;
if(num % 2 == 0)    num = num / 2;
if(num % 3 == 0)    num = num / 3;
if(num % 5 == 0)    num = num / 5;
}

if(tmp == 1)
return true;
else
return false;
}
};

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.

解答:
查看 hint,可以知道每个出现在序列中的数,都是前面某个数乘以系数2,3或5之后的结果

于是,记录上一次乘以2,3或5之前的那个数pos2, pos3, pos5,然后比较乘以系数之后的结果的最小值,放在这个序列。然后即时更新pos2, pos3, pos5。

这是我第一个版本的错误代码:

class Solution {
public:
int nthUglyNumber(int n) {
if(n <= 0)  return 0;
int* nums = new int[n + 1]; nums[0] = 0; nums[1] = 1;
int pos2, pos3, pos5; pos2 = pos3 = pos5 = 1;
for(int i = 2; i <= n; i++) {
if(nums[pos2]*2 <= nums[pos3]*3 && nums[pos2]*2 <= nums[pos5]*5) {
nums[i] = nums[pos2]*2;
pos2 = i;
}
else if(nums[pos3]*3 <= nums[pos2]*2 && nums[pos3]*3 <= nums[pos5]*5) {
nums[i] = nums[pos3]*3;
pos3 = i;
}
else {
nums[i] = nums[pos5]*5;
pos5 = i;
}
}
return nums
;
}
};
这个版本的错误在于:

更新pos2, pos3, pos5。正确的思路是:每个出现在序列中的数,都是前面某个数(不一定是平方数)乘以系数2,3或5之后的结果。每次更新为 i 只能保留序列中的数是平方数。正确的做法,应该是在上一次的位置依次后移一位,表示原有位置已经取过
没有去重。会产生 1,2,3,4,5,6,6……6 = 2*3 = 3*2 重复取值;
修改之后的 AC 版本:

class Solution {
public:
int nthUglyNumber(int n) {
if(n <= 0)  return 0;
int* nums = new int[n + 1]; nums[0] = 0; nums[1] = 1;
int pos2, pos3, pos5; pos2 = pos3 = pos5 = 1;
for(int i = 2; i <= n; i++) {
if(nums[pos2]*2 <= nums[pos3]*3 && nums[pos2]*2 <= nums[pos5]*5) {
nums[i] = nums[pos2]*2;
pos2 ++;
if(nums[i] % 3 == 0) pos3 ++;
if(nums[i] % 5 == 0) pos5 ++;
}
else if(nums[pos3]*3 <= nums[pos2]*2 && nums[pos3]*3 <= nums[pos5]*5) {
nums[i] = nums[pos3]*3;
pos3 ++;
if(nums[i] % 2 == 0) pos2 ++;
if(nums[i] % 5 == 0) pos5 ++;
}
else {
nums[i] = nums[pos5]*5;
pos5 ++;
if(nums[i] % 2 == 0) pos2 ++;
if(nums[i] % 3 == 0) pos3 ++;
}
}
return nums
;
}
};


Super Ugly Number

Write a program to find the nth super ugly number.

Super ugly numbers are positive numbers whose all prime factors are in the given prime list
primes
of size
k
. For example,
[1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32]
is the sequence of the first 12 super ugly numbers given
primes
=
[2, 7, 13, 19]
of size 4.

Note:

(1)
1
is a super ugly number for any given
primes
.

(2) The given numbers in
primes
are in ascending order.

(3) 0 <
k
≤ 100, 0 <
n
≤ 106, 0 <
primes[i]
< 1000.

解答:

思路与上一题相同。不过,此时优化了一下,不需要每次取整,而是更准确的判断潜在乘积而去重:

class Solution {
public:
int nthSuperUglyNumber(int n, vector<int>& primes) {
int k = primes.size();
vector<int> pos(k, 0);
vector<int> ugly(n, INT_MAX);
ugly[0] = 1;

for(int i = 1; i< n; i++)
{
for(int j = 0; j < k; j++)
ugly[i] = (ugly[i] < ugly[pos[j]] * primes[j]) ? ugly[i] : (ugly[pos[j]] * primes[j]);

for(int j = 0; j < k; j++)
if(ugly[i] == ugly[pos[j]] * primes[j]) pos[j]++;
}
return ugly[n - 1];
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ leetcode ugly number