▶ 三个与丑数相关的问题

▶ 第 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. 递归--练习2--noi6261汉诺塔

    递归--练习2--noi6261汉诺塔 一.心得 先把递推公式写出来,会很简单的 二.题目 6261:汉诺塔问题 总时间限制:  1000ms 内存限制:  65536kB 描述 约19世纪末,在欧州 ...

  2. ORA-12505: TNS: 监听程序当前无法识别连接描述符中所给出的SID等错误解决方法

    程序连接orarle报ORA-12505错误 一.异常{ ORA-12505, TNS:listener does not currently know of SID given in connect ...

  3. js获取当前日期(年月日格式)

    function getNowFormatDate() { var date = new Date(); var seperator1 = "-"; var year = date ...

  4. 【hive】count() count(if) count(distinct if) sum(if)的区别

    表名: user_active_day (用户日活表) 表内容: user_id(用户id)   user_is_new(是否新用户 1:新增用户 0:老用户) location_city(用户所在地 ...

  5. Newtonsoft.Json JsonHelper

    Json.net 简单封装 using System; using System.Linq; using Newtonsoft.Json; using Newtonsoft.Json.Serializ ...

  6. (UDP)socket编程

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  7. iOS-----MFMessageCompose 和 MFMailComposeViewController的使用方法

    MFMessageCompose 和 MFMailComposeViewController的使用方法 使用MFMessageComposeViewCOntroller发短信 应用想自己提供界面让用户 ...

  8. train validation test

    http://stats.stackexchange.com/questions/19048/what-is-the-difference-between-test-set-and-validatio ...

  9. 获取bing带swim的网址列表

    需求背景: 应老婆要求,搜集带有swim关键字的网站.实现过程: 使用requests模块通过bing接口搜索swim关键,将返回内容按需求进行处理,得到网站列表. 注:代码比较拙,老司机就不要弄废时 ...

  10. gpio_get_value的定义 (转)

    gpio_get_value等一系列函数,并非Linux标准函数,而是跟硬件相关的. 通常我们说的driver都是跟外围设备相关的,所以需要我们自己开发,但是这次我们说到的gpio是跟soc相关的,其 ...