1. 程式人生 > 其它 >劍指offer-醜數

劍指offer-醜數

描述

把只包含質因子2、3和5的數稱作醜數(Ugly Number)。例如6、8都是醜數,但14不是,因為它包含質因子7。 習慣上我們把1當做是第一個醜數。求按從小到大的順序的第N個醜數。

求解思路:

思路1:

  1. 首先編寫函式,判斷某一個數是否屬於醜數。
  2. 然後通過迴圈找到第index個醜數。
 1     int GetUglyNumber_Solutions(int index) {
 2         int count=0;
 3         int num=1;
 4         while(count<index){
 5             if(isUglyNum(num)){
6 count++; 7 } 8 ++num; 9 } 10 return --num; 11 } 12 13 // 沒仔細看題目,以為是要判斷一個數是否是醜數 14 // 事實證明,挨個判別會導致執行超時。 15 bool isUglyNum(int num){ 16 // 過濾的思想,依次把2,3,5因子全都刷掉,看結果是不是1 17 while(num%2==0) num=num/2; 18 while
(num%3==0) num=num/3; 19 while(num%5==0) num=num/5; 20 if(num==1) return true; 21 return false; 22 }

果然,很順利地超時了。

思路2:

  1. 假設我們現有已經有了一個醜數的陣列exit,那我們的任務就是確定這個陣列的下一個醜數。
  2. 由於醜數必定可分解為2*x、3*y以及5*z三者的至少其中之一,現在的任務變成了:
    • 記錄x,y,z的值,使得2x,3y,5z的值剛好稍大於現有陣列的最後一個元素。
    • 取2x,3y,5z三者的最小值,即為下一個醜數。
 1
class Solution { 2 public: 3 int GetUglyNumber_Solution(int index) { 4 // 題目提示二分,那就老老實實用二分吧 5 // 沒思路,怎麼用到二分的? 6 // 題解的思路:由於醜數是由已有的醜數佇列乘2,3,5得到的 7 // 所以確定現有的醜數佇列後,怎麼確定下一個最小的醜數呢? 8 // 這個數可能會被分解乘2*x,3乘y,5乘z,這三個值取最小值就是下一個醜數了 9 // 那麼x,y,z怎麼求呢?用指標 10 vector<int> exit={1}; 11 int p2=0,p3=0,p5=0; // 三個指標首先都指向1 12 for(int i=0;i<index;++i){ 13 int newUgly=min(2*exit[p2],min(3*exit[p3],5*exit[p5])); 14 exit.push_back(newUgly); 15 if(newUgly==2*exit[p2]) ++p2; // 不移動的話永遠是這個最小 16 if(newUgly==3*exit[p3]) ++p3; 17 if(newUgly==5*exit[p5]) ++p5; 18 } 19 return exit[index-1]; 20 } 21 };
心之所願,永不相忘