【力扣hot100】刷题笔记Day22

前言

  • 局势紧迫起来了呀,同学们都开始找实习了,赶紧刷完hot100开找了

215. 数组中的第K个最大元素 - 力扣(LeetCode)

最小堆: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) 
```

347. 前 K 个高频元素 - 力扣(LeetCode)

计数器: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)
```

295. 数据流的中位数 - 力扣(LeetCode)

最小堆 + 最大堆

```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发现接不了码注册不了了,可恶,浪费我学习时间,呸!
相关推荐
非 白1 小时前
数据结构——树
数据结构·笔记·考研
Dizzy.5173 小时前
数据结构(查找)
数据结构·学习·算法
E___V___E4 小时前
MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 高级篇 part 2
数据库·笔记·mysql
hello_simon4 小时前
【Word转PDF】在线Doc/Docx转换为PDF格式 免费在线转换 功能强大好用
职场和发展·pdf·word·学习方法·word转pdf·石墨文档·word转换
分别努力读书6 小时前
acm培训 part 7
算法·图论
武乐乐~6 小时前
欢乐力扣:赎金信
算法·leetcode·职场和发展
Jared_devin6 小时前
数据结构——模拟栈例题B3619
数据结构
'Debug6 小时前
算法从0到100之【专题一】- 双指针第一练(数组划分、数组分块)
算法
sushang~7 小时前
leetcode21.合并两个有序链表
数据结构·链表
Fansv5877 小时前
深度学习-2.机械学习基础
人工智能·经验分享·python·深度学习·算法·机器学习