一、题目
1、审题
2、分析
给出一个整数数组,数组本来为有序的且可能存在重复整数。
现在将数组后面未知个连续的元素移动到数组前面,形成新的数组。此时,判断 target 是否存在于该新数组中。
二、解答
1、思路:
方法一、
①、由于数组分成了两部分有序的数字组合,先利用二分查找找到中间数字集合的下标;
②、在数组的前部分有序元素和后部分有序元素中分别进行二分查找 target,若找到,返回 true, 否则返回 false。
public boolean search(int[] nums, int target) { int low = 0; int high = nums.length - 1; if(high < 0) return false; while(low < high) { int mid = (low + high) / 2; if(nums[low] > nums[mid]) high = mid; else if(nums[low] < nums[mid]) low = mid; else { // nums[low] == nums[mid] if(nums[low] < nums[high]){ low = high; break; } else if(nums[low] == nums[high] ) low++; else {// nums[low] > nums[high] if(low == mid) break; low = mid; } } } int mid = low; int index; if(target > nums[0]) { index = binarySearch(nums, 0, mid, target); } else if(target < nums[0]) { index = binarySearch(nums, mid+1, nums.length-1, target); } else { return true; } return index != -1; } private int binarySearch(int[] nums, int start, int end, int target) { while(start <= end) { int mid = (start + end) / 2; if(nums[mid] < target) start = mid+1; else if(nums[mid] > target) end = mid - 1; else return mid; } return -1; }
方法二、
将数组当成一个整体直接进行二分查找,只是修改查找条件。
public boolean search(int[] nums, int target) { int start = 0; int end = nums.length - 1; int mid = -1; while(start <= end) { mid = (start + end) / 2; if(nums[mid] == target) return true; //If we know for sure right side is sorted or left side is unsorted if(nums[mid] < nums[end] || nums[mid] < nums[start]) { if(target > nums[mid] && target <= nums[end]) start = mid + 1; else end = mid - 1; } //If we know for sure left side is sorted or right side is unsorted else if(nums[mid] > nums[start] || nums[mid] > nums[end]) { if(target < nums[mid] && target >= nums[start]) { end = mid - 1; } else { start = mid + 1; } } //If we get here, that means nums[start] == nums[mid] == nums[end], then shifting out //any of the two sides won't change the result but can help remove duplicate from //consideration, here we just use end-- but left++ works too else { end--; } } return false; }