这篇博客记录我对剑指offer第2版"面试题39:数组中出现次数超过一半的数字"题解1的一句话的一个小误解,以及汇总一下涉及partition算法的相关题目。

在剑指offer第2版"面试题39:数组中出现次数超过一半的数字"的解法一(基于partition,且哨兵选择数组第一个元素)中,有这么一句话:

我们有成熟的时间复杂度为O(n)的算法得到数组中任意第k大的数字,这句话让我产生了一点误解,让我误以为"只需要调用一次partition就能找到第k大的数",但是实际上最差情况下需要调用n次partition函数才能找到第k大的数。因为partition每次都返回的是哨兵的位置,但是在函数运行过程中,随着l,r入参的变化,哨兵(数组首位元素)的位置是随之变化的,具有不确定性。

所以基于partition获取数组中任意第k大元素的时间复杂度应该如下:

  1. 最好时间复杂度 O(1) : 第一次循环就找到正确的哨兵(即,第k大元素)
  2. 最差时间复杂度 n*O(n): 最后一次才找到正确的哨兵
  3. (加权)平均复杂度 这个我不太会算,估计是O(n)

估算过程:

3.1 加权平均复杂度 = 某概率值*O(n)

3.2 概率值是常数,然后去掉常数项,得O(n)

partition的Go代码如下:

// partition代码的时间复杂度是O(n),因为需要通过for循环遍历数组,并把每个元素都划分到大分区或小分区中。
func partition(nums []int, l, r int) int {
// 1. 哨兵 取第一个元素
v := nums[l]
// 2. 大小分区的定义和初始化 [l+1,p]<v && [p+1,cur-1]>v
p := l
// 3. 处理哨兵之后的每一个元素
cur := l + 1
for ; cur <= r; cur++ {
if nums[cur] < v {
nums[cur], nums[p+1] = nums[p+1], nums[cur]
p++
}
}
nums[p], nums[l] = nums[l], nums[p] // 哨兵和小分区的最后一个元素交换,使得哨兵左边是小的,右边是大的.
return p
}

另外,还有以下这些算法题涉及了partition函数的运用,他们的共同特点都是需要用partition查找xxx位置的数字。

  1. Majority Element(本博客讨论的题) : partition查找m位置的数(中位数:索引为n/2)
  2. Kth Largest Element in an Array : partiton查找k位置的数
  3. 剑指offer面试题40:最小的k个数 : partiton查找k位置的数,但是只返回k位置左边的数,也就是小于哨兵的那些数

记录我对'我们有成熟的时间复杂度为O(n)的算法得到数组中任意第k大的数'的误解的更多相关文章

  1. 从数组中任意取出2个数,判断他们的和是否为输入的数字sum,时间复杂度为0(n^2),空间复杂度0(1)

    从数组中任意取出2个数,判断他们的和是否为输入的数字sum,时间复杂度为0(n^2),空间复杂度0(1) 假设数据已经是排序好的 #include <stdio.h> #include & ...

  2. 求数组中的最小子数组,时间复杂度o(n),java

    石家庄铁道大学 信1405-1 班 唐炳辉 题目:给定一个整数数组,找到一个具有最小和的子数组.返回其最小和. 设计思路:两个变量 ,一个记录当前并入的数组的值,另外一个记录所算过得最大的数组的值,当 ...

  3. 某整形数组中除了两个单身整数外, 其余的整数都是成对出现的, 利用C/C++代码求出这两个单身整数。 要求: 时间复杂度o(n), 空间复杂度o(1)------某公司招聘试题

    先看看这个题目:某整形数组中除了两个单身整数外, 其余的整数都是成对出现的, 利用C代码求出这两个单身整数. 要求: 时间复杂度o(n), 空间复杂度o(1). 我们先用最傻瓜的方式来做吧: #inc ...

  4. 在一个数组中,除了两个数外,其余数都是两两成对出现,找出这两个数,要求时间复杂度O(n),空间复杂度O(1)

    题目:在一个数组中,除了两个数外,其余数都是两两成对出现,找出这两个数,要求时间复杂度O(n),空间复杂度O(1) 分析:这道题考察位操作:异或(^),按位与(&),移位操作(>> ...

  5. 用O(1)的时间复杂度,找到栈和队列中的最小(大)值

    最近刷剑指offer,看到两道编程题,考察在O(1)的复杂度内,找出最值. 觉得很有意思,很有借鉴意义,故记录在此. 需要注意的是,这里所说的O(1) 有个前提, 就是已经通过某种容器的存储方式进行初 ...

  6. 给定一数组,输出满足2a=b(a,b代表数组中的数)的数对,要求时间复杂度尽量低。

    //时间复杂度O(n),空间复杂度O(n) void findSequence(int* arr, int len) { int* hashtable = new int[RANGE]; memset ...

  7. pig中查询top k,返回每个hour和ad_network_id下最大两个记录(SUBSTRING,order,COUNT_STAR,limit)

    pig里面是有TOP函数,不知道为什么用不了.有时间要去看看pig源码了. SET job.name 'top_k'; SET job.priority HIGH; --REGISTER piggyb ...

  8. 查找数组中重复的唯一元素+时间复杂度O(n)+空间复杂度O(1)

    这是我BIGO前端面试时,面试官给我出的一道题,题目是长度为N的数组,元素大小范围在[1,N-1],只有一个重复的元素,用O(n)的时间复杂度和O(1)的空间复杂度找出来这个重复的元素, 大致思路 1 ...

  9. 如何在O(n)的时间复杂度内找出数组中出现次数超过了一半的数

    方法一:每次取出两个不同的数,剩下的数字中重复出现次数超过一半的数字肯定,将规模缩小化.如果每次删除两个不同的数,这里当然不是真的把它们踢出数组,而是对于候选数来说,出现次数减一,对于其他数来说,循环 ...

随机推荐

  1. object转为string

    object为null时 错误:object.tostring() 空指针 正确:(string)object

  2. dfs题型二(迷宫问题)

    取自:<王道论坛计算机考研机试指南>6.5节 例 6.7 Temple of the bone(九度 OJ 1461)时间限制:1 秒 内存限制:32 兆 特殊判题:否题目描述:The d ...

  3. freopen函数的使用以及freopen与fopen的区别

    freopen函数的使用:参见这篇博客https://www.cnblogs.com/moonlit/archive/2011/06/12/2078712.html 当我们求解acm题目时,通常在设计 ...

  4. 题解【UVA839】天平 Not so Mobile

    Description Input Output Examples Input 1 0 2 0 4 0 3 0 1 1 1 1 1 2 4 4 2 1 6 3 2 Output YES Transla ...

  5. js对象的深拷贝及其的几种方法

    深拷贝和浅拷贝是javascript中一个比较复杂的问题,也是面试官最喜欢问的问题之一,通过这个为可以看出是否入门,深拷贝和浅拷贝也是初学者经常犯错一个点. 简单来说深拷贝是拷贝储存在栈中的对象,而浅 ...

  6. MODULE BUILD FAILED: ERROR: COULDN’T FIND PRESET “ES2015” RELATIVE TO DIRECTORY

    npm run dev 遇到报错: Module build failed: Error: Couldn't find preset "es2015" relative to di ...

  7. DFT 问答 III

    1.Boundary scan Boundary Scan就是我们俗称的边界扫描.Boundary Scan是上世纪90年代由 Joint Test Action Group(JTAG)提出的,它的初 ...

  8. intellij手动创建Mybatis遇到java.io.IOException: Could not find resource mybatis.xml

    将配置文件夹设置成resources即可

  9. 动态路由协议 RIP

    RIP:Routing Information Protocol.RFC1058. 距离矢量协议:有间隔的多少和方向.传递的是路由条目.每个路由器不知道网络的完整拓扑结构,OSPF知道. 度量值:每种 ...

  10. 有趣、实用的c# 游戏源码下载网站

    在游戏开发的学习或工作中,利用完好的游戏源码可以事半功倍,不仅可以逆向学习开拓思维,也可以大大减少设计周期. 那想用c#来编写游戏的话,游戏源码在哪里找呢?下面整理了几个性价比高一些的网站,推荐给大家 ...