代码改变世界

[LeetCode] 215. Kth Largest Element in an Array_Medium tag: sort, Heap, quickSort

2021-06-28 09:04  Johnson_强生仔仔  阅读(42)  评论(0编辑  收藏  举报

Given an integer array nums and an integer k, return the kth largest element in the array.

Note that it is the kth largest element in the sorted order, not the kth distinct element.

 

Example 1:

Input: nums = [3,2,1,5,6,4], k = 2
Output: 5

Example 2:

Input: nums = [3,2,3,1,2,4,5,5,6], k = 4
Output: 4

 

Constraints:

  • 1 <= k <= nums.length <= 104
  • -104 <= nums[i] <= 104

 

Ideas:

1. sort   T: O(n * lgn)    S: O(1)

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        nums.sort()
        return nums[len(nums) - k]

 

2. 利用heap, 维持一个size为k的heap,每次insert都是lgk的时间,所以T: O(n * lgk)    S: O(k)

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        return heapq.nlargest(k, nums)[-1]

 

3. 利用quicksort的思想来快速sort, 这样来关心最后n - k 的sort的顺序。只要保证n - k的数在相应的位置上即可,不用担心n- k 前面的数到底是不是sort了。

T: average O(n), worst O(n ^ 2)

参考quickSort use two pointers to decrease Time into O(n * lgn ) or O(n), 跟这个题目的做法一样[LeetCode] 973. K Closest Points to Origin_Medium tag: Sort, heap, quickSort

code

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        n = len(nums)
        l, r = 0, n - 1
        while l < r:
            index = self.partition(nums, l, r)
            if index == n - k:
                return nums[index]
            elif index < n - k:
                l = index + 1
            else:
                r = index - 1
        return nums[l]
    
    def partition(self, nums, l, r):
        pivot = nums[r]
        index = l
        for i in range(l, r):
            if nums[i] < pivot:
                nums[i], nums[index] = nums[index], nums[i]
                index += 1
        
        nums[index], nums[r] = nums[r], nums[index]
        return index

 Update on 10/23/2023,  利用更多的space,来让code变得更加concise,是相同的逻辑(可以考虑面试先用这个,如果面试官需要inplace,可以再用上面的方法)

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        nums = [-num for num in nums]
        return (- 1) * self.quickSelect(nums, k)
    
    def quickSelect(self, nums, k):
        pivot = random.choice(nums)
        left = [v for v in nums if v < pivot]
        eq = [v for v in nums if v == pivot]
        right = [v for v in nums if v > pivot]
        if k <= len(left):
            return self.quickSelect(left,  k)
        if len(left) + len(eq) < k:
            return self.quickSelect(right, k - len(left) - len(eq))
        return pivot