1、题目描述
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
2、算法分析
本题采用二分算法进行查找目标值target
旋转后的数组,给定一个目标值target,如果数组中存在这个值,返回true;数组中不存在这个值,返回false
数组的下标从0开始
数组是非降序的:第一种是升序;第二种是数组中的数字一样,或者穿插数字,如11101,无序的。
题目中说的是旋转后的数组,又有了3种情况:
1、10111
2、原数组升序,旋转后前半部分大部分有序:2345671
3、原数组升序,旋转后后半部分大部分有序:6712345
3、代码实现
class Solution {
/*
本题采用二分算法进行查找目标值target
旋转后的数组,给定一个目标值target,如果数组中存在这个值,返回true;数组中不存在这个值,返回false
数组的下标从0开始
数组是非降序的:第一种是升序;第二种是数组中的数字一样,或者穿插数字,如11101,无序的。
题目中说的是旋转后的数组,又有了3种情况:
1、10111
2、原数组升序,旋转后前半部分大部分有序:2345671
3、原数组升序,旋转后后半部分大部分有序:6712345
*/
public boolean search(int[] nums, int target) {
// 首先判断数组是否存在;nums.length == 0 数组存在,但是里面内内容;nums == null数组不存在
if(nums.length == 0 || nums == null){
return false;
}
// 定义旋转后数组初始下标
int start = 0;
// 定义旋转后数组的尾部下标
int end = nums.length -1;
// 定义旋转后数组的中间下标
int mid;
// 对数组遍历,因为是寻找元素,从头到尾都要遍历到
while(start <= end){
// 取数组中间值
mid = start + (end - start) / 2;
// 第一种情况:目标值等于中间值
if(nums[mid] == target){
return true;
}
//第二种情况:1011111,nums[start] == nums[mid],初始值等于中间值
if(nums[start] == nums[mid]){
// 相当于 去掉重复的干扰项
start++;
// 结束本次if判断
continue;
}
// 第三种情况:序列前半部分有序,并且 target在数组的前半部分
if(nums[start] < nums[mid]){
//target在前半部分,nums[mid] == target
if(nums[mid] >= target && nums[start] <= target){
end = mid;
// 否则在另一半不部分
}else{
start = mid + 1;
}
}else {
// 后半部分有序,并且target在后半部分
if(nums[mid] < target && nums[end] >= target){
start = mid + 1;
} else{
// 否则就去前半部分去找
end = mid - 1;
}
}
}
// 没找大,返回 false
return false;
}
}