• 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
  • 相关阅读:
    【实习】vue input下拉及搜索功能
    JAVA向上转型和向下转型
    编译原理FIRSTVT和LASTVT
    生鲜蔬果社区团购商城小程序的作用是什么
    【快应用】manifest文件配置权限出错总结
    Visual Studio 2022下载安装及使用教程
    怎样将Vue+SpringBoot项目发布到阿里云服务器
    【PID优化】基于萤火虫算法PID控制器优化设计含Matlab源码
    Mybatis 10
    关于vue首屏加载loading问题
  • 原文地址:https://blog.csdn.net/navicheung/article/details/134194878