這篇博客記錄我對劍指offer第2版"面試題39:數組中出現次數超過一半的數字"題解1的一句話的一個小誤解,以及彙總一下涉及partition算法的相關題目。面試
在劍指offer第2版"面試題39:數組中出現次數超過一半的數字"的解法一(基於partition,且哨兵選擇數組第一個元素)中,有這麼一句話:
咱們有成熟的時間複雜度爲O(n)的算法獲得數組中任意第k大的數字
,這句話讓我產生了一點誤解,讓我誤覺得"只須要調用一次partition就能找到第k大的數",可是實際上最差狀況下須要調用n次partition函數才能找到第k大的數。由於partition每次都返回的是哨兵的位置,可是在函數運行過程當中,隨着l,r入參的變化,哨兵(數組首位元素)的位置是隨之變化的,具備不肯定性。算法
因此基於partition獲取數組中任意第k大元素的時間複雜度應該以下:數組
估算過程:
3.1 加權平均複雜度 = 某機率值*O(n)
3.2 機率值是常數,而後去掉常數項,得O(n)函數
partition的Go代碼以下:code
// partition代碼的時間複雜度是O(n),由於須要經過for循環遍歷數組,並把每一個元素都劃分到大分區或小分區中。 func partition(nums []int, l, r int) int { // 1. 哨兵 取第一個元素 v := nums[l] // 2. 大小分區的定義和初始化 [l+1,p]<v && [p+1,cur-1]>v p := l // 3. 處理哨兵以後的每個元素 cur := l + 1 for ; cur <= r; cur++ { if nums[cur] < v { nums[cur], nums[p+1] = nums[p+1], nums[cur] p++ } } nums[p], nums[l] = nums[l], nums[p] // 哨兵和小分區的最後一個元素交換,使得哨兵左邊是小的,右邊是大的. return p }
另外,還有如下這些算法題涉及了partition函數的運用,他們的共同特色都是須要用partition查找xxx位置的數字。索引