LeetCode (39) Ugly Number I II (丑数)

Ugly Number I

题目描述

Write a program to check whether a given number is an ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 6, 8 are ugly while 14 is not ugly since it includes another prime factor 7.

Note that 1 is typically treated as an ugly number.

题目定义如果一个整数的质因子只包含2,3,5则一个数为丑数。题目要求判断一个数是否为丑数。

解题代码

题目解法可以比较直接的方法就是对一个数重复除以2,3,5直到这个数不存在2,3,5这三个因子为止,若此时得到的结果不为1,则说明该数不是丑数。这个思路代码实现起来也很简单。

class Solution {
public:
    bool isUgly(int num) {
        if(num < 1) return false;
        if(num == 1) return true;

        vector<int> num_vect;
        num_vect.push_back(2);
        num_vect.push_back(3);
        num_vect.push_back(5);

        for(size_t i=0; i!=num_vect.size();++i)
        {
            while(num % num_vect[i] == 0)
            {
                num = num / num_vect[i];
            }
        }

        if(num == 1) return true;
        else return false;
    }
};

Ugly Number II

题目描述

Write a program to find the n-th ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.

Note that 1 is typically treated as an ugly number.

第二题在第一题的基础上,进一步让我们获得第n个丑数。

解题思路

本题最简单的解法就是暴力解法,从1开始判断一个数是不是丑数,如果是丑数则技术count++,直到得到第n个丑数为止,但是这样做效率会比较低下,有很多重复判断的地方。

一个新的丑数可以看做是一个旧的丑数乘以2,3,5得到的(第一个丑数是1,第二个为2,则第二个可以看做第一个丑数*2得到了第二个丑数),本题解题难点在于维护丑数数列为从小到大排列的顺序。

根据上述思路可以做如下实现:

  • 维护三个列表l2,l3,l5,分别是当前处理的丑数num的2,3,5倍,因此三个列表组内均是遵从从小到大排列的规则;
  • 每次获得三个列表的第一个结点(最小的结点)最为当前丑数num,根据当前丑数值想三个列表末端插入新的较大的丑数值,等待后续处理;
  • 若列表的第一个结点与当前丑数num相等,则删除列表第一个结点(表示该丑数已经被计数);
  • 题目的初始条件为num = 1, count = 1;

实现代码为:

class Solution {
public:
    int getMin(int a, int b, int c)
    {
        return a < b ? (a < c ? a : c) : (b < c ? b : c);
    }
    int nthUglyNumber(int n) {
       int count = 1;
       int num = 1;
       list<int> l2;
       list<int> l3;
       list<int> l5;

       while(count != n)
       {
           l2.push_back(2*num);
           l3.push_back(3*num);
           l5.push_back(5*num);

           int l2min = l2.front();
           int l3min = l3.front();
           int l5min = l5.front();

           int minNum = getMin(l2min, l3min, l5min);
           if(l2min == minNum) l2.pop_front();
           if(l3min == minNum) l3.pop_front();
           if(l5min == minNum) l5.pop_front();
           num = minNum;
           count++;
       }

       return num;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值