• LeetCode //C - 215. Kth Largest Element in an Array


    215. Kth Largest Element in an Array

    Given an integer array nums and an integer k, return the k t h k^{th} kth largest element in the array.

    Note that it is the k t h k^{th} kth largest element in the sorted order, not the k t h k^{th} kth distinct element.

    Can you solve it without sorting?
     

    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 < = n u m s . l e n g t h < = 1 0 5 1 <= k <= nums.length <= 10^5 1<=k<=nums.length<=105
    • − 1 0 4 < = n u m s [ i ] < = 1 0 4 -10^4 <= nums[i] <= 10^4 104<=nums[i]<=104

    From: LeetCode
    Link: 215. Kth Largest Element in an Array


    Solution:

    Ideas:

    1. Partitioning: The array is partitioned around a randomly chosen ‘pivot’ element. Partitioning means rearranging the array so that:

    • All elements greater than the pivot come before the pivot.
    • All elements equal to the pivot come next.
    • All elements less than the pivot come last.

    2. Selection:

    • If the pivot’s position is exactly k after partitioning, then the pivot is the k-th largest element, and we return it.
    • If the pivot’s position is greater than k, we know that the k-th largest element must be to the left of the pivot, so we recursively select from the left subarray.
    • If the pivot’s position is less than k, we select from the right subarray.

    3. Three-Way Partitioning: The implementation uses a three-way partition to deal with duplicates efficiently. Instead of two partitions (less than and greater than the pivot), it creates three:

    • Elements less than the pivot.
    • Elements equal to the pivot.
    • Elements greater than the pivot.

    This is particularly efficient if there are many duplicates because it ensures that we only have to recurse on one of the partitions that actually contains the k-th largest element.

    4. Iterative Approach: Instead of the standard recursive approach used in QuickSelect, this code uses an iterative loop, which can be more space-efficient (it uses less stack space) and might be slightly faster due to less overhead from function calls.

    5. Random Pivot Selection: By randomly selecting a pivot each time we partition, we reduce the likelihood that we’ll encounter the worst-case performance of O ( n 2 ) O(n^2) O(n2) time, which can happen if we consistently pick bad pivots (such as when the array is already sorted or contains many identical elements).

    6. Random Seed Initialization: Before running QuickSelect, we initialize the random seed with srand(time(NULL)). This ensures that different runs of the program will use different seeds for the random number generator, which in turn makes it very likely that different pivot elements will be chosen in different runs.

    Code:
    void swap(int* a, int* b) {
        int temp = *a;
        *a = *b;
        *b = temp;
    }
    
    // This function partitions the array into three parts:
    // - Elements greater than the pivot
    // - Elements equal to the pivot
    // - Elements less than the pivot
    void partition(int* nums, int left, int right, int* lp, int* rp) {
        if (right - left <= 1) {
            if (nums[left] < nums[right])
                swap(&nums[left], &nums[right]);
            *lp = left;
            *rp = right;
            return;
        }
    
        int pivot = nums[right];
        int less = left; // Track start of less than pivot
        int great = right; // Track end of greater than pivot
        int i = left;
        while (i <= great) {
            if (nums[i] > pivot) {
                swap(&nums[i++], &nums[less++]);
            } else if (nums[i] < pivot) {
                swap(&nums[i], &nums[great--]);
            } else {
                i++;
            }
        }
        *lp = less; // Start of elements equal to pivot
        *rp = great; // End of elements equal to pivot
    }
    
    int quickSelect(int* nums, int left, int right, int k) {
        srand(time(NULL)); // Seed for randomness
        while (left <= right) {
            int lp, rp;
            partition(nums, left, right, &lp, &rp); // Perform the partitioning
            if (k >= lp && k <= rp) // If k is within the equal range, return the element
                return nums[k];
            else if (k < lp)
                right = lp - 1; // Discard right side
            else
                left = rp + 1; // Discard left side
        }
        return -1; // If the loop exits, the input was not valid
    }
    
    int findKthLargest(int* nums, int numsSize, int k) {
        return quickSelect(nums, 0, numsSize - 1, k - 1); // k - 1 because arrays are 0-indexed
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
  • 相关阅读:
    如何确定论文题目?
    Java_笔记_继承_虚方法表_成员变量方法构造_thisSuper
    Proxmox VE 修改集群名称
    怎么将电脑excel文档内的数据转换为图片形式
    详解集群级备份恢复:物理细粒度备份恢复
    行政管理专业如何选择合适的毕业论文题目?
    学习开发一个RISC-V上的操作系统(汪辰老师) — 01-helloRVOS程序讲解
    进阶指针(四)—— 加强对指针,数组名,sizeof,strlen的理解
    Springboot——拦截器
    基于k8s的CI/CD的实现
  • 原文地址:https://blog.csdn.net/navicheung/article/details/134194878