题目描述:
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
代码:
class Solution {
public int search(int[] nums, int target) {
int start=0;
int end=nums.length-1;
while(start<=end){
int mid=(start+end)/2;
if(nums[mid]==target){
return mid;
}
if(nums[start]==target){
return start;
}
if(nums[end]==target){
return end;
}
if(nums[mid]>nums[start]){//中间点mid的左侧有序
if(target<nums[mid]&&target>nums[start]){//target位于mid左侧
end=mid-1;
}else{
start=mid+1;
}
}else{//中间点mid的右侧有序
if(target>nums[mid]&&target<nums[end]){//target位于mid右侧
start=mid+1;
}else{
end=mid-1;
}
}
}
return -1;
}
}
解题思路:
题目是想在一个经过旋转的有序数组中找到目标值,当看到在有序数组中查找时首先应该联想到二分查找,所以此题为二分查找的变型。与二分查找不同的是,在判断目标点target该处于中间点mid左侧还是右侧时的情况有很多种,所以要列举全部情况会让思路混乱。
- 首先确定[4,5,6,7,0,1,2]这个数组在[4-7]是有序的,[0-2]是有序的[7,0]是无序的。所以能通过对比中间点mid和初始点start的大小来判断当前数组哪一部分有序。if(nums[mid]>nums[start])说明中间点mid的左侧是有序的,右侧是无序的。反之中间点mid的右侧是有序的,左侧是无序的。
- 再判断目标点target一定处于有序区的情况,当满足if(target<nums[mid]&&target>nums[start])时,目标点target处于中间点mid的左侧有序区,当满足if(target>nums[mid]&&target<nums[end]),目标点target处于中间点右侧的有序区。其它条件下的情况都处于无序区。
- 每次循环查找时判断start、end和mid点是否与target相等,如果相等,则返回target值在数组中对应的索引位置。
通过列举有序区的情况,可以避免列举无序区的多种情况造成的思路混乱。