▶ 三个与丑数相关的问题

▶ 第 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. PowerDesigner16工具学习笔记-建立BPM

    根据不同用途,BPM分为分析性(Analysis).执行型(Executable)和协作型(Collaborative) BPM的类型 业务流程语言 描述  分析型  Analysis  提供流程层次 ...

  2. Powerdesigner颜色设置

    Powerdesigner颜色设置    

  3. 16Aspx源码论坛

    16Aspx源码论坛: http://bbs.16aspx.com/index.aspx

  4. 在centos7下安装java8和mysql

    一般学习java和部署项目都是在本地部署,但是生产环境一般都是在linux环境下,部署和安装环境都是在控制台下进行操作的,没有windows的可视化的操作界面,对与linux的命令掌握和操作对小白来说 ...

  5. Build Tree View Structure for SharePoint List Data

    博客地址 http://blog.csdn.net/foxdave 此文参考自->原文链接 版权归原作者所有,我只是进行一下大致的翻译 应坛友要求,帮助验证一下功能. SharePoint列表数 ...

  6. myeclipse单步调试

    如何进行myclipse的单步调式与跟踪?希望大虾们详细点,多谢. 打断点,然后运行,进debug试图,按F6执行一行,按F5是钻进去执行 追问 朋友,能详细点吗? 本人是初学 回答 如图 如若成功请 ...

  7. Leetcode 1022. Sum of Root To Leaf Binary Numbers

    dfs class Solution: def sumRootToLeaf(self, root: TreeNode) -> int: stack=[(root,0)] ans=[] bi_st ...

  8. adb命令安装apk

    1.将需要安装的apk放在platform-tools下 2.将手机和电脑连接,在cmd中输入 adb devices查看 3.使用adb命令安装apk,在cmd中输入:adb install apk ...

  9. C# 序列化详解,xml序列化,json序列化对比

    本文讲讲一些纯技术的东西.并且讲讲一些原理性的东西,和一般的百度的文章不一致,如果你对序列化不清楚,绝对可以很有收获. 技术支持QQ群(主要面向工业软件及HSL组件的):592132877  (组件的 ...

  10. matlab 将一堆文件名读到一个文本里面windows版本里

    有点坑: 在windows下,这么写,打印时也会把\n当成字符串打印出来 path= strcat('/home/wang/Desktop/trainset/num0/',file(i).name,' ...