LeetCode (39) Ugly Number I II (醜數)

張小小Angela發表於2015-09-22

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;
    }
};

相關文章