【LeetCode】搜索旋转排序数组 [M](二分)
创始人
2024-04-30 22:14:53
0

33. 搜索旋转排序数组 - 力扣(LeetCode)

一、题目

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4

示例 2:​​​​​​​

输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1

示例 3:​​​​​​​

输入:nums = [1], target = 0
输出:-1

提示:

  • 1 <= nums.length <= 5000
  • -10^4 <= nums[i] <= 10^4
  • nums 中的每个值都 独一无二
  • 题目数据保证 nums 在预先未知的某个下标上进行了旋转
  • -10^4 <= target <= 10^4

二、代码

class Solution {public int search(int[] nums, int target) {// 设置左右边界指针int l = 0;int r = nums.length - 1;// 开始二分while (l <= r) {// 计算中间下标int m = (l + r) >> 1;// 如果中间值正好等于target,直接返回下标mif (nums[m] == target) {return m;}// 如果三个下标位置的数相等,并且他们又不等于target([L] == [M] == [R] != target),这种情况是没有办法二分的,因为无法确定断电在左侧还是在右侧if (nums[l] == nums[m] && nums[m] == nums[r]) {// 这种情况下让L往下走,L++,直到遇到一个不是num[M]的位置,在当前L...R上继续二分while (l != m && nums[l] == nums[m]) {l++;}// 执行到这里,有两种情况:// 1) L == M L...M都一路都相等// 2) 从L到M终于找到了一个不等的位置if (l == m) { // L...M 一路都相等// L一直往右,到M了,一路都是num[M],那么在M+1到R上二分l = m + 1;continue;}}// 执行到这里,arr[M]一定是 != num的// [L] [M] [R] 不都一样的情况, 如何二分的逻辑// [L] != [M]if (nums[l] != nums[m]) {// 如果[L] < [M],说明左侧是有序的,那么断点应该在右侧if (nums[l] < nums[m]) {// 如果target的范围就在左侧有序的范围内,那么我们就对左侧进行二分if (target >= nums[l] && target < nums[m]) {r = m - 1;// 否则,target就应该在无序的右侧,我们就去右侧进行二分} else {l = m + 1;}// 这个情况就是右侧是有序的,断点在左侧} else {// 如果target的范围就在右侧有序的范围内,那么我们就对右侧进行二分if (target > nums[m] && target <= nums[r]) {l = m + 1;// 否则,target就应该在无序的左侧,我们就去左侧进行二分 } else {r = m - 1;}}// [M] != [R]} else {// 如果[M] < [R],说明右侧是有序的,那么断点应该在左侧if (nums[m] < nums[r]) {if (target > nums[m] && target <= nums[r]) {l = m + 1;} else {r = m - 1;}// 这个情况就是左侧是有序的,断点在右侧} else {if (target >= nums[l] && target < nums[m]) {r = m - 1;} else {l = m + 1;}}}}// 如果整个二分过程没有找到target,就说明数组中没有target,返回-1return -1;}
}

三、解题思路 

将数组分成左右两部分,如果[L] < [M],那么说明左部分一定是有序的,断点一定在右侧。反之,如果[M] < [R],那么说明右部分一定是有序的,断点一定在左侧。因为断点所在的那一侧一定会是[L] > [M]或[M] > [R],这一点随便举例子就能发现。

相关内容

热门资讯

安卓双系统添加应用,轻松实现多... 你有没有想过,你的安卓手机里可以同时运行两个系统呢?听起来是不是很酷?想象一边是熟悉的安卓系统,一边...
pipo安卓进系统慢,探究pi... 最近是不是发现你的Pipo安卓系统更新或者运行起来特别慢?别急,今天就来给你好好分析分析这个问题,让...
怎样使用安卓手机系统,安卓手机... 你有没有发现,安卓手机已经成为我们生活中不可或缺的一部分呢?从早晨闹钟响起,到晚上睡前刷剧,安卓手机...
双系统安卓安装caj,轻松实现... 你有没有想过,你的安卓手机里装上双系统,是不是就能同时享受安卓和Windows系统的乐趣呢?没错,这...
安卓使用ios系统教程,安卓用... 你是不是也和我一样,对安卓手机上的iOS系统充满了好奇?想要体验一下苹果的优雅和流畅?别急,今天我就...
安卓系统gps快速定位,畅享便... 你有没有遇到过这样的情况:手机里装了各种地图导航软件,但每次出门前都要等上好几分钟才能定位成功,急得...
安卓手机系统更新原理,原理与流... 你有没有发现,你的安卓手机最近是不是总在提醒你更新系统呢?别急,别急,让我来给你揭秘一下安卓手机系统...
安卓系统通知管理,全面解析与优... 你有没有发现,手机里的通知就像是一群调皮的小精灵,时不时地跳出来和你互动?没错,说的就是安卓系统的通...
安卓系统手机哪买,揭秘哪里购买... 你有没有想过,拥有一部安卓系统手机是多么酷的事情呢?想象你可以自由安装各种应用,不受限制地探索各种功...
安卓系统 ipv4,基于安卓系... 你知道吗?在智能手机的世界里,有一个系统可是无人不知、无人不晓,那就是安卓系统。而在这个庞大的安卓家...
目前安卓是什么系统,探索安卓系... 亲爱的读者,你是否曾好奇过,如今安卓系统究竟是什么模样?在这个科技飞速发展的时代,操作系统如同人体的...
安卓6.0系统比5.0,从5.... 你有没有发现,自从手机更新了安卓6.0系统,感觉整个人都清爽了不少呢?没错,今天咱们就来聊聊这个话题...
安卓2.36系统升级,功能革新... 你知道吗?最近安卓系统又来了一次大变身,那就是安卓2.36系统升级!这可不是一个小打小闹的更新,而是...
安卓系统源码怎么打开,并可能需... 你有没有想过,安卓系统的源码就像是一扇神秘的门,隐藏着无数的技术秘密?想要打开这扇门,你得掌握一些小...
安卓8.0系统体验视频,智能革... 你有没有听说安卓8.0系统最近可是火得一塌糊涂啊!作为一个紧跟科技潮流的数码达人,我当然要来给你好好...
宣传系统漫画app安卓,探索安... 亲爱的读者们,你是否曾在某个午后,百无聊赖地打开手机,想要寻找一些轻松愉悦的读物?今天,我要给你介绍...
鸿蒙替换安卓系统吗,开启智能生... 你知道吗?最近科技圈里可是炸开了锅,因为华为的新操作系统鸿蒙系统,据说要大举进军手机市场,替换掉安卓...
手机安卓系统深度清理,解锁手机... 手机里的东西是不是越来越多,感觉就像一个装满了杂物的储物柜?别急,今天就来教你一招——手机安卓系统深...
安卓上的windows系统,融... 你有没有想过,在安卓手机上也能体验到Windows系统的魅力呢?没错,这就是今天我要跟你分享的神奇故...
安卓系统焦点变化事件,Andr... 你知道吗?在安卓系统的世界里,最近发生了一件超级有趣的事情——焦点变化事件。这可不是什么小打小闹,它...