丑数的思想
来源:互联网 发布:涨乐财富通mac版 编辑:程序博客网 时间:2024/04/28 21:24
前言
这同样是算法思想的一篇总结篇,由面试问题得来。
在leetcode上有这样一道题目:求取第n个丑数。质因子只有2,3,5的数称为丑数,比如4(2*2),9(4*2),10(2*5),14(2*7),18(2*9)…….
题目连接即解法戳这里
解法1:
暴力就不说了。
解法2:
仔细想一想,这里面所有的丑数都是由前面旧的丑数和(2或3或5)构成的。假设之前有个丑数序列为a[1],a[2],a[3],难点在于,你不知道下一个丑数,是由a[1]*5,a[2]*3,a[3]*2中哪一个,以及,a[1] * 2 或 a[1]*3或a[1]*5的乘积有没有用过。所以,维持了3个类似指针的变量p2,p3,p5,分别记录没有与2,3,5相组合的第一个位置。p2=1时,如果a[p2]*2已经用过了,那么p2++,就是说a[1]*2已经用过了,p2指向2,下次2要和a[2]进行组合了。p3,p5同理,这样就可以得到代码。下一个丑数d,一定是由a[p2]*2,a[p3]*3,a[p5]*5这些从来没有用过的代码组成的,这样就得到了核心代码。
num=1;ugly[0]=1; while(num<index) { //肯定是由下面这3个数中最小的组成下一个丑数。 int new2=ugly[idx2]*2; int new3=ugly[idx3]*3; int new5=ugly[idx5]*5; int tempVal=min(min(new2,new3), new5); //找到是谁称为下一个丑数,找到了说明当前位置已经用过了,++; if(tempVal==new2) idx2++; if(tempVal==new3) idx3++; if(tempVal==new5) idx5++; ugly[i]=tempVal; num++; } return ugly[index-1];
丑数的升级版本。
这是某个大公司出过的一道题目。也是leetcode上面的原题,具体题目题号我已经忘记了,找到这个题号再来补充吧。
给你两个整数数组a[m],b[n],每次从a[m]中取一个数a[i],b[n]中取一个数b[j],得到a[i]*b[j],得到前k个最小的a[i]*b[j]。
这个题目就是上面丑数的变形,上面的题目只有2,3,5这三个数组成,而这里是由两个序列a[m],b[n]组成。上一题中,2,3,5可以无限使用,比如丑数72(2*2*2*3*3),而这个题,每次只能由a[i]*b[j]组成,不存在无数次使用的情况。但是思路是一样的,即维护m个指针p[m],p[i]指向当前第一个没有与a[j]使用过的位置。
核心代码如下。
int p[m];for(int i=0;i<k;i++){ int minn = MAXN; for(int j=0;j<m;j++){ if(minn>a[p[j]]*b[j]){ minn = a[p[j]]*b[j]; minpos = j; } } for(int j=0;j<m;j++){ if(minpos==j){ p[j]++; } }}
但是其实这个题目还是可以简化,就是利用堆的思想。
求前k个最小的a[i]*b[j],将a[0]*b[j](j从0到m-1),先全部放到小顶堆中。小顶堆的根root一定是下一个符合要求的数。假设当前小顶堆为根root为a[p[i]]*b[j]。去掉root,把p[j]++,把a[p[j]]*b[j]加入到小顶堆中,维护堆。简单起见,这里可以使用优先队列来实现(优先队列就是用堆来维护的,优先队列中的数据并不是全部有序的,只是队头是最大或最小的),维护的复杂度为log(n)。
- 丑数的思想
- 丑数-以空间换时间的思想
- 丑数的处理
- 丑数的求解
- 丑数的问题
- 300内的丑数
- 丑数求解以及丑数的优化
- 丑数
- 丑数
- 丑数
- 丑数
- 丑数
- 丑数
- 丑数
- 丑数
- 丑数
- 丑数
- 丑数
- js对象中什么是可枚举性(enumerable)?
- @RequestMapping 用法详解之地址映射(转)
- ReentrantLock 实现原理
- H
- js城市二级连动
- 丑数的思想
- SCALA HTTP get请求
- gif 格式图片详解
- C++继承时派生类的成员访问属性
- get_mainarea()详解
- MATLAB R2014a 装 limsvm-3.17
- Plug-in org.eclipse.jdt.ui was unable to load class
- 图像轮廓的提取
- 水平垂直居中