Leetcode Day18 堆

Python中关于堆的操作

注意, python默认的是最小堆

什么时候想到用堆

A: 流!或者我们只关心k个元素

373 查找和最小的前k对数字

给定两个以 非递减顺序排列 的整数数组 nums1 和 nums2 , 以及一个整数 k 。

定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。

请找到和最小的 k 个数对 (u1,v1), (u2,v2) ... (uk,vk) 。

输入: nums1 = 1,7,11, nums2 = 2,4,6, k = 3

输出: 1,2,1,4,1,6

解释: 返回序列中的前 3 对数:

1,2\],\[1,4\],\[1,6\],\[7,2\],\[7,4\],\[11,2\],\[7,6\],\[11,4\],\[11,6

python 复制代码
class Solution:
    def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
        m = len(nums1)
        n = len(nums2)

        visited = set()
        ans = []
        h = []
        heappush(h, (nums1[0] + nums2[0], 0, 0))
        visited.add((0, 0))
        while len(ans) < k:
            num, i, j = heappop(h)
            ans.append([nums1[i], nums2[j]])
            if (i + 1, j) not in visited and i + 1 < m and j  < n:
                heappush(h, (nums1[i+1] + nums2[j], i+1, j))
                visited.add((i+1, j))

            if (i, j + 1) not in visited and i < m and j + 1 < n:
                heappush(h, (nums1[i] + nums2[j + 1], i, j + 1))
                visited.add((i, j+1))
        return ans

后面的优化就是怎么样能不用hashset

换个角度,如果要把 (i,j) 入堆,那么之前出堆的下标对是什么?

根据上面的讨论,出堆的下标对只能是 (i−1,j) 和 (i,j−1)。

只要保证 (i−1,j) 和 (i,j−1) 的其中一个会将 (i,j) 入堆,而另一个什么也不做,就不会出现重复了!

不妨规定 (i,j−1) 出堆时,将 (i,j) 入堆;而 (i−1,j) 出堆时只计入答案,其它什么也不做。

换句话说,在 (i,j) 出堆时,只需将 (i,j+1) 入堆,无需将 (i+1,j) 入堆。

但若按照该规则,初始仅把 (0,0) 入堆的话,只会得到 (0,1),(0,2),⋯ 这些下标对。

所以初始不仅要把 (0,0) 入堆,(1,0),(2,0),⋯ 这些都要入堆。

python 复制代码
class Solution:
    def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
        ans = []
        h = [(nums1[i] + nums2[0], i, 0) for i in range(min(len(nums1), k))]
        while len(ans) < k:
            _, i, j = heappop(h)
            ans.append([nums1[i], nums2[j]])
            if j + 1 < len(nums2):
                heappush(h, (nums1[i] + nums2[j + 1], i, j + 1))
        return ans

347. 前 K 个高频元素

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按任意顺序返回答案。

输入: nums = 1,1,1,2,2,3, k = 2

输出: 1,2

O ( n l o g n ) O(nlogn) O(nlogn)的算法显然很简单, 但有没有方法可以降一下这个呢? 事实上, 我们只关心前k个, 我们变能把复杂度降为 O ( n l o g k ) O(nlogk) O(nlogk), 那么能保持这个前k个元素的结构自然就是堆了.

python 复制代码
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        frequencyMap = {}
        for num in nums:
            if num in frequencyMap:
                frequencyMap[num] += 1
            else:
                frequencyMap[num] = 1

        minHeap = []
        for item, freq in frequencyMap.items():
            print(minHeap)
            if len(minHeap) < k:
                heappush(minHeap, (freq, item))
            else:
                top_node = minHeap[0]
                if freq > top_node[0]:
                    heappop(minHeap)
                    heappush(minHeap, (freq, item))
        return [num for freq, num in minHeap]

23 合并k个升序链表

python 复制代码
ListNode.__lt__ = lambda a, b: a.val < b.val  # 让堆可以比较节点大小

class Solution:
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        cur = dummy = ListNode()  # 哨兵节点,作为合并后链表头节点的前一个节点
        h = []
        for head in lists:
            if head:
                h.append(head)
        heapify(h)  # 堆化
        while h:  # 循环直到堆为空
            node = heappop(h)  # 剩余节点中的最小节点
            if node.next:  # 下一个节点不为空
                heappush(h, node.next)  # 下一个节点有可能是最小节点,入堆
            cur.next = node  # 合并到新链表中
            cur = cur.next  # 准备合并下一个节点
        return dummy.next  # 哨兵节点的下一个节点就是新链表的头节点
相关推荐
wenyq715 分钟前
LeetCode 123. Best Time to Buy and Sell Stock III
leetcode
碧海银沙音频科技研究院1 小时前
基于ATS308X的无线语音交互对话功能实现
人工智能·嵌入式硬件·深度学习·算法
尹玉玺2 小时前
从原子残片到天道公理:以德谟克利特思想全貌,重新定界西方唯物认知的历史层级与边界
人工智能·算法·架构
青少儿编程课堂2 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:差分数组与区间修改实战解析
c++·python·算法·bfs·信息学竞赛
重生之小比特2 小时前
【算法拾光】二分查找|二分查找 + 再排序数组中查找元素的第一个和最后一个位置
算法·leetcode·职场和发展
文丑颜不良啊2 小时前
LeetCode76~100题目解析
java·leetcode
零基础1233 小时前
基于模型的强化学习与不基于模型的强化学习:核心区别与实战选择
python·算法
罗西的思考14 小时前
【Agentic RL】Dressage Staleness 控制深度分析
人工智能·算法·机器学习
quaer14 小时前
弗洛伊德算法--判圈法寻找环的入口O(n) O(1)
数据结构·算法
文丑颜不良啊15 小时前
LeetCode51~75题目解析
leetcode