接前文,除了广泛使用在快速排序中。Partition算法还可以很容易的实现在无序序列中使用O(n)的时间复杂度查找kth(第k大(小)的数)。

同样根据二分的思想,每完成一次Partition我们可以轻松的知道该位置前面有几个比自己小的数,后面有几个比自己大的数(或逆序相反)。所以也能知道自己是第几大或者小的数。

查找kth(大/小)

func partition(left int, right int, arr []int) (int) {
i := left
j := right
pivot := arr[left]
for i != j {
for i < j && arr[j] >= pivot {
j--
} for i < j && arr[i] <= pivot {
i++
} if i < j{
arr[i], arr[j] = arr[j], arr[i]
}
}
arr[left], arr[i] = arr[i], arr[left]
return i
} func findKthSmallestNumber(arr[]int, k int) (int) {
left := 0
right := len(arr)-1
targetNumber := 0
for left <= right {
pos := partition(left, right, arr)
if pos == k-1 {
targetNumber = arr[pos]
break
} else if pos > k-1 {
right = pos - 1
} else {
left = pos + 1
}
}
return targetNumber
} func main() {
list := []int{4, 3, 1, 4, 5, 6, 3}
fmt.Println(findKthSmallestNumber(list, 6))
}

逻辑是每次partition回传的位置,都是分割好的位置。

那么我们假设默认pivot设置的数总是操作数组(假如是按照正序排列,即比pivot大的数放右边,比pivot小的数放左边)的第一个数。分割完毕后,我们拿着回传的pivot位置同要寻找的k小的数做比较。

如果 pivot = k-1 那么说明这就是我们要找的那个位置,直接返回即可。pivot返回的是索引位置,比如我们要找第二小的数,索引位置就应该是1。

如果 pivot > k-1 那么说明我们要找的数在pivot的左边,这时我们需要将right置为pos索引-1

如果 pivot < k-1 那么说明我们要找的数载pivot的右边,这时我们需要将left的值置为pos索引+1

另外特别要注意的一点就是边界的问题。由于上面我使用的例子中right就是传递的索引的终点为之,所以left是有可能等于right的情况的,这时要让程序进入循环正确退出。如果你使用的是len数量版本的partition算法,就不需要这样做。

Dutch national flag problem:

荷兰国旗问题,同样是经典的Partition算法的问题。通过一次扫描来进行归类,依然是他核心思想。解决这个问题我们除了要同时使用头部指针,尾部指针以外。还需要使用一个当前位置的指针来扫描。

func threeWayPartition(list []int, target int) {
var smallestPos, scanPos int
biggestPos := len(list)-1 for scanPos <= biggestPos {
if list[scanPos] < target {
list[scanPos], list[smallestPos] = list[smallestPos], list[scanPos]
scanPos++
smallestPos++
} else if list[scanPos] > target {
list[scanPos], list[biggestPos] = list[biggestPos], list[scanPos]
biggestPos--
} else {
scanPos ++
}
}
}

首先扫描的当前位置只能小于和等于指向最大指针的位置。因为我们总是使用scanPos位置上的数来进行判断的,如果这里是小于而不是小于等于的话就意味着指向最大值的指针位置所在的值miss了。

说明这个之后,其他的就可以分为三种情况。

如果scanPos > target的话 就会跟后面指向大值的指针交换,然后大值指针往后退一

如果scanPos < target的话 就会跟前面指向小值的指针交换,然后当前指针位置和指向最小值的指针同进一

如果scanPos = target的话 当前指针继续往前,指向小值的指针会原地不动。

用心感受一下,其实还是蛮简单的。。

Partition算法以及其应用详解下(Golang实现)的更多相关文章

  1. Partition算法以及其应用详解上(Golang实现)

    最近像在看闲书一样在看一本<啊哈!算法> 当时在amazon上面闲逛挑书,看到巨多人推荐这本算法书,说深入浅出简单易懂便买来阅读.实际上作者描述算法的能力的确令人佩服.就当复习常用算法吧. ...

  2. python 排序算法总结及实例详解

    python 排序算法总结及实例详解 这篇文章主要介绍了python排序算法总结及实例详解的相关资料,需要的朋友可以参考下 总结了一下常见集中排序的算法 排序算法总结及实例详解"> 归 ...

  3. SSL/TLS协议详解(下)——TLS握手协议

    本文转载自SSL/TLS协议详解(下)--TLS握手协议 导语 在博客系列的第2部分中,对证书颁发机构进行了深入的讨论.在这篇文章中,将会探索整个SSL/TLS握手过程,在此之前,先简述下最后这块内容 ...

  4. [js高手之路]深入浅出webpack教程系列3-配置文件webpack.config.js详解(下)

    本文继续接着上文,继续写下webpack.config.js的其他配置用法. 一.把两个文件打包成一个,entry怎么配置? 在上文中的webpack.dev.config.js中,用数组配置entr ...

  5. SSD算法及Caffe代码详解(最详细版本)

    SSD(single shot multibox detector)算法及Caffe代码详解 https://blog.csdn.net/u014380165/article/details/7282 ...

  6. 红黑树原理详解及golang实现

    目录 红黑树原理详解及golang实现 二叉查找树 性质 红黑树 性质 operation 红黑树的插入 golang实现 类型定义 leftRotate RightRotate Item Inter ...

  7. 关联规则算法(The Apriori algorithm)详解

    一.前言 在学习The Apriori algorithm算法时,参考了多篇博客和一篇论文,尽管这些都是很优秀的文章,但是并没有一篇文章详解了算法的整个流程,故整理多篇文章,并加入自己的一些注解,有了 ...

  8. SSD(single shot multibox detector)算法及Caffe代码详解[转]

    转自:AI之路 这篇博客主要介绍SSD算法,该算法是最近一年比较优秀的object detection算法,主要特点在于采用了特征融合. 论文:SSD single shot multibox det ...

  9. CSS2.1SPEC:视觉格式化模型之width属性详解(下)

    本文承接CSS2.1SPEC:视觉格式化模型之width属性详解(上),继续分析CSS视觉格式化模型中width以及相关值的计算问题: 注:与上节不同,本节的demo中由于出现了float,absol ...

随机推荐

  1. 关于connect by rownum与connect by leve

    http://www.itpub.net/forum.php?mod=viewthread&tid=1570306 http://www.itpub.net/forum.php?mod=vie ...

  2. P1433 吃奶酪(搜索DFS+记忆化)

    emmmmm,我还是看了题解的....尴尬,其实不用记忆化搜索也是可以的.因为我不用也是最后一个点超时.但是我是用的贪心+DFS...超时的原因是贪心....mmp,本来加贪心就是为了不超时.... ...

  3. day26 Python __getattribute__

    __getattr__#不存在的属性访问,触发__getattr__ class Foo: def __init__(self,x): self.x=x def __getattr__(self, i ...

  4. Oracle报错ORA-16433非归档丢失redo无法启动的恢复过程

    [案例]Oracle报错ORA-16433非归档丢失redo无法启动的恢复过程 转惜纷飞 今天ML的群中女神和travel在纠结一个恢复的问题,11.2.0.3版本,非归档,大概是rm掉current ...

  5. Luogu1627 [CQOI2009]中位数

    Luogu1627 [CQOI2009]中位数 给出一个 \(n\) 的排列,统计该排列有多少个长度为奇数的连续子序列的中位数是 \(k\) \(n\leq10^5\) \(trick\) :因为不需 ...

  6. 2018-2019-2 20175310 实验二《Java面向对象程序设计》实验报告

    2018-2019-2 20175310 实验二<Java面向对象程序设计>实验报告 一.实验步骤及内容 (一).面向对象程序设计-1 参考 http://www.cnblogs.com/ ...

  7. 【mongoDB查询进阶】聚合管道(一) -- 初识

    https://segmentfault.com/a/1190000010618355 前言:一般查询可以通过find方法,但如果是比较复杂的查询或者数据统计的话,find可能就无能为力了,这时也许你 ...

  8. 基于Vue.js 2.0 + Vuex打造微信项目

    一.项目简介 基于Vue + Vuex + Vue-router + Webpack 2.0打造微信界面,实现了微信聊天.搜索.点赞.通讯录(快速导航).个人中心.模拟对话.朋友圈.设置等功能. 二. ...

  9. FineUIMvc随笔(3)不能忘却的回发(__doPostBack)

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. 用户反馈 有网友在官方论坛抛出了这么一个问题,似乎对 FineUIMvc 中的浏览器端与服务器端的交互方式很有异议. 这里面的关 ...

  10. PayPal、支付宝诞生的故事 | 概述起源篇

    你知道第三方支付是如何由来的吗? 第三方支付概述 说起第三方支付,好像大家都知道,天天不是用支付宝和微信吗?支付宝和微信支付确实是行业内非常具有代表的第三方支付公司,但现在他们已经不完全是一家第三方支 ...