程序员面试金典 - 面试题 10.03. 搜索旋转数组
题目难度: 中等
原题链接
今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~
题目描述
搜索旋转数组。给定一个排序后的数组,包含 n 个整数,但这个数组已被旋转过很多次了,次数不详。请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的。若有多个相同元素,返回索引值最小的一个。
示例 1:
- 输入: arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 5
- 输出: 8(元素 5 在该数组中的索引)
示例 2:
- 输入:arr = [15, 16, 19, 20, 25, 1, 3, 4, 5, 7, 10, 14], target = 11
- 输出:-1 (没有找到)
提示:
- arr 长度范围在[1, 1000000]之间
题目思考
- 直接查找好找吗, 如何对问题进行简化?
解决方案
思路
- 根据题目描述, 这个数组虽然原始是排序的, 但现在经过了旋转, 而且其中还可能有重复元素
- 这时候如果仍然直接应用传统的二分查找的话, 就需要大量的条件判断, 比如先判断哪一侧有序, 再判断有序侧的区间起点终点和 target 的关系, 判断逻辑较为复杂
- 我们可以换一个角度分析, 如果能够找到旋转点, 这样就可以将当前数组划分成左右两个有序部分了, 然后就可以转换成经典的二分查找, 即依次对左右部分进行二分, 从而大大降低代码的复杂程度
- 那么如果找到旋转点呢? 很显然旋转点位于整个数组的无序侧, 所以我们也可以使用一个二分查找, 只需要找到无序侧, 然后继续对那一侧进行二分查找即可; 这里唯一需要注意的是, 如果无法判断是否无序, 需要额外判断当前终点是否是旋转点, 是的话需要直接跳出循环
- 找到旋转点后, 我们就可以对划分成的左右两部分依次应用传统二分查找了, 由于题目要求返回目标值的最小下标, 所以只有当左侧没找到的话才继续查找右侧, 如果都没找到的话就返回-1
- 下面的代码就对应了上面的整个过程, 并且有详细的注释, 方便大家理解
复杂度
- 时间复杂度
O(N)
: 最差情况(所有数字都相等)下, 需要遍历每个数字一遍 - 空间复杂度
O(1)
: 只使用了几个常数空间的变量
代码
class Solution:def search(self, arr: List[int], target: int) -> int:# 问题转换+找旋转点+两次二分# 第一步, 先找旋转点, 将数组划分成左右两个有序部分s, e = 0, len(arr) - 1while s < e:m = (s + e) >> 1if arr[m] < arr[e]:# 右侧有序, 旋转点必在[s,m]区间e = melif arr[m] == arr[e]:# 无法判断右侧是否有序, 将e减1后再次循环判断if arr[e - 1] > arr[e]:# 注意这里可能出现旋转点就是e的情况, 例如11121, 此时如果直接-1就错了, 需要额外判断, e是旋转点的话直接跳出循环breake -= 1else:# 右侧无序, 旋转点必在[m+1,e]区间s = m + 1# 此时旋转点即为e (注意不是s, 因为有可能是因为上面的break直接跳出的循环)# 注意也有可能arr本身就是有序的, 此时得到的e就是下标0# 也即原数组划分成了[0,e-1]和[e,len(arr)-1]两个有序区间def bisearch(s, e):# 常规有序数组二分找等于target的最小下标res = float("inf")while s <= e:m = (s + e) >> 1if arr[m] >= target:if arr[m] == target:res = min(res, m)e = m - 1else:s = m + 1return -1 if res == float("inf") else res# 第二步, 再对左右两个有序部分应用常规二分找target, 如果左侧部分找到后就不再继续l = bisearch(0, e - 1)if l != -1:return lr = bisearch(e, len(arr) - 1)if r != -1:return rreturn -1
大家可以在下面这些地方找到我~
程序员面试金典 - 面试题 10.03. 搜索旋转数组相关推荐
- 程序员面试金典 - 面试题 10.03. 搜索旋转数组(二分查找)
1. 题目 搜索旋转数组.给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详. 请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的.若有多个相同元素,返回索引值最小 ...
- 程序员面试金典 - 面试题 10.11. 峰与谷
题目难度: 中等 原题链接 今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 在一个整数数组中,"峰& ...
- 60. Leetcode 面试题 10.03. 搜索旋转数组 (二分查找-局部有序)
搜索旋转数组.给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详.请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的.若有多个相同元素,返回索引值最小的一个.示例1 ...
- leetcode面试题 10.03. 搜索旋转数组(二分法)
搜索旋转数组.给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详.请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的.若有多个相同元素,返回索引值最小的一个. 示例 ...
- 程序员面试金典 - 面试题 16.03. 交点(数学)
1. 题目 给定两条线段(表示为起点start = {X1, Y1}和终点end = {X2, Y2}),如果它们有交点,请计算其交点,没有交点则返回空值. 要求浮点型误差不超过10^-6.若有多个交 ...
- 程序员面试金典 - 面试题 05.03. 翻转数位(位运算)
1. 题目 给定一个32位整数 num,你可以将一个数位从0变为1.请编写一个程序,找出你能够获得的最长的一串1的长度. 示例 1: 输入: num = 1775(11011101111) 输出: 8 ...
- [Leetcode][程序员面试金典][面试题08.03][JAVA][魔术索引][递归][优化]
[问题描述][简单] [解答思路] 1. 逐个查找 时间复杂度:O(N) 空间复杂度:O(1) public int findMagicIndex(int[] nums) {for (int i = ...
- 程序员面试金典 - 面试题 10.10. 数字流的秩(map/树状数组)
文章目录 1. 题目 2. 解题 2.1 map 2.2 树状数组 1. 题目 假设你正在读取一串整数.每隔一段时间,你希望能找出数字 x 的秩(小于或等于 x 的值的个数). 请实现数据结构和算法来 ...
- 程序员面试金典 - 面试题 10.11. 峰与谷(排序/不排序)
1. 题目 在一个整数数组中,"峰"是大于或等于相邻整数的元素,相应地,"谷"是小于或等于相邻整数的元素. 例如,在数组{5, 8, 2, 6, 3, 4, 3 ...
最新文章
- 【python教程】对多线程中join()的详细教程
- springboot2.5.0 整合 redis 配置详解
- 在vivado里用rtl描述_如何利用Vivado HLS处理许多位准确或任意精度数据类型
- 为什么GOF的23种设计模式里面没有MVC?
- 从C# 3.0到F#
- 算法笔记(胡凡)刷题笔记目录
- c2c网站开店的流程图_C2C电子商务网站的交易流程
- 【JavaWeb】用监听器实现单一登录
- 宁波中小学生计算机技术展示,宁波市第25届中小学生计算机程序设计竞赛复赛试题(小学组).doc...
- 使用 Learner Lab - 学生
- Python作业:公鸡5元/只,母鸡3元/只,小鸡1元3只。问100元怎么买到100只。
- jupyter文件自动保存为html,使用jupyter notebook将文件保存为Markdown,HTML等文件格式...
- Vue子组件绑定事件无效
- Dart笔记(10):Runes
- [YOLOv7]基于YOLO&Deepsort的交通车流量统计系统(源码&部署教程)
- anchor base和anchor free, 小物体检测, YOLO V1-3 9000 V4 V5 的区别,yolov5-8, yolox创新点
- App通过QQ/微信登录绑定用户信息的一般流程
- ARM9 SWI软件中断
- Google earth engine(GEE)——在GEE地图上加载图表
- 腾达n4怎么设置虚拟服务器,win10系统电脑设置腾达n4无线路由器的具体教程
热门文章
- JavaScript语言精粹-读书笔记(1)
- 多级缓存之Google Guava的实现方案
- Vue环境的搭建和在vscode上的应用(Window10)
- 《西游记》师徒四人给我们的职场启发
- java粒子特效教程_使用particles.js实现网页背景粒子特效
- 汽车电源acc模式_ACC的完整形式是什么?
- metronic php 后台,发一个自己写的通用后台(Yii2+metronic_v4.5.6)
- 怎么将Excel多个工作表另存为独立工作簿
- html用文本档案设置表格,phpspreadsheet 中文文档(四) 创建电子表格+档案格式
- 移动咪咕盒子红外遥控驱动