[LeetCode]33. Search in Rotated Sorted Array

Problem

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).

1
2
3
4
5
6
7
8
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

Solution

Analysis

给定一个升序有序数组, 这个数组以某个数为轴发生了颠倒. 同时给定一个数target, 在翻转数组中查找这个数, 如果找到返回下标, 如果没找到返回-1. 假定数组中不存在重复数字.

要求时间复杂度是O(logn).

给定的是一个有序数组,同时要求时间复杂度O(logn), 从这两点可以看出应该使用二分查找方法. 那么接下来的问题就变成如何确定下一步的查找范围,特别是当mid数不是查找目标时. 到底是变换left左边界还是右边界right. 如何变化,变化的条件是什么?

因为数组翻转后, nums[left == 0] > nums[right == size-1]. 通过比较nums[mid]和nums[left], nums[right]可以确定局部有序的部分,然后在范围内就进行二分查找.

这里通过比较nums[mid]和nums[left]和nums[right]的大小进行判断. 当nums[mid] < nums[right]时,说明mid-right这部分是有序的, 接着判断target是否在这个数组范围内, 通过比较target和nums[mid], nums[right]的大小进行判断, 如果在,变换left左边界, 如果不在变换right右边界. 否则,nums[mid] > nums[right]时,比较和上面类似.

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;

while (left <= right){// 变换时,跳过mid, 不做多余的比较
int mid = left + (right - left) / 2;
if (nums[mid] == target) // found
return mid;
// 如果target就在left处, 这样left变为mid+1, 导致出错.
else if (nums[mid] < nums[right]){// 先检测后半段;因为有可能mid==left
if (nums[mid] < target && nums[right] >= target)
left = mid + 1;
else
right = mid -1;
}
else {//nums[left] <= nums[mid]
if (nums[left] <= target && nums[mid] > target)
right = mid - 1;
else
left = mid + 1;
}
}
return -1;
}
};
您的支持就是我更新的最大动力!谢谢!