题目难度: 中等

原题链接

今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

搜索旋转数组。给定一个排序后的数组,包含 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]之间

题目思考

  1. 直接查找好找吗, 如何对问题进行简化?

解决方案

思路

  • 根据题目描述, 这个数组虽然原始是排序的, 但现在经过了旋转, 而且其中还可能有重复元素
  • 这时候如果仍然直接应用传统的二分查找的话, 就需要大量的条件判断, 比如先判断哪一侧有序, 再判断有序侧的区间起点终点和 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. 搜索旋转数组相关推荐

  1. 程序员面试金典 - 面试题 10.03. 搜索旋转数组(二分查找)

    1. 题目 搜索旋转数组.给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详. 请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的.若有多个相同元素,返回索引值最小 ...

  2. 程序员面试金典 - 面试题 10.11. 峰与谷

    题目难度: 中等 原题链接 今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 在一个整数数组中,"峰& ...

  3. 60. Leetcode 面试题 10.03. 搜索旋转数组 (二分查找-局部有序)

    搜索旋转数组.给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详.请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的.若有多个相同元素,返回索引值最小的一个.示例1 ...

  4. leetcode面试题 10.03. 搜索旋转数组(二分法)

    搜索旋转数组.给定一个排序后的数组,包含n个整数,但这个数组已被旋转过很多次了,次数不详.请编写代码找出数组中的某个元素,假设数组元素原先是按升序排列的.若有多个相同元素,返回索引值最小的一个. 示例 ...

  5. 程序员面试金典 - 面试题 16.03. 交点(数学)

    1. 题目 给定两条线段(表示为起点start = {X1, Y1}和终点end = {X2, Y2}),如果它们有交点,请计算其交点,没有交点则返回空值. 要求浮点型误差不超过10^-6.若有多个交 ...

  6. 程序员面试金典 - 面试题 05.03. 翻转数位(位运算)

    1. 题目 给定一个32位整数 num,你可以将一个数位从0变为1.请编写一个程序,找出你能够获得的最长的一串1的长度. 示例 1: 输入: num = 1775(11011101111) 输出: 8 ...

  7. [Leetcode][程序员面试金典][面试题08.03][JAVA][魔术索引][递归][优化]

    [问题描述][简单] [解答思路] 1. 逐个查找 时间复杂度:O(N) 空间复杂度:O(1) public int findMagicIndex(int[] nums) {for (int i = ...

  8. 程序员面试金典 - 面试题 10.10. 数字流的秩(map/树状数组)

    文章目录 1. 题目 2. 解题 2.1 map 2.2 树状数组 1. 题目 假设你正在读取一串整数.每隔一段时间,你希望能找出数字 x 的秩(小于或等于 x 的值的个数). 请实现数据结构和算法来 ...

  9. 程序员面试金典 - 面试题 10.11. 峰与谷(排序/不排序)

    1. 题目 在一个整数数组中,"峰"是大于或等于相邻整数的元素,相应地,"谷"是小于或等于相邻整数的元素. 例如,在数组{5, 8, 2, 6, 3, 4, 3 ...

最新文章

  1. 【python教程】对多线程中join()的详细教程
  2. springboot2.5.0 整合 redis 配置详解
  3. 在vivado里用rtl描述_如何利用Vivado HLS处理许多位准确或任意精度数据类型
  4. 为什么GOF的23种设计模式里面没有MVC?
  5. 从C# 3.0到F#
  6. 算法笔记(胡凡)刷题笔记目录
  7. c2c网站开店的流程图_C2C电子商务网站的交易流程
  8. 【JavaWeb】用监听器实现单一登录
  9. 宁波中小学生计算机技术展示,宁波市第25届中小学生计算机程序设计竞赛复赛试题(小学组).doc...
  10. 使用 Learner Lab - 学生
  11. Python作业:公鸡5元/只,母鸡3元/只,小鸡1元3只。问100元怎么买到100只。
  12. jupyter文件自动保存为html,使用jupyter notebook将文件保存为Markdown,HTML等文件格式...
  13. Vue子组件绑定事件无效
  14. Dart笔记(10):Runes
  15. [YOLOv7]基于YOLO&Deepsort的交通车流量统计系统(源码&部署教程)
  16. anchor base和anchor free, 小物体检测, YOLO V1-3 9000 V4 V5 的区别,yolov5-8, yolox创新点
  17. App通过QQ/微信登录绑定用户信息的一般流程
  18. ARM9 SWI软件中断
  19. Google earth engine(GEE)——在GEE地图上加载图表
  20. 腾达n4怎么设置虚拟服务器,win10系统电脑设置腾达n4无线路由器的具体教程

热门文章

  1. JavaScript语言精粹-读书笔记(1)
  2. 多级缓存之Google Guava的实现方案
  3. Vue环境的搭建和在vscode上的应用(Window10)
  4. 《西游记》师徒四人给我们的职场启发
  5. java粒子特效教程_使用particles.js实现网页背景粒子特效
  6. 汽车电源acc模式_ACC的完整形式是什么?
  7. metronic php 后台,发一个自己写的通用后台(Yii2+metronic_v4.5.6)
  8. 怎么将Excel多个工作表另存为独立工作簿
  9. html用文本档案设置表格,phpspreadsheet 中文文档(四) 创建电子表格+档案格式
  10. 移动咪咕盒子红外遥控驱动