假设按照升序排序的数组在预先未知的某个点上进行了旋转。
例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] 。
编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。
示例
输入: nums = [2,5,6,0,0,1,2], target = 0
输出: true
输入: nums = [2,5,6,0,0,1,2], target = 3
输出: false
解法
33.搜索旋转排序数组 中我们使用的是二分查找,同样的,本题解法也为二分查找,因为数组中可能包含重复元素,所以我们要额外判断下中位数与边界的关系。
nums[left] < nums[mid]
说明数组前有序,如 4 5 6 7 8 1 2 3nums[left] > nums[mid]
说明数组后有序,如 6 7 8 1 2 3 4 5nums[left] == nums[mid]
说明有重复元素或中位数为左边界,如 6 6 7 8 或 6 7
对于情况1 2,我们使用二分查找;对于情况3,我们判断nums[mid]
是否为目标值,若是,则返回true;若不是,则向右移动左边界。
public bool Search(int[] nums, int target)
{
if (nums.Length == 0) return false;
int left = 0;
int right = nums.Length - 1;
while (left < right)
{
int mid = (left + right) / 2;
if (nums[left] < nums[mid])//前有序 4 5 6 7 8 1 2 3
{
if (nums[left] <= target && target <= nums[mid])
{
right = mid;
}
else left = mid + 1;
}
else if (nums[left] > nums[mid])//后有序 6 7 8 1 2 3 4 5
{
if (nums[mid] <= target && target <= nums[right])
{
left = mid;
}
else right = mid - 1;
}
else//重复或中位数为首位 6 6 7 8 或 6 7
{
if (nums[left] == target) return true;
else left++;
}
}
return nums[left] == target;
}