冒泡排序和遞歸算法優化

冒泡排序算法

第一,冒泡排序是原地排序算法嗎?數組

冒泡的過程只涉及相鄰數據的交換操做,只須要常量級的臨時空間,因此它的空間複雜度爲 O(1),是一個原地排序算法。 函數

第二,冒泡排序是穩定的排序算法嗎?優化

在冒泡排序中,只有交換才能夠改變兩個元素的先後順序。爲了保證冒泡排序算法的穩定spa

性,當有相鄰的兩個元素大小相等的時候,咱們不作交換,相同大小的數據在排序先後不會code

改變順序,因此冒泡排序是穩定的排序算法。blog

第三,冒泡排序的時間複雜度是多少?排序

最好狀況下,要排序的數據已是有序的了,咱們只須要進行一次冒泡操做,就能夠結束 了,因此最好狀況時間複雜度是 O(n)。而最壞的狀況是,要排序的數據恰好是倒序遞歸

排列 的,咱們須要進行 n 次冒泡操做,因此最壞狀況時間複雜度爲 O(n2)。 get

冒泡排序優化(沒有交換,提早退出)

// 冒泡排序,a 表示數組,n 表示數組大小 
public void bubbleSort(int[] a, int n) {
    if (n <= 1) return; for (int i = 0; i < n; ++i) { // 提早退出冒泡循環的標誌位 boolean flag = false; for (int j = 0; j < n - i - 1; ++j) { if (a[j] > a[j+1]) { // 交換 int tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; flag = true; // 表示有數據交換 }  } if (!flag) break; // 沒有數據交換,提早退出  } }

 

遞歸

遞歸須要知足的三個條件:

1. 一個問題的解能夠分解爲幾個子問題的解,何爲子問題?子問題就是數據規模更小的問題。

2. 這個問題與分解以後的子問題,除了數據規模不一樣,求解思路徹底同樣

3. 存在遞歸終止條件:把問題分解爲子問題,把子問題再分解爲子子問題,一層一層分解下去,不能存在無限循環,這就須要有終止條件。

基本公式

f(n) = f(n-1)+f(n-2)

遞歸代碼要警戒重複計算

除此以外,使用遞歸時還會出現重複計算的問題。例如 f(6) = f(5) + f(4) , f(7) = f(6) + f(5) , 能夠看到計算f(6) 和 f(7) 的時候,明顯的重複計算了f(5)。

public int f(int n) {
    if (n == 1) return 1;
    if (n == 2) return 2;
    // hasSolvedList 能夠理解成一個 Map,key 是 n,value 是 f(n)
    if (hasSolvedList.containsKey(n)) {
        return hasSovledList.get(n);
    }
    int ret = f(n-1) + f(n-2);
    hasSovledList.put(n, ret);
    return ret;
}        

遞歸還有不少其餘問題,例如在時間效率上,遞歸代碼裏多了不少函數調用,當這些函數調用的數量較大時,就會積聚成 一個可觀的時間成本。

相關文章
相關標籤/搜索