经典算法:无序数组寻找第K大的数值

开发 前端 算法
有一个无序整数数组,请你根据排序思路,找出数组中第K大的数。给定一个整数数组a, 请返回第K (1<=K<=n) 大的数(包括重复的元素,不用去重),保证答案存在。

[[409182]]

1. 寻找第K大

题意

有一个无序整数数组,请你根据排序思路,找出数组中第K大的数。

给定一个整数数组a, 请返回第K (1<=K<=n) 大的数(包括重复的元素,不用去重),保证答案存在。

示例

  1. 输入 [3,2,1,5,6,4] , 2 
  2. 返回值 5 

2. 常规思路

先对无序数组进行排序,然后对有序数组进行查找。

至于选择什么排序算法,有待确定。

先看一下,各种排序算法的复杂度以及稳定性。

看完上面比较之后,可能你心中已经有了自己的答案。

3. 解题思路

常规思路需要两大步:

  1. 先整体排序
  2. 在有序中查找目标值

那么,针对这道题,我们能不能在排序的过程中就确定目标值呢?

思考一下快排的二分特性:

  1. 先找出一个数值的位置,该数值的左侧比自己小,右侧比自己大(整个数组一分为二)
  2. 再分别进行左、右两部分进行步骤1的操作,直至整个数组有序。

这里需要知道的是,在快排中某个数值左侧比自己小,右侧比自己大。该数值的位置就是在最终有序数组中的位置,也就是说可以在查找中确定目标位置。并且,在本题的处理过程中,平均情况下只处理1/2的数据量。

经典算法:无序数组寻找第K大的数值

动图 - 快排算法

快排算法查找过程:

4. Go代码实现

  1. func findKLargest(arr []int, k intint { 
  2.     iflen(arr) == 0 || k > len(arr) { 
  3.         return-1 
  4.     } 
  5.  
  6.     var find func(k int, l, r intint 
  7.     find = func(k int, l, r intint { 
  8.         /* 
  9.         // 对于正常的快排,需要下面的代码 
  10.         if l >= r { 
  11.             return 
  12.         } 
  13.         // 然而这里不需要,在寻找第k大的数据时 一般是 l==r 
  14.         */ 
  15.         ll := l 
  16.         rr := r 
  17.         target := arr[l] 
  18.  
  19.         // 倒序(第K大使用)排列 是 target >= arr[r]  / target <= arr[l] 
  20.         // 正序(第k小使用)排列 是 target <= arr[r]  / target >= arr[l] 
  21.         for l < r { 
  22.             for l < r && target >= arr[r] { 
  23.                 r-- 
  24.             } 
  25.             arr[l] = arr[r] 
  26.  
  27.             for l < r && target <= arr[l] { 
  28.                 l++ 
  29.             } 
  30.             arr[r] = arr[l] 
  31.         } 
  32.        
  33.         arr[l] = target 
  34.         // k在l的右侧 
  35.         // 为什么 下面无论是在左右侧,第一个参数都是k呢? 
  36.         // 因为,k指的是要找的数值的下标位置(第k大就是下标k-1) 
  37.         // 无论在左右侧,对于数组arr来说,其对应的下标都是固定的 
  38.         // 并且 l/r 每次都会变动,所以k这里是固定的 
  39.         if k > l { 
  40.             // 这里的  l+1, rr 也是数组的下标 
  41.             return find(k, l+1, rr) 
  42.         }elseif k < l { 
  43.             // k在l的左侧 
  44.             // 这里的  ll, l-1 也是数组的下标 
  45.             return find(k, ll, l-1) 
  46.         } 
  47.  
  48.         // 此时目标自位置l处的target,就是第k个大的数值 
  49.         return target 
  50.     } 
  51.  
  52.     // 第k大的数值,对应排序之后就是,数组下标k-1 
  53.     finds := find(k-1, 0, len(arr)-1) 
  54.  
  55.     return finds 

 求第K大,则对数组排序排列。

求第K小,则对数组正序排列。

无论如何,都是从头开始找,这样处理更简单。

 

责任编辑:姜华 来源: 今日头条
相关推荐

2021-06-29 23:34:35

无序数据数组

2021-02-01 10:17:14

编程C语言计算机

2017-07-18 10:50:38

前端JavaScript排序算法

2018-04-25 08:10:50

算法k-means代码

2011-01-26 09:14:43

数据挖掘

2021-10-31 07:38:37

排序算法代码

2022-04-06 10:06:37

判断算法数值校验

2021-10-18 11:29:48

奇偶排序数组数据结构算法

2016-01-29 11:00:55

数据挖掘算法大数据

2013-02-25 09:46:35

数据挖掘算法ICDM

2022-03-10 12:03:33

Python算法代码

2014-08-29 09:56:47

排序数组编程技巧

2015-07-29 15:11:17

Playground数值算法

2021-02-22 07:58:45

算法进程调度

2018-11-14 09:40:05

排序算法Java编程语言

2018-10-27 15:47:35

CART算法决策树

2023-10-06 23:56:42

顺序查找Python

2020-10-15 12:30:37

Python编程语言

2021-07-06 07:01:35

旋转数组数字

2021-10-14 11:31:28

数组面试题中心下标
点赞
收藏

51CTO技术栈公众号