每日题解:LeetCode 215. 数组中的第K个最大元素

news/2024/5/20 0:30:15 标签: 快速排序, leetcode

题目地址
个人博客地址

题目描述

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

示例 1:

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

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

说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

解法

JAVA

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

CPP

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
         int left=0,len=nums.size(),right=len-1;
        int target=len-k;
        int ans;
        while ((ans = partition(nums, left, right)) != target ) {
            if(ans<target){
                left=ans+1;
            }else if(ans>target){
                right=ans-1;
            }
        }
        return nums[ans];
    
    }

     int partition(vector<int> &vector, int left, int right) {
        int temp=vector[left];
        int leftIndex=left;
        for (int i = left+1; i <= right; ++i) {
            if(vector[i]<temp){
                leftIndex++;
                swap(vector, leftIndex, i);
            }
        }
        swap(vector, leftIndex, left);
        return leftIndex;
    }
     void swap(vector<int> &vector, int left, int right) {
        int temp=vector[left];
        vector[left]=vector[right];
        vector[right]=temp;
    }
    
};

解题思路

优先队列

这里是直接调用JAVA的API实现最小堆的做法,PriorityQueue(优先队列)优先队列的作用是能保证每次取出的元素都是队列中权值最小,即默认栈顶是最小元素
将元素的排序交给PriorityQueue进行维护,由于需要找到第K个最大元素,就是从大到小进行排序数组,找到倒数第k个元素,只要维护一个只有k大小的最小堆就可以了

  1. 遍历数组,
  2. 当堆的元素个数小于k时,直接添加到堆中
  3. 当堆的元素个数大于k时,当遍历的元素大于堆顶元素时,堆顶元素弹出,然后添加当前遍历的数组
 for (int num : nums) {
        if (heap.size() < k){
            heap.offer(num);
        } else {
            if (num > heap.peek()){
                heap.poll();
                heap.offer(num);
            }
        }
    }

减治法

这里主要思路参考了李哥的题解,李哥的题解每次都让人恍然大悟!!
假设nums[target]是目标答案下标值,通过某方法将下标范围存放[0,target-1]nums[target]小的值,比nums[target]大的值放在[target+1,nums..size()]范围内,由于答案是第k大的元素,按照自然顺序进行排序的,应该是target=nums..size()-k,当我们按照target左小右大思路存放数组元素,nums[target]就是我们最终的答案

  1. nums[0] 到 nums[target - 1] 中的所有元素都不大于 nums[target];
  2. nums[target + 1] 到 nums[,nums…size()]] 中的所有元素都不小于 nums[target]
    我们以[3,2,1,5,6,4] 为例,第一次寻找比num[0]小的元素,下标停在元素1的位置
    在这里插入图片描述
    此时,leftIndex-1左边应该都是比num[0]小元素,leftIndex+1右边都是num[0]大的元素,这是我们还需要num[0]和leftIndex进行互换,
    在这里插入图片描述
    换个思路寻找第K个最大元素,其实就寻找第 target=nums.size()- k元素,我们只要保证target元素左小右大就可以了
    这里我是将排序和赋值放到了whlie循环条件中,完成了排序和判断,当然也可以使用whlie(true)形成死循环阻塞,在while循环内进行赋值
int left = 0, len = nums.size(), right = len - 1;
        int target = len - k;
        int ans;
        while ((ans = partition(nums, left, right)) != target) {
            if (ans < target) {
                left = ans + 1;
            } else if (ans > target) {
                right = ans - 1;
            }
        }
        return nums[ans];

这里其实是快速排序的思路,每次我们选择一个数作为标记,待排序结束后,将标记存到其正确的位置

int partition(vector<int> &vector, int left, int right) {
        int temp = vector[left];
        int leftIndex = left;
        //遍历元素,发现当前元素比目前的元素小的就进行元素值互换,并且leftIndex下标往后移动,保存下一个比temp元素
        for (int i = left + 1; i <= right; ++i) {
            if (vector[i] < temp) {
                leftIndex++;
                swap(vector, leftIndex, i);
            }
        }
        //这里就是最后需要将当前值放到leftIndex位置上,这里其实就是图中所示的3和1的位置互换
        swap(vector, leftIndex, left);
        return leftIndex;
    }

http://www.niftyadmin.cn/n/1514961.html

相关文章

js实现一键回到顶部小效果

<style>*{margin: 0;padding: 0;}header{height: 400px;background: #ddd;}section{height: 1800px;width: 1130px;margin: 0 auto;background: #f99;}footer{height: 600px;background: #ddd;}#goTop{width: 50px;height: 50px;/*未给父元素设置top和bottom,就可以被束缚…

vue知识点总结,你想要的几乎都有哦!

今天来对vue框架相关知识做个总结~ 声明&#xff1a;其中包括一些网上视频课程、官网中讲到的内容。 废话不多说&#xff0c;知识点来咯~ 1.什么是MVVM&#xff1f; MVVM 模式不需要用户收到操作 dom 元素,将数据绑定到 viewModel 层上&#xff0c;会自动将数据渲染到页面中&a…

每日题解:LeetCode 23. 合并K个排序链表

题目地址 个人博客地址 题目描述 合并 k 个排序链表&#xff0c;返回合并后的排序链表。请分析和描述算法的复杂度。 示例:输入: [1->4->5,1->3->4,2->6 ] 输出: 1->1->2->3->4->4->5->6解法 CPP class Solution { public:ListNode* …

element-ui时间插件的范围设置

满足条件&#xff1a; 1.开始时间和结束时间均在包括今天在内的日期之前&#xff1b; 2.开始时间不设限制&#xff1b; 3.所选结束时间与所选开始时间间隔不能超过三个月。

每日题解:LeetCode 718. 最长重复子数组

题目地址 个人博客地址 题目描述 给两个整数数组 A 和 B &#xff0c;返回两个数组中公共的、长度最长的子数组的长度。 示例&#xff1a;输入&#xff1a; A: [1,2,3,2,1] B: [3,2,1,4,7] 输出&#xff1a;3 解释&#xff1a; 长度最长的公共子数组是 [3, 2, 1] 。提示&…

每日题解:LeetCode 32. 最长有效括号

题目地址 个人博客地址 题目描述 给定一个只包含 ‘(’ 和 ‘)’ 的字符串&#xff0c;找出最长的包含有效括号的子串的长度。 示例 1:输入: "(()" 输出: 2 解释: 最长有效括号子串为 "()"示例 2:输入: ")()())" 输出: 4 解释: 最长有效括号子…

element可编辑表格验证问题

前提&#xff1a;表格里设置可编辑表单。 注意事项&#xff1a; 1.校验需要触发表单&#xff0c;而表格需要时数组。因此表单绑定的是一个对象&#xff0c;表格中绑定的是该对象中的数组。 2.prop动态绑定。 3.必要的情况下可以添加key的。&#xff08;:key‘scope.row.key’&a…

vue项目部署方式:tomcat部署和nginx部署

关于vue部署 1.nginx转发 一般项目前后端分离得话&#xff0c;都会用nginx作为反向代理转发的。 因为项目要兼容ie9,使用axios发ajax请求的时候,不能通过CORS解决跨域的问题,所以尝试部署nginx作反向代理. 参考:vuewebpackvue-router(history) 部署到nginx服务器下&#xff0c;…