▶ 三个与丑数相关的问题

▶ 第 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的更多相关文章

  1. 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 ...

  2. [LeetCode] 313. Super Ugly Number 超级丑陋数

    Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all ...

  3. Leetcode 313. super ugly number

    Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose all ...

  4. 313. Super Ugly Number

    题目: Write a program to find the nth super ugly number. Super ugly numbers are positive numbers whose ...

  5. [LeetCode]313. Super Ugly Number超级丑数,丑数系列看这一道就行了

    丑数系列的题看这一道就可以了 /* 和ugly number2差不多,不过这次的质因子多了,所以用数组来表示质因子的target坐标 target坐标指的是这个质因子此次要乘的前任丑数是谁 */ pu ...

  6. 313 Super Ugly Number 超级丑数

    编写一段程序来寻找第 n 个超级丑数.超级丑数是指其所有质因数都在长度为k的质数列表primes中的正整数.例如,[1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] ...

  7. 【leetcode】313. Super Ugly Number

    题目如下: 解题思路:总结一下这么几点,一出一进,优先级队列排序,保证每次输出的都是当前的最小值.解法大致如图: 代码如下: #include<map> #include<queue ...

  8. Leetocde的两道丑数题目:264. 丑数 II➕313. 超级丑数

    Q: A: 用变量记录已经✖2.✖3.✖5的元素下标i2.i3.i5.表示截止到i2的元素都已经乘过2(结果添加到序列尾部的意思),i3.i5同理.这样每次可以循环可以O(1)时间找到下一个最小的丑数 ...

  9. Leetcode之动态规划(DP)专题-264. 丑数 II(Ugly Number II)

    Leetcode之动态规划(DP)专题-264. 丑数 II(Ugly Number II) 编写一个程序,找出第 n 个丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示例: 输入: n ...

随机推荐

  1. C# DataTable Compute方法的使用

    在开发中需要对DataTable的数据进行处理,比如累加,求最大最小及平均值等,以前都采用手工对DataTable进行循环并计算的方式,现在发现DataTable的Compute方法可以轻松实现这些功 ...

  2. 2018HN多校

    http://acm.hi-54.com/contest_problemset.php?cid=1455 A : 摩斯密码 概览问题列表状态排名 Progress Bar 时间限制:1 Sec 内存限 ...

  3. spring boot 使用velocity模板(十六)

    (不要使用这种模板了,spring boot最新版已经不支持了.使用FreeMarker吧:http://blog.csdn.net/clementad/article/details/5194262 ...

  4. Work Queues(点对多)

    Work Queues(点对多) 多个消费者在同一个消息队列中获取消息的情况.在有些应用当中,消费端接收到消息任务需要长时间的处理,如果等上一个消息处理完成以后再取下一个数据进行处理的话,势必会有一些 ...

  5. [转载]字符串匹配的KMP算法

    作者: 阮一峰 日期: 2013年5月 1日 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另 ...

  6. cx_oracle 安装和配置

    前提条件: 已经成功安装python 已经成功安装oracle客户端 1.去官网上下载对应版本的cx_oracle http://cx-oracle.sourceforge.net/ 注意版本必须与p ...

  7. 『转』三星推出Android智能手表Galaxy Gear

    苹果定下来本月10日召开新品发布会,而它的竞争对手三星却抢先一步.今天凌晨,三星在德国柏林一口气发布了三款重量级产品.三星智能手表Galaxy Gear最引人关注,其将于9月25日陆续在全球上市,售价 ...

  8. 【linux】查看进程

    查询所有:ps aux 查询某个用户:ps -u abc 终止某个进程:kill

  9. MySQL 服务正在启动 .MySQL 服务无法启动。系统出错。发生系统错误 1067。进程意外终止。

    MySQL 服务正在启动 .MySQL 服务无法启动.系统出错.发生系统错误 1067.进程意外终止. 检查了一个晚上才发现是---配置问题 #Path to installation directo ...

  10. antd中form自定义rules

    1.使用getFieldDecorator <FormItem label="手机号" > {getFieldDecorator('phone', { initialV ...