Ugly Numbers问题
算法一 Ugly Numbers
一、问题描述
质因子只有2、3、5的数称为丑数,为了方便,1也被归为丑数(1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15…)
现给出一个正整数n,求第n个丑数
二、常规解法
难点1. 如何求丑数
下图是百度百科给出的质因子定义
因为任何正整数都可以写成独一无二的质因子分解式,且丑数的质因子只有2,3,5,所以
任意丑数N = 2^n1 * 3^n2 * 5^n3(n1 >= 0 && n2 >= 0 && n3 >= 0)
除1以外,n1,n2,n3比不全为0,不妨设n1>0,此时
不为1的丑数N = N1 * 2N1 = 2^(n1 - 1) * 3^n2 * 5^n3( (n1-1) >= 0 && n2 >= 0 && n3 >= 0)
有没有发现N1也是个丑数呢?所以除1外的所有丑数都能写成2或者3或者5乘以另一个比他小的丑数。
所以前N个丑数一定包含下列的集合里
2*N1、2*N2、2*N3、....、2*Nn-1
3*N1、3*N2、3*N3、....、3*Nn-1
5*N1、5*N2、5*N3、....、5*Nn-1
(N1=1,Ni代表第i个丑数,)
然后利用归并,取出这个集合的第n个数。
难点2. 去除重复元素
这个问题的本质是:我们产生的新丑数必定是当前3个序列中的最小值,其他2序列的丑数必定是大于等于它的关系。(好像没有表达清楚,(⊙o⊙)…)
实现代码
#include <stdio.h>#define N 2000#define min(a,b) ((a)<(b)?(a):(b)) long long int getNthUglyNumber(int n) {// 元素类型是 long long int!long long int uglyNumbers[N] = { 1 };int tail = 1;int indexOf2 = 0;int indexOf3 = 0;int indexOf5 = 0;for (int i = 0; i < n; ++i) {long long int multipleOf2 = uglyNumbers[indexOf2] * 2;long long int multipleOf3 = uglyNumbers[indexOf3] * 3;long long int multipleOf5 = uglyNumbers[indexOf5] * 5;long long int uglyNumber = min(multipleOf2, min(multipleOf3, multipleOf5));if (uglyNumber == multipleOf2) {++indexOf2;}if (uglyNumber == multipleOf3) {++indexOf3;}if (uglyNumber == multipleOf5) {++indexOf5;}uglyNumbers[tail++] = uglyNumber;}return uglyNumbers[n - 1];
}int main() {// int n = 11;// for (int i = 1; i < n; ++i) {// printf("%d'th ugly number is %d\n", i, getNthUglyNumber(i));// }printf("%d'th ugly number is %d\n", 7, getNthUglyNumber(7));printf("%d'th ugly number is %d\n", 10, getNthUglyNumber(10));printf("%d'th ugly number is %d\n", 15, getNthUglyNumber(15));printf("%d'th ugly number is %d\n", 150, getNthUglyNumber(150));return 0;
}
复杂度分析
1.时间复杂度: O(n)因为只有一个for循环
2.空间复杂度: O(N),因为我们分配了一个N的数组来记录前N个元素
3.LeeCode执行结果
三、拓展解法
这些解法不一定会比常规解法优秀,但是可能能帮给你开阔思路
思路一、数组法
// 伪代码 这个方法我没有实现
#define N 10000000int getNthUglyNumber(int n) {// Note: 用户空间能否分配如此大的空间?char arr[N] = { 0, 1 };int count = 0;for (int i = 0; i < N; ++i) {if (arr[i] == 0)continue;// Note:2 * i会不会比 N 大?arr[2 * i] = 1;arr[3 * i] = 1;arr[5 * i] = 1;if (++count == n)return i;}
}
这个方法其实是我第一次想出来的,问题很明显,我也标出来了,但是如果你的n很小的时候还是挺好用的,不过空间复杂度很高。
思路二、利用正整数的独一无二质因子分解式和二分查找
#include <iostream>
#include <set>
#include <algorithm>#define N 40
#define LEFT 1
#define RIGHT 21474836647int getUglyNumberCountLessAndEqualThanN(long long int* powerOf2, int size, long long int n) {int count = 0;for (long long int multipleOf5 = 1; multipleOf5 <= n; multipleOf5 *= 5) {for (long long int multipleOf3 = 1; multipleOf3 * multipleOf5 <= n; multipleOf3 *= 3) {count += std::upper_bound(powerOf2, powerOf2 + size, n / (multipleOf5 * multipleOf3)) - powerOf2;}}return count;
}long long int getNthUglyNumber(int n) {long long int powerOf2[N] = { 1 };for (int i = 1; i < N; ++i)powerOf2[i] = powerOf2[i - 1] * 2;long long int possible_result = -1;// N = 2^n1 * 3^n2 * 5^n3long long int left = LEFT;long long int right = RIGHT;while (left <= right) {long long int midst = (left + right) / 2;if (getUglyNumberCountLessAndEqualThanN(powerOf2, N, midst) < n) {left = midst + 1;} else {// maybe midst is the Nth ugly number.possible_result = midst;right = midst - 1;}}return possible_result;
}int main() {int n = 12;// printf("%d'th ugly number is %d\n", n, getNthUglyNumber(n));for (int i = 1; i < n; ++i) {printf("%d'th ugly number is %d\n", i, getNthUglyNumber(i));}printf("%d'th ugly number is %d\n", 7, getNthUglyNumber(7));printf("%d'th ugly number is %d\n", 10, getNthUglyNumber(10));printf("%d'th ugly number is %d\n", 15, getNthUglyNumber(15));printf("%d'th ugly number is %d\n", 150, getNthUglyNumber(150));
}
这种做法很巧妙,但是不利于n很小的情况。下面贴出LeeCode的执行结果
这个算法时间复杂度就不那么明显了,GeeksForGeeks给出的如下图,二分查找是0(logN),但是计数函数的复杂度咋处理。。
四、参考资料
1.题目连接:
https://leetcode.com/problems/ugly-number-ii/
2.参考资料
https://www.geeksforgeeks.org/ugly-numbers/
3.其他
https://baike.baidu.com/item/%E8%B4%A8%E5%9B%A0%E6%95%B0
Ugly Numbers问题相关推荐
- [POJ1338]Ugly Numbers
[POJ1338]Ugly Numbers 试题描述 Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequ ...
- poj 1338 Ugly Numbers(丑数模拟)
转载请注明出处:http://blog.csdn.net/u012860063? viewmode=contents 题目链接:http://poj.org/problem?id=1338 Descr ...
- 136 - Ugly Numbers
Ugly Numbers Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 1, 2, 3, ...
- Poj 1338 Ugly Numbers(数学推导)
一.题目大意 本题要求写出前1500个仅能被2,3,5整除的数. 二.题解 最初的想法是从1开始检验该数是否只能被2,3,5整除,方法是这样的,对于一个数,如果它能被2整除,就除以2,如果它能被3整除 ...
- POJ1338 Ugly Numbers(解法二)【废除!!!】
本文废除!!! 参考链接:POJ1338 Ugly Numbers[水题] 问题链接:POJ1338 Ugly Numbers.基础级练习题,用C语言编写程序. 题意简述:不能被2.3和5以外的素数整 ...
- POJ1338 Ugly Numbers
问题链接:POJ1338 Ugly Numbers.基础级练习题,用C++语言编写程序. 题意简述:不能被2.3和5以外的素数整除的数称为丑数,找出第1500个丑数. 问题分析:换句话说,丑数的因子只 ...
- UVA - 136:Ugly Numbers
Ugly Numbers 来源:UVA 标签: 参考资料:<算法竞赛入门经典>P120 相似题目: 题目 Ugly numbers are numbers whose only prime ...
- 【例题5-7 UVA - 136】Ugly Numbers
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 每个丑数x,都能生成3个丑数2x,3x,5x 则我们以1作为起点. 生成丑数. 每次取出set里面最小的那个数. 然后用它去生成其他 ...
- 比紫书优化,14行代码AC——例题 5-7 丑数(Ugly Numbers,UVa 136)——解题报告
题意: 丑数是一些因子只有2,3,5的数.数列1,2,3,4,5,6,8,9,10,12,15--写出了从小到大的前11个丑数,1属于丑数.现在请你编写程序,找出第1500个丑数是什么. 没有输入 输 ...
最新文章
- 你可以恢复模糊的图像吗?
- 用html做12进制时钟特效,js+css3实现简单时钟特效
- su oracle : 只切换用户,而不切换环境;就是说切到oracle用户后,使用的依旧是root的环境。 su - oracle :同时切换用户和环境
- 不允许程序员透露薪资!!!凭啥?
- python绘制多个条形图_python – 在Matplotlib中绘制多个直方图 – 颜色或并排条形图...
- 随想录(招聘怎样的员工)
- 土方计算软件FastTFT V15.1.0更新说明(支持AutoCAD2020平台)
- python波形分析_[转载]频谱分析:基于python画出时域频域波形
- 心不唤物,物不至,聊聊积极心态重要性
- 某东满3000减2020真的有这个劵么
- 键盘 部分 按键 ~ 需要长按才能打出来
- PS 2019 cc衣服换色+去白边
- sh文件加密解密gzexe(Cannot decompress $0)
- 基于Python的图片批量转PDF实现
- Cocos2d-x 2.0.1 学习tests示例(一)Manual Transformation
- android app 清理缓存图片,支付宝APP怎么清理缓存 支付宝安卓版缓存清理方法
- 实验1 BP神经网络实验
- 传统CD车机面板操作说明
- 档案十防环境控制设备之3D可视化管控一体化平台图片鉴赏
- Image Printing Program Based on Halftoning
热门文章
- Scalable Object Detection using Deep Neural Networks 阅读笔记
- 端粒效应《The Telemere Effect》程序员的养生指南(二)情绪、思维模式与健康
- db2 improt from coldel0x7c
- 软考高项目:项目人力资源管理真题
- WGS84坐标系转为西安80坐标系的解决方式
- 熊孩子乱敲键盘攻破linux桌面,“熊孩子”乱敲键盘就攻破了 Linux 桌面,大神:17 年前我就警告过你们...
- 请叫我程序员!(一)
- 外行假装内行,我也来谈谈SAP BAPI和BADI
- MySQL导入数据库1118错误解决方案[ERR] 1118 - Row size too large (> 8126). Changing some columns to TEXT or BLOB
- mac关闭php,mac强制退出程序的方法有哪些