選擇排序也是利用了「擋板法」這個經典思想。java
擋板左邊是已排序區間,右邊是未排序區間,那麼每次的「選擇」是去找右邊未排序區間的最小值,找到以後和擋板後面的第一個值換一下,而後再把擋板往右移動一位,保證排好序的這些元素在擋板的左邊。git
好比以前的例子:{5, 2, 0, 1}github
咱們用一個擋板來分隔數組是否排好序,
用指針 j 來尋找未排序區間的最小值;算法
第一輪 j 最初指向 5,而後遍歷整個未排序區間,最終指向 0,那麼 0 就和擋板後的第一個元素換一下,也就是和 5 交換一下位置,擋板向右移動一位,結束第一輪。api
第二輪,j 從擋板後的2開始遍歷,最終指向1,而後1和擋板後的第一個元素 2 換一下,擋板向右移動一位,結束第二輪。數組
第三輪,j 從2開始遍歷,最終指向2,而後和2本身換一下,擋板向右移動一位,結束第三輪。學習
還剩一個元素,不用遍歷了,就結束了。優化
選擇排序與以前的插入排序對比來看,要注意兩點:spa
因此選擇排序的擋板左邊最開始不能有任何元素。指針
class Solution { public void selectionSort(int[] input) { if(input == null || input.length <= 1) { return; } for(int i = 0; i < input.length - 1; i++) { int minValueIndex = i; for(int j = i + 1; j < input.length; j++) { if(input[j] < input[minValueIndex]) { minValueIndex = j; } } swap(input, minValueIndex, i); } } private void swap(int[] input, int x, int y) { int tmp = input[x]; input[x] = input[y]; input[y] = tmp; } }
最內層的 if 語句每執行一次是 O(1) ,那麼要執行多少次呢?
因此加起來,總共是:
(n-1) + (n-2) + … + 1 = n*(n-1) / 2 = O(n^2)
是這樣算出來的,而不是一拍腦殼說兩層循環就是 O(n^2).
這個很簡單,最多的狀況是 call swap() 的時候,而後 call stack 上每一層就用了幾個有限的變量,因此是 O(1)。
那天然也是原地排序算法了。
這個答案是否認的,選擇排序並無穩定性。
由於交換的過程破壞了原有的相對順序,好比: {5, 5, 2, 1, 0} 這個例子,第一次交換是 0 和 第一個 5 交換,因而第一個 5 跑到了數組的最後一位,且再也無翻身之地,因此第一個 5 第二個 5 的相對順序就已經打亂了。
這個問題在石頭哥的那篇谷歌面經文章裏有被考到哦,若是尚未看過這篇面經文章的,在公衆號裏回覆「谷歌」二字,就能夠看到了。
選擇排序的其中一步是選出每一輪的最小值,那麼這一步若是使用 heapify() 來優化,就能夠從 O(n) 優化到 O(logn),這其實就變成了 heapSort.
若是你喜歡這篇文章,記得給我點贊留言哦~大家的支持和承認,就是我創做的最大動力,咱們下篇文章見!
我是小齊,紐約程序媛,終生學習者,天天晚上 9 點,雲自習室裏不見不散!
更多幹貨文章見個人 Github: https://github.com/xiaoqi6666...