IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> leetcode----215.数组中的第k个最大元素(优先队列和快速选择两种解法) -> 正文阅读

[数据结构与算法]leetcode----215.数组中的第k个最大元素(优先队列和快速选择两种解法)

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

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

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

思路:

  • 排序

这是最容易想到的思路,首先将数组排序,然后取倒数第k个就是所求。注意Arrays.sort()默认为自然排序,无法对基本数据类型的数据进行自定义排序,但是可以对其包装类Integer类型的数组自定义排序。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        return nums[nums.length - k];
    }
}
  • 优先队列

java的优先队列默认实现为小顶堆。将数组中的元素依次入队列,在此过程中,维护一个长度为k的队列,当队列长度大于k时,将堆顶元素(当前队列中最小的元素)出队,这样当整个数组遍历完之后,我们就留下了较大的k个元素,即堆顶为第k大元素。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        Queue<Integer> priorityQueue = new PriorityQueue<>();

        for(int num: nums){
            priorityQueue.offer(num);
            if(priorityQueue.size() > k){
                priorityQueue.poll();
            }
        }

        return priorityQueue.peek();
    }
}
  • 快速选择算法

快速选择算法是快速排序算法的优化版本。

快速排序的逻辑是,若要对 nums[l..r] 进行排序,我们先找一个分界点 p,通过交换元素使得 nums[l..r] 都小于等于 nums[p],且 nums[p+1..r] 都大于 nums[p],然后递归地去 nums[l..p-1]nums[p+1..r] 中寻找新的分界点,最后整个数组就被排序了。

需要优化的点在这里:每一次快排之后,分界点p的位置会被确定,我们要求的是第k大元素,这个第k大元素在升序后的数组中的位置为nums.length - k。既然我们知道了所求元素的位置,且每一次快排会确定分界点p的位置。那我们可以是用确定位置的分界点p和k作比较,若p < k,则说明第k大元素肯定在区间[p+1, r],若p > k,则说明第k大元素肯定在区间[l, p - 1]p == k,则nums[p]即为所求。

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int l = 0, r = nums.length - 1;
        k = nums.length - k;

        while(l <= r){
            int p = partition(nums, l, r);

            if(p < k){
                l = p + 1;
            } else if(p > k){
                r = p - 1;
            } else {
                return nums[p];
            }
        }
        return -1;
    }

    private int partition(int[] nums, int l, int r) {
        if (l == r) {
            return l;
        }

        int pivot = nums[l];

        int i = l, j = r + 1;
        while (true){
            //保证nums[l...i]都小于分界点pivot
            while (nums[++i] < pivot){
                if (i == r) {
                    break;
                }
            }
			
            //保证nums[j...r]都大于分界点pivot
            while (nums[--j] > pivot){
                if (j == l) {
                    break;
                }
            }
			
            if(i >= j) {
                break;
            }
            //走到这里一定有
            //nums[i] > pivot && nums[j] < pivot
            //此时需要交换 nums[i] 和 nums[j],
            swap(nums, i, j);
        }
        //此时i指向右半区间第一个大于pivot的数
        //j指向左半区间最后一个小于pivot的数
        //所以应该将j与分界点l交换
        //这样才满足以nums[pivot]分界点,左半区间都小于它,右半区间都大于它
        swap(nums,j,l);
        return j;
    }

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

整理思路,记录博客,以便复习。若有误,望指正~

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-04 13:41:40  更:2022-01-04 13:43:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 18:29:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码