よくある質問:無秩序配列のk番目に大きい数(python)
考え方1:暴力解法
配列を並べ替えてk番目の位置を見つけます
アルゴリズムの時間的複雑度はO(N log N),空間的複雑度はO(1)である.
考え方2:速排思想を利用する
(https://blog.csdn.net/wenqiwenqi123/article/details/81669899)クイックソートは、1つの要素を正しい位置に交換するたびに、左の要素を大きくし、右の要素を小さくします.このアルゴリズムは毎回ピボットを選択し、ソートした後、ピボットの位置を表示します.その位置がKより大きい場合、前のサブシーケンスのK番目の大きな要素が要求されることを示す.逆に、Kより小さい場合は、後のシーケンスのK番目〜前のシーケンスの長さの要素が要求されることを示す.
このようにして、この問題を速い考えで解決できる問題に変えた.高速ソートの場合、アルゴリズムの複雑さはO(N*logN)である.このアルゴリズムのアルゴリズム複雑度はO(N)である.どうしてですか.
実はこの場所のアルゴリズムの複雑さの分析はとても面白いです.1回目の交換はアルゴリズム複雑度がO(N)であり,次のプロセスは高速ソートとは異なり,高速ソートは両側のデータを処理し続け,再結合し,合成操作のアルゴリズム複雑度がO(1)であるため,総アルゴリズム複雑度がO(N*logn)である(このように理解でき,交換ごとにN,合計logn回用いられる).しかし,ここではピボットの相対位置(Kの左または右)を決定した後,残りの半分を処理する必要はない.つまり,2回目の挿入アルゴリズムの複雑さはO(N)ではなくO(N/2)であるということは同じではないか.実は違います.次のプロセスは1+1/2+1/4+...<2です.言い換えれば、O(2 N)のアルゴリズム複雑度、つまりO(N)のアルゴリズム複雑度です.
考え方3:ソートの挿入
k個の最大数を探すので、すべての数を完全にソートする必要はありません.k個の現在の最大数だけを保持するたびに、新しく来た要素を現在のk個のツリーの最小数と比較するたびに、新しい要素が大きい場合は配列に挿入し、そうでない場合はスキップします.サイクル終了後の配列の最小数は、k番目に大きい数を見つけることです.時間複雑度(n-k)logk
考え方4:スタックソート
kサイズの最小スタックを維持し、配列の各要素についてスタックトップのサイズを判断し、スタックトップが大きい場合は無視し、そうでない場合は、スタックトップをポップアップし、現在の値をスタックに挿入し、最小スタックを調整し続けます.時間複雑度O(n*logk)
1つ目:ライブラリ関数の使用
第二種類:手動で積み上げる
配列を並べ替えてk番目の位置を見つけます
sorted(nums)[-k]
アルゴリズムの時間的複雑度はO(N log N),空間的複雑度はO(1)である.
考え方2:速排思想を利用する
(https://blog.csdn.net/wenqiwenqi123/article/details/81669899)クイックソートは、1つの要素を正しい位置に交換するたびに、左の要素を大きくし、右の要素を小さくします.このアルゴリズムは毎回ピボットを選択し、ソートした後、ピボットの位置を表示します.その位置がKより大きい場合、前のサブシーケンスのK番目の大きな要素が要求されることを示す.逆に、Kより小さい場合は、後のシーケンスのK番目〜前のシーケンスの長さの要素が要求されることを示す.
このようにして、この問題を速い考えで解決できる問題に変えた.高速ソートの場合、アルゴリズムの複雑さはO(N*logN)である.このアルゴリズムのアルゴリズム複雑度はO(N)である.どうしてですか.
実はこの場所のアルゴリズムの複雑さの分析はとても面白いです.1回目の交換はアルゴリズム複雑度がO(N)であり,次のプロセスは高速ソートとは異なり,高速ソートは両側のデータを処理し続け,再結合し,合成操作のアルゴリズム複雑度がO(1)であるため,総アルゴリズム複雑度がO(N*logn)である(このように理解でき,交換ごとにN,合計logn回用いられる).しかし,ここではピボットの相対位置(Kの左または右)を決定した後,残りの半分を処理する必要はない.つまり,2回目の挿入アルゴリズムの複雑さはO(N)ではなくO(N/2)であるということは同じではないか.実は違います.次のプロセスは1+1/2+1/4+...<2です.言い換えれば、O(2 N)のアルゴリズム複雑度、つまりO(N)のアルゴリズム複雑度です.
def quicksort(num ,low ,high): #
if low< high:
location = partition(num, low, high)
quicksort(num, low, location - 1)
quicksort(num, location + 1, high)
def partition(num, low, high):
pivot = num[low]
while (low < high):
while (low < high and num[high] > pivot):
high -= 1
while (low < high and num[low] < pivot):
low += 1
temp = num[low]
num[low] = num[high]
num[high] = temp
num[low] = pivot
return low
def findkth(num,low,high,k): # k
index=partition(num,low,high)
if index==k:return num[index]
if index<k:
return findkth(num,index+1,high,k)
else:
return findkth(num,low,index-1,k)
pai = [2,3,1,5,4,6]
# quicksort(pai, 0, len(pai) - 1)
print(findkth(pai,0,len(pai)-1,0))
考え方3:ソートの挿入
k個の最大数を探すので、すべての数を完全にソートする必要はありません.k個の現在の最大数だけを保持するたびに、新しく来た要素を現在のk個のツリーの最小数と比較するたびに、新しい要素が大きい場合は配列に挿入し、そうでない場合はスキップします.サイクル終了後の配列の最小数は、k番目に大きい数を見つけることです.時間複雑度(n-k)logk
def Find_Kth_max(array,k):
for i in range(1,k):
for j in range(i,0,-1):
if array[j] > array[j-1]:
array[j],array[j-1] = array[j-1],array[j]
else:
pass
for i in range(k,len(array)):
if array[i] > array[k-1]:
array[k-1] = array[i]
for j in range(k-1,0,-1):
if array[j] > array[j-1]:
array[j],array[j-1] = array[j-1],array[j]
else:
pass
return array[k-1]
print(Find_Kth_max([2,1,4,3,5,9,8,0,1,3,2,5],3))
考え方4:スタックソート
kサイズの最小スタックを維持し、配列の各要素についてスタックトップのサイズを判断し、スタックトップが大きい場合は無視し、そうでない場合は、スタックトップをポップアップし、現在の値をスタックに挿入し、最小スタックを調整し続けます.時間複雑度O(n*logk)
1つ目:ライブラリ関数の使用
class Solution:
def findKthLargest(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
return heapq.nlargest(k, nums)[-1]
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
heap = []
for x in nums:
heapq.heappush(heap, x)
if len(heap) > k:
heapq.heappop(heap)
return heapq.heappop(heap) # [5,6]
第二種類:手動で積み上げる
def heap_build(parent,heap):
child = 2*parent+1
while child<len(heap):
if child+1<len(heap) and heap[child+1]<heap[child]:
child = child+1
if heap[parent]<= heap[child]:
break
heap[parent],heap[child] = heap[child],heap[parent]
parent,child = child,2*child+1
return heap
def Find_heap_kth(array,k):
if k > len(array):
return None
heap = array[:k]
for i in range(k,-1,-1):
heap_build(i,heap)
for j in range(k,len(array)):
if array[j]>heap[0]:
heap[0] = array[j]
heap_build(0,heap)
return heap[0]
print(Find_heap_kth([2,1,4,3,5,9,8,0,1,3,2,5],6))