• 【Leetcode】215. 数组中的第K个最大元素


     方法一:

    这个题目首先一看就有两个方法,一个是使用基于树的算法,也就是heap堆排序,经过一番奇巧淫技之后,时间复杂度是O(n*log k)。另一个就是使用数组的算法,可以选择的算法有选择排序O(n^2),快速排序O(nlogn),冒泡排序O(n^2)或者插入排序O(n^2)等等。那么本题目最快的方法就是使用一个不太寻常的heap sort,或者使用基于数组的sort。首先我们用最容易想到的,基于数组的sort,代码如下:

    class Solution:
        def findKthLargest(self, nums: List[int], k: int) -> int:
            #这个题目显然可以使用heap来完成
            sort_list=sorted(nums)
            return sort_list[-k]

    然后来看看结果:

     不会吧不会吧!竟然打败了97%的用户???据我所知,python的sorted函数其实使用了快速排序,那么时间复杂度是O(nlogn),那我们用时间复杂度更小的heap sort来试试看?

     方法二:

    我们直接使用python当中heap的库,这样使用起来更方便一点,不然就要手撕heap了!我们将所有的元素加入进heap当中,进行排序,时间复杂度是O(nlogn)代码如下:

    class Solution:
        def findKthLargest(self, nums: List[int], k: int) -> int:
            heap = []
            for num in nums:
                heapq.heappush(heap, num)
                if len(heap) > k:
                    heapq.heappop(heap)
            return heap[0]

    最终的运行结果如下:

     方法三:

    这居然连快速排序还不如....显然不是最优的解法,我们使用第三种解法,对heap进行不同的处理,最后的时间复杂度是O(nlogk),由于Python自带的heapq模块只能够建立小顶堆,也就是min-heap,无法建立max-heap。我们速度最快的这种方法是使用的max-heap才能够达到这样的时间复杂度,而Python的heapq以及sorted底层都是用速度飞快的C语言实现的,我如果用Python手撸一个max—heap,最后可能还比不上Python自带的sorted或者heapq。尝试了一下的代码如下,使用数组实现heap:

    class Solution:
        def findKthLargest(self, nums: List[int], k: int) -> int:
            heap = Heap(k + 1)
            for num in nums:
                if not heap.push(num):
                    heap.pop()
                    heap.push(num)
            if heap.size == k + 1:
                heap.pop()
            return heap.peek()
            
    class Heap:
        def __init__(self, length):
            self.heap = [0] * (length + 1)
            self.size = 0
        
        def push(self, val):
            if self.size == len(self.heap) - 1:
                return False
            self.size += 1
            self.heap[self.size] = val
            self.shift_up(self.size)
            return True
        
        def pop(self):
            val = self.heap[1]
            self.heap[1] = self.heap[self.size]
            self.heap[self.size] = 0
            self.size -= 1
            self.shift_down(1)
            return val
        
        def peek(self):
            return self.heap[1]
        
        def shift_up(self, i):
            val = self.heap[i]
            while i >> 1 > 0:
                parent = i >> 1
                if val < self.heap[parent]:
                    self.heap[i] = self.heap[parent]
                    i = parent
                else:
                    break
            self.heap[i] = val
        
        def shift_down(self, i):
            val = self.heap[i]
            while i << 1 <= self.size:
                child = i << 1
                if child != self.size and self.heap[child + 1] < self.heap[child]:
                    child += 1
                if val > self.heap[child]:
                    self.heap[i] = self.heap[child]
                    i = child
                else:
                    break
            self.heap[i] = val

    最后时间复杂度居然只打败了百分之三十的people,还真不如直接heapq和快速排序了...

  • 相关阅读:
    正则表达式的三种模式【贪婪、勉强、侵占】的分析
    php实用的文件上传类
    php简单实用的验证码生成类
    phpstorm不安装apache就可以本地测试PHP
    Ajax技术——带进度条的文件上传
    Mybatis 多表查询及查询结果映射
    关于textarea包在div的自适应问题
    Luogu P3200 [HNOI2009]有趣的数列
    群&置换群&burnside
    卡特兰树
  • 原文地址:https://www.cnblogs.com/geeksongs/p/14681832.html
Copyright © 2020-2023  润新知