[LeetCode]33 旋转后的有序数组中的搜索
来源:互联网 发布:怎样修改淘宝掌柜名字 编辑:程序博客网 时间:2024/05/24 03:22
Search in Rotated Sorted Array(旋转后的有序数组中的搜索)
【难度:hard or Easy】
Suppose a sorted array 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.
假设一有序数组在你不知道的情况下绕某一点旋转,如[0,1,2,4,5,6,7]旋转后变为了[4,5,6,7,0,1,2]。给定一个目标值,如果在旋转后的数组中能够找到,则返回其下标,否则返回-1。
解题思路
一看到有序数组,大家很自然就想到使用二分查找的方法,快速有效。但是旋转后的数组顺序已经改变了,常规的二分查找不能奏效。通过观察,我们知道原来全体有序的数组在旋转后变为了两个部分内部有序,因此如果对二分查找的方法进行一些调整,还是可以实现查找功能的。
我来举个例子:
假如有这样旋转后的数组为
[12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
如果目标值为14, 那么我们可以把数组理解为下面的样子:
[12, 13, 14, 15, 16, 17, 18, 19, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX]如果目标值为 7, 则将数组理解为下面的样子:
[INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, INT_MIN, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
那么对于上面的情况,使用常规的二分查找是可以实现的。
但是我们在数组情况未知下,不是真的这样去修改数组内容,而是在运行时动态地更改我们看到的数据的样子。
如何更改?关键在于这几行代码:
int mid = (low+high)/2;int num = (nums[mid] < nums[0]) == (target < nums[0]) ? nums[mid] : target < nums[0] ? INT_MIN : INT_MAX;if (num < target) low = mid+1;else if (num > target) high = mid;else return mid;
这段代码的作用是,判断中点的值nums[mid]与目标值target是否都在nums[0]的同一边(同true或同false):
1)是,则取num = nums[mid],根据num和target的大小关系来判断target可能位于的区间;
2)否,则进一步判断target < nums[0]是否成立:
如果成立,则说明nums[mid] >= nums[0],区间[0,mid]是升序区间,target不可能存在这个区间内,将num设置为INT_MIN,从而在下一个判断语句中将下边界变为mid+1;
如果不成立,则说明target >= nums[0] && nums[mid] < nums[0]为true,那么区间[mid,size-1]内的所有数小于target,将num设置为INT_MAX,从而在下一个判断语句中将上边界变为mid(而不是mid-1,因为mid-1还未与target比对)
c++代码如下:
class Solution {public: int search(vector<int>& nums, int target) { if (nums.empty()) return -1; int low = 0; int high = nums.size(); while (low < high) { int mid = (low+high)/2; int num = (nums[mid] < nums[0]) == (target < nums[0]) ? nums[mid] : target < nums[0] ? INT_MIN : INT_MAX; if (num < target) low = mid+1; else if (num > target) high = mid; else return mid; } return -1; }};
但是,除了二分查找的方法外,有个简单又粗暴的解法——遍历查找!
可能这道题的样例组数不够大,我使用上面的方法和遍历查找的方法耗时都在4ms,但是遍历查找无疑是最最直接,代码量还小。
遍历c++代码如下:
class Solution {public: int search(vector<int>& nums, int target) { if (nums.empty()) return -1; int high = nums.size(); for (int i = 0; i < high; i++) if (nums[i] == target) return i; return -1; }};
- [LeetCode]33 旋转后的有序数组中的搜索
- [LeetCode]153 有序数组旋转后的最小值
- [LeetCode]154 有序数组旋转后的最小值 II
- leetcode 6. 在有序数组旋转后搜索 Search in Rotated Sorted Array
- leetcode 7. 在有序可重复数组旋转后搜索 Search in Rotated Sorted Array II
- leetcode之数组类之数组的旋转与分治类-----OJ 189/33/81/153/154 数组旋转 旋转数组搜索 88 有序数组合并 4 两个有序数组寻找第K个元素/中位数 35 寻找插入位置
- 求出有序数组旋转后的最小值
- 有序数组旋转后的元素值查找
- 有序数组旋转后数组最小值
- 有序数组旋转的问题
- 查找有序旋转数组中的最小值
- 有序数组或者有序数组的旋转数组 查找最小值
- 有序数组的旋转数组的最小值
- LeetCode OJ 之 Find Minimum in Rotated Sorted Array (查找旋转有序数组中的最小值)
- 搜索行列有序的数组
- 有序输出 加倍后的数组 中的数
- 在旋转后的有序数组中查找元素,要求O(logn)的时间复杂度
- 在旋转后的有序数组中查找元素,要求O(logn)的时间复杂度
- 用socket通讯示例代码
- 在web.xml中配置了struts2的filter后访问jsp出现404
- hdu 1423 Greatest Common Increasing Subsequence(最长公共上升子序列dp)
- JavaSE学习笔记_7:Java内部类
- 小demo—实现访问网站总人数的记录
- [LeetCode]33 旋转后的有序数组中的搜索
- 11.Kibana用户指南(User Guide)
- Android学习-Http请求
- mysql数据库char与varchar区别
- Cacti安装教程
- spring ibatis struts
- 项目中关于clone的一些感悟
- CSS3学习
- JavaSE学习笔记_6:Java-Object类