题目描述
Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e.,0 1 2 4 5 6 7might become4 5 6 7 0 1 2).
You are given a target value to search. If found in the array return its index, otherwise return -1.
You may assume no duplicate exists in the array.
- 思路
求某数是否在该数组中,该数组是经过某个支点反转后的数组。法一:(不含重复元素)除了暴力求解外,可以比较第一个和最后一个元素的大小来确定是否是整体有序的,是则直接二分,否则找到支点并二分找。
令l,r(初始分别为第一个下标位置和最后一个下标位置)分别表示第一部分的最后一个下标位置和第二部分的第一个下标位置,当有序时或者两者相差1时表示找到了支点,由于反转后第二部分的最大值肯定小于第一部分的最小值,所以利用这个特点就可以选择合适的部分进行二分了。法二:(通用)找到序列的中点,每次遍历看前半部分的特点。若当前中点即为搜索的值则直接返回;若前半部分第一个数小于最后一个数,则说明此时属于递增的序列,通过判断target范围来调整左右指针;若前半部分第一个数大于最后一个数,则说明此时后半部分是递增序列(前半部分含有部分本应属于后半部分的数),同理根据target值判断左右指针;否则缩小搜素范围继续查找。
//无重复数字
public class Solution {
public int search(int[] A, int target) {
if(A == null || A.length == 0)
return -1;
if(A[0] <= A[A.length-1]){ //没有反转
return binarySearch(A, 0, A.length-1, target);
}else{ //反转
int l = 0; //最终记录前半部分的最后一位下标
int r = A.length - 1; //最终记录后半部分的第一位下标
while(A[l] > A[r]){
if(r - l == 1){
break;
}
int mid = l + (r - l) / 2;
if(A[mid] == target){
return mid;
}else if(A[mid] > A[l]){
l = mid;
}else{
r = mid;
}
}
if(A[A.length-1] >= target){
return binarySearch(A, r, A.length-1, target);
}else{
return binarySearch(A, 0, l, target);
}
}
}
public int binarySearch(int[] arr, int l, int r, int k){
while(l <= r){
int mid = l + (r - l) / 2;
if(arr[mid] == k){
return mid;
}else if(arr[mid] > k){
r = mid - 1;
}else{
l = mid + 1;
}
}
return -1;
}
}
//有重复数字
public class Solution {
public boolean search(int[] A, int target) {
if(A == null || A.length == 0)
return false;
int left = 0;
int right = A.length-1;
while(left <= right){
int mid = (left + right) / 2;
if(A[mid] == target){
return true;
}else if(A[left] < A[mid]){
if(A[left] <= target && target < A[mid]){
right = mid - 1;
}else{
left = mid + 1;
}
}else if(A[left] > A[mid]){
if(target > A[mid] && target <= A[right]){
left = mid + 1;
}else{
right = mid - 1;
}
}else{
left ++;
}
}
return false;
}
}