c++ 数组中的最大元素_509,数组中的第K个最大元素

5b9603f18ac7d2945dd9e901f70f9ae3.png

The old dreams were good dreams. They didn’t work out, but I’m glad I had them. 

曾经的梦都是美梦,虽未成真,但庆幸我曾拥有过。

问题描述

在未排序的数组中找到第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个最大的元素,所以最简单的一种方式就是先对数组进行排序,然后再查找。关于排序,我公众号之前介绍了有十几种排序算法,具体可以在公众号的目录中查看。代码比较简单,我们来看一下

1public int findKthLargest(int[] nums, int k) {
2    Arrays.sort(nums);//先排序
3    return nums[nums.length - k];//在查找
4}

使用最小堆

这题只让找出最大的第k个元素即可,没说一定要对数组进行排序,所以我们还可以使用最小堆来解决。解决方式就是一个个遍历原数组的值,添加到堆中,添加之后如果堆中元素个数大于k的时候,我们就把最顶端的元素给移除掉,因为是最小堆,所以移除的就是堆中最小的值。

 1public int findKthLargest(int[] nums, int k) {
2    final PriorityQueue queue = new PriorityQueue<>(); 3    for (int val : nums) { 4        queue.add(val);//加入堆中 5        //如果堆中元素大于k,则把堆顶元素给移除 6        if (queue.size() > k) 7            queue.poll(); 8    } 9    return queue.peek();//返回堆顶元素10}

参考快速排序

快速排序是先选择一个中枢(一般我们选第一个),然后遍历后面的元素,最终会把数组分为两部分,前面部分比中枢值小,后面部分大于或等于中枢值。

  1. 分开之后中枢值所在的位置如果从后面数是第k个,我们直接返回中枢值即可。

  2. 如果从后面数大于k,说明要找的值还在后面这部分,我们只需按照同样的方式从后面部分开始找即可。

  3. 如果从后面数小于k,说明要找的值在前面部分,我们同样从前面部分开始查找。

原理比较简单,我们来看下代码

 1public int findKthLargest(int[] nums, int k) {
2    k = nums.length - k;//注意这里的k已经变了
3    int lo = 0, hi = nums.length - 1;
4    while (lo <= hi) {
5        int i = lo;
6        //这里把数组以A[lo]的大小分为两部分,
7        //一部分是小于A[lo]的,一部分是大于A[lo]的
8        // [lo,i]=A[lo]
9        for (int j = lo + 1; j <= hi; j++)
10            if (nums[j] 11                swap(nums, j, ++i);
12        swap(nums, lo, i);
13        if (k == i)
14            return nums[i];
15        else if (k 16            hi = i - 1;
17        else
18            lo = i + 1;
19    }
20    return -1;
21}
22
23//交换两个元素的值
24private void swap(int[] nums, int i, int j) {
25    if (i != j) {
26        nums[i] ^= nums[j];
27        nums[j] ^= nums[i];
28        nums[i] ^= nums[j];
29    }
30}

上面swap方法是交换两个数字的值,一般情况下我们会使用一个临时变量temp来解决,哪种方式都是可以了,具体可以看下357,交换两个数字的值,这里介绍了几种交换的方式。

aee01d7b8bbfd44754365f2c3a5322a4.gif

●498,回溯算法解活字印刷

●451,回溯和位运算解子集

●450,什么叫回溯算法,一看就会,一写就废

●446,回溯算法解黄金矿工问题

截止到目前我已经写了500多道算法题了,为了方便大家阅读,我把部分算法题整理成了pdf文档,目前有800多页,大家可以在公众号中回复关键字“pdf”即可获取下载链接。

如果觉得有用就点个"赞"吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值