题目描述

题解
// 这个题想到二分查找不难,但是能把边界条件分清楚写清楚就不简单了。
// 分析旋转后的排序如下:
// ========================== 旋转后的排序情况 =======================
// 没有旋转的原数组[1,2,3,4,5,6,7],mid = 3
// 旋转后:
// 一,nums[mid]比nums[left]小 - [6,7,0,1,2,4,5]型:
// 1.target在mid右边 - (target比nums[mid]大 && 比nums[right]小或相等)
// 2.target在mid左边 - target比nums[mid]小
// - (target比nums[mid]大 && 比nums[left]大)
// 二,nums[mid]比nums[left]大 - [2,4,5,6,7,0,1]型:
// 1.target在mid右边 - (target比nums[mid]小 && 比nums[left]小)
// - target比nums[mid]大
// 2.target在mid左边 - (target比nums[mid]小 && 比nums[left]大或相等)
// ===================================================================
// 可以看到,当nums[mid]比nums[left]小时,数组为[6,7,0,1,2,4,5]型,
// target在mid右边只有1种情况,而target在mid左边时,有2种情况,
// 那我们可以只在if中讨论target在mid右边的条件,
// 剩下的其他情况都属于target在mid左边的时候,留给else即可。这样可以大大缩短
// 代码量。其他情况则同理。
//
// 排除特殊情况,之后初始化左右指针left和right。
// while循环开始二分查找,中点为mid = (left + right) / 2,如果nums[mid]等于target
// 直接返回mid。如果不是,则直接按照我们上面分析旋转后的排序情况进行if-else条件判断。
// 直到找到nums[mid] == target,或者left和right指针相遇(left = right),while循环
// 停止,说明没找到target,返回-1。
//
// 执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
// 内存消耗:37.9 MB, 在所有 Java 提交中击败了53.93%的用户
class Solution {
public int search(int[] nums, int target) {
int len = nums.length
if (len == 0) return -1
if (len == 1)
return (nums[0] == target) ? 0 : -1
int left = 0, right = len - 1
while (left <= right) {
int mid = (left + right) / 2
if (nums[mid] == target)
return mid
if (nums[left] > nums[mid]) {
if (nums[mid] < target && target <= nums[right])
left = mid + 1
else
right = mid - 1
}
else { // nums[left] <= nums[mid]
if (target < nums[mid] && nums[left] <= target)
right = mid - 1
else
left = mid + 1
}
}
return -1
}
}