1. 程式人生 > >演算法學習筆記之尋找第1500個醜數

演算法學習筆記之尋找第1500個醜數

最近在閱讀《演算法新解》(劉新宇 著),書寫得很不錯,推薦程式們閱讀。前言中有個例子,是尋找第1500個醜數,所謂醜數是指僅含2、3、5這三個素因子的自然數。作者在書中給出了虛擬碼。作為練習,記錄下自己的程式碼。

一、暴力查詢法

演算法思路 :迭代每個自然數,逐一判斷是否是醜數,並觀察累計計數是否達到1500,如果是,則成功找到了第1500個醜數

#include <iostream>
#include <limits.h>
#include <time.h>

using namespace std;

bool isUgly(int);


int main() {
    cout << "尋找第1500個醜數" << endl;
    clock_t start_time = clock();

    int count = 1;  //我們認為1是第1個醜數
    for(int i=2;i<INT_MAX;i++){
        if(isUgly(i)){
            if(++count == 1500) {
                cout << "第1500個醜數是: " << i << endl;
                break;
            }
        }
    }

    clock_t end_time = clock();
    cout << "執行總耗時(秒): " << static_cast<double>(end_time - start_time)/CLOCKS_PER_SEC << endl;
    return 0;
}

bool isUgly(int number){
    while(number > 1){
        if(number % 2 == 0) number /= 2; else break;
        if(number == 1) return true;
    }
    while(number > 1){
        if(number % 3 == 0) number /= 3; else break ;
        if(number == 1) return true;
    }
    while(number > 1){
        if(number % 5 == 0) number /= 5; else break;
        if(number == 1) return true;
    }
    return false;
}

該方法確實過於簡單粗暴了。上面程式在筆記本上執行的結果是


二、多佇列方法

    使用構造法,逐一構造出遞增的醜數,直到構造到第N個醜數,返回。劉新宇使用了queue作為資料結構,且提出可使用多個queue,生成新醜數並插入不同queue的思路也非常好(想不到作者是怎樣構思出來的)。下面是本人的練習程式碼:

#include <iostream>
#include <stdlib.h>
#include <queue>
#include <time.h>
using namespace std;
typedef unsigned long ul;
ul findNthUglyNumber(int);

int main(){
    int N;
    cout << "輸入想查詢第幾個醜數: N= " << endl;
    cin >> N;
    clock_t start_time = clock();
    ul result = findNthUglyNumber(N);
    clock_t end_time = clock();

    cout << "第" << N << "個醜數為: " << result << endl;
    cout << "執行總耗時(秒): " << static_cast<double>(end_time - start_time)/CLOCKS_PER_SEC << endl;
    return 0;
}

ul findNthUglyNumber(int n){
    if(n == 1) return  1;
    queue<ul> q1,q2,q3;
    q1.push(2);
    q2.push(3);
    q3.push(5);
    ul minValue;
    while(n-- > 1){
        minValue = min(min(q1.front(),q2.front()),q3.front());
        if (minValue == q1.front()){
            q1.pop();
            q1.push(minValue*2);
            q2.push(minValue*3);
            q3.push(minValue*5);
        }else if(minValue == q2.front()){
            q2.pop();
            q2.push(minValue*3);
            q3.push(minValue*5);
        }else{
            q3.pop();
            q3.push(minValue*5);
        }
    }
    return minValue;
}

執行效果如下:


方法二的計算耗時為方法一的13萬分之一。OMG,資料結構與演算法真是一個有意思的東西。