数组中第K个最大元素

2023-12-26T16:38:16.png
这道题目我面试的时候,至少遇到过两次,原理都懂,但是面试的时候每次写都能墨迹好久,下面用两种方式解该题(下面的解法leetcode会超时,暂时先不管)
用堆排序解决,需要清楚父节点和左右子节点对应的索引关系,建堆的时候需要保证父节点的value大于两个子节点的value:

class Solution:
    # left = parent*2 + 1, right = parent*2 + 2
    def swap_heap(self,nums,index):
        n = len(nums)
        if index < n:
            parent_value = nums[index]
            left_flag = False
            right_flag = False
            left = index*2 + 1
            if left < n:
                left_flag = True
            right = index*2 + 2
            if right < n:
                right_flag = True
            max_value = max(parent_value, nums[left] if left_flag else parent_value, nums[right] if right_flag else parent_value)
            if left_flag and max_value == nums[left]:
                nums[index] = nums[left]
                nums[left] = parent_value
                self.swap_heap(nums,left)
            elif right_flag and max_value == nums[right]:
                nums[index] = nums[right]
                nums[right] = parent_value
                self.swap_heap(nums,right)
    
    def create_heap(self,nums):
        index = len(nums)-1
        while index >= 0:
            self.swap_heap(nums,index)
            index -=1  
    
    def print_heap(self,nums,k):
        cur_value = -1
        while k >0:
            cur_value = nums[0]
            nums[0] = nums[-1]
            nums = nums[:-1]
            self.swap_heap(nums,0)
            k -= 1
        return cur_value


    def findKthLargest(self, nums: List[int], k: int) -> int:
        self.create_heap(nums)
        return self.print_heap(nums,k)

用快速排序的方法解:

class Solution:

    def partition_func(self,nums):
        target = nums[0]
        i = 1
        j = 0
        while i < len(nums):
            if nums[i] > target:
                j += 1
                temp = nums[j]
                nums[j] = nums[i]
                nums[i] = temp
            i += 1
        nums[0] = nums[j]
        nums[j] = target
        return j

    def findKthLargest(self, nums: List[int], k: int) -> int:
        index = self.partition_func(nums)
        if index + 1 == k:
            return nums[index] 
        if index+1 < k:
            return self.findKthLargest(nums[index+1:],k-index-1)
        else:
            return self.findKthLargest(nums[:index],k)

查找和最小的 K 对数字

2024-01-07T23:48:46.png
理解起来很简单,所有的pair有$len(nums1)*len(nums2)$个,即如下所示:
2024-01-08T00:19:39.png
2024-01-08T00:21:30.png
参考 【宫水三叶】详解「多路归并」&「二分」两种思路, 多路归并技巧总结 🔥🔥🔥

class Solution:
    def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
        ret = []
        flag = False
        # 第一个数组越小,归并的数量越小,时间复杂度越低
        if len(nums1) > len(nums2):
            flag = True
            nums1,nums2 = nums2,nums1
        pq = []
        # 用第一排的数来建堆,如果需要的k个pair小于并列数,取k
        for i in range(min(len(nums1),k)):
            heapq.heappush(pq,(nums1[i] + nums2[0], i, 0))
        while len(ret) < k and pq:
            # 出堆
            _, a, b = heapq.heappop(pq)
            # 保证存放按原始位置
            ret.append([nums2[b], nums1[a]] if flag else [nums1[a], nums2[b]])
            # 进堆
            if b+1 < len(nums2):
                heapq.heappush(pq, (nums1[a] + nums2[b + 1], a, b + 1))
        return ret