215. Kth Largest Element in an Array - cocoder39/coco39_LC GitHub Wiki

215. Kth Largest Element in an Array

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]

Notes 2022:

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        low, high = 0, len(nums)-1
        while low <= high:
            pivot_idx = random.randint(low, high) # not sorted so not use middle 
            partition_idx = self.partition(nums, low, high, pivot_idx)
            if partition_idx == k - 1:
                return nums[partition_idx]
            elif partition_idx < k - 1:
                low = partition_idx + 1
            else:
                high = partition_idx - 1        
        return nums[k-1]
    
    # partition nums[low: high+1] such that nums[low: idx] > nums[idx] > nums[idx+1: high+1] 
    # in other words, nums[idx] is the idx+1-th largest
    def partition(self, nums: List[int], low: int, high: int, pivot_idx: int) -> int:
        # using nums[high]: working but might fall into worst case
        # using nums[idx]: working and likely to avoid worst case
        pivot = nums[pivot_idx]
        nums[pivot_idx], nums[high] = nums[high], nums[pivot_idx]
        
        
        partition_idx = low
        for i in range(low, high): # skip nums[high] intentionally
            if nums[i] > pivot:
                nums[partition_idx], nums[i] = nums[i], nums[partition_idx]
                partition_idx += 1
        nums[partition_idx], nums[high] = nums[high], nums[partition_idx]
        return partition_idx

==========================================================================================

two-way-partition. best/average case bi-partitions the array into two balanced halves, t(n) = t(n/2) + O(n) = O(1 + 2 + 4 + ... + n) = O((1 - 2*lgn) / (1-2))= O(n). However, the worst case partitions would results in t(n) = t(n-1) + O(n) = O(n^2)

tip:

  • how to use shuffle
  • how to write bug free partition
  • how to write bug free binary search

corner case is low == high, then you have to use low = p + 1 or high = p - 1 to shrink the searching range. Meanwhile, start + 1 in partition() is invalid, attention the the bug

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        shuffle(nums);
        int sz = nums.size(), low = 0, high = sz - 1;
        while (low <= high) { // low < high doesn't matter
            int p = partition(nums, low, high);
            if (p == k - 1) { // attention k - 1, not k
                return nums[p];
            } else if (p < k - 1) {
                low = p + 1; //attention p + 1 not p
            } else { // p > k
                high = p - 1; //attention p - 1 not p
            }
        }
        return nums[k - 1];
    }
private:
    void shuffle(vector<int>& nums) {
        int sz = nums.size();
        for (int i = sz - 1; i > 0; i--) {
            int j = rand() % (i + 1); // [0, i]
            swap(nums[i], nums[j]);
        }
    }
    
    int partition(vector<int>& nums, int low, int high) {
    /*  an valid implementation
        int pivot = nums[high], i = low;
        for (int j = low; j < high; j++) {
            if (nums[j] > pivot) {
                swap(nums[i++], nums[j]);
            }
        }
        swap(nums[i], nums[high]);
        return i;
    */
        int pivot = nums[low];
        int start = low + 1, end = high;
        while (start <= end) { 
            if (nums[start] > pivot) {
                start++;
            } else if (nums[end] <= pivot) {
                end--;
            } else {
                swap(nums[start++], nums[end--]);
            }
        }
        /* a buggy implementation
        swap(nums[low], nums[start]); //start is not guaranteed valid
        return start;
        */
        swap(nums[low], nums[end]);
        return end;
    }
};

time complexity of using sorting is O(n logn)

using priority_queue is O(n lgk)

int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int> pq;
        for (int i = 0; i < nums.size(); i++) {
            pq.push(-nums[i]);
            if (pq.size() > k) { //pop less than kth largest => min heap
                pq.pop();
            }
        }
        return -pq.top();
    }
⚠️ **GitHub.com Fallback** ⚠️