冒泡排序算法
第一,冒泡排序是原地排序算法嗎?數組
冒泡的過程只涉及相鄰數據的交換操做,只須要常量級的臨時空間,因此它的空間複雜度爲 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; }
遞歸還有不少其餘問題,例如在時間效率上,遞歸代碼裏多了不少函數調用,當這些函數調用的數量較大時,就會積聚成 一個可觀的時間成本。