「这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战」
前言
力扣第八十一题 搜索旋转排序数组 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
一、思路
这一题与前面的三十三题,唯一的不同就是数组中可能会有重复值,所以基本的解题思路是差不多的,仍然使用的是二分法。
这一题的关键就是通过 target
与 nums[mid]
、nums[left]
和 nums[right]
进行比较,从而判断 target
是否在 [0 ~ k]
的非递减区间内,或 target
是否在
[k ~ n]
的非递减区间内。
出现相同的值带来的影响就是,当 nums[mid] == nums[left] == nums[right]
时,无法判断 target
是在 [left, mid]
或 [mid, right]
中。所以,当出现
这种情况时,我们简单的将 left
和 right
都减一。
大致的实现步骤如下所示:
- 初始化值,
left = 0
,right = len -1
- 使用
二分法
进行取值,nums[mid]
大致会出现以下几种情况
nums[left] <= nums[mid]
说明左半边是非递减的,如果值在左半边,则丢弃右边。反之也是一样nums[left] <= nums[mid]
说明右半边包含了[k ~ n]
这一段,判断值是否在[k ~ n]
这一段非递减区间上,如果在则丢弃左半边。如果不在,则丢弃右半边。
举个例子
此处以 nums = {3,1,2,2,2}, target =1
作为例子
left = 0, right = 4, mid = 2
,因nums[left] > nums[mid]
,且值不在[k ~ n]
中,故将right = mid -1 = 1
left = 0, right = 1, mid = 0
,此时nums[right] == target
,故返回true
二、实现
实现代码
public boolean search(int[] nums, int target) {
int len = nums.length;
if (len == 0) {
return false;
}
int left = 0, right = len - 1;
while (left <= right) {
int mid = (left + right) / 2;
// 相等的情况
if (nums[mid] == target || nums[left] == target || nums[right] == target) {
return true;
}
// 特殊情况:缩小区间
if (nums[left] == nums[mid] && nums[mid] == nums[right]) {
++left;
--right;
} else if (nums[left] <= nums[mid]) { // 左边是递增的
if (nums[left] < target && target < nums[mid]) { // 值在左边
right = mid - 1;
} else {
left = mid + 1;
}
} else { // 该区间有[0 ~ k]
if (nums[mid] < target && target < nums[len - 1]) { // 判断是否在[0 ~ k] 上
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return false;
}
测试代码
public static void main(String[] args) {
int[] nums = {3,1,2,2,2};
int target = 1;
boolean flag = new Number81().search(nums, target);
System.out.println("test");
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~