前言
- 局势紧迫起来了呀,同学们都开始找实习了,赶紧刷完hot100开找了
最小堆:O(nlogk)
```python
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
minheap = [] # 优先队列(最小堆),push和pop为O(logk)
for num in nums:
heapq.heappush(minheap, num) # 放入k个数,此时堆顶为最小值
if len(minheap) > k: # 超过k个数就pop掉最小值
heapq.heappop(minheap) # 剩下的就是前k大数
return minheap[0] # 堆顶就是第k大数
```
快速排序:O(n)
```python
# 快排模板
def quick_sort(arr):
if len(arr) <= 1: # 递归结束
return arr
else:
pivot = arr[0] # 选择基准值
less = [x for x in arr[1:] if x <= pivot] # 小的放左边
greater = [x for x in arr[1:] if x > pivot] # 大的放右边
return quick_sort(less) + [pivot] + quick_sort(greater) # 重新组合
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
def quick_sort(nums, k):
pivot = random.choice(nums) # 随机选择基准数防止退化成O(n2)
big, equal, small = [], [], [] # 大于、等于、小于 pivot 的元素
for num in nums:
if num > pivot:
big.append(num)
elif num < pivot:
small.append(num)
else:
equal.append(num)
# 第k大元素在big里
if k <= len(big):
return quick_sort(big, k) # 递归进big里找
# 第k大元素在small里
elif k > len(nums) - len(small):
return quick_sort(small, k - len(nums) + len(small)) # 递归进small里找
# 第k大元素在equal里,直接返回pivot
return pivot
return quick_sort(nums, k)
```
计数器:O(nlogn)
```python
# 补充Counter用法,用于统计可哈希对象(比如列表、元组等)中每个元素的出现次数
import collections
nums = [1, 2, 3, 1, 2, 1]
count = collections.Counter(nums)
# 访问元素的计数
print(count[1]) # 输出元素 1 出现的次数
# 返回出现频率最高的元素及其出现次数
most_common_elements = count.most_common(2) # 频率最高的前两个元素及其次数
print(most_common_elements)
# 更新 Counter 对象
count.update([1, 2, 3]) # 更新计数器以包括新元素
# 删除元素或重置元素计数
del count[1] # 删除元素 1 的计数
count.clear() # 清空计数器
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
count = collections.Counter(nums)
return [item[0] for item in count.most_common(k)]
```
最小堆:O(nlogk)
```python
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
mp = {} # 统计频率
for num in nums:
mp[num] = mp.get(num, 0) + 1
minheap = []
for num, freq in mp.items():
heapq.heappush(minheap, (freq, num)) # 按照频率排序
if len(minheap) > k: # 大于k就弹出最小值
heapq.heappop(minheap) # 最后剩下频率前k
return [item[1] for item in minheap] # 返回频率前k的num
```
快速排序:O(n)
```python
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
mp = {} # 统计频率
for num in nums:
mp[num] = mp.get(num, 0) + 1
# mp = collections.Counter(nums)
num_cnt = list(mp.items())
topKs = self.findTopK(num_cnt, k, 0, len(num_cnt)-1)
return [item[0] for item in topKs]
def findTopK(self, num, k, l, r):
if l >= r: return num[:k] # 递归到0/1个元素,说明已完成前k排序
pivot = random.randint(l ,r) # 随机选择基准值下标
num[pivot], num[l] = num[l], num[pivot] # 把基准数换到最左边
pivot = l # 更新基准值下标
swap_i = pivot + 1 # 用于交换较小值
for i in range(l + 1, r + 1):
if num[i][1] > num[pivot][1]: # 把大于基准数的放左边(和快排相反)
num[i], num[swap_i] = num[swap_i], num[i]
swap_i += 1
num[swap_i-1], num[pivot] = num[pivot], num[swap_i-1] # 把基准值放中间
pivot = swap_i - 1 # 此时基准值在中间
if k == pivot: # 左边正好是前k大数
return num[:k]
elif k > pivot: # 左边不足前k大数,去右边找
return self.findTopK(num, k, pivot + 1, r)
else: # 左边超过前k大数,去左边找
return self.findTopK(num, k, l, pivot - 1)
```
最小堆 + 最大堆
```python
from heapq import *
class MedianFinder:
def __init__(self):
self.A = [] # 小顶堆,保存较大的一半
self.B = [] # 大顶堆,保存较小的一半
def addNum(self, num: int) -> None:
if len(self.A) != len(self.B): # m > n,奇数,补充B
heappush(self.A, num)
heappush(self.B, -heappop(self.A)) # 淘汰下的最小值放到B里
else: # m = n,偶数,补充A
heappush(self.B, -num)
heappush(self.A, -heappop(self.B)) # 淘汰下的最大值放到A里
def findMedian(self) -> float:
if len(self.A) != len(self.B): # m > n,奇数
return self.A[0]
else: # m = n,偶数
return (self.A[0] - self.B[0]) / 2.0
```
后言
- 学快排学了好久,脑子要炸掉了,另外想注册Claude发现接不了码注册不了了,可恶,浪费我学习时间,呸!