Partion函数最早出现于快速排序算法,但其代表的分治思想,在《剑指offer》这本书中求数组中位数(面试题39,数组中出现次数超过一半的数字)中也有所涉及,将其汇总在一起,称之为Partition函数及其周边。
  快速排序完整代码Github连接
  数组中位数完整Github连接
  TopK问题完整代码Github连接
  若打开Github网址有困难,可以参考我的这篇文章程序员常用网站加速方法

1. 快速排序

 1.1 快排之Partion函数

  Partition函数是快速排序的核心。下面代码是我基于c++语言对快速排序算法的实现。

#include <iostream>
#include <ctime>// exch array[i] and array[j]
void Exch(int *array, int i, int j);
void RandShuffle(int *array, int lo, int hi);//find j, and make array[i] <= array[j], when 0 <=i <= j-1
//            make array[i] >= array[j], when j < j+1 < len -1
int Partition(int * array, int len, int lo, int hi)
{int i = lo;int j = hi+1 ;//后撤一步while (true){while (array[++i] <= array[lo] && i < hi);//停在“大”数字,或者递减数组,一直到hiwhile (array[--j] >= array[lo] && j > lo);//停在“小”数字,或者递增数组,一直到loif (i >= j) break;//此处i和j的最终停止范围,j<i,除非数组本身递减此时i=jExch(array, i, j);}Exch(array, j, lo);//此处i和j不等价,因为99%的情形下,j=i-1;1%的情形始,i=j=hi(递减)return j;}
int QuickSort(int *array, int len, int lo, int hi)
{if (lo >= hi)return 1;//递归终止条件,递归子问题的数组已经变成一个元素,此时就可以return了。RandShuffle(array, lo, hi);//每一次打乱递归子数组的顺序,使得达到一种均衡效率。//递归调用必须有一个父问题---》(简单)子问题的过程int target = Partition(array, len, lo, hi);QuickSort(array, len, lo, target - 1);QuickSort(array, len, target + 1, hi);return 1;
}int main(int argv, char * argc)
{int array[5] = { 0, 4, 3, 2, 1};int len = sizeof(array) / sizeof(int);//数组输入检查if (array == nullptr || len < 1){return -1;}//主体int lo = 0;int hi = len - 1;QuickSort(array, len, lo, hi);...return 0;
}

 1.2 快排算法中,最终状态下i和j的位置关系分析

  首先,要强调一点最终是lo和j指向的元素进行,因为J最终会停留在小于等于array[lo]的位置,而i则大部分情形下会停留在大于等于array[lo]的位置,就像这样。
  array的lo和hi段普通情形:满足j<ij<ij<i,且j=i−1j=i-1j=i−1

  array的lo和hi段递减情形:此时i=j=hii=j=hii=j=hi

array的lo和hi段递增情形:此时j<ij<ij<i,且j=i−1j=i-1j=i−1

  综上所述,i和j并非等价的关系,大部分情形下,i=j+1,且j代表的总是小于等于a[lo]的元素,因此将其与a[lo]交换,这样符合交换后,小—target—大的顺序。

 1.3 快排算法的计算复杂度

  网上已经有不少的证明计算复杂度的博客 ,我认为只需大概理解理想情况下的每次等分的证明情形即可。
  然后需要有一个直观反射弧,如果T(l)=2T(l−1)+nT(l)=2T(l-1)+nT(l)=2T(l−1)+n这样的推导通式,其计算复杂度为o(nlogn)o(nlogn)o(nlogn)。再有就是,记住T(1)=0T(1)=0T(1)=0,算法的迭代次数为二叉树的高度lognlognlogn,可以有助于自己必要时刻随时推出该计算复杂度。

2. Partition在求数组中位数中的应用

  面试题39:数组中出现次数超过一半的数字。
  分析,出现次数超过一半的数字,等同于该数组的中位数。分析见下图

  • 若数组元素个数n为奇数:对于排完序数组

  • 若数组元素个数n为偶数:对于排完序数组


  但如果仔细分析,上述排序数组,并非需要严格有序,如果我们去先排序的话,最低的时间复杂度也需要o(nlogn)o(nlogn)o(nlogn),但事实上,只要保证[0+len-1]/2处元素,大于其左边元素,小于其右边元素,此时其即为中位数,这个要求显然比严格有序要低,后面会证明,达到这种效果,最快的算法为o(n)o(n)o(n)。
  看到“保证[0+len-1]/2处元素,大于其左边元素,小于其右边元素”这种要求,应该可以联系到我们已有的一些"武器库" : Partition函数。
  只不过这次我们不再调用递归算法,而是采用while循环,这样当找到中位数时理解可以中止程序(递归比较适用于把所有的元素都理顺)。
  核心代码如下:

 int target = hi / 2;int return_value = Partition(array, lo, hi);while (return_value != target){if (return_value > target){lo = lo;hi = return_value-1;return_value = Partition(array, lo, hi);}else{lo = return_value+1;hi = hi;return_value = Partition(array, lo, hi);}}

2.2 Partition函数求数组的中位数补充知识

  

时间复杂度时o(n)。基于Partition函数的算法的时间复杂度的分析不是很直观,本书限于篇幅不作详细讨论,感兴趣的读者可以参考《算法导论》等书籍的相关章节。

  该Partition函数会修改数组的内容。事实上对于“数组中超过一半的数字”除了从中位数的角度出发,还可以从原始超过一半来出发,我把这种解法称之为“动物世界”,具体见《剑指offer》杂篇

3. Partition函数在Topk问题中的应用

 3.1 面试题40:最小的k个数

  题目:输入n个整数,找出其中最小的k个数。例如,输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
  TopK的解题思路之一同求中位数一样,将排序问题退化为相对有序问题,此时计算复杂度从nlog(n)nlog(n)nlog(n)退化为o(n)o(n)o(n)。解题思路同中位数一样,只不过期望的“卡点”位置变为k−1k-1k−1。完整代码见:
TopK问题完整代码Github连接
  相当于于中位数相比,仅仅改变了如下几行代码:

//中位数版本
int target = hi / 2;
int return_value = Partition(array, lo, hi);
while (return_value != target)//topk版本
while (target != k - 1){if (target > k - 1)

《剑指offer》Partition函数及其Partition函数周边相关推荐

  1. 剑指offer系列-30.包含min函数的栈

    剑指offer系列第30题.包含min函数的栈 题目描述: 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中, 调用 min.push 及 pop 的时间复杂度都是 ...

  2. 剑指offer 面试题1:赋值运算符函数【C++版本】

    题目总结与代码归档: [剑指offer-2]题目目录[C++版本] GitHub代码路径: GitHub 面试题1 赋值运算符函数 题目: 如下为类型CMyString的声明,请为该类型添加赋值运算符 ...

  3. 【剑指Offer】20包含min函数的栈

    题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 时间限制:1秒:空间限制:32768K:本题知识点:栈 解题思路 # -*- codi ...

  4. 【剑指offer】登峰造极--包含min函数的栈

    时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M 热度指数:439567 本题知识点: 栈 算法知识视频讲解 题目描述 定义栈的数据结构,请在该类型中实现一个能够 ...

  5. 《剑指offer》写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。...

    弱菜刷题还是刷中文题好了,没必要和英文过不去,现在的重点是基本代码能力的恢复. [题目] 剑指offer 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. [思路] 直觉 ...

  6. 剑指offer:包含min函数的栈 python实现

    题目 题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 解题思路 暴力做法: 遍历一遍,找最小的数,然后返回. # -*- coding ...

  7. 《LeetCode力扣练习》剑指 Offer 30. 包含min函数的栈 Java

    <LeetCode力扣练习>剑指 Offer 30. 包含min函数的栈 Java 一.资源 题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调 ...

  8. 【LeetCode】剑指 Offer 30. 包含min函数的栈

    [LeetCode]剑指 Offer 30. 包含min函数的栈 文章目录 [LeetCode]剑指 Offer 30. 包含min函数的栈 一.辅助栈 一.辅助栈 解题思路: 普通栈的 push() ...

  9. 赋值运算符函数__from 剑指Offer

    前段时间忙于项目,难得偷得几日闲,为即将到来的就业季做准备.在面试时,应聘者要注意多和考官交流,只有具备良好的沟通能力,才能充分了解面试官的需求,从而有针对性地选择算法解决问题. 题目来源于<剑 ...

最新文章

  1. 共享数字经济之光!世界互联网大会重磅发布“30位新生代数字经济人才”
  2. shell字符串的处理
  3. 开源跳板机(堡垒机)Jumpserver v0.3.0 发布
  4. 如何搭建socks5和ss节点_redis cluster搭建实践(非常详细,值得收藏)
  5. MFC遍历指定目录下的所有文件/文件夹(不遍历子目录)
  6. 使用WebService与Oracle EBS进行集成(上)
  7. git reset --hard命令小结
  8. 软件测试面试题目—接口测试面试题,梦寐以求的答案来了
  9. WPS表格简单入门_我的笔记_一些常用操作
  10. 丝般顺滑!全新垃圾回收器 ZGC 初体验 | 龙蜥技术
  11. thingJS模模搭(campusbuilder/momoda)及3dsmax插件遇到的坑
  12. 三升序列 和递增序列
  13. chatgpt如何自动生成角色prompt模板
  14. SEER见证人操作指南
  15. 画仓鼠大赛 结果公布
  16. PPT动画中点击、之前、之后的区别
  17. python时区、时差、时间差转换——datetime.timedelta类介绍
  18. 《笨办法学python》加分习题31——我的答案
  19. 计算机网络体系结构-移动IP
  20. 【Python】netwokx生成图源码

热门文章

  1. 通证经济大局观(十五):稀缺性与权衡取舍
  2. js一个文件上传成功后的响应事件处理
  3. 世界首款全片幅微单眼Sony A7R 评测:标志微单眼迈进全片幅
  4. centos+jenkins+nginx+gitlab前端自动化部署全记录
  5. 从阿里9面到腾讯5面后被字节捞走,四年Android 开发辛酸之路…,androidstudio汉化
  6. poj3074,3076 数独!(DLX)
  7. 阔别7年,故地重游---崇明岛
  8. selenium原理python_从python角度解析selenium原理
  9. 2019年定制安卓app开发的五大优势
  10. 定期修改mysql 密码_MySQL修改账号密码方法大全