剑指offer:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
问题:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
通俗易懂的解释:
首先从丑数的定义我们知道,一个丑数的因子只有2,3,5,那么丑数p = 2 ^ x * 3 ^ y * 5 ^ z,换句话说一个丑数一定由另一个丑数乘以2或者乘以3或者乘以5得到,那么我们从1开始乘以2,3,5,就得到2,3,5三个丑数,在从这三个丑数出发乘以2,3,5就得到4,6,10,6,9,15,10,15,25九个丑数,我们发现这种方法会得到重复的丑数,而且我们题目要求第N个丑数,这样的方法得到的丑数也是无序的。那么我们可以维护三个队列:
(1)丑数数组: 1
乘以2的队列:2
乘以3的队列:3
乘以5的队列:5
选择三个队列头最小的数2加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(2)丑数数组:1,2
乘以2的队列:4
乘以3的队列:3,6
乘以5的队列:5,10
选择三个队列头最小的数3加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(3)丑数数组:1,2,3
乘以2的队列:4,6
乘以3的队列:6,9
乘以5的队列:5,10,15
选择三个队列头里最小的数4加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(4)丑数数组:1,2,3,4
乘以2的队列:6,8
乘以3的队列:6,9,12
乘以5的队列:5,10,15,20
选择三个队列头里最小的数5加入丑数数组,同时将该最小的数乘以2,3,5放入三个队列;
(5)丑数数组:1,2,3,4,5
乘以2的队列:6,8,10,
乘以3的队列:6,9,12,15
乘以5的队列:10,15,20,25
选择三个队列头里最小的数6加入丑数数组,但我们发现,有两个队列头都为6,所以我们弹出两个队列头,同时将12,18,30放入三个队列;
……………………
疑问:
1.为什么分三个队列?
丑数数组里的数一定是有序的,因为我们是从丑数数组里的数乘以2,3,5选出的最小数,一定比以前未乘以2,3,5大,同时对于三个队列内部,按先后顺序乘以2,3,5分别放入,所以同一个队列内部也是有序的;
2.为什么比较三个队列头部最小的数放入丑数数组?
因为三个队列是有序的,所以取出三个头中最小的,等同于找到了三个队列所有数中最小的。
实现思路:
我们没有必要维护三个队列,只需要记录三个指针显示到达哪一步;“|”表示指针,arr表示丑数数组;
(1)1
|2
|3
|5
目前指针指向0,0,0,队列头arr[0] * 2 = 2, arr[0] * 3 = 3, arr[0] * 5 = 5
(2)1 2
2 |4
|3 6
|5 10
目前指针指向1,0,0,队列头arr[1] * 2 = 4, arr[0] * 3 = 3, arr[0] * 5 = 5
(3)1 2 3
2| 4 6
3 |6 9
|5 10 15
目前指针指向1,1,0,队列头arr[1] * 2 = 4, arr[1] * 3 = 6, arr[0] * 5 = 5
………………
代码:
class Solution {
public:int GetUglyNumber_Solution(int index) {// 0-6的丑数分别为0-6if(index < 7) return index;//p2,p3,p5分别为三个队列的指针,newNum为从队列头选出来的最小数int p2 = 0, p3 = 0, p5 = 0, newNum = 1;vector<int> arr;arr.push_back(newNum);while(arr.size() < index) {//选出三个队列头最小的数newNum = min(arr[p2] * 2, min(arr[p3] * 3, arr[p5] * 5));//这三个if有可能进入一个或者多个,进入多个是三个队列头最小的数有多个的情况if(arr[p2] * 2 == newNum) p2++;if(arr[p3] * 3 == newNum) p3++;if(arr[p5] * 5 == newNum) p5++;arr.push_back(newNum);}return newNum;}
};
剑指offer:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。相关推荐
- 【leetcode】 剑指 Offer学习计划(java版本含注释)(上)
目录 前言 第一天(栈与队列) 剑指 Offer 09. 用两个栈实现队列(简单) 剑指 Offer 30. 包含min函数的栈(简单) 第二天(链表) 剑指 Offer 06. 从尾到头打印链表(简 ...
- 剑指offer:丑数
题目描述 把只包含质因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含质因子7. 习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第N个丑数. 解题思 ...
- 剑指offer(26-33题)详解
文章目录 26 二叉搜索树与双向链表 27 字符串的排列 28 数字中出现次数超过一半的数字(待优化)★ 29 最小的K个数 30 连续子数组最大和 31 整数中1出现的次数 32 把数组排成最小的数 ...
- 《剑指offer》-- 把数组排成最小的数、丑数、二进制中1的个数、表示数值的字符串、替换空格
一.把数组排成最小的数: 1.题目: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为 ...
- 剑指offer之31-35题解
剑指offer之31-35题解 目录 整数中1出现的次数(从1到n整数中1出现的次数) 把数组排成最小的数 丑数 第一个只出现一次的字符位置 数组中的逆序对 31. 整数中1出现的次数(从1到n整数中 ...
- 牛客网剑指offer编程实践31-40题
31. 整数中1出现的次数(从1到n整数中1出现的次数) 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12. ...
- 剑指offer(刷题31-40)--c++,Python版本
文章目录 目录 第31 题: 解题思路: 代码实现: c++ python 第32题: 解题思路: 代码实现: c++ python 第33题: 解题思路: 代码实现: c++ python 第34题 ...
- 剑指Offer丑数问题
这是剑指第一次卡死我的题--记录一下 首先看题目: 把只包含质因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含质因子7. 习惯上我们把1当做是第一个丑数 ...
- 剑指offer 手刷python 汇总整理版本~
文章目录 0.递归&脑力 斐波那契数列 数值的n次方 二分法和牛顿迭代法求平方根 丑数 正则表达式匹配 [LeetCode#42. Trapping Rain Water 收集雨水](http ...
最新文章
- 从OpenStack Newton发布看开源云计算
- (原创)c#学习笔记05--变量的更多内容01--类型转换01--隐式转换
- 【图像超分辨率】Understanding Deformable Alignment in Video Super-Resolution
- Git分支操作与远程仓库的使用
- IOS开发之格式化日期时间
- @tap和@click的区别_计算属性---uview工作笔记001
- 8051 r0-r7 是什么
- LR11安装报错:此计算机上缺少vc2005_sp1_with_atl_fix_redist,请安装所有缺少的必要组件,然后重新运行此安装。
- 无标度网络和小世界网络的区别
- cs224n课后作业
- Excel·VBA单元格区域行列数转换函数
- windows2008R2 TSL1.0升级成1.2的解决方案
- c语言写字机器人,写字机器人(基于STM32简易实现)
- TIA博途_基于SCL语言制作模拟量输入输出全局库的具体方法
- 华为手机不小心点了始终_华为手机有一个设置,用过一次就再也离不开了,你打开了吗?...
- python三维曲面拟合_用Python拟合多项式曲面
- Python基于pyzbar、opencv、pyqt5库,实现二维码识别 gui 应用程序开发
- 裸辞接单第一个月的收入
- 【今日CV 计算机视觉论文速览 第140期】Wed, 3 Jul 2019
- 《野兽绅士》总结2——斗士都有自己的全金属外壳