【力扣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发现接不了码注册不了了,可恶,浪费我学习时间,呸!
相关推荐
小爬虫程序猿24 分钟前
如何利用Python解析API返回的数据结构?
数据结构·数据库·python
m0_571957582 小时前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
龙鸣丿2 小时前
Linux基础学习笔记
linux·笔记·学习
pianmian14 小时前
python数据结构基础(7)
数据结构·算法
Nu11PointerException4 小时前
JAVA笔记 | ResponseBodyEmitter等异步流式接口快速学习
笔记·学习
亦枫Leonlew6 小时前
三维测量与建模笔记 - 3.3 张正友标定法
笔记·相机标定·三维重建·张正友标定法
考试宝6 小时前
国家宠物美容师职业技能等级评价(高级)理论考试题
经验分享·笔记·职场和发展·学习方法·业界资讯·宠物
好奇龙猫6 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
sp_fyf_20247 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
ChoSeitaku7 小时前
链表交集相关算法题|AB链表公共元素生成链表C|AB链表交集存放于A|连续子序列|相交链表求交点位置(C)
数据结构·考研·链表