2020-03-02:在无序数组中,如何求第K小的数?

福哥答案2021-03-02:

1.堆排序。时间复杂度:O(N*lgK)。有代码。
2.单边快排。时间复杂度:O(N)。有代码。
3.bfprt算法。时间复杂度:O(N)。有代码。

代码用golang编写,代码如下:

```go
package main

import (
"container/heap"
"fmt"
"math/rand"
"sort"
)

func main() {

//1 2 3 4 5 6 7
arr := []int{1, 2, 3, 4, 5, 10, 9, 8, 7, 6}
ret := minKth1(arr, 7)
fmt.Println("1.堆排序:", ret)

ret = minKth2(arr, 7)
fmt.Println("2.单边快排:", ret)

ret = minKth3(arr, 7)
fmt.Println("3.bfprt算法:", ret)

}

// 利用大根堆,时间复杂度O(N*logK)
func minKth1(arr []int, k int) int {
maxHeap := &IntHeap{}
heap.Init(maxHeap)
for i := 0; i < k; i++ {
heap.Push(maxHeap, arr[i])
}
for i := k; i < len(arr); i++ {
heap.Push(maxHeap, arr[i])
heap.Pop(maxHeap)
//heap.Push(maxHeap, arr[i])
}
return heap.Pop(maxHeap).(int)
}

type IntHeap sort.IntSlice

func (h IntHeap) Len() int { return len(h) }
func (h IntHeap) Less(i, j int) bool { return !(h[i] < h[j]) }
func (h IntHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }

//func (h IntHeap) Len() int { return sort.IntSlice(h).Len() }
//func (h IntHeap) Less(i, j int) bool { return !sort.IntSlice(h).Less(i, j) }
//func (h IntHeap) Swap(i, j int) { sort.IntSlice(h).Swap(i, j) }

func (h *IntHeap) Push(x interface{}) {
//fmt.Println("push----")
// Push and Pop use pointer receivers because they modify the slice's length,
// not just its contents.
*h = append(*h, x.(int))
}

func (h *IntHeap) Pop() interface{} {

old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}

// 改写快排,时间复杂度O(N)
// k >= 1
func minKth2(arr []int, k int) int {
arrc := make([]int, len(arr))
copy(arrc, arr)
return process2(arrc, 0, len(arr)-1, k-1)
}

// arr 第k小的数
// process2(arr, 0, N-1, k-1)
// arr[L..R] 范围上,如果排序的话(不是真的去排序),找位于index的数
// index [L..R]
func process2(arr []int, L int, R int, index int) int {
if L == R { // L = =R ==INDEX
return arr[L]
}
// 不止一个数 L + [0, R -L]
pivot := arr[L+rand.Intn(R-L)]
rang := partition(arr, L, R, pivot)
if index >= rang[0] && index <= rang[1] {
return arr[index]
} else if index < rang[0] {
return process2(arr, L, rang[0]-1, index)
} else {
return process2(arr, rang[1]+1, R, index)
}
}

func partition(arr []int, L int, R int, pivot int) []int {
less := L - 1
more := R + 1
cur := L
for cur < more {
if arr[cur] < pivot {
less++
arr[less], arr[cur] = arr[cur], arr[less]
cur++
} else if arr[cur] > pivot {
more--
arr[cur], arr[more] = arr[more], arr[cur]
} else {
cur++
}
}
return []int{less + 1, more - 1}
}

// 利用bfprt算法,时间复杂度O(N)
func minKth3(arr []int, k int) int {
arrc := make([]int, len(arr))
copy(arrc, arr)
return bfprt(arrc, 0, len(arr)-1, k-1)
}

// arr[L..R] 如果排序的话,位于index位置的数,是什么,返回
func bfprt(arr []int, L int, R int, index int) int {
if L == R {
return arr[L]
}
// L...R 每五个数一组
// 每一个小组内部排好序
// 小组的中位数组成新数组
// 这个新数组的中位数返回
pivot := medianOfMedians(arr, L, R)
rang := partition(arr, L, R, pivot)
if index >= rang[0] && index <= rang[1] {
return arr[index]
} else if index < rang[0] {
return bfprt(arr, L, rang[0]-1, index)
} else {
return bfprt(arr, rang[1]+1, R, index)
}
}

// arr[L...R] 五个数一组
// 每个小组内部排序
// 每个小组中位数领出来,组成marr
// marr中的中位数,返回
func medianOfMedians(arr []int, L int, R int) int {
size := R - L + 1
offset := 0
if size%5 != 0 {
offset = 1
}
mArr := make([]int, size/5+offset)
for team := 0; team < len(mArr); team++ {
teamFirst := L + team*5
// L ... L + 4
// L +5 ... L +9
// L +10....L+14
mArr[team] = getMedian(arr, teamFirst, getMin(R, teamFirst+4))
}
// marr中,找到中位数
// marr(0, marr.len - 1, mArr.length / 2 )
return bfprt(mArr, 0, len(mArr)-1, len(mArr)/2)
}

func getMedian(arr []int, L int, R int) int {
insertionSort(arr, L, R)
return arr[(L+R)/2]
}

func insertionSort(arr []int, L int, R int) {
for i := L + 1; i <= R; i++ {
for j := i - 1; j >= L && arr[j] > arr[j+1]; j-- {
arr[j], arr[j+1] = arr[j+1], arr[j]
}
}
}
func getMin(a int, b int) int {
if a < b {
return a
} else {
return b
}
}
```
执行结果如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210302204502410.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80ODUwMjA2Mg==,size_16,color_FFFFFF,t_70)
***
[左神java代码](https://github.com/algorithmzuo/algorithmbasic2020/blob/master/src/class29/Code01_FindMinKth.java)
[评论](https://user.qzone.qq.com/3182319461/blog/1614640507)

2020-03-02:在无序数组中,如何求第K小的数?的更多相关文章

  1. *HDU2852 树状数组(求第K小的数)

    KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  2. 从数组中找出第K大的数

    利用改进的快排方法 public class QuickFindMaxKValue { public static void main(String[] args) { int[] a = {8, 3 ...

  3. 快速查找无序数组中的第K大数?

    1.题目分析: 查找无序数组中的第K大数,直观感觉便是先排好序再找到下标为K-1的元素,时间复杂度O(NlgN).在此,我们想探索是否存在时间复杂度 < O(NlgN),而且近似等于O(N)的高 ...

  4. 【算法】数组与矩阵问题——找到无序数组中最小的k个数

    /** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...

  5. 求一无序数组中第n大的数字 - 快速选择算法

    逛别人博客的时候,偶然看到这一算法题,顺便用C++实现了一下. 最朴素的解法就是先对数组进行排序,返回第n个数即可.. 下面代码中用的是快速选择算法(不晓得这名字对不对) #include <v ...

  6. 如何寻找无序数组中的第K大元素?

    如何寻找无序数组中的第K大元素? 有这样一个算法题:有一个无序数组,要求找出数组中的第K大元素.比如给定的无序数组如下所示: 如果k=6,也就是要寻找第6大的元素,很显然,数组中第一大元素是24,第二 ...

  7. 无序数组中第Kth大的数

    题目:找出无序数组中第Kth大的数,如{63,45,33,21},第2大的数45. 输入: 第一行输入无序数组,第二行输入K值. 该是内推滴滴打车时(2017.8.26)的第二题,也是<剑指of ...

  8. 《程序员代码面试指南》第八章 数组和矩阵问题 找到无序数组中最小的k 个数

    题目 找到无序数组中最小的k 个数 java代码 package com.lizhouwei.chapter8; /** * @Description: 找到无序数组中最小的k 个数 * @Autho ...

  9. 小米笔试题:无序数组中最小的k个数

    题目描述 链接:https://www.nowcoder.com/questionTerminal/ec2575fb877d41c9a33d9bab2694ba47?source=relative 来 ...

  10. 从长度为 M 的无序数组中,找出N个最小的数

    从长度为 M 的无序数组中,找出 N个最小的数 在一组长度为 n 的无序的数组中,取最小的 m个数(m < n), 要求时间复杂度 O(m * n) 网易有道面试题 const minTopK ...

随机推荐

  1. Activiti7开发(一)

    0.前言 开发背景 项目开发设计审批工作流,企业微信的审批不错,但是下拉列表不支持后期添加,所以只能自己实现,通过gitee查找相关工作流的开源项目,参考有 闲鹿(RuoYi+Activiti6) h ...

  2. SpringBoot使用邮件发送

    使用场景: 定时任务报错 消息推送 日志报错提醒 1.导入依赖 <dependency> <groupId>org.springframework.boot</group ...

  3. 11.3 shtctl的指定省略(harib08c)

    ps:能力有限,若有错误及纰漏欢迎指正.交流 11.3 shtctl的指定省略(harib08c) 对bootpack.h做了如下改动 struct SHEET { unsigned char *bu ...

  4. Dcat admin 多文件上传,七牛云云端上传

    进入官网  Dcat Admin - Php后台开发框架 这里要选择1.x 下面来安装框架 安装完laravel之后,需要修改.env文件,设置数据库链接设置正确 安装 dcat-admin comp ...

  5. windows cmd基础命令

    cmd md 新建目录rd 删除目录(非空目录)rd 删除目录下所有文件cd 改变当前目录cd .. 返回上一级目录cd \ 返回根目录d: 切换盘符到D盘dir 显示当前目录下的文件del 1.tx ...

  6. Redis - 对象结构

    简介 Redis 使用对象存储数据库中的键和值,每当在 Redis 中创建一个新的键值对时,都会创建两个对象:一个是键对象,另一个是值对象. 其中,Redis 的每种对象都由对象结构和对应编码的数据结 ...

  7. VUE百度地图API调用(手机端、PC端、微信通用)

    百度地图API-示例中心: https://lbsyun.baidu.com/jsdemo.htm#aCreateMap 1.引入百度地图(此处用到的是V2.0版本) 1> 建立一个js文件,例 ...

  8. QML和QT

    推荐一些学习qml教程 Qt官方的QML教程: https://doc.qt.io/qt-5/qtqml-index.html,这是一个由Qt官方提供的完整的QML教程,包含了所有基本知识和高级语法. ...

  9. CentOS7-自动化部署web集群

    一.项目要求 1.创建role,通过role完成项目(可能需要多个role) 2.部署nginx调度器(node2主机) 3.部署2台lnmp服务器(node3,node4主机) 4.部署mariad ...

  10. 在react中使用wangEditorV5

    wangEditor是基于JavaScript和css的一款web富文本编辑器,是国内比较好用的一款轻量级富文本编辑器,上手简单,易用且开源免费. 官方文档:http://www.wangeditor ...