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. js第三方

    1.0 https://github.com/aui/artDialog 2.0 前端开发仓库 http://code.ciaoca.com/ 3.0 打赏 https://github.com/gr ...

  2. .NET4.5新特性之异步编程(Async和Await)的使用

    一.简介 首先来看看.net的发展中的各个阶段的特性:NET 与C# 的每个版本发布都是有一个"主题".即:C#1.0托管代码→C#2.0泛型→C#3.0LINQ→C#4.0动态语 ...

  3. C#开发微信门户及应用(18)-微信企业号的通讯录管理开发之成员管理

    在上篇随笔<C#开发微信门户及应用(17)-微信企业号的通讯录管理开发之部门管理>介绍了通讯录的部门的相关操作管理,通讯录管理包括部门管理.成员管理.标签管理三个部分,本篇主要介绍成员的管 ...

  4. 微信js框架第二篇(创建完整界面布局)

    接着昨天的继续谈关于微信新出的这个js框架,今天主要谈一个页面的创建到布局的详细步骤. 一.创建一个完整页面       页面你可以创建在项目的任何节点,只要你在入口文件正确引入创建该页面的路径就可使 ...

  5. 使用SSH上传安装eclipse

    安装eclipse 步骤: 1.上传eclipse tar文件 2.[root@localhost soft]# tar -zxvf eclipse-jee-galileo-SR2-linux-gtk ...

  6. 【原】JAVA SE编码规范

    /* * 编码规范: * 1.所有的命名遵循"见名知意"的原则 * 2.所有的命名不允许使用汉字或拼音 * 3.Java的工程命名建议使用小写,比如:oa.crm.cms... * ...

  7. DevExpress VCL v16.1.3发布

    ExpressPDFViewer # BC3840:包含action标题和action提示的 Action classes 和 resource strings 重命名: class名称末尾中包含'A ...

  8. visual studio自动导入 using 的快捷键

    快捷键是  shift + alt + f10 ,从 vs 2012开始 还增加了 ctrl+.  功能名称叫: 视图.显示智能标记

  9. Unix&Linux技术文章目录(2015-12-22更新)

    Unix & Linux 方面的博客整理.归纳分类,要坚持不懈的学习Unix &Linux,加油!技术需要累积和沉淀.更需要锲而不舍的精神.持之以恒的毅力!借此下面名句勉励自己! 书上 ...

  10. SQL Server封闭掉 触发器递归

    SQL Server关闭掉 触发器递归SQL Server  是有一个开关, 可以关闭掉 触发器递归的.EXEC sp_dboption '数据库名字', 'recursive triggers', ...