leetcode刷題 2 排序(待更新)

2022-08-22 09:48:11 字數 3637 閱讀 6698

參考五分鐘學演算法

穩定性:假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次序保持不變,即在原序列中,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指占用額外記憶體 冒泡,插入,歸併排序都是保證穩定性的,其他都不是 現代作業系統很少使用堆排序,因為它無法利用區域性性原理進行快取,也就是陣列元素很少和相鄰的元素進行比較和交換。快速排序是最快...