263. Ugly Number + 264. Ugly Number II + 313. Super Ugly Number
▶ 三个与丑数相关的问题
▶ 第 263题,判定一个数字是否是丑数,即其素因子是否仅由 2,3,5 构成。
● 常规消除判别,4 ms
class Solution
{
public:
bool isUgly(int num)
{
if (num < )
return false;
for (; !(num % ); num /= );
for (; !(num % ); num /= );
for (; !(num % ); num /= );
return num == ;
}
};
● 递归方法,6 ms
class Solution
{
public:
bool isUgly(int num)
{
if (num < )
return false;
return judge(num);
}
bool judge(int n)
{
if (n < )
return true;
if (!(n % ))
return isUgly(n / );
else if (!(n % ))
return isUgly(n / );
else if (!(n % ))
return isUgly(n / );
return false;
}
};
▶ 第 264 题,计算第 n 个丑数。第 263 题就是个坑,不能用逐个判断的方法来找,否则超时
● 用第 263 题的方法逐个检查,计算 1352 时超时,使用递归法逐个检查也是计算 1352 时超时。
class Solution
{
public:
bool isUgly(int num)
{
if (num < )
return false;
for (; !(num % ); num /= );
for (; !(num % ); num /= );
for (; !(num % ); num /= );
return num == ;
}
int nthUglyNumber(int n)
{
int i, count;
for (i = , count = ; count < n; i++)
{
if (isUgly(i))
count++;
}
return i - ;
}
};
● 筛法,空间开销爆炸,丑数的增长速度远小于自然数的增长速度
class Solution
{
public:
int nthUglyNumber(int n)
{
if (n < )
return n;
vector<bool>table(n * , false);
int i, count;
for (i = ; i < ; table[i++] = true);// 1 ~ 6 都是丑数,table[0] 闲置
for (; i < n * ; i++)
table[i] = !(i % ) && table[i / ] || !(i % ) && table[i / ] || !(i % ) && table[i / ];
for (i = ,count = ; i < n * && count < n; i++)
{
if (table[i])
count++;
}
return i - ;
}
};
● 代码,8 ms,正解,每次从已经有的丑数中选出三个来分别乘以 2,乘以 3,乘以 5,谁最小就收录为新的丑数,同时选取的指针向大端移动一格
class Solution
{
public:
int nthUglyNumber(int n)
{
if (n < )
return n;
vector<int> table(n);
int i, t2, t3, t5;
for (i = table[] = , t2 = t3 = t5 = ; i < n; i++)
{
table[i] = min(table[t2] * , min(table[t3] * , table[t5] * ));
if (table[i] == table[t2] * )
t2++;
if (table[i] == table[t3] * )
t3++;
if (table[i] == table[t5] * )
t5++;
}
return table[n - ];
}
};
● 代码,41 ms,使用优先队列,每次将出队的丑数的 2 倍,3 倍,5 倍分别入队,排在后边备选
class Solution
{
public:
int nthUglyNumber(int n)
{
if (n == )
return ;
priority_queue<int, vector<int>, greater<int>> q;
int i, temp;
for (i = , q.push(); i < n; i++)
{
for (temp = q.top(), q.pop(); !q.empty() && q.top() == temp; q.pop());// 删除队头等值重复
if (temp <= 0x7fffffff / )
q.push(temp * );
if (temp <= 0x7fffffff / )
q.push(temp * );
if (temp <= 0x7fffffff / )
q.push(temp * );
}
return q.top();
}
};
● 代码,计算不超过一个给定的正整数的丑数的个数,再对所求第 n 个丑数进行二分搜索,计算 1600 时超时。
■ 重要的点:
class Solution
{
public:
int nums5(int val)// 计算不超过 val 的正整数中形如 5^p 的数字个数
{
int n = ;
for (n = ; val >= ; n++, val /= );
return n;
}
int nums35(int val)// 计算不超过 val 的正整数中形如 3^q × 5^p 的数字个数
{
int n;
for (n = ; val >= ; n += + nums5(val), val /= );
// 第 k 次循环时向 n 增添 3^(k-1) (一个)及形如 3^(k-1) × 5^p 的数字个数(等价于 val / 3^(k-1) 中形如 5^p 的数字个数)
return n;
}
int nums235(int val)// 计算不超过 val 的正整数中形如 2^r × 3^q × 5^p 的数字个数(丑数个数)
{
int n;
for (n = ; val >= ; n += + nums35(val), val /= );
// 第 k 次循环时向 n 增添 2^(k-1) (一个)及形如 2^(k-1) × 3^q × 5^p 的数字个数(等价于 val / 2^(k-1) 中形如 3^q × 5^p 的数字个数)
return n;
}
int nthUglyNumber(int n)//用二分法查找第 n 个丑数,若 ≤ x 的丑数个数是 n,而 ≤ x - 1 的丑数个数是 n - 1,则 x 就是第 n 个丑数
{
if (n < )
return n;
n--; // 之后的算法中认为 2 是第一个丑数
int valLp, numLp, valRp, numRp, valMp, numMp;
for (valLp = , valRp = , numLp = , numRp = ; numRp < n; valLp = valRp, numLp = numRp, valRp = valLp * , numRp = nums235(valRp));
// 不断扩大扩大搜索范围,使得在 [ valLp, valRp ] 范围内有 [ numLp, numRp ] 个丑数,valRp = 2 × valLp,numLp ≤ n ≤ numRp
if (numRp == n) // 恰好碰到了上限
return valRp;
for(valMp = (valLp + valRp) / ;; valMp = (valLp + valRp) / )
{
numMp = nums235(valMp);
if (valRp == valMp + && numMp == n - && numRp == n)// val 和 num 在 Mp 和 Rp 之间都有跳跃,Rp 即为所求
return valRp;
if (valMp == valLp + && numLp == n - && numMp == n)// val 和 num 在 Lp 和 Mp 之间都有跳跃,Mp 即为所求
return valMp;
if (numMp >= n) // Mp 偏大
valRp = valMp, numRp = numMp;
else // Mp 偏小
valLp = valMp, numLp = numMp;
}
}
};
▶ 第 313 题,扩展丑数,将上述限制条件 “素因子仅由 2,3,5 构成” 改为素因子由一个数组指定,仍然要求第 n 个丑数。
● 代码,31 ms,将上述选最小的方法进行扩展
class Solution
{
public:
int nthSuperUglyNumber(int n, vector<int>& primes)
{
const int m = primes.size();
vector<int> table(n), count(m, );
int i, j, minValue;
for (i = table[] = ; i < n; table[i++] = minValue)
{
for (j = , minValue = 0x7fffffff; j < m; j++)
{
if (minValue > primes[j] * table[count[j]])
minValue = primes[j] * table[count[j]];
}
for (j = ; j < m; j++)
{
if (minValue == primes[j] * table[count[j]])
count[j]++;
}
}
return table[n - ];
}
};
● 大佬的代码,20 ms,基本相同的算法,优化了循环过程
class Solution
{
public:
int nthSuperUglyNumber(int n, vector<int>& primes)
{
vector<int> ugly(n, ), ind(primes.size(), ), val(primes.size(), );
int i, j, next;
for (i = , ugly[] = ; i < n; ugly[i++] = next)
{
for (j = , next = INT_MAX; j < primes.size(); j++)
{
if (val[j] == ugly[i - ])
val[j] = ugly[ind[j]++] * primes[j];
next = next < val[j] ? next : val[j];
}
}
return ugly[n - ];
}
};
263. Ugly Number + 264. Ugly Number II + 313. Super Ugly Number的更多相关文章
- leetcode 263. Ugly Number 、264. Ugly Number II 、313. Super Ugly Number 、204. Count Primes
263. Ugly Number 注意:1.小于等于0都不属于丑数 2.while循环的判断不是num >= 0, 而是能被2 .3.5整除,即能被整除才去除这些数 class Solution ...
- [LeetCode] 313. Super Ugly Number 超级丑陋数
Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all ...
- Leetcode 313. super ugly number
Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all ...
- 313. Super Ugly Number
题目: Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose ...
- [LeetCode]313. Super Ugly Number超级丑数,丑数系列看这一道就行了
丑数系列的题看这一道就可以了 /* 和ugly number2差不多,不过这次的质因子多了,所以用数组来表示质因子的target坐标 target坐标指的是这个质因子此次要乘的前任丑数是谁 */ pu ...
- 313 Super Ugly Number 超级丑数
编写一段程序来寻找第 n 个超级丑数.超级丑数是指其所有质因数都在长度为k的质数列表primes中的正整数.例如,[1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] ...
- 【leetcode】313. Super Ugly Number
题目如下: 解题思路:总结一下这么几点,一出一进,优先级队列排序,保证每次输出的都是当前的最小值.解法大致如图: 代码如下: #include<map> #include<queue ...
- Leetocde的两道丑数题目:264. 丑数 II➕313. 超级丑数
Q: A: 用变量记录已经✖2.✖3.✖5的元素下标i2.i3.i5.表示截止到i2的元素都已经乘过2(结果添加到序列尾部的意思),i3.i5同理.这样每次可以循环可以O(1)时间找到下一个最小的丑数 ...
- Leetcode之动态规划(DP)专题-264. 丑数 II(Ugly Number II)
Leetcode之动态规划(DP)专题-264. 丑数 II(Ugly Number II) 编写一个程序,找出第 n 个丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示例: 输入: n ...
随机推荐
- C# DataTable Compute方法的使用
在开发中需要对DataTable的数据进行处理,比如累加,求最大最小及平均值等,以前都采用手工对DataTable进行循环并计算的方式,现在发现DataTable的Compute方法可以轻松实现这些功 ...
- 2018HN多校
http://acm.hi-54.com/contest_problemset.php?cid=1455 A : 摩斯密码 概览问题列表状态排名 Progress Bar 时间限制:1 Sec 内存限 ...
- spring boot 使用velocity模板(十六)
(不要使用这种模板了,spring boot最新版已经不支持了.使用FreeMarker吧:http://blog.csdn.net/clementad/article/details/5194262 ...
- Work Queues(点对多)
Work Queues(点对多) 多个消费者在同一个消息队列中获取消息的情况.在有些应用当中,消费端接收到消息任务需要长时间的处理,如果等上一个消息处理完成以后再取下一个数据进行处理的话,势必会有一些 ...
- [转载]字符串匹配的KMP算法
作者: 阮一峰 日期: 2013年5月 1日 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另 ...
- cx_oracle 安装和配置
前提条件: 已经成功安装python 已经成功安装oracle客户端 1.去官网上下载对应版本的cx_oracle http://cx-oracle.sourceforge.net/ 注意版本必须与p ...
- 『转』三星推出Android智能手表Galaxy Gear
苹果定下来本月10日召开新品发布会,而它的竞争对手三星却抢先一步.今天凌晨,三星在德国柏林一口气发布了三款重量级产品.三星智能手表Galaxy Gear最引人关注,其将于9月25日陆续在全球上市,售价 ...
- 【linux】查看进程
查询所有:ps aux 查询某个用户:ps -u abc 终止某个进程:kill
- MySQL 服务正在启动 .MySQL 服务无法启动。系统出错。发生系统错误 1067。进程意外终止。
MySQL 服务正在启动 .MySQL 服务无法启动.系统出错.发生系统错误 1067.进程意外终止. 检查了一个晚上才发现是---配置问题 #Path to installation directo ...
- antd中form自定义rules
1.使用getFieldDecorator <FormItem label="手机号" > {getFieldDecorator('phone', { initialV ...