【题目】

我们把只包含质因子2、3和5的数称作丑数(Ugly Number),例如:2,3,4,5,6,8,9,10,12,15,等,习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第1500个丑数。

【分析】

这是一道在网络上广为流传的面试题,据说google曾经采用过这道题。

所谓一个数m是另一个数n的因子,是指n能被m整除,也就是n % m == 0。根据丑数的定义,丑数只能被2、3和5整除。也就是说如果一个数如果它能被2整除,我们把它连续除以2;如果能被3整除,就连续除以3;如果能被5整除,就除以连续5。如果最后我们得到的是1,那么这个数就是丑数,否则不是。

基于前面的分析,我们可以写出如下的函数来判断一个数是不是丑数:

最普通(也最耗时)的做法是从1开始遍历,然后判断这个数的因式分解中只包含2,3,5,满足则找到了一个,一直找下去,直到第n个被找出!测试了一下,找第1500个丑数耗时40秒!

【方案1】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 
bool IsUglyNumber(int n)
{
    )
        n /= ;
    )
        n /= ;
    )
        n /= ;
    ;
}

int GetUglyNumber_Solution1(int index)
{
    )
        ;

;
    ;
    while(uglyFound < index)
    {
        number++;
        if (IsUglyNumber(number))
        {
            uglyFound++;
        }
    }
    return number;
}

我们只需要在函数GetUglyNumber_Solution1中传入参数1500,就能得到第1500个丑数。该算法非常直观,代码也非常简洁,但最大的问题我们每个整数都需要计算。即使一个数字不是丑数,我们还是需要对它做求余数和除法操作。因此该算法的时间效率不是很高。

接下来我们换一种思路来分析这个问题,试图只计算丑数,而不在非丑数的整数上花费时间。根据丑数的定义,丑数应该是另一个丑数乘以2、3或者5的结果(1除外)。因此我们可以创建一个数组,里面的数字是排好序的丑数。里面的每一个丑数是前面的丑数乘以2、3或者5得到的。

假设数组ugly[N]中存放不断产生的丑数,初始只有一个丑数ugly[0]=1,由此出发,下一个丑数由因子2,3,5竞争产生,得到ugly[0]*2, ugly[0]*3, ugly[0]*5, 显然最小的那个数是新的丑数,所以第2个丑数为ugly[1]=2,开始新一轮的竞争,由于上一轮竞争中,因子2获胜,这时因子2对应的索引应该加1,变为1,得到ugly[1]*2,ugly[0]*3,ugly[0]*5, 因子3获胜,ugly[2]=3,同理,下次竞争时因子3对应的索引应该加1,变为1,即:ugly[1]*2, ugly[1]*3, ugly[0]*5, 因子5获胜,得到ugly[3]=5,重复这个过程,直到第n个丑数产生。总之:每次竞争中有一个(也可能是两个)因子胜出,下一次竞争中胜出的因子对应的索引应该加1!

方案2】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
int mymin(int a, int b, int c)
{
    int tmp = a < b ? a : b;
    int res = tmp < c ? tmp : c;
    return res;
}

int GetUglyNumber_Solution2(int index)
{
    )
        ;
    int *ugly = new int[index];
    ugly[;
    ;
    ;
    ;

;
    while(uglyIndex < index)
    {
        );
        // store ugly number
        ugly[uglyIndex] = minValue;
        uglyIndex++;

// find index which gets minValue, and then move it next
)
            index2++;
        )
            index3++;
        )
            index5++;
    }
    ];
    delete []ugly;
    return result;
}

 【参考】

http://zhedahht.blog.163.com/blog/static/2541117420094245366965/

http://www.cppblog.com/zenliang/articles/131094.html

http://www.cnblogs.com/coser/archive/2011/03/07/1976525.html

37.寻找丑数[Ugly numbers]的更多相关文章

  1. 丑数(Ugly Numbers, UVa 136)

    丑数(Ugly Numbers, UVa 136) 题目描述 我们把只包含因子2.3和5的数称作丑数(Ugly Number).求按从小到大的顺序的第1500个丑数.例如6.8都是丑数,但14不是,因 ...

  2. 九度OJ 1214 寻找丑数【算法】

    题目地址:http://ac.jobdu.com/problem.php?pid=1214 题目描述: 把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因 ...

  3. Luogu2723丑数Humble Numbers【归并排序】

    Luogu2723丑数Humble Numbers 题目背景 对于一给定的素数集合 S = {p1, p2, ..., pK},考虑一个正整数集合,该集合中任一元素的质因数全部属于S.这个正整数集合包 ...

  4. 洛谷P2723 丑数 Humble Numbers

    P2723 丑数 Humble Numbers 52通过 138提交 题目提供者该用户不存在 标签USACO 难度普及/提高- 提交  讨论  题解 最新讨论 暂时没有讨论 题目背景 对于一给定的素数 ...

  5. 基于visual Studio2013解决面试题之0701寻找丑数

     题目

  6. 洛谷P2723 丑数 Humble Numbers [2017年 6月计划 数论07]

    P2723 丑数 Humble Numbers 题目背景 对于一给定的素数集合 S = {p1, p2, ..., pK},考虑一个正整数集合,该集合中任一元素的质因数全部属于S.这个正整数集合包括, ...

  7. [Swift]LeetCode263. 丑数 | Ugly Number

    Write a program to check whether a given number is an ugly number. Ugly numbers are positive numbers ...

  8. 笔试算法题(20):寻找丑数 & 打印1到N位的所有的数

    出题:将只包含2,3,5的因子的数称为丑数(Ugly Number),要求找到前面1500个丑数: 分析: 解法1:依次判断从1开始的每一个整数,2,3,5是因子则整数必须可以被他们其中的一个整除,如 ...

  9. 【转载】丑数humble numbers

    转载地址:http://blog.csdn.net/qwerty_xk/article/details/12749961 题:只有2 3 5 这三个因子的数,求第1500个   设1为第一个丑数,求第 ...

随机推荐

  1. 问问题_为什么关闭浏览器后Session会失效

    首先需要理解一下几点: 1.Http是无状态的,即对于每一次请求都是一个全新的请求,服务器不保存上一次请求的信息 2.Session是保存在服务端的,为什么后续请求会读取到session?因为请求会包 ...

  2. 【CodeForces 596A】E - 特别水的题5-Wilbur and Swimming Pool

    Description After making bad dives into swimming pools, Wilbur wants to build a swimming pool in the ...

  3. 【前端学习】git命令行界面

    学习目标:掌握git命令行界面的操作.掌握最基本的clone add commit push pull操作. 先下载客户端:http://github-windows.s3.amazonaws.com ...

  4. 【poj3177】 Redundant Paths

    http://poj.org/problem?id=3177 (题目链接) 题意 给出一个n个节点m条边的无向图,求最少连几条边使图中没有桥. Solution 我们可以发现,用最少的边使得图中没有桥 ...

  5. SqlServer建表规范

    一.数据库在建表时,一般默认字段如下,也算是标准字段吧 删除标志:DeletionStateCode 创建时间:CreateOn 创建人:CreateBy 更新时间:ModifiedOn 更新人:Mo ...

  6. 迪杰斯特拉(Java)

    public class Dijsktra { public static void main(String[] args) { Dijsktra d=new Dijsktra(); int[][] ...

  7. POJ3020Antenna Placement(最小路径覆盖+重在构图)

    Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7788   Accepted: 3880 ...

  8. 什么是领域模型(domain model)?贫血模型(anaemic domain model) 和充血模型(rich domain model)有什么区别

    http://blog.csdn.net/helloboat/article/details/51208128 领域模型是领域内的概念类或现实世界中对象的可视化表示,又称为概念模型或分析对象模型,它专 ...

  9. JS触发事件大全

          事件 浏览器支持 解说 一般事件 onclick IE3.N2 鼠标点击时触发此事件 ondblclick IE4.N4 鼠标双击时触发此事件 onmousedown IE4.N4 按下鼠 ...

  10. html表单验证程序

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...