# 面试题: 丑数

/*

题目: 我们把只包含因子 2,3和5的数称为丑数。求按从小到大的顺序的第1500个丑数,
例如 6,8 都是丑数,但是14 不是,因为它包含因子 7. 习惯上我们把1 当作第一个丑数。
*/
# 题目分析:

// 所谓丑数就是能连续被 2,3,5 整除最后得到1 的整数;
//比如 整数6是丑数,先将6连续除2,商3,如果余数为0,则继续将3除3,商1,余数为0,
//继续将1除5,商0,余1; 则6是丑数;
 
# 基于上面的思想我们可以下出下面的代码<为代码效果明显起见,都已找第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)相关推荐

  1. java---面试题 丑数

    时间限制:1秒 空间限制:32768K 题目描述 把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含因子7. 习惯上我们把1当做是第一个丑数.求按 ...

  2. 剑指Offer49—丑数

    剑指Offer49-丑数 题意 我们把只包含质因子 2.3 和 5 的数称作丑数(Ugly Number).求按从小到大的顺序的第 n 个丑数. 丑数即只能被 2.3.5 整除.判断一个数是不是丑数的 ...

  3. 【IT笔试面试题整理】丑数

    [试题描述]我们把只包含因子2.3和5的数称作丑数.求按从到大的顺序的第1500个丑数.例如6,8是丑数,而14不是,因为它包含因子7.习惯上把1当作第一个丑数. 根据丑数的定义,丑数应该是另一个丑数 ...

  4. 输入一个数寻找丑数C语言,数据结构与算法试题80道.doc

    数据结构与算法试题80道 由于这些题,实在太火了.所以,应广大网友建议要求,在此把之前已整理公布的前80题, 现在,一次性分享出来.此也算是前80题第一次集体亮相. 此些题,已有上万人,看到或见识到, ...

  5. 程序员面试题精选100题(37)-寻找丑数[算法]

    题目:我们把只包含因子 2. 3和 5的数称作丑数(Ugly Number).例如 6. 8都是丑数,但 14不是,因为它包含因子 7.习惯上我们把 1当做是第一个丑数.求按从小到大的顺序的第 150 ...

  6. 面试题之丑数的C++实现求解(孤陋寡闻了,才知道丑数这么high的东东)

    问题描述: 我们把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第1500个丑数.( ...

  7. [剑指offer]面试题34:丑数

    面试题34:丑数 题目:我们把只包含因子2.3和5的数称作丑数(Ugly Number).求按从小到大的顺序的第1500个丑数.例如6.8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当做第一 ...

  8. 【剑指offer】面试题49:丑数

    我们把只包含因子 2.3 和 5 的数称作丑数(Ugly Number).求按从小到大的顺序的第 n 个丑数. 示例: 输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, ...

  9. 剑指offer 面试题49. 丑数

    我们把只包含因子 2.3 和 5 的数称作丑数(Ugly Number).求按从小到大的顺序的第 n 个丑数. 示例: 输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, ...

  10. 剑指offer——面试题34:丑数

    剑指offer--面试题34:丑数 Solution1: 最容易想到的,也是最不可能AC的 class Solution {public:int GetUglyNumber_Solution(int ...

最新文章

  1. asp.net mvc 简易上传功能
  2. C#中的{n}运算符
  3. Java反射最佳实践
  4. 0227互联网新闻 | 腾讯与英特尔联合推出云游戏平台“腾讯即玩”;华为企业业务MWC现场发布数字平台...
  5. 五分钟没有操作自动退出_智阅云自动阅读器app下载-智阅云自动阅读器app安卓版下载v1.0...
  6. XAML实例教程系列 - 命名空间(NameSpace) 三
  7. 给SAP云平台的global账号添加Leonardo机器学习服务
  8. Coursera自动驾驶课程第18讲:The Planning Problem
  9. 疲劳驾驶样本集_谷歌AI最新3D数据集,1.5万张动图,让AR主宰你的生活
  10. NSIS UI 美化类插件分享
  11. 晚上没有路灯,我骑的很慢
  12. 低代码和零代码火了,十大利器推荐!
  13. HTML input控件
  14. Redis实现邮件激活码保存
  15. java/php/net/python城市管理综合执法系统设计
  16. layabox 打印_Layabox 集成指南
  17. 用互联网大脑模型分析滴滴的战略意图和战术失误
  18. Qt三方库开发技术:二维码生成、识别以及条码识别
  19. js 数据类型之字符串
  20. 就业协议服务器是什么意思,什么是就业协议

热门文章

  1. EasyCVR平台如何实现超低延时的安防视频监控直播?
  2. Xcom传送文件实例
  3. Idea字体美化终极解决方案
  4. Referenced file contains errors解决
  5. 关于错误local variable ‘str‘ referenced before assignment
  6. github图书馆座位预约_我们在Github上分析了60,678个图书馆–这是前100名
  7. 矩阵键盘——按下矩阵按键,数码管显示出位置对应的字符(0123 4567 89Ab CdEF)
  8. 1050: 找出直系亲属
  9. lncRNA数据分析专题
  10. win7浏览器主页修改不过来_win7系统浏览器主页修改不了的解决方法