搜索旋转排序数组 II
已知存在一个按非降序排列的整数数组 nums
,数组中的值不必互不相同。
在传递给函数之前,nums
在预先未知的某个下标 k
(0 <= k < nums.length
)上进行了 旋转 ,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]
(下标 从 0 开始 计数)。例如, [0,1,2,4,4,4,5,6,6,7]
在下标 5
处经旋转后可能变为 [4,5,6,6,7,0,1,2,4,4]
。
给你 旋转后 的数组 nums
和一个整数 target
,请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums
中存在这个目标值 target
,则返回 true
,否则返回 false
。
你必须尽可能减少整个操作步骤。
示例 1:
输入:nums = [2,5,6,0,0,1,2], target = 0
输出:true
示例 2:
输入:nums = [2,5,6,0,0,1,2], target = 3
输出:false
思路
这个问题是经典的旋转排序数组查找问题,常见的解法是使用 二分查找 来在旋转数组中查找目标值。由于数组是旋转排序的,因此二分查找的条件和传统的有序数组稍有不同,但核心思想依然是利用二分查找的对数时间复杂度。
解题思路
- 旋转排序数组在某一点被旋转,使得数组的一部分是有序的,另一部分也是有序的。我们可以根据这个性质在二分查找中决定要查找哪个部分。
- 由于数组可能包含重复元素,这给二分查找带来了一些挑战。特别是在有重复元素的情况下,我们可能无法直接确定哪个部分是有序的。因此,我们需要处理一些特殊的情况。
解法
- 使用二分查找的思想,首先设定两个指针
left
和right
指向数组的起始和结束位置。 - 每次计算中间点
mid
,然后根据nums[mid]
和目标值target
的关系,决定应该缩小哪一侧的查找范围。 - 由于有重复元素,当
nums[left] == nums[mid] == nums[right] 时
,我们无法确定哪一部分是有序的,因此需要通过增加left
或减少right
来跳过重复的元素。
class Solution {
public boolean search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right){
int mid = left + (right - left) / 2;
if(nums[mid] == target){
return true;
}
//处理重复的部分
if(nums[left] == nums[mid] && nums[mid] == nums[right]){
left++;
right--;
}else if(nums[left] <= nums[mid]){ //左半部分有序
if(target >= nums[left] && target < nums[mid]){
right = mid - 1;
}else{
left = mid + 1;
}
}else{ //右半部分有序
if(target > nums[mid] && target <= nums[right]){
left = mid + 1;
}else{
right = mid - 1;
}
}
}
return false;
}
}
标签:排序,target,nums,mid,II,查找,数组,81,left
From: https://www.cnblogs.com/drunkerl/p/18642207