继续打卡算法题,今天学习的是LeetCode的第81题搜索旋转排序数组 II,这道题目是道中等题
。算法题的一些解题思路和技巧真的非常巧妙,每天看一看算法题和解题思路,我相信对我们的编码思维和编码能力有一些提升。
分析一波题目
本题目是LeetCode第33题搜索旋转排序数组
的升级版本,本题难点在于数组中有重复数值。
第33题已经说明旋转后的有序特点。
二分中间位置mid前的数据是严格递增的,这种情况和普通的二分求解一样。看目标数据在不在前半部分。
比如 0,0,1,2,2,5,6,7,8 在位置4旋转之后变成了2,5,6,7,8,0,0,1,2 第一次二分后,前半部分2,5,6,7,8 是严格递增的。这种情况二分搜索就好搜索了。
二分中间位置mid前的数据不是严格递增的,这种情况需要看目标数据在不在后半部分。后半部分是有序的。
再比如 比如 0,0,1,2,2,5,6,7,8 在位置6旋转变成了6,7,8,0,0,1,2,2,5 这样第一次二分后,前半部分 6,7,8,0,0是分两个阶段的,但是后半半部分1,2,2,5
是有序的。
而本题是数组中数字有重复,因此我们只要在33题的基础上加上去重
就可以解决了。
本题解题技巧
1、二分法是搜索有序数组的,借助旋转后的特点,二分法同样可以搜索。本题需要注意去重逻辑
编码解决
class Solution {
public boolean search(int[] nums, int target) {
int n = nums.length;
if (n == 0) {
return false;
}
if (n == 1) {
return nums[0] == target ? true : false;
}
int l = 0, r = n - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (nums[mid] == target) return true;
//相同的数,去重
if (nums[l] == nums[mid] && nums[mid] == nums[r]) {
++l;
--r;
} else if (nums[l] <= nums[mid]) {
//左边是严格递增的
//数据在左边
if (nums[l] <= target && target < nums[mid]) {
r = mid - 1;
} else {
//数据在右边
l = mid + 1;
}
} else {
//数据在右边
if (nums[mid] < target && target <= nums[n - 1]) {
l = mid + 1;
} else {
//数据在左边
r = mid - 1;
}
}
}
return false;
}
}
总结
1、本题的关键是理解两个旋转有序数组后的特点。
I. 二分中间位置mid前的数据是严格递增的,这种情况和普通的二分求解一样。看目标数据在不在前半部分。
II. 二分中间位置mid前的数据不是严格递增的,这种情况需要看目标数据在不在后半部分。