面试题 丑数(10)
# 面试题: 丑数
题目: 我们把只包含因子 2,3和5的数称为丑数。求按从小到大的顺序的第1500个丑数,
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>int Number_Chou(int num)
{while(num%2 == 0)num /= 2;while(num%3 == 0)num /= 3;while(num%5 == 0)num /= 5;return (num == 1) ? 1:0;//最后商为1则返回;
}int Search_Chou(int num)
{int count = 0;int steps = 0;if(num <= 0)return 0;while(count < num){++steps;//当前操作数if(Number_Chou(steps))count++;//丑数个数}return steps;
}int main()
{int start = GetTickCount();//计时函数int end = 0;int num = 1500;int ret = Search_Chou(num);end = GetTickCount();printf("所用时间:%d秒\n\n所求丑数为:%d\n\n",(end - start)/1000,ret);system("pause");return 0;
}
如前所述,我们发现采用遍历法求第K个丑数的效率十分低下,我们在前面求第1500个丑数花去了33秒的时间,这还
是在我I7 3770K的电脑上运行的。所以我们考虑有没有一种更加高效的方法。在面试题9:斐波那契数列中我们使用
了一种“用空间还时间”的方法来提高求斐波那契数列的速度。这种编程思想也可以应用在这道题目当中,我们为所有求出的丑数创建数组,不在非丑数上面浪费时间。
根据丑数的定义,我们可以知道丑数可以由另外一个丑数乘以2,3或者5得到。因此我们创建一个数组,里面的数字
是排好序的丑数,每一个丑数都是前面的丑数乘以2,3或者5得到的。这种思路的关键在于怎样确保数组里面的数字
是排序的。
假设丑数数组中已经有若干个排好序的丑数,比如1,2,3,4,5。我们把当前丑数数组中的最大数记为M,这里
M=5。我们接下来分析如何生成下一个丑数。根据前面的介绍,我们知道这个丑数肯定是前面丑数数组中的数字乘以
2,3,5得到的。所以我们首先考虑把已有的每个丑数乘以2,在乘以2的时候,能够得到若干个小于或者等于M的结
果。由于是按照顺序生成的,小于或者等于M的数肯定已经在丑数数组当中了,我们不需要再次考虑;当然还会得到
若干大于M的结果,但是我们只需要第一个大于M的结果,因为我们希望丑数是按顺序排列的,所以其他更大的结果
可以以后考虑。我们把得到的第一个乘以2以后得到的大于M的结果记为M2。同样,我们把已有的每一个丑数乘以3和
5,能得到第一个大于M的结果M3和M5。那么M后面的那一个丑数应该是M2,M3和M5当中的最小值:Min
(M2,M3,M5)。比如将丑数数组中的数字按从小到大乘以2,直到得到第一个大于M的数为止,那么应该是2*2=4<M,
3*2=6>M,所以M2=6。同理,M3=6,M5=10。所以下一个丑数应该是6。
前面分析的时候,提到把已有的每个丑数分别都乘以2,3和5。事实上这不是必须的,因为已有的丑数是按顺序存放
在数组中的,对乘以2而言,肯定存在某一个丑数T2,排在它之前的每一个丑数乘以2得到的结果都会小于等于(<=)已
有最大的丑数,在它之后的每一个丑数乘以2得到的结果都会大于已有的最大丑数。因此我们只需要记下这个丑数的
位置,同时每次生成新的丑数的时候去更新这个T2。对于乘以3和5,同样存在这样的T3和T5。
#基于上面的思路我们有可以写下面的代码:
#include<stdio.h>
#include<stdlib.h>int Min(int num1,int num2,int num3)
{int min = (num1 < num2) ? num1 : num2;min = (min < num3) ? min : num3;return min;
}int Search_Chou(int num)
{int ret = 0;int change = 1;int min = 0;int *ob2 = NULL;int *ob3 = NULL;int *ob5 = NULL;int *ptr = (int *)malloc(num*sizeof(int));if(ptr == NULL)printf("out of memery\n");if(num<0)return 0;ptr[0] = 1;ob2 = ptr;ob3 = ptr;ob5 = ptr;while(change < num){min = Min((*ob2)*2,(*ob3)*3,(*ob5)*5);ptr[change] = min;//最小的放进去while((*ob2)*2 <= ptr[change])//注意这里都是小于等于++ob2;//记录当前位置while((*ob3)*3 <= ptr[change])++ob3;//记录当前位置while((*ob5)*5 <=ptr[change])++ob5;//记录当前位置++change;}ret = ptr[change - 1];//注意返回值的下标;free(ptr);//记得释放ptr = NULL;return ret;
}int main()
{int num = 1500;int ret = 0;ret = Search_Chou(num);printf("所求丑数为:%d\n",ret);system("pause");return 0;
}
#结果瞬间出来,效率可见一斑;
# 基于上述思路,在下面列出一种便于理解的代码,与上述思路一样,作为参考;
int Search_Chou()
{int num[]=new int[1501]; num[0] = 0; num[1] = 1; int two = 0,three = 0,five = 0;//刚好大于现有最大丑数的三个 for(int i = 1; i <= 1499; i++){//每次找出一个丑数 for(int j = 1; j <= i ; j++)//从头向后扫描,若某数的两倍刚好大于上回找出的丑数,将它值记录下来 if((2*num[j-1] <= num[i])&&(2*num[j] > num[i])) two=num[j]*2; for(int j = 1; j <= i ; j++)//从头向后扫描,若某数的三倍刚好大于上回找出的丑数,将它值记录下来 if((3*num[j-1] <= num[i])&&(3*num[j] > num[i])) three=num[j]*3; for(int j = 1; j <= i ; j++)//从头向后扫描,若某数的五倍刚好大于上回找出的丑数,将它值记录下来 if((5*num[j-1] <= num[i])&&(5*num[j] > num[i])) five=num[j]*5; //比较出三个数中最小的 if(two>=three&&five>=three) num[i+1] = three; else if(two>=five&&three>=five) num[i+1] = five; else if(five>=two&&three>=two) num[i+1] = two; } return num[i+1];
}
@ 关于丑数这个神奇的概念就说到这里,在这里给大家推荐一本书《编程之美》,里面的解体思路都是由简入深,非
常适合培养我们的解题思路!
Ps: 爱拼才会赢!
Thanks!
面试题 丑数(10)相关推荐
- java---面试题 丑数
时间限制:1秒 空间限制:32768K 题目描述 把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含因子7. 习惯上我们把1当做是第一个丑数.求按 ...
- 剑指Offer49—丑数
剑指Offer49-丑数 题意 我们把只包含质因子 2.3 和 5 的数称作丑数(Ugly Number).求按从小到大的顺序的第 n 个丑数. 丑数即只能被 2.3.5 整除.判断一个数是不是丑数的 ...
- 【IT笔试面试题整理】丑数
[试题描述]我们把只包含因子2.3和5的数称作丑数.求按从到大的顺序的第1500个丑数.例如6,8是丑数,而14不是,因为它包含因子7.习惯上把1当作第一个丑数. 根据丑数的定义,丑数应该是另一个丑数 ...
- 输入一个数寻找丑数C语言,数据结构与算法试题80道.doc
数据结构与算法试题80道 由于这些题,实在太火了.所以,应广大网友建议要求,在此把之前已整理公布的前80题, 现在,一次性分享出来.此也算是前80题第一次集体亮相. 此些题,已有上万人,看到或见识到, ...
- 程序员面试题精选100题(37)-寻找丑数[算法]
题目:我们把只包含因子 2. 3和 5的数称作丑数(Ugly Number).例如 6. 8都是丑数,但 14不是,因为它包含因子 7.习惯上我们把 1当做是第一个丑数.求按从小到大的顺序的第 150 ...
- 面试题之丑数的C++实现求解(孤陋寡闻了,才知道丑数这么high的东东)
问题描述: 我们把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第1500个丑数.( ...
- [剑指offer]面试题34:丑数
面试题34:丑数 题目:我们把只包含因子2.3和5的数称作丑数(Ugly Number).求按从小到大的顺序的第1500个丑数.例如6.8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当做第一 ...
- 【剑指offer】面试题49:丑数
我们把只包含因子 2.3 和 5 的数称作丑数(Ugly Number).求按从小到大的顺序的第 n 个丑数. 示例: 输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, ...
- 剑指offer 面试题49. 丑数
我们把只包含因子 2.3 和 5 的数称作丑数(Ugly Number).求按从小到大的顺序的第 n 个丑数. 示例: 输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, ...
- 剑指offer——面试题34:丑数
剑指offer--面试题34:丑数 Solution1: 最容易想到的,也是最不可能AC的 class Solution {public:int GetUglyNumber_Solution(int ...
最新文章
- asp.net mvc 简易上传功能
- C#中的{n}运算符
- Java反射最佳实践
- 0227互联网新闻 | 腾讯与英特尔联合推出云游戏平台“腾讯即玩”;华为企业业务MWC现场发布数字平台...
- 五分钟没有操作自动退出_智阅云自动阅读器app下载-智阅云自动阅读器app安卓版下载v1.0...
- XAML实例教程系列 - 命名空间(NameSpace) 三
- 给SAP云平台的global账号添加Leonardo机器学习服务
- Coursera自动驾驶课程第18讲:The Planning Problem
- 疲劳驾驶样本集_谷歌AI最新3D数据集,1.5万张动图,让AR主宰你的生活
- NSIS UI 美化类插件分享
- 晚上没有路灯,我骑的很慢
- 低代码和零代码火了,十大利器推荐!
- HTML input控件
- Redis实现邮件激活码保存
- java/php/net/python城市管理综合执法系统设计
- layabox 打印_Layabox 集成指南
- 用互联网大脑模型分析滴滴的战略意图和战术失误
- Qt三方库开发技术:二维码生成、识别以及条码识别
- js 数据类型之字符串
- 就业协议服务器是什么意思,什么是就业协议
热门文章
- EasyCVR平台如何实现超低延时的安防视频监控直播?
- Xcom传送文件实例
- Idea字体美化终极解决方案
- Referenced file contains errors解决
- 关于错误local variable ‘str‘ referenced before assignment
- github图书馆座位预约_我们在Github上分析了60,678个图书馆–这是前100名
- 矩阵键盘——按下矩阵按键,数码管显示出位置对应的字符(0123 4567 89Ab CdEF)
- 1050: 找出直系亲属
- lncRNA数据分析专题
- win7浏览器主页修改不过来_win7系统浏览器主页修改不了的解决方法