算法-数组中的第K个最大元素

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

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

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

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

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

提示:

1 <= k <= nums.length <= 105
-10^4 <= nums[i] <= 104

方法一:使用快速排序,时间复杂度为O(nlog(n))的。我们要求的是第k大的数,例如1,2,3,4,5,6第2大的数是5,第4大的数是3。因此在n = 6,第k大的数的索引是n - k + 1。
因此在升序快排中第k大的数是第n-k个元素
在降序排列中第k大的数就是第k个元素

class Solution {
public:
	//降序排列
    int k_sort(vector<int> q, int k, int l, int r)
    {
        if(l >= r) return q[l];
        int x = q[(l + r) / 2], i = l - 1, j = r + 1;
        while(i < j)
        {
            do i ++; while(q[i] > x);
            do j --; while(q[j] < x);
            if(i < j) swap(q[i], q[j]);
        }
        int sr = j - l + 1; //这个是经常错的地方,j - l + 1
        if(k <= sr) return k_sort(q, k, l, j);
        else
        {
            return k_sort(q, k - sr, j + 1, r);
        }
    }

    int findKthLargest(vector<int>& nums, int k) {
        int n = nums.size();
        int res = k_sort(nums, k , 0, n - 1);
        return res;
    }
};
class Solution {
public:


    int k_sort(vector<int> q, int k, int l, int r)
    {
        if(l >= r) return q[l];
        int x = q[(l + r) / 2], i = l - 1, j = r + 1;
        while(i < j)
        {
            do i ++; while(q[i] < x);
            do j --; while(q[j] > x);
            if(i < j) swap(q[i], q[j]);
        }
        int sr = j - l + 1; //这个是经常错的地方,j - l + 1
        if(k <= sr) return k_sort(q, k, l, j);
        else
        {
            return k_sort(q, k - sr, j + 1, r);
        }
    }

    int findKthLargest(vector<int>& nums, int k) {
        int n = nums.size();
        int res = k_sort(nums, n - k + 1 , 0, n - 1);
        return res;
    }
};

快速排序解法

class Solution {
public:

    int quick_sort(vector<int> &q, int l, int r, int k)
    {
        if(l >= r) return q[l];
        int x = q[(l + r) >> 1], i = l - 1, j =  r + 1;
        while(i < j)
        {
            do i ++; while(q[i] > x);
            do j --; while(q[j] < x);
            if( i < j) swap(q[i], q[j]);
        }
        int sr = j - l + 1;
        if(k <= sr) return quick_sort(q, l, j, k);
        else
        {
            return quick_sort(q, j + 1, r, k - sr);
        }
    }
    int findKthLargest(vector<int>& nums, int k) {
        int n = nums.size();
        int kk = quick_sort(nums, 0, n - 1, k);
        return kk;
    }
};

方法二:维护一个大根堆,将数组所有数据和堆顶比较一遍并减掉前面最小的数据直到堆的大小为n - k + 1,最后输出堆顶即可O(nlogn)。

class Solution {
public:

    void down(vector<int> &nums, int u, int n)
    {
        int t = u;
        if(2 * u + 1 < n && nums[2 * u + 1] > nums[t]) t = 2 * u + 1;
        if(2 * u + 2 < n && nums[2 * u + 2] > nums[t]) t = 2 * u + 2;
        if(t != u)
        {
            swap(nums[t], nums[u]);
            down(nums,t,n);
        }
    }
    int findKthLargest(vector<int>& nums, int k) {
        int n = nums.size();
        for(int i = n / 2; i >= 0; i --) down(nums, i, n);//构建堆
        int ed = n;
        int tt = k - 1; //直接去掉前k-1大的数,剩下的最大就是第k大的数
        while(tt --)
        {
            nums[0] = nums[-- ed];
            down(nums, 0, ed);
        }
        return nums[0];
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值