1、题目描述
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
2、示例
示例 1:
输入: nums = [4,5,6,7,0,1,2]
, target = 0
输出: 4
示例 2:
输入: nums = [4,5,6,7,0,1,2]
, target = 3
输出: -1
3、解题思路
方法:二分查找
题目要找到一种 O(logN)O(logN) 时间内的搜索方法,这提示我们可以用二分查找的方法。
算法非常直接:
- 找到旋转的下标
rotation_index
,也就是数组中最小的元素。二分查找在这里可以派上用场。 - 在选中的数组区域中再次使用二分查找。
4、代码实现
1 class Solution {
2 public int search(int[] nums, int target) {
3 if (nums == null || nums.length == 0) {
4 return -1;
5 }
6 if (nums.length == 1) {
7 return nums[0] == target ? 0 : -1;
8 }
9
10 // 旋转处(最小值)的索引
11 int rotateIndex = nums.length;
12 // 二分查找,找出旋转处(最小值)的索引位置
13 int left = 0, right = nums.length - 1;
14 while (left <= right) {
15 int mid = (left + right) / 2;
16 if (mid == nums.length - 1)
17 break;
18 if (nums[mid] > nums[mid + 1]) {
19 rotateIndex = mid + 1;
20 break;
21 } else {
22 if (nums[mid] >= nums[0]) {
23 left = mid + 1;
24 } else {
25 right = mid - 1;
26 }
27 }
28 }
29
30 // 分段二分查找,先判断target处于哪一段
31 int index = -1;
32 if (target >= nums[0]) {
33 left = 0;
34 right = rotateIndex - 1;
35 } else {
36 left = rotateIndex;
37 right = nums.length - 1;
38 }
39 while (left <= right) {
40 int mid = (left + right) / 2;
41 if (nums[mid] == target) {
42 index = mid;
43 break;
44 } else if (nums[mid] > target) {
45 right = mid - 1;
46 } else {
47 left = mid + 1;
48 }
49 }
50 return index;
51 }
52 }