在数组的题目中,一旦涉及到数组有序就要考虑二分法的使用。这道题是二分法的变形使用,在题解中看到一个很有趣的思路:
因为是旋转数组,因此肯定有一个分界点,这个分界点左边是递减的,右边是递增的,那么在二分遍历时候,可以采用边遍历边有序的策略:
(1)更新mid = l + (r - l) / 2,在l <= r的情况下,判断target和num[0]的大小关系
(1.1)如果target大于num[0],说明target在分界点的左边。如果此时的num[mid]小于num[0],说明num[mid]在分界点右边,那么把num[mid]变为无穷大(改变num[mid]的值并不影响target,因为二者在分界线不同两边)
(1.2)如果target小于等于num[0],说明target在分界点的右边。如果此时的num[mid]大于num[0],说明num[mid]在分界点左边,那么把num[mid]变为无穷小
在所有的值都经过1.1、1.2两步后,数组整体会变成一个“有序的”。
(2)判断target和num[mid]的大小关系(对应1.1和1.2里的另外两种情况),若target == num[mid],OK返回mid
(2.1)若target > num[mid],l = mid + 1,回到(1)
(2.2)若target < num[mid],r = mid - 1,回到(1)
(3)如果中途没有返回mid的话说明没找到,因此返回-1
题解中的解释:
记录一下代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
if(n == 1)
{
return target == nums[0] ? 0 : -1;
}
int l = 0;
int r = n - 1;
while(l <= r)
{
int mid = l + (r - l) / 2;
if(target >= nums[0])
{
if(nums[mid] < nums[0])
{
nums[mid] = INT_MAX;
}
}
else
{
if(nums[mid] >= nums[0])
{
nums[mid] = INT_MIN;
}
}
if(nums[mid] == target)
{
return mid;
}
else if(nums[mid] < target)
{
l = mid + 1;
}
else
{
r = mid - 1;
}
}
return -1;
}
};