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 <= numsi <= 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;
    }
}
相关推荐
hold?fish:palm2 小时前
9 找到字符串中所有字母异位词
c++·算法·leetcode
Sw1zzle2 小时前
算法入门(六):贪心算法 - 基础入门(Leetcode 121/455/860/376/738)
算法·leetcode·贪心算法
青山木3 小时前
Hot 100 --- 岛屿数量
java·数据结构·算法·leetcode·深度优先·广度优先
危桥带雨3 小时前
排序算法(快排、归并、计数、基数排序)
数据结构·算法·排序算法
啦啦啦啦啦zzzz3 小时前
算法:回溯算法
c++·算法·leetcode
小肝一下6 小时前
3. 单链表
c语言·数据结构·c++·算法·leetcode·链表·dijkstra
tachibana26 小时前
hot100 前 K 个高频元素(347)
java·数据结构·算法·leetcode
长不胖的路人甲8 小时前
选择排序 Java 实现 + 完整思路解析
java·算法·排序算法
To_OC14 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
旖-旎15 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题