题目描述
给出一个转动过的有序数组,你事先不知道该数组转动了多少
(例如,0 1 2 4 5 6 7可能变为4 5 6 7 0 1 2).
在数组中搜索给出的目标值,如果能在数组中找到,返回它的索引,否则返回-1。
假设数组中不存在重复项。
解题思路:
(1)暴力搜索法,时间复杂度为O(n)
public class Solution {
public int search(int[] A, int target) {
//暴力搜索法,时间复杂度为O(n)
for(int i =0 ; i < A.length; i++){
if(A[i] == target)
return i;
}
return -1;
}
}
(2)二分查找法,时间复杂度为O(logn)
分析:有序数组A 0 1 2 4 5 6 7转动后变为4 5 6 7 0 1 2,可以将其分为左右两个有序的部分:
4 5 6 7 | 0 1 2,左半部分为4 5 6 7,右半部分为 0 1 2
定义我们需要寻找的目标数据target要么在左半部分(target >= A[0]),要么在右半部分(target < A[0]),分为这三种情况:
定义左右边界low,high, middle = low + (high - low)/2
(1)目标数据target = A[middle],则返回
(2)目标数据在左半部分(target >= A[0])
此时分为两种情况:
1> A[middle] < target 且A[middle] >= A[0],则向右找,low = middle + 1
2> 其他情况,A[middle] > targe,则向左找,high = middle - 1
(3)目标数据在右半部分(target < A[0])
此时分为两种情况:
1> A[middle] > target 且 A[middle] < A[0],则向右找,high = middle - 1
2> 其他情况,A[middle] < target ,则向左找,low = middle + 1
public class Solution {
public int search(int[] A, int target) {
//二分查找
int low = 0, high = A.length - 1;
while (low <= high) {
int middle = low + (high - low) / 2;
if(A[middle] == target)
return middle;
//在左半有序部分
if (target >= A[0]) {
if(A[middle] < target && A[middle] >= A[0]){
low = middle + 1;
}else{
high = middle - 1;
}
}else{ //在右半有序部分
if(A[middle] > target && A[middle] < A[0]){
high = middle - 1;
}else{
low = middle + 1;
}
}
}
return -1;
}
}