码迷,mamicode.com
首页 > 编程语言 > 详细

数组中的第K个最大元素

时间:2021-06-23 16:38:41      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:最大   示例   translate   rgba   mask   turn   sla   输入   元素   

https://leetcode-cn.com/problems/kth-largest-element-in-an-array/

 

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

在未排序的数组中找到第 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 ≤ 数组的长度。

 

问题思路:数组中的第K个最大元素可以借用快排的思路,通过匹配哨兵位置进行左右查找,相当于半分治(只递归一半,并非整个原问题分解为子问题)。

1.通过快排思路,校正第一个哨兵的位置(左侧元素小于哨兵,右侧元素大于哨兵),通过比较哨兵的位置,来确定递归(分治)方向。

2.将原问题在整个区间找到哨兵的位置分解为在子区间找到对应哨兵的位置。

3.当哨兵的位置恰好为第k大位置时,返回哨兵的值。

 

代码设计思路

1.因为设计的分治思路(分治方向只往正确的方向走,也就是单通道,一直在重复一条递归道路,即最深的递归层的返回值可以返回至最外层。也就是说可以值返回一个结果,因此无需比较众多的返回值结果)。设计递归出口,当哨兵位置恰好准确时,返回哨兵取值。否则分解为对应左右区间的子问题。

2.分解的区间为哨兵的左右区间,因此递归区间无需加入哨兵位置。

 

# 本题遇到bug,在借鉴快排思路时,只进行的左右各一次的填坑。并没有结束第一轮填坑操作。所以,需要注意在使用快排时,最外层需要while(i<j)以便完成整轮快排。

 

 

class Solution {
public:
    void dfs(vector<int>& arr, int l, int r){
        if(l>=r)
            return;
        int pivot = arr[l];
        int i = l;
        int j = r;
        while(i<j){
            while(i < j && arr[j] >= pivot){
                j--;
            }
            arr[i] = arr[j];
            while(i < j && arr[i] <= pivot){
                i++;
            }
            arr[j] = arr[i];
        }
        arr[i] = pivot;

        // 分治
        dfs(arr, l, i-1);
        dfs(arr, i+1, r);
        
    }

    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        dfs(arr, 0, arr.size()-1);
        vector<int> res;
        for(int i=0; i<k; i++){
            res.push_back(arr[i]);
        }
        return res;
    }
};

 

数组中的第K个最大元素

标签:最大   示例   translate   rgba   mask   turn   sla   输入   元素   

原文地址:https://www.cnblogs.com/ygtzds/p/14920491.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!