【力扣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发现接不了码注册不了了,可恶,浪费我学习时间,呸!
相关推荐
deardeer73 分钟前
Leetcode算法基础篇-分治算法
数据结构·算法·leetcode
乘风破浪的咸鱼君5 分钟前
2024/9/21 leetcode 19题 24题
数据结构·算法·leetcode
晚睡早起₍˄·͈༝·͈˄*₎◞ ̑̑26 分钟前
苍穹外卖学习笔记(九)
java·spring boot·笔记·mybatis
月夕花晨37433 分钟前
C++学习笔记(35)
c++·笔记·学习
小松学前端39 分钟前
第四章 4.2 时间复杂度
java·数据结构·算法·排序算法
小彭爱敲代码1 小时前
第十四届蓝桥杯嵌入式国赛
c语言·物联网·职场和发展·蓝桥杯
紧派1 小时前
计算机科学(学习笔记四)
笔记·学习
Long long 521 小时前
常见排序详解
数据结构·算法·排序算法
小周的C语言学习笔记1 小时前
鹏哥C语言49---第5次作业:选择语句 if 和 switch
c语言·开发语言·c++·算法
李妖妖的拯救者1 小时前
C语言小tip之动态内存常见错误
c语言·c++·算法