《剑指offer》Partition函数及其Partition函数周边
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函数周边相关推荐
- 剑指offer系列-30.包含min函数的栈
剑指offer系列第30题.包含min函数的栈 题目描述: 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中, 调用 min.push 及 pop 的时间复杂度都是 ...
- 剑指offer 面试题1:赋值运算符函数【C++版本】
题目总结与代码归档: [剑指offer-2]题目目录[C++版本] GitHub代码路径: GitHub 面试题1 赋值运算符函数 题目: 如下为类型CMyString的声明,请为该类型添加赋值运算符 ...
- 【剑指Offer】20包含min函数的栈
题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 时间限制:1秒:空间限制:32768K:本题知识点:栈 解题思路 # -*- codi ...
- 【剑指offer】登峰造极--包含min函数的栈
时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M 热度指数:439567 本题知识点: 栈 算法知识视频讲解 题目描述 定义栈的数据结构,请在该类型中实现一个能够 ...
- 《剑指offer》写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。...
弱菜刷题还是刷中文题好了,没必要和英文过不去,现在的重点是基本代码能力的恢复. [题目] 剑指offer 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. [思路] 直觉 ...
- 剑指offer:包含min函数的栈 python实现
题目 题目描述 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 解题思路 暴力做法: 遍历一遍,找最小的数,然后返回. # -*- coding ...
- 《LeetCode力扣练习》剑指 Offer 30. 包含min函数的栈 Java
<LeetCode力扣练习>剑指 Offer 30. 包含min函数的栈 Java 一.资源 题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调 ...
- 【LeetCode】剑指 Offer 30. 包含min函数的栈
[LeetCode]剑指 Offer 30. 包含min函数的栈 文章目录 [LeetCode]剑指 Offer 30. 包含min函数的栈 一.辅助栈 一.辅助栈 解题思路: 普通栈的 push() ...
- 赋值运算符函数__from 剑指Offer
前段时间忙于项目,难得偷得几日闲,为即将到来的就业季做准备.在面试时,应聘者要注意多和考官交流,只有具备良好的沟通能力,才能充分了解面试官的需求,从而有针对性地选择算法解决问题. 题目来源于<剑 ...
最新文章
- 共享数字经济之光!世界互联网大会重磅发布“30位新生代数字经济人才”
- shell字符串的处理
- 开源跳板机(堡垒机)Jumpserver v0.3.0 发布
- 如何搭建socks5和ss节点_redis cluster搭建实践(非常详细,值得收藏)
- MFC遍历指定目录下的所有文件/文件夹(不遍历子目录)
- 使用WebService与Oracle EBS进行集成(上)
- git reset --hard命令小结
- 软件测试面试题目—接口测试面试题,梦寐以求的答案来了
- WPS表格简单入门_我的笔记_一些常用操作
- 丝般顺滑!全新垃圾回收器 ZGC 初体验 | 龙蜥技术
- thingJS模模搭(campusbuilder/momoda)及3dsmax插件遇到的坑
- 三升序列 和递增序列
- chatgpt如何自动生成角色prompt模板
- SEER见证人操作指南
- 画仓鼠大赛 结果公布
- PPT动画中点击、之前、之后的区别
- python时区、时差、时间差转换——datetime.timedelta类介绍
- 《笨办法学python》加分习题31——我的答案
- 计算机网络体系结构-移动IP
- 【Python】netwokx生成图源码
热门文章
- 通证经济大局观(十五):稀缺性与权衡取舍
- js一个文件上传成功后的响应事件处理
- 世界首款全片幅微单眼Sony A7R 评测:标志微单眼迈进全片幅
- centos+jenkins+nginx+gitlab前端自动化部署全记录
- 从阿里9面到腾讯5面后被字节捞走,四年Android 开发辛酸之路…,androidstudio汉化
- poj3074,3076 数独!(DLX)
- 阔别7年,故地重游---崇明岛
- selenium原理python_从python角度解析selenium原理
- 2019年定制安卓app开发的五大优势
- 定期修改mysql 密码_MySQL修改账号密码方法大全