生活随笔
收集整理的這篇文章主要介紹了
数据结构与算法--丑数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
找出排在第n位大的丑數
public class FindUglyNumber {public static void main(String[] args
) {Long time
= System.currentTimeMillis();System.out
.println(getNumberOfUglyNumber(900));Long time_1
= System.currentTimeMillis();System.out
.println(time_1
- time
);}public static Integer getNumberOfUglyNumber(Integer position
){if(position
<= 0){return -1;}Integer count
= 0;for (int i
=0; true;i
++){if(isUglyNumber(i
)){count
++;if(count
.equals(position
)){return i
;}}}}public static boolean isUglyNumber(Integer number
) {if(number
<= 0){return false;}while (number
% 2 == 0) {number
/= 2;}while (number
% 3 == 0) {number
/= 3;}while (number
% 5 == 0){number
/= 5;}return number
== 1;}
}
public class FindUglyNumber {public static void main(String[] args
) {Long time_1
= System.currentTimeMillis();System.out
.println(getNumberOfUglyNumber_1(900));Long time_2
= System.currentTimeMillis();System.out
.println(time_2
- time_1
);}public static Integer getNumberOfUglyNumber_1(Integer position
){if(position
<=0 ){return -1;}List<Integer> uglyNumberList
= new ArrayList<>();Integer count
=0;for (int i
=0;true;i
++){if(isUglyNumber(i
, uglyNumberList
)){count
++;if(count
.equals(position
)){return i
;}uglyNumberList
.add(i
);}}}public static boolean isUglyNumber(Integer number
, List<Integer> uglyNumberList
) {if(number
<= 0){return false;}while (number
% 2 == 0) {number
/= 2;if(uglyNumberList
.contains(number
)){return true;}}while (number
% 3 == 0) {number
/= 3;if(uglyNumberList
.contains(number
)){return true;}}while (number
% 5 == 0){number
/= 5;if(uglyNumberList
.contains(number
)){return true;}}return number
== 1;}
}
-
如上方案運行后結果并沒有如我們預期得到優化,時間反而更長了,基本要n分鐘才能出結果
-
問題在循環運算的過程中我們每次運算都會判斷結果是否包含在已有丑數中
-
但是 List的content方法的耗時比實際運算的時間多多了,因此它的耗時反而增加了
-
本想空間換時間,但是算法應該沒寫好,是一次失敗的優化,接著找更優的方案
-
方案三:
- 以上兩種方案都是對數字逐個判斷,方案二中的思路是可以借鑒的,是否還有更優的解,無需逐個判斷我們通過算法求出還存在的丑數
- 在方案二中我們提出了這個數學規律:當找出一個丑數s 時候,那么在這個丑數基礎上s * 2,s * 3,s * 5,必然也是丑數
- 有如上規則的話,我們就有辦法通過這個規則找出還沒有界別出的丑數,但是難點在于我們需要按順序排列
- 按順序找的話,我們只能找出比當前找出的最大丑數 大的最小丑數,比較拗口,舉例如下
- 當前丑數有{1,2,3,4} 那么我們能通過2,3,5 的乘法找出2,3,4,6,10 ,但是符合當前要求的只有5
- 因此我們用如下規則查詢:
- 將2,3,5 與現有丑數數組中所有的數字依次做乘法,并且將大于當前最大丑數max的值記錄下來記為k
- 找出記錄k中最小的值,就是我們需要找的下一個丑數
- 經過如上分析有如下代碼:
public class FindUglyNumber {public static void main(String[] args
) {Long time_2
= System.currentTimeMillis();System.out
.println(getNumberOfUglyNumber_2(1500));System.out
.println(System.currentTimeMillis() - time_2
);}public static Integer getNumberOfUglyNumber_2(Integer position
){if(position
<= 0){return -1;}Integer[] uglyArray
= new Integer[position
];uglyArray
[0] = 1;Integer nowPosition
= 1;Integer max
= uglyArray
[0];while (nowPosition
< position
){Integer newMax
= findMinUgly(max
, uglyArray
, nowPosition
);max
= newMax
;uglyArray
[nowPosition
] = newMax
;nowPosition
++;}return uglyArray
[position
- 1];}public static Integer findMinUgly(Integer max
, Integer[] uglyArray
, Integer nowPosition
){Integer min
= Integer.MAX_VALUE
;for (int i
= 0; i
< nowPosition
; i
++) {Integer temp_2
= uglyArray
[i
] * 2;if(temp_2
> max
&& temp_2
< min
){min
= temp_2
;}Integer temp_3
= uglyArray
[i
] * 3;if(temp_3
> max
&& temp_3
< min
){min
= temp_3
;}Integer temp_5
= uglyArray
[i
] * 5;if(temp_5
> max
&& temp_5
< min
){min
= temp_5
;}}return min
;}
}
- 經過如上優化后,第1500 位丑數的求解控制在46毫秒以內這基本上可以算合格的解法了
- 但是其實還是有優化空間的,也就是我們在findMinUgly中循環做乘法運算求最小丑數的時候,有一部分乘法是完全沒必要的
- 例如當我們當前的最大丑數是k的時候,在2,3,5與第 n個丑數做乘法的結果中 5*n < k
- 其中5*n是n 以及n之前 所有丑數能計算出的最大丑數還是 小于 k,就說明n 之前的所有乘法都是不必要的
- 通過對這個點的優化可以節省很多計算時間。
- 小優化如下:
public class FindUglyNumber {public static void main(String[] args
) {Long time_2
= System.currentTimeMillis();System.out
.println(getNumberOfUglyNumber_2(1500));System.out
.println(System.currentTimeMillis() - time_2
);}public static Integer getNumberOfUglyNumber_2(Integer position
){if(position
<= 0){return -1;}Integer[] uglyArray
= new Integer[position
];uglyArray
[0] = 1;Integer nowPosition
= 1;Integer max
= uglyArray
[0];while (nowPosition
< position
){Integer newMax
= findMinUgly(max
, uglyArray
, nowPosition
);max
= newMax
;uglyArray
[nowPosition
] = newMax
;nowPosition
++;}return uglyArray
[position
- 1];}public static Integer findMinUgly(Integer max
, Integer[] uglyArray
, Integer nowPosition
){Integer min
= Integer.MAX_VALUE
;for (int i
= 0; i
< nowPosition
; i
++) {Integer temp_5
= uglyArray
[i
] * 5;if(temp_5
< max
){continue;}if(temp_5
> max
&& temp_5
< min
){min
= temp_5
;}Integer temp_2
= uglyArray
[i
] * 2;if(temp_2
> max
&& temp_2
< min
){min
= temp_2
;}Integer temp_3
= uglyArray
[i
] * 3;if(temp_3
> max
&& temp_3
< min
){min
= temp_3
;}}return min
;}
}
- 經過如上一個小的優化點,可以將1500 位的查找控制在30 毫秒以內
上一篇:數據結構與算法–將數組排成最小的數
下一篇:數據結構與算法–第一個只出現一次的字符
總結
以上是生活随笔為你收集整理的数据结构与算法--丑数的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。