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. 2011奥斯卡最佳纪录片《监守自盗(Inside Job)》小结

    影片探讨了2008年金融危机产生的原因. 美国忽略1933年的旧法律,立新法,以放松金融监管. 投资银行被允许更高的杠杆率,33:1,也就是说,投资物跌价3%就会导致破产. 投资银行放贷,但是转手将贷 ...

  3. 查看Sql Server被锁的表以及解锁

    查看被锁表: select spId from master..SysProcesses where db_Name(dbID) = '数据库名称' and spId <> @@SpId ...

  4. C# 高效编程笔记2

    C# 高效编程笔记2 1.理解GetHashCode()的陷阱 (1)作用:作为基于散列集合定义键的散列值,如:HashSet<T>,Dictionary<K,V>容器等 (2 ...

  5. JsCharts图表的介绍和简单使用

    一.JSCharts介绍 JScharts是一个用于在浏览器直接绘制图表的javascript工 具包.JScharts支持柱状图.圆饼图以及线性图,可以直接将这个图插入网页, JScharts图的数 ...

  6. python 数据类型 ---字符串

    1. 字符串去除空白 ,strip() , 包括空格,tab键, 换行符 >>> name = " Frank " >>> name.strip ...

  7. spring aop注解方式与xml方式配置

    注解方式 applicationContext.xml 加入下面配置 <!--Spring Aop 启用自动代理注解 --> <aop:aspectj-autoproxy proxy ...

  8. Microsoft.CodeAnalysis 入门

    1 安装 Microsoft.CodeAnalysis 我这里创建的是WPF的项目,首先再VS2015中用NuGet控制台进行安装 Install-Package Microsoft.CodeAnal ...

  9. Ext JS 如何动态加载JavaScript创建窗体

    JavaScript不需要编译即可运行,这让JavaScript构建的应用程序可以变得很灵活.我们可以根据需要动态从服务器加载JavaScript脚本来创建和控制UI来与用户交互.下面结合Ext JS ...

  10. Bootstrap之导航条

    基本导航条 <!-- navbar-inverse相反颜色风格 --> <!-- navbar-static-top去除圆角 --> <!-- navbar-fixed- ...