• LeetCode 215. 数组中的第K个最大元素


    题目链接

    215. 数组中的第K个最大元素

    题目思路

    这个题最容易的思想就是先进行排序,排序完从后往前数k位即可。这个时间复杂度为O(nlogn),但是我们其实没必要对整个数组进行完全的排序。
    第二种方法的有化解有优先队列(大顶堆),我们维护大小为k的大顶堆,然后遍历完整个数组之后,我们的大顶堆中存放的是前k个最大的元素,我们一个一个取出来直到最后那个就行。
    这样仍然是会涉及到堆的重排序问题,依然是O(nlogn)的时间复杂度,不过这个算法会比较容易想。
    第三种方法就是直接使用快速排序的划分思想,因为我们快排每次划分后的中轴都是固定好位置的,而它的左边元素都比它小,右边元素都比它大。
    我们可以利用这个思想,直接找到对应的中轴,而不需要去考虑剩余那些元素的相互间的有序性。

    代码实现

    class Solution {
        public int findKthLargest(int[] nums, int k) {
            int left = 0;
            int right = nums.length - 1;
            int length = nums.length;
            //因为k一定存在,所以可以写永久循环
            while(true){
                //获取当前返回的下标
                int cur = helper(nums,left,right);
                //因为是第K大的元素,其下标就是length-k
                if(cur == length - k){
                    return nums[cur];
                }else if( cur > length - k){
                    right = cur - 1;
                }else{
                    left = cur + 1;
                }
            }
        }
    
        private int helper(int[] nums, int l, int r){
            int left = l;
            int right = r;
            int flag = nums[left++];
            //这里一定要写小于等于,不然会把有序的数组变无序呜呜呜
            while(left <= right){
                //右边大于等于左手边flag位无所谓,重要的是还是得left<=right
                while(left <= right && nums[right] >= flag){
                    right--;
                }
                //左手边不能出现和flag位相等的数据。
                while(left <= right && nums[left] < flag){
                    left++;
                }
                //如果两个指针相与,直接跳出循环加快速度。
                if(left >= right){
                    break;
                }
                int temp =  nums[right];
                nums[right] = nums[left];
                nums[left] = temp;
            }
            //交换浮标位和右指针位。
            nums[l] = nums[right];
            nums[right] = flag;
            return right;
        }
    }
    

    总结

    这个题三个月前做过一次,今天每日一题又做了一次,虽然还是被边界条件卡了下,但是只WA了一次,比上次要好点。

    快排分区的模板代码

        private int partition(int[] array, int start, int end) {
            int pivot = array[start];// 采用子序列的第一个元素作为枢纽元素
            while (start < end) {//
                // 从后往前在后半部分中寻找第一个小于枢纽元素的元素
                while (start < end && array[end] >= pivot) {
                    --end;
                }
                // 将这个比枢纽元素小的元素交换到前半部分
                swap(array, start, end);
                // 从前往后在前半部分中寻找第一个大于枢纽元素的元素
                while (start < end && array[start] <= pivot) {
                    ++start;
                }
                swap(array, start, end);// 将这个枢纽元素大的元素交换到后半部分
            }
            return start;// 返回枢纽元素所在的位置
        }
    
  • 相关阅读:
    从json中获取自己想要的属性
    对称加密解密
    springboot 读取resource目录下的文件
    安装nginx 配置了ssl 启动报错
    复利计算--4.0 单元测试之JAVA版-软件工程
    《构建之法》前三章读后感
    单利 复利计算器程序1.0 2.0 3.0 [ 合 ] 之 WEB
    操作系统 实验一 命令解释程序的编写
    单利 复利计算器程序1.0 2.0 3.0 [ 合 ] 之 C语言
    统计实验数据 总结实验结果
  • 原文地址:https://www.cnblogs.com/ZJPaang/p/13207045.html
Copyright © 2020-2023  润新知