20 找出第1500个丑数
来源:互联网 发布:男性网络个人基金产品 编辑:程序博客网 时间:2024/06/05 11:42
前言
本博文部分图片, 思路来自于剑指offer 或者编程珠玑
问题描述
思路
对于这个问题, 两种思路
思路一 : 万事不能离的穷举算法, 从1开始穷举, ….是狠
思路二 : 丑数不是只由2,3,5构成的嘛,而且我们拿到的数也是由2,3,5构成的,而且是最小的10个,那么第11个一定就比前十个数中的某一个多一个因子2,或者因子3,或者因子5……也就是说,第11个丑数一定是前十个丑数中某一个丑数的2倍,或者3倍,或者5倍!![refer : http://blog.csdn.net/jinzheng069/article/details/8799009]
其实 对于书中说的 “根据丑数的性质, 一个丑数必然是另外一个丑数乘以2/ 3/ 5得到的结果“, 对于 这句话, 还懵懂了一会儿,, 但是 看了一下上面的这篇播客的这句话, 幡然醒悟啊…
根据这个思路, 我们就可以递推出各个丑数了
参考代码
/** * file name : Test14FindUglyNumber.java * created at : 5:05:23 PM Jun 8, 2015 * created by 970655147 */package com.hx.test05;public class Test14FindUglyNumber { // 丑数问题[质因数只有2, 3, 5的数] public static void main(String []args) { int n = 400; long start = System.currentTimeMillis(); findUglyNumber01(n); findUglyNumber02(n); findUglyNumber03(n); long spent = System.currentTimeMillis() - start; Log.log("spent : " + spent + " ms .."); } // 穷举, 找出第n个丑数,, public static void findUglyNumber01(int n) { int cnt = 0; int cur = 1; while(cnt < n) { if(isUglyNumber(cur ++) ) { cnt ++; } } Log.log(cur-1); } // 递推寻找丑数, 一个丑数必然是另一个丑数的*2, *3, *5 这样依次递推, 顺序的求解每一个丑数 public static void findUglyNumber02(int n) { int[] uglyNumbers = new int[n+1]; uglyNumbers[0] = 1; int size = 1, cnt = 1; int idxFor2 = findFloorFor(uglyNumbers, size, 2); int idxFor3 = findFloorFor(uglyNumbers, size, 3); int idxFor5 = findFloorFor(uglyNumbers, size, 5); while(cnt < n) { int valFor2 = uglyNumbers[idxFor2] * 2; int valFor3 = uglyNumbers[idxFor3] * 3; int valFor5 = uglyNumbers[idxFor5] * 5; int min = getMin(valFor2, valFor3, valFor5); if(min == valFor2) { idxFor2 ++; } if(min == valFor3) { idxFor3 ++; } if(min == valFor5) { idxFor5 ++; } uglyNumbers[cnt ++] = min;// Log.log(min); } Log.log(uglyNumbers[n-1]); } // 计算丑数, 来自剑指offer // 没太搞懂while循环的目的啊, 似乎是为了更新各个idx, 使得该idx对应的数据*各自的基数大于当前找到的丑数[当前最大的丑数] public static void findUglyNumber03(int n) { int[] uglyNumbers = new int[n+1]; uglyNumbers[0] = 1; int cnt = 1; int idxFor2 = 0; int idxFor3 = 0; int idxFor5 = 0; while(cnt < n) { int valFor2 = uglyNumbers[idxFor2] * 2; int valFor3 = uglyNumbers[idxFor3] * 3; int valFor5 = uglyNumbers[idxFor5] * 5; int min = getMin(valFor2, valFor3, valFor5); uglyNumbers[cnt ++] = min; while(uglyNumbers[idxFor2] * 2 <= min) { idxFor2 ++; } while(uglyNumbers[idxFor3] * 3 <= min) { idxFor3 ++; } while(uglyNumbers[idxFor5] * 5 <= min) { idxFor5 ++; }// Log.log(min); } Log.log(uglyNumbers[n-1]); } // 获取x, y, z中较小者 private static int getMin(int valFor2, int valFor3, int valFor5) { return getMin(valFor2, getMin(valFor3, valFor5)); } // 获取x, y中较小者 private static int getMin(int x, int y) { return x > y ? y : x; } // 找到uglyNumber乘以product中第一个大于最大的值的索引 private static int findFloorFor(int[] uglyNumbers, int cnt, int product) { int curMax = uglyNumbers[cnt - 1]; for(int i=0; i<cnt; i++) { if(uglyNumbers[i] * product > curMax) { return i; } } return -1; } // 判断一个数是不是丑数 [丑数 : 只能被2, 3, 5整除的数] private static boolean isUglyNumber(int n) { while ((n&1) == 0) { n >>= 1; } while (n % 3 == 0) { n /= 3; } while (n % 5 == 0) { n /= 5; } return n == 1; }}
效果截图
总结
对于思路二三, 使用了少量的空间存储计算所需的资源, 以及相关性质 使得计算时间大大的提高
注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!
0 0
- 20 找出第1500个丑数
- 找出第10001个质数。
- 找出第n大元素
- 丑数,即只有2,3,5因子的整数,找出第n 个丑数
- 找出数组中第k个元素
- 找出第K大的数字
- 找出第k大的数字
- 找出第k个最小的元素
- 找出单链表中倒数第 K个结点
- 找出第K大的数
- 找出两有序数组第k小
- 找出第k大的数
- 找出第k大的数
- 找出第K大的数<数组>
- 题目7:找出第10001个质数。
- 找出第n个斐波那契数
- 找出第k大的数
- 找出第n个ugly number
- [iOS学习]block初识
- HDOJ1713(相遇周期)(有点坑)
- 程序猿的爱情(一)
- 读书笔记--ContentProvider
- eclipse中装了MyEclipse插件之后不能创建web project
- 20 找出第1500个丑数
- 用 IntelliJ IDEA 15.x 创建并发布JavaWeb项目
- AngularJS 数据建模
- HBase API的简单的介绍
- Codeforces Round #339(Div.2)
- js数组的sort排序详解
- Java API 与HBase交互实例
- 按钮的点击效果设置
- linux添加新用户或删除用户