T33. Search in Rotated Sorted Array【Medium】
题目
假设有一个升序的数组以某个未知的支点旋转。
(例如,0 1 2 3 4 5 6 7 可以变成 4 5 6 7 0 1 2)
假设这个数组中没有重复的元素,给你一个 target(目标数),如果在这个数组中找到则返回它的 index,如果找不到就返回 -1
思路
首先,一般的有序的数组,查找一个数字一般都是用二分法,因为这样比较有效率。
按题中说法旋转数组后,分成的两半仍然是排好序的数组。
例如,4 5 6 7 0 1 2,左边的 4 5 6 7,以及右边的 0 1 2 都是排好序的,可以先确定 target 在哪边,然后继续二分查找。不过这个代码是从中间二分,分到的一半可能还是有两段排序的代码,需要继续分,就是很神奇的代码。
具体看代码以及注释~还是这句话,最好自己拿个例子试试,瞬间清晰!
信我 (ง •̀_•́)ง !
代码
代码取自 Top Solution,稍作注释
public int search(int[] nums, int target) {
//定位数组头和尾
int start = 0;
int end = nums.length - 1;
//start > end时表示里面不包含了,跳出循环
while (start <= end){
int mid = (start + end) / 2;
//找到匹配值,返回index
if (nums[mid] == target)
return mid;
//通过nums[start] <= nums[mid]表明start~mid这段是正确升序的
if (nums[start] <= nums[mid]){
//这就是二分法的做法,判断点在哪里,然后通过把start或者end赋予新的mid左右的值,表示选择前一段或者后一段
if (target < nums[mid] && target >= nums[start])
end = mid - 1;
else
start = mid + 1;
}
//通过nums[mid] <= nums[end]表明mid ~ end这段是正确升序的
if (nums[mid] <= nums[end]){
//这就是二分法的做法,判断点在哪里,然后通过把start或者end赋予新的mid左右的值,表示选择前一段或者后一段
if (target > nums[mid] && target <= nums[end])
start = mid + 1;
else
end = mid - 1;
}
}
//不存在的,返回-1
return -1;
}
补充
注意啦~这里是代码里的东西要补充说一下!一开始不明白这代码为什么要这么多if。
这里是有对应关系的,先判断在 start~mid是升序的才能用 target < nums[mid] && target >= nums[start] ,来判断 target 在不在这一段,然后若不是才说是在 mid ~ end的。(希望只有我一个人最开始第一眼没有看出来 ╮(๑•́ ₃•̀๑)╭...)
if (nums[start] <= nums[mid]){
if (target < nums[mid] && target >= nums[start])
end = mid - 1;
else
start = mid + 1
}