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

一、题目描述

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

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

示例 1:

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

输出:5

示例 2:

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

输出:4

提示:

1 <= k <= nums.length <= 104

-104 <= nums[i] <= 104

二、题目解析

1、插入排序

复制代码
class Solution {
    public int findKthLargest(int[] nums, int k) {
        insertSort(nums);
        return nums[k - 1];
    }
    public void insertSort(int[] nums) {
        for(int i = 1;i < nums.length;i++){
            int target = nums[i];
            int j = i - 1;;
            for(;j >= 0;j--){
                if(nums[j] < target){
                    nums[j+1] = nums[j];
                }else{//找到第一个大于待排元素的元素
                    break;
                }            
            }
            //注意此处不能为nums[j+1] = nums[i],因为在交换过程中nums[i]被改变
            nums[j+1] = target;
        }
    }
}

2、快速排序思想1(一次扫描交换一个到目标位置)

左指针指向i=0,待排元素,(循环遍历前存储待排元素)

右指针指向j=length-1,最后一个元素。

从j位置往前遍历,找到大于待排元素,把该元素换到左指针指向位置(此时右指针位置废弃);

从i位置往后遍历,找到小于待排元素,把该元素换到右指针指向位置(上轮的废弃位置;且此时左指针位置废弃,下一轮遍历将交换到该位置);

再从j位置往前遍历,以此类推。

在此过程中,i走过的区域都是大于等于待排元素的,j走过的区域都是小于待排元素的,最后i和j相遇且指向的都是废弃元素。直接把待排元素排到这里即可。

复制代码
class Solution {
    public int findKthLargest(int[] nums, int k) {
        quickSort(nums,0,nums.length - 1);
        return nums[k-1];
    }
    public void quickSort(int[] nums,int start,int end){
    //递归结束条件
        if(start >= end){
            return;
        }
        int mid = (start + end) / 2;
        swap(nums,start,mid);
        int index = partition(nums,start,end);
        quickSort(nums,start,index - 1);
        quickSort(nums,index + 1,end);
    }
    public int partition(int[] nums,int start,int end) {
        
        int i = start,j = end;
        int target = nums[start];
        while(i < j){
            while(nums[j] < target && i < j){
                j--;
            }
            nums[i] = nums[j];
            while(nums[i] >= target && i < j){
                i++;
            }
            nums[j] = nums[i];
        }
        //最后return i或者j位置上的元素都可以,因为打破while的时候i==j
        nums[j] = target;
        return j;

    }
    public void swap(int[] nums,int i,int j){
        int temp = nums[j];
        nums[j] = nums[i];
        nums[i] = temp;
    }
}

3、快速排序思想2(一次扫描交换两个到目标位置)

i指针向右扫描,寻找小于target的元素;

j指针向左扫描,寻找大于等于target的元素;

当都找到的时候进行交换,

交换后开始下一轮寻找,当i,j指针相遇的时候,i指针扫描过的区域都满足大于等于target,j指针扫描过的区域都满足小于target,相遇位置即为target元素最终位置,进行交换即可。

这里需要注意一些边界条件,如循环退出条件,交换前提.

复制代码
class Solution {
    public int findKthLargest(int[] nums, int k) {
        quickSort(nums,0,nums.length - 1);
        return nums[k-1];
    }
    public void quickSort(int[] nums,int start,int end){
        if(start >= end){
            return;
        }
        int mid = (start + end) / 2;
        swap(nums,start,mid);
        int index = partition(nums,start,end);
        quickSort(nums,start,index - 1);
        quickSort(nums,index + 1,end);
    }
    public int partition(int[] nums,int start,int end) {
        
        int i = start,j = end;
        int target = nums[start];
        while(i < j){
            while(i < j && nums[j] < target){
                j--;
            }
            while(i < j && nums[i] >= target){
                i++;
            }
            if(i < j){
                swap(nums,i,j);
                //因为加上这两行导致可能会跳过符合要求的元素;应让i,j指针在下轮循环中自行寻找。
                // i++;
                // j--;
            }
        }
        swap(nums,start,i);
        return i;
    }
    public void swap(int[] nums,int i,int j){
        int temp = nums[j];
        nums[j] = nums[i];
        nums[i] = temp;
    }
}

3、冒泡排序

复制代码
class Solution {
    public int findKthLargest(int[] nums, int k) {
        bubbleSort(nums);
        return nums[k-1];
    }
    public void bubbleSort(int[] nums){
        //冒泡1次确定1个最小元素放到最后一个位置,冒泡nums.length-1次可排完全部
        for(int i = 0;i < nums.length;i++){
          //每轮冒泡从第一个元素开始依次与右边元素比较(注意j的结束区间)
            for(int j = 0;j < nums.length - i - 1;j++){
                if(nums[j] < nums[j+1]){
                    swap(nums,j,j+1);
                }
            }
        }
    }
       
    public void swap(int[] nums,int i,int j){
        int temp = nums[j];
        nums[j] = nums[i];
        nums[i] = temp;
    }
}
相关推荐
老鼠只爱大米1 分钟前
LeetCode算法题详解 438:找到字符串中所有字母异位词
算法·leetcode·双指针·字符串匹配·字母异位词·滑动窗口算法
AlenTech31 分钟前
198. 打家劫舍 - 力扣(LeetCode)
算法·leetcode·职场和发展
重生之后端学习36 分钟前
21. 合并两个有序链表
java·算法·leetcode·链表·职场和发展
源代码•宸36 分钟前
Leetcode—1266. 访问所有点的最小时间【简单】
开发语言·后端·算法·leetcode·职场和发展·golang
YuTaoShao1 小时前
【LeetCode 每日一题】712. 两个字符串的最小ASCII删除和——(解法一)记忆化搜索
算法·leetcode·职场和发展
圣保罗的大教堂2 小时前
leetcode 1266. 访问所有点的最小时间 简单
leetcode
源代码•宸3 小时前
Leetcode—85. 最大矩形【困难】
经验分享·算法·leetcode·职场和发展·golang·单调栈
平哥努力学习ing3 小时前
《数据结构》-第八章 排序
数据结构·算法·排序算法
Swift社区3 小时前
LeetCode 472 连接词
算法·leetcode·职场和发展
Dream it possible!3 小时前
LeetCode 面试经典 150_二分查找_搜索旋转排序数组(114_33_C++_中等)
c++·leetcode·面试