Leetcode No.81 搜索旋转排序数组 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
提示:
1 <= nums.length <= 5000 -10^4 <= nums[i] <= 10^4 题目数据保证 nums 在预先未知的某个下标上进行了旋转 -10^4 <= target <= 10^4
进阶:
这是 搜索旋转排序数组 的延伸题目,本题中的 nums 可能包含重复元素。 这会影响到程序的时间复杂度吗?会有怎样的影响,为什么?
二、解题思路
使用二分查找,初始化两个变量low=0,hight=nums.length-1
1、mid=(low+high)/2
2、假如nums[mid]等于target,返回下标mid
3、当nums[mid]小于nums[high]时,说明mid->high右侧是有序的,判断target是否在右侧,否则往左侧查找
4、当nums[mid]大于nums[high]时,说明low->mid左侧是有序的,判断target是否在左侧,否则往右侧查找
5、当low>high时,表示没有找到,返回-1
对于数组中有重复元素的情况,二分查找时可能会有 a[l]=a[mid]=a[r],此时无法判断区间 [l,mid] 和区间[mid+1,r] 哪个是有序的。
例如nums=[3,1,2,3,3,3,3],target=2,首次二分时无法判断区间 [0,3] 和区间 [4,6] 哪个是有序的。
对于这种情况,我们只能将当前二分区间的左边界加一,右边界减一,然后在新区间上继续二分查找。
三、代码
1、递归
class Solution {
public boolean search(int[] nums, int target) {
int rs=fun(nums, 0, nums.length - 1, target);
if(rs==-1){
return false;
}else{
return true;
}
}
private int fun(int[] nums, int low, int high, int target) {
if (low > high)
return -1;
int mid = (low + high) / 2;
if (nums[mid] == target)
return mid;
if(nums[mid]==nums[low]&&nums[mid]==nums[high]){
low++;
high--;
return fun(nums, low, high, target);
}else if (nums[mid] <= nums[high]) {
//右侧是有序的
if (nums[mid] <= target && target <= nums[high])
//目标值在右侧
return fun(nums, mid + 1, high, target);
else
//目标值在左侧
return fun(nums, low, mid - 1, target);
}else{
//左侧是有序的
if (nums[low] <= target && target < nums[mid])
//目标值在左侧
return fun(nums, low, mid - 1, target);
else
//目标值在右侧
return fun(nums, mid + 1, high, target);
}
}
}
2、双指针
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;
}
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;
}
}
四、复杂度分析
时间复杂度:O(n),其中 n 是数组 nums 的长度。最坏情况下数组元素均相等且不为 target,我们需要访问所有位置才能得出结果。
空间复杂度:O(1)。
相关文章
- 支付宝数字人民币在哪怎么开通 怎么使用数字人民币付款
- 熬了一个通宵,终于把Reids的7千万个Key删完了,今天脑子都嗡嗡响!
- 面试官:为什么在系统中不推荐双写?
- 8个超实用的iPhone隐藏功能和技巧,你可能还不知道
- 支付宝闪现数字人民币
- 为什么苹果五年不卡,安卓只能用两三年?这几个原因说到点上了
- 苹果发布iOS 14.6新测试版:改进性能和Bug
- 难住了N个面试者,http协议无状态中的 "状态" 到底指的是什么?!
- 算法的艺术:MySQL order by对各种排序算法的巧用
- 教你一招把老照片无损地扫描到手机上,特别清晰,永久保存起来
- 微信群里隐藏着一个永久免费无限空间,很多人都不知道,太实用了
- 这两款iPhone不要升级iOS14.5.1,将会被降频
- 苹果 iOS 15 爆料汇总:除了新图标、新锁屏、新通知,还有这 3 大变化
- 500多位专家参与App Store的审核过程;不到1%的被拒开发者提出申诉
- 报告称美国只有4%的iOS用户选择接受广告追踪
- 取代安卓!曝华为鸿蒙OS计划适配高通平台
- 自动化做任务、收能量工具Hamibot,我愿称它为神器
- 手机系统要不要常更新?认准这三点最重要!
- iOS 14.5.1 / 12.5.3 系统来了,越狱依然支持
- 我C,MySQL双主架构,原来能这么玩