215.第K个最大的数

2019-08-06  本文已影响0人  建设路寡妇村村长

问题描述

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

解题思路

首先能想到的是最笨的方法,即,我们先将整个数组进行排序,然后取倒数第k个数。但是,再我将代码写好后,提交到 leetcode上时,我发现它会提示我“超时”(-v-)...
然后我就去看了其他人的一些思路,比较典型的就有堆排序算法以及快速选择算法。下面就来介绍一下这两种算法。

具体代码

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        #返回数组中第k个最大元素,也就是数组升序排序后,从右往左数的第k个数字

        # # 法1.使用Python内置的sorted,这个得知道
        # return sorted(nums)[-k]

        # # 法2.调用包,使用堆排序,速度相当快。
        # import heapq
        # return heapq.nlargest(k,nums)[-1];

        # 法3.使用堆排序:查找第k大的数值
        def maxHeapify(nums, st_idx, ed_idx):
            # 最大堆调整,将堆的末端子节点作调整,使得子节点永远小于父节点
            index = st_idx
            # 不断地向下调整
            while True:
                index = 2 * st_idx + 1
                # 如果调整到最后部分,就跳出
                if index > ed_idx:
                    break
                # 如果左孩子小于右孩子,则index变成右孩子
                if index + 1 <= ed_idx and nums[index + 1] > nums[index]:
                    index += 1
                # 如果左孩子大于父节点,则互换
                if nums[index] > nums[st_idx]:
                    nums[st_idx], nums[index] = nums[index], nums[st_idx]
                    st_idx = index
                else:
                    break
        # 创建大根堆
        for idx in range((len(nums) - 2) // 2, -1, -1):
            maxHeapify(nums, idx, len(nums) - 1)

        # 交换堆顶与堆尾 
        for head_end in range(len(nums)-1, 0, -1):
            nums[head_end], nums[0] = nums[0], nums[head_end]
            maxHeapify(nums, 0, head_end-1)
            if len(nums)-head_end == k:      # 遇到倒序个数就是k的话就返回
                return nums[head_end]      
        return nums[0]                     
class Solution:
    def findKthLargest(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        def partition(left, right, pivot_index):
            pivot = nums[pivot_index]
            nums[pivot_index], nums[right] = nums[right], nums[pivot_index]  
            
         
            store_index = left
            for i in range(left, right):
                if nums[i] < pivot:
                    nums[store_index], nums[i] = nums[i], nums[store_index]
                    store_index += 1

            nums[right], nums[store_index] = nums[store_index], nums[right]  
            
            return store_index
        
        def select(left, right, k_smallest):
            
            if left == right:     
                return nums[left]  
            
            pivot_index = random.randint(left, right)     
                                  
            pivot_index = partition(left, right, pivot_index)
            
            if k_smallest == pivot_index:
                 return nums[k_smallest]
            elif k_smallest < pivot_index:
                return select(left, pivot_index - 1, k_smallest)
            else:
                return select(pivot_index + 1, right, k_smallest)

        return select(0, len(nums) - 1, len(nums) - k)

上一篇下一篇

猜你喜欢

热点阅读