题目
升序排列的整数数组 nums 在预先未知的某个点上进行了旋转(例如, [0,1,2,4,5,6,7] 经旋转后可能变为 [4,5,6,7,0,1,2] )。
请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
示例 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:
输入:nums = [1], target = 0
输出:-1
思路
这道题用顺序查找会超时,即时间复杂度需要在O(n)以下,很容易想到二分查找。每次将待搜索区域,分成[left...mid]和[mid+1...right]两部分。需要注意的是,[left...mid]和[mid+1...right]其中必有一部分是完全升序排列的。也就是说,每次折半会将原搜索序列变成一个升序序列和一个无序序列。判断target是否在升序序列中是很容易的,因此如果target在升序的这部分则在这部分查找,否则在另一部分查找。
折半查找计算mid,mid=(left+right)/2。mid可能等于left(这时候left到right只有两个数),但不可能等于right。
代码
public int search(int[] nums, int target) {
int left=0,right=nums.length-1,mid;
while(left<=right){
mid=(left+right)/2;
if(nums[mid]==target) return mid;
//前半部分为升序序列
//这里判断条件中的等于号必须带上,因为mid可能等于left。而如果mid=left,那么还是应该将前半部分当作一个升序序列(实际上只有一个数),后半部分是无序的。
if (nums[mid] >= nums[left]) {
//target在升序序列中
if (target >= nums[left]&&target<nums[mid]) right = mid - 1;
//target在无序序列中
else left = mid + 1;
}
//后半部分为升序序列
else {
//target在升序序列中
if (target > nums[mid]&&target<=nums[right]) left = mid + 1;
//target在无序序列中
else right = mid - 1;
}
}
return -1;
}
原题链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array