參考五分鐘學演算法
穩定性:假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序後的序列中,r[i]仍在r[j]之前,則稱這種排序演算法是穩定的;否則稱為不穩定的。(相等元素相對位置不變)
45輸入乙個正整數陣列,把陣列裡所有數字拼接起來排成乙個數,列印能拼接出的所有數字中最小的乙個。
示例 1:
輸入: [10,2]
輸出: "102"
示例 2:
輸入: [3,30,34,5,9]
輸出: "3033459"
將陣列裡數字當作字串拼接起來,nm > mn那麼就交換n與m,將m移動到n的前面。選擇排序:
class solution:
def minnumber(self, nums: list[int]) -> str:
nums = [str(i) for i in nums]
for i in range(len(nums)-1):
for j in range(i+1, len(nums)):
if nums[i] + nums[j] > nums[j] + nums[i]:
nums[i],nums[j] = nums[j],nums[i]
return "".join(nums)
注意第一層迴圈到len(nums)-1
因為受到第二層迴圈i+1到 len(nums)
的限制。
參考兩個指標i,j分別從左邊和右邊往中間掃,當
nums[i]>基準
,nums[j]《基準
交換他們,最終可確定基準所在位置。這道題每次都捨棄一部分陣列,將符合條件的放入buffer中,減少了運算,也是類似的思想。
例如:求前k個元素(由小到大)
def quick_select_without_optimizer(arr, k):
n = len(arr)
# 如果k大於n,沒啥好說的,直接返回
if k >= n:
return arr
# 快取
buffer =
while arr:
# 選擇最後乙個元素作為標桿
mark = arr.pop()
less, greater = ,
# 遍歷陣列,將元素分為less和greater
for x in arr:
if x <= mark:
else:
# 判斷三種情況,如果相等直接返回
if len(less) == k:
return less
# 如果小於,將less存入buffer,因為它一定是答案的一部分,可以簡化計算
elif len(less) < k:
buffer += less
# k要減去less的長度
k -= len(less)
arr = [mark] + greater
else:
# 如果大於,直接捨棄右邊
單向掃瞄,只有j從左到右掃瞄一遍,i指向小於基準區間的最右邊,j指向大於基準區間的最左邊,如上圖。
public void qsort(int a,int begin,int end)
public int partition(int a,int p ,int r)
}swap(a, i + 1, j);
return i + 1;
}
快排的問題在於,最壞情況(逆序)下時間複雜度為o(n^2)
。發生這種情況問題在於初始值的選擇,也就是每次基準的選擇。為了解決這種情況,引入bfprt演算法(blum、floyd、pratt、rivest、tarjan五位大牛首字母)。
因此也叫中位數的中位數演算法。具體複雜度分析參考,這個演算法複雜度只有o(n)
,當然只是尋找基準,不是排序,算是快排的準備步驟。
def bfprt(arr, l=none, r=none):
if l is none or r is none:
l, r = 0, len(arr)
length = r - l
# 如果長度小於5,直接返回中位數
if length <= 5:
arr[l: r] = insert_sort(arr[l: r])
return l + length // 2
medium_num = l
start = l
# 否則每5個數分組
while start + 5 < r:
# 對每5個數進行插入排序
arr[start: start + 5] = insert_sort(arr[start: start + 5])
arr[medium_num], arr[start + 2] = arr[start + 2], arr[medium_num] #將所有的中位數都放在陣列前面
medium_num += 1
start += 5
# 特殊處理最後不足5個的情況
if start < r:
arr[start:r] = insert_sort(arr[start:r])
_l = r - start
arr[medium_num], arr[start + _l // 2] = arr[start + _l // 2], arr[medium_num]
medium_num += 1
# 遞迴呼叫,對中位數繼續求中位數
return bfprt(arr, l, medium_num)
之後再呼叫這個函式獲取基準值即可,這只是避免快排最壞情況發生,選擇基準的一種做法。接著差不多:
def quick_select(arr, k):
n = len(arr)
if k >= n:
return arr
mark = bfprt(arr) # 基準獲取
arr[mark], arr[-1] = arr[-1], arr[mark]
buffer =
while arr:
mark = arr.pop()
less, greater = ,
for x in arr:
if x <= mark:
else:
if len(less) == k:
return buffer + less
elif len(less) < k:
k -= len(less)
buffer += less
arr = [mark] + greater
else:
arr = less
leetcode刷題 演算法(2) 排序演算法(下)
排序演算法總結 2.11 kth元素 2.12 幾種方法,關鍵 堆 快排 還不是很熟練 2.出現頻率最多的 k 個元素 桶排序,未作出 3.按照字元出現次數對字串排序 同上ok 4.按顏色進行排序 ok215.kth largest element in an array medium 1.採用庫函...
刷題1 排序1
學python有一段時間了,刷題試試。題 給定兩個字串 s 和 t 編寫乙個函式來判斷 t 是否是 s 的乙個字母異位詞。1.s anagram t nagaram 輸出true 2.s rat t car 輸出false 輸出true需要滿足的條件 1.字串的個數相等 2.元素一樣 故而我的想法是...
刷題(3) 排序(1)
注意 n指資料規模 k指 桶 的個數 in place指占用常數記憶體,不占用額外記憶體 out place指占用額外記憶體 冒泡,插入,歸併排序都是保證穩定性的,其他都不是 現代作業系統很少使用堆排序,因為它無法利用區域性性原理進行快取,也就是陣列元素很少和相鄰的元素進行比較和交換。快速排序是最快...