前言
- 局势紧迫起来了呀,同学们都开始找实习了,赶紧刷完hot100开找了
215. 数组中的第K个最大元素 - 力扣(LeetCode)
-
计数排序:O(max(n,S))
-
class Solution: def findKthLargest(self, nums: List[int], k: int) -> int: # 使用计数排序 # 统计数的范围 # -- 根据计数排序,还需统计数的范围,设定max-min+1的0值数组长度,且统计数时下标刚好-min来衡量 # 本题已明确表明nums[i]范围为-10000-10000 因此可设定数组长度为20001 count = [0] * 20001 # 统计数组中每个值出现的次数 for num in nums: count[num + 10000] += 1 # 因为要找数组中第k个最大的元素,因此从后往前遍历 寻找第k个最大的 cnt = 0 for i in range(len(count)-1, -1,-1): cnt += count[i] if cnt >= k: return i - 10000
-
-
最小堆:O(nlogk)
-
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)
-
# 快排模板 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)
-
347. 前 K 个高频元素 - 力扣(LeetCode)
- 参考郁郁雨学姐的题解
-
计数器:O(nlogn)
-
# 补充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)
-
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)
295. 数据流的中位数 - 力扣(LeetCode)
-
最小堆 + 最大堆
- 参考K神题解
-
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发现接不了码注册不了了,可恶,浪费我学习时间,呸!