• 【数据结构与算法】排序经典题总结


    数组中的第K个最大元素

    LeetCode:数组中的第K个最大元素

    题目描述:

    在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

    示例:

    输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
    输出: 4
    

    思想:

    方法一:优先队列:可直接使用PriorityQueue建立小根堆。遍历数组,所有元素入队,保证Queue中只有k个元素,超过k就出队,这样最后Queue中剩余的k个元素一定前k个最大元素。时间复杂度O(nlog2k),空间复杂度O(k)

    方法二:快速选择:基于快速排序的方法。这里与快排的区别在于,partition取得枢轴之后,左子表或者右子表,选一个继续操作即可,快排是左右子表都要继续递归。

    注意:由于本题存在极端样例,导致快排耗时依然很高(因为快排是越混乱,速度相对越快)。这里用到一个小技巧,partition方法中选择初始枢轴时,不直接选择low指针对应的元素,而是用随机数取一个下标

        if(high>low){
            int idx = (int)(low+1+Math.random()*(high-low));
            arr[idx]^=arr[low];
            arr[low]^=arr[idx];
            arr[idx]^=arr[low];
        }
    

    加了这一步之后,耗时击败99%。时间复杂度O(n),空间复杂度O(1)

    代码:

    方法一:优先队列

    public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        for(int item : nums){
            queue.offer(item);
            if(queue.size()>k) queue.poll();
        }
        return queue.peek();
    }
    

    方法二:快速选择

    public int findKthLargest(int[] nums, int k) {
        int low = 0;
        int high = nums.length-1;
        k = nums.length-k;
        while(low<high){
            int i = partition(nums,low,high);
            if(i==k) return nums[i];
            if(i>k) high = i - 1;
            else low = i + 1;
        }
        return nums[k];
    }
    
    private int partition(int[] arr, int low, int high){
        //这一步炒鸡关键
        if(high>low){
            int idx = (int)(low+1+Math.random()*(high-low));
            arr[idx]^=arr[low];
            arr[low]^=arr[idx];
            arr[idx]^=arr[low];
        }
        
        int pivotKey = arr[low];
        while(low<high){
            while(low<high&&arr[high]>=pivotKey) --high;
            arr[low] = arr[high];
            while(low<high&&arr[low]<=pivotKey) ++low;
            arr[high] = arr[low];
        }
        arr[low] = pivotKey;
        return low;
    }
    
  • 相关阅读:
    bzoj1257
    bzoj1833
    bzoj3505
    bzoj2226
    bzoj1263
    bzoj2429
    bzoj1854
    bzoj3555
    bzoj1877
    放两个模版
  • 原文地址:https://www.cnblogs.com/buptleida/p/14274148.html
Copyright © 2020-2023  润新知