Skip to content

Latest commit

 

History

History
358 lines (290 loc) · 8.35 KB

215.Kth_Largest_Element_in_an_Array.md

File metadata and controls

358 lines (290 loc) · 8.35 KB
  1. Kth Largest Element in an Array 难度 中等

https://leetcode-cn.com/problems/kth-largest-element-in-an-array/

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

相关企业

Facebook|122

字节跳动|18

亚马逊 Amazon|18

领英 LinkedIn|17

微软 Microsoft|8

相关标签

  • Array
  • Divide and Conquer
  • Quickselect
  • Sorting
  • Heap (Priority Queue)

相似题目

  • Wiggle Sort II 中等
  • Top K Frequent Elements 中等
  • Third Maximum Number 简单
  • Kth Largest Element in a Stream 简单
  • K Closest Points to Origin 中等

4 methods

  • Sort: Time O(nlogn); Space O(logn)
  • Partition: Time O(n); Space O(logn)
  • Priority Queue: O(nlogk); O(k)
  • Heap: O(n + klogn); O(logn)

Slow: sort, Time O(nlogn); Space O(logn)

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        nums = sorted(nums, reverse=True)
        return nums[k-1]

Partition, Time O(n); Space O(logn)

python

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        numslen = len(nums)
        if not nums or k < 1 or k > numslen:
            return -1
        
        # k largest == len-k+1 smallest
        return self.partition(nums, 0, numslen - 1, numslen - k)


    def partition(self, nums, start, end, k):
        # it has been guranteed start <= k <= end
        if start >= end:
            return nums[k]
        
        left = start
        right = end 
        pivotvalue = nums[(start + end) // 2]

        while left <= right:
            while left <= right and nums[left] < pivotvalue:
                left += 1
            while left <= right and nums[right] > pivotvalue:
                right -= 1

            if left <= right:
                nums[left], nums[right] = nums[right], nums[left]                
                left += 1
                right -= 1

        # this also works
        # self.partition(nums, start, right, k)
        # self.partition(nums, left, end, k)

        # faster than above one, not complete array need to be sorted, partial sorted is enough
        if k <= right: 
            self.partition(nums, start, right, k)
        if k >= left: 
            self.partition(nums, left, end, k)

        return nums[k]

java

class Solution {
    public int findKthLargest(int[] nums, int k) {
        if (nums == null || nums.length == 0 || k < 1 || k > nums.length){
            return -1;
        }

        return this.partition(nums, 0, nums.length-1, nums.length-k);
    }

    private int partition(int[] nums, int start, int end, int k){
        if (start >= end){
            return nums[k];
        } 

        int left = start;
        int right = end;
        int pivotvalue = nums[(start + end) / 2];

        while (left <= right){
            while (left <= right && nums[left] < pivotvalue){
                left ++;
            }
            while (left <= right && nums[right] > pivotvalue){
                right --;
            }

            if (left <= right){
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left ++;
                right --;
            }
        }

        if (k <= right) {
            return this.partition(nums, start, right, k);
        }
        if (k >= left) {
            return this.partition(nums, left, end, k);
        }
        return nums[k];
    }
}

cpp

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        if (nums.size() == 0 || k < 1 || k > nums.size()){
            return -1;
        }

        return this->partition(nums, 0, nums.size()-1, nums.size()-k);
    }

private:
    int partition(vector<int>& nums, int start, int end, int k){
        if (start >= end){
            return nums[k];
        }

        int left = start, right = end;
        int pivotvalue = nums[(start + end) / 2];

        while (left <= right){
            while (left <= right && nums[left] < pivotvalue){
                left ++;
            }
            while (left <= right && nums[right] > pivotvalue){
                right --;
            }

            if (left <= right){
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left ++;
                right --;
            }
        }

        if (k <= right) { return this->partition(nums, start, right, k); }
        if (k >= left) { return this->partition(nums, left, end, k); }
        return nums[k];
    }
};

go

func findKthLargest(nums []int, k int) int {
    if (nums == nil || len(nums) == 0 || k < 1 || k > len(nums)){
        return -1;
    }

    return partition(nums, 0, len(nums)-1, len(nums)-k);
}

func partition(nums []int, start int, end int, k int) int{
    if (start >= end){
        return nums[k];
    }

    left := start
    right := end
    pivotvalue := nums[(start + end) / 2]

    for (left <= right){
        for (left <= right && nums[left] < pivotvalue){
            left ++;
        }
        for (left <= right && nums[right] > pivotvalue){
            right --;
        }

        if (left <= right){
            nums[left], nums[right] = nums[right], nums[left];
            left ++;
            right --;
        }
    }

    if (k <= right) { return partition(nums, start, right, k); }
    if (k >= left) { return partition(nums, left, end, k); }
    return nums[k];
}

Priority queue: O(nlogk); O(k)

Priority queue is an abstract data type. It has multiple ways to implement it. Java and cpp have built-in implementations for it.

(Python queue.PriorityQueue is for messages. Not for general Priority Queue here.)

java

class Solution {
    public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>(); // init a pq 
        // ordered by natural order

        for (int num: nums){
            pq.offer(num); //insert and sort
            if (pq.size() > k) {
                pq.poll(); // rm head (smallest)
            }
        }
        return pq.peek(); // get head (smallest)
    }
}

cpp

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        if (nums.size() == 0 || k < 1 || k > nums.size()){
            return -1;
        }

        std::priority_queue<int, std::vector<int>, std::greater<int>> pq; // head/top is smallest
        for (int i = 0; i < nums.size(); i ++){
            pq.push(nums[i]); // insert and sort
            if (pq.size() > k){
                pq.pop();
            }
            
        }
        return pq.top();
    }
};

Heap: O(n + klogn); O(logn)

Time O(n) for building heap. O(klogn) for deleting. Space O(logn) because of the recursively using space.

python

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

Go

Go has a heap package but you still need to implement some function for it when using.

import "container/heap"

// heap asks for implementation of Len() Less() Swap() Push() Pop()

type myMinIntHeap []int 

func (h myMinIntHeap) Len() int { return len(h) }
func (h myMinIntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h myMinIntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *myMinIntHeap) Push(x interface{}){
    *h = append(*h, x.(int))
}

func (h *myMinIntHeap) Pop() interface{}{
    old := *h
    n := len(old)
    lastelem := old[n-1]
    *h = old[0 : n-1]
    return lastelem;
}

func findKthLargest(nums []int, k int) int {
    if (nums == nil || len(nums) == 0 || k < 1 || k > len(nums)){
        return -1;
    }

    hp := &myMinIntHeap{}
    heap.Init(hp)
    for _, num := range nums {
        heap.Push(hp, num)
        if hp.Len() > k {
            heap.Pop(hp)
        }
    }
    return heap.Pop(hp).(int)
}