Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Your algorithm's runtime complexity must be in the order of O(log n).

Example 1:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Example 2:

Input: nums = [4,5,6,7,0,1,2], target = 3
Output: -1

这道题让在旋转数组中搜索一个给定值,若存在返回坐标,若不存在返回 -1。我们还是考虑二分搜索法,但是这道题的难点在于不知道原数组在哪旋转了,还是用题目中给的例子来分析,对于数组 [0 1 2 4 5 6 7] 共有下列七种旋转方法(红色表示中点之前或者之后一定为有序的):

0  1  2   4  5  6  7

7  0  1   2  4  5  6

6  7  0   1  2  4  5

5  6  7   0  1  2  4

4  5  6  7  0  1  2

2  4  5  6  7  0  1

1  2  4  5  6  7  0

二分搜索法的关键在于获得了中间数后,判断下面要搜索左半段还是右半段,观察上面红色的数字都是升序的(Github 中可能无法显示颜色,参见博客园上的帖子),可以得出出规律,如果中间的数小于最右边的数,则右半段是有序的,若中间数大于最右边数,则左半段是有序的,我们只要在有序的半段里用首尾两个数组来判断目标值是否在这一区域内,这样就可以确定保留哪半边了,代码如下:

解法一:

class Solution {
public:
int search(vector<int>& nums, int target) {
int left = , right = nums.size() - ;
while (left <= right) {
int mid = left + (right - left) / ;
if (nums[mid] == target) return mid;
if (nums[mid] < nums[right]) {
if (nums[mid] < target && nums[right] >= target) left = mid + ;
else right = mid - ;
} else {
if (nums[left] <= target && nums[mid] > target) right = mid - ;
else left = mid + ;
}
}
return -;
}
};

看了上面的解法,你可能会产生个疑问,为啥非得用中间的数字跟最右边的比较呢?难道跟最左边的数字比较不行吗,当中间的数字大于最左边的数字时,左半段也是有序的啊,如下所示(蓝色表示中点之前一定为有序的):

0  1  2   4  5  6  7

7  0  1   2  4  5  6

6  7  0   1  2  4  5

5  6  7   0  1  2  4

4  5  6  7  0  1  2

2  4  5  6  7  0  1

1  2  4  5  6  7  0

貌似也可以做,但是有一个问题,那就是在二分搜索中,nums[mid] 和 nums[left] 还有可能相等的,当数组中只有两个数字的时候,比如 [3, 1],那该去取那一边呢?由于只有两个数字且 nums[mid] 不等于 target,target 只有可能在右半边出现。最好的方法就是让其无法进入左半段,就需要左半段是有序的,而且由于一定无法同时满足 nums[left] <= target && nums[mid] > target,因为 nums[left] 和 nums[mid] 相等,同一个数怎么可能同时大于等于 target,又小于 target。由于这个条件不满足,则直接进入右半段继续搜索即可,所以等于的情况要加到 nums[mid] > nums[left] 的情况中,变成大于等于,参见代码如下:

解法二:

class Solution {
public:
int search(vector<int>& nums, int target) {
int left = , right = nums.size() - ;
while (left <= right) {
int mid = left + (right - left) / ;
if (nums[mid] == target) return mid;
if (nums[mid] >= nums[left]) {
if (nums[left] <= target && nums[mid] > target) right = mid - ;
else left = mid + ;
} else {
if (nums[mid] < target && nums[right] >= target) left = mid + ;
else right = mid - ;
}
}
return -;
}
};

讨论:这道题的二分搜索的解法实际上是博主之前的总结帖 LeetCode Binary Search Summary 二分搜索法小结 中的第五类,也是必须要将 right 初始化为 nums.size()-1,且循环条件必须为小于等于。二分搜索法真是博大精深,变化莫测啊~

Github 同步地址:

https://github.com/grandyang/leetcode/issues/33

类似题目:

Search in Rotated Sorted Array II

Find Minimum in Rotated Sorted Array

参考资料:

https://leetcode.com/problems/search-in-rotated-sorted-array/

https://leetcode.com/problems/search-in-rotated-sorted-array/discuss/14436/Revised-Binary-Search

https://leetcode.com/problems/search-in-rotated-sorted-array/discuss/14435/Clever-idea-making-it-simple

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Search in Rotated Sorted Array 在旋转有序数组中搜索的更多相关文章

  1. [LeetCode] 33. Search in Rotated Sorted Array 在旋转有序数组中搜索

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  2. [CareerCup] 11.3 Search in Rotated Sorted Array 在旋转有序矩阵中搜索

    11.3 Given a sorted array of n integers that has been rotated an unknown number of times, write code ...

  3. LeetCode 33 Search in Rotated Sorted Array(循环有序数组中进行查找操作)

    题目链接 :https://leetcode.com/problems/search-in-rotated-sorted-array/?tab=Description   Problem :当前的数组 ...

  4. LeetCode Search in Rotated Sorted Array 在旋转了的数组中查找

    Search in Rotated Sorted Array Suppose a sorted array is rotated at some pivot unknown to you before ...

  5. [LeetCode] Find Minimum in Rotated Sorted Array 寻找旋转有序数组的最小值

    Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...

  6. [LeetCode] 153. Find Minimum in Rotated Sorted Array 寻找旋转有序数组的最小值

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  7. leetcode题解:Search in Rotated Sorted Array(旋转排序数组查找)

    题目: Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7  ...

  8. LeetCode 153. Find Minimum in Rotated Sorted Array寻找旋转排序数组中的最小值 (C++)

    题目: Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. ( ...

  9. Leetcode153. Find Minimum in Rotated Sorted Array寻找旋转排序数组中最小值

    假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 请找出其中最小的元素. 你可以假设数组中不存在重 ...

随机推荐

  1. 【分布式】Zookeeper系统模型

    一.前言 前面已经讲解了Zookeeper的一些应用场景,但是并没有深入到Zookeeper内部进行分析,本篇将讲解其系统模型. 二.系统模型 2.1 数据模型 Zookeeper的数据节点称为ZNo ...

  2. TCP四种计时器

    TCP共使用以下四种计时器,即重传计时器.坚持计时器.保活计时器和时间等待计时器 .这几个计时器的主要特点如下:      1.重传计时器      当TCP发送报文段时,就创建该特定报文段的重传计时 ...

  3. MySQL实现两张表数据的同步

    有两张表A和B,要求往A里面插入一条记录的同时要向B里面也插入一条记录,向B里面插入一条记录的同时也向A插入一条记录.两张表的结构不同,需要将其中几个字段对应起来.可以用下面的触发器实现. 表A的触发 ...

  4. Springl利用Aspectj的扩展实现Aop

    1. Spring为什么要使用Aspectj Spring Aop:Spring自己原生的Aop,只能用一个词来形容:难用. 你需要实现大量的接口,继承大量的类,所以spring aop一度被千夫所指 ...

  5. Mybatis常用总结:参数,返回,执行sql,include等

    1.参数注入1.1用#{0},#{1}的形式,0代表第一个参数,1代表第二个参数 public List<RecordVo> queryList(String workerId, Inte ...

  6. ECharts的简单使用过程

    网页中经常要使用图表,以前使用的是highcharts插件,现在发现echarts使用起来和highcharts差不多,但是个人感觉echarts更酷炫,以下是echarts的使用过程,其实highc ...

  7. PHP变量

    变量的声明 PHP变量声明必须是$(美元符号)+变量名进行命名,同时在=(赋值操作符)后进行赋值 声明后的变量不是仅可以在一个<?php 这里是php代码 ?>使用,它还可以在当前页面所有 ...

  8. Mac 热键大全

    屏幕捕捉快捷键动作............................保存到............-快捷键 全屏捕捉........................桌面(.PDF文件)..... ...

  9. HTTP协议下保证密码不被获取更健壮方式

    说到在http协议下用户登录如何保证密码安全这个问题:    小白可能第一想法就是,用户在登录页面输入密码进行登录时,前台页面对用户输入的密码进行加密,然后把加密后的密码作为http请求参数通过网络发 ...

  10. nw.js自定义最小化图标的click事件

    选择frameless时,最小化和关闭按钮的点击事件需要自己来做,办法是: /* * 下面两个模块一定要引入到js文件中 */ var gui = require('nw.gui'); var win ...