google面试题目:寻找丑数--使用double防止数据溢出

本文讨论了Google面试中的一道题目,涉及如何使用double类型来防止在寻找丑数过程中因整数运算导致的数据溢出问题。通过对整数运算的巧妙转换,可以有效避免溢出并确保计算的正确性。
摘要由CSDN通过智能技术生成
/*******************************************************************************
google面试题目:我们把只包含因子2、3和5的数称作丑数(Ugly Number)。
例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。
求按从小到大的顺序的第2012个丑数。


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


本质就是2 ,3 ,5 的乘积的组合,不过要按照顺序组合,
每次都将2,3,5乘以一个已经是丑数的数,
再比较三者的大小,小的进入数组,然后继续比较
例如:1是丑数,那么下一个2 * 1、3 * 1和5*1,
那么获得的是2,2进入数组,下面比较的是2*2、3*1 和5*1
( 重视因为后面的3*1和5*1的大小并不断定,所以还要持续进行比较)
获得3进入数组,再比较 2 * 2、3 * 2和5*1.


感谢网友的评论,发现了程序的问题
是因为int型表示数据范围有限倒置数据溢出,后来改成unsigned long int 仍然溢出
最后只能改成double 了
三者的表示的数据范围如下:



numeric_limits<int>::max --> 2147483647    第1692个丑数越界
numeric_limits<unsigned long int>::max --> 4294967295  第1849个丑数越界
numeric_limits<double>::max --> 1.79769e+308



************************************************************************/



************************************************************************/
#include<iomanip> // 精度控制头文件
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<limits>
using namespace std;


/*the smallest in the three*/
//无符号长整型    防止数据溢出
double mymin(double a, double b, double c)
{
    double temp = (a < b ? a : b);
    return (temp < c ? temp : c);
}
//无符号长整型    防止数据溢出
double FindUgly(int n)
{
    double* ugly = new double[n];
    ugly[0] = 1;
    int index2 = 0;
    int index3 = 0;
    int index5 = 0;
    int index = 1;
    while (index < n)
    {
        double val = mymin(ugly[index2]*2, ugly[index3]*3, ugly[index5]*5);
        //竞争产生下一个丑数
        if (val == ugly[index2]*2)
        //将产生这个丑数的index*向后挪一位;
            ++index2;
        if (val == ugly[index3]*3)
        //这里不能用elseif,因为可能有两个最小值,这时都要挪动;
            ++i
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值