解法都在代码里,不懂就留言或者私信,这个题目一定要注意重复元素的情况sh
public static boolean search(int[] nums, int target) {
/**空数组不可能找到任何数*/
if(nums == null || nums.length == 0) {
return false;
}
/**如果就一个数看看相等不想等就行,这个其实也可以包括这下面的查找过程中*/
if(nums.length == 1) {
return target == nums[0];
}
/**其他的情况我们采用二分查找(伪二分)*/
return searchInRange(nums, 0, nums.length - 1, target);
}
public static boolean searchInRange(int[] nums, int left, int right, int target) {
if(left > right) return false;
if(nums[left] == target || nums[right] == target) {
return true;
}
while(left <= right) {
/**本题的难度在于可以重复,那我们就只能根据某个条件判断一个区间发生了反转,而另外一个区间是有序的
* 如果大于等于有序区间最小值,小于等于有序区间最大值就可以使用二分查找在有序区间查找
* 否则继续while循环,只是把left和right做相应的变更
* 下面我们分析具体的场景:1. 如果mid位置的值比left和right位置的都大,说明mid~right之间一定发生了反转
* 而left~mid之间是有序的 2. 如果mid位置的值比left和right位置都小,则left~mid之间一定发生了反转,而
* mid~right之间是有序的 3.其他情况因为涉及重复的情况,无法判断,只能顺序查找了*/
int mid = left + ((right-left)>>1);
if(nums[mid] == target) {
return true;
}
if(nums[mid] > nums[left] && nums[mid] > nums[left]) {
if(nums[left] < target && nums[mid] > target) {
return bSearch(nums, left + 1, right - 1, target);
} else {
return searchInRange(nums, mid + 1, right, target);
}
} else if(nums[mid] < nums[left] && nums[mid] < nums[right]) {
if(nums[mid] < target && nums[right] > target) {
return bSearch(nums, mid + 1, right - 1, target);
} else {
return searchInRange(nums, left + 1, right - 1, target);
}
} else {
return searchInRange(nums, left + 1, mid - 1, target) || searchInRange(nums, mid+1,right-1, target);
}
}
return false;
}
public static boolean bSearch(int[] nums, int left, int right, int target) {
if(left > right) {
return false;
}
while(left <= right) {
int mid = left + ((right-left)>>1);
if(nums[mid] == target) {
return true;
} else if(nums[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return false;
}
某些原因无法上网站执行,贴一个手机的结果,这个题目也是我临时写的,可能有的考虑不一定周全,如果有更优解法,稍后我再贴上来
标签:面试题,right,return,target,nums,mid,II,81,left From: https://blog.csdn.net/Chang_Yafei/article/details/141358658