Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e.,0 1 2 4 5 6 7
might 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.
Example
For[4, 5, 1, 2, 3]
andtarget=1
, return2
.
For[4, 5, 1, 2, 3]
andtarget=0
, return-1
.
Note1
M1可能落在左半边, 也可能落在右半边. M1 >= S1, 左; M1 < S1, 右
即把数组分为了两部分,粉色部分[S,M]和橙色部分[M]
我们想去掉一半, 让它仍保持RSA(rotated sorted array)
如果M落在左, 切掉[S,M]; 如果M落在右, 切掉[M,E]
分类讨论,这里选择比较和mid和start位置数的大小来决定抛弃哪一半:
nums[mid] == target --> return mid
nums[start] < nums[mid]: 在左边
nums[start] <= target <= nums[mid] --> 在左边:end = mid
else --> 在右边: start = mid
start >= mid: 在右边
nums[mid] <= target <= nums[end] --> 在右边:start = mid
Code1
public class Solution {
/**
* @param A: an integer rotated sorted array
* @param target: an integer to be searched
* @return: an integer
*/
public int search(int[] A, int target) {
// write your code here
if (A == null || A.length == 0) {
return -1;
}
int start = 0, end = A.length - 1;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (A[mid] == target) {
return mid;
}
if (A[start] < A[mid]) {
if (A[start] <= target && target <= A[mid]) {
end = mid;
} else {
start = mid;
}
} else {
if (A[mid] <= target && target <= A[end]) {
start = mid;
} else {
end = mid;
}
}
}
if (A[start] == target) {
return start;
}
if (A[end] == target) {
return end;
}
return -1;
}
}
Note2
如果我们这里允许重复, 这里考虑最坏情况:
这个问题在面试中不会让实现完整程序
只需要举出能够最坏情况的数据是 [1,1,1,1... 1] 里有一个0即可。
在这种情况下是无法使用二分法的,复杂度是O(n)
因此写个for循环最坏也是O(n),那就写个for循环就好了
如果你觉得,不是每个情况都是最坏情况,你想用二分法解决不是最坏情况的情况,那你就写一个二分吧。
反正面试考的不是你在这个题上会不会用二分法。这个题的考点是你想不想得到最坏情况。
二分法,增加一个分支,最坏情况会一直增加,这样就是O(n):
else if (nums[start] == nums[mid]) {
start++;
}
Code2
public class Solution {
/**
* @param A: an integer ratated sorted array and duplicates are allowed
* @param target: An integer
* @return: a boolean
*/
public boolean search(int[] nums, int target) {
// write your code here
if (nums == null || nums.length == 0) {
return false;
}
int start = 0, end = nums.length - 1;
while (start + 1 < end) {
int mid = (end - start) / 2 + start;
if (nums[mid] == target) {
return true;
}
if (nums[start] < nums[mid]) {
if (nums[start] <= target && target <= nums[mid]) {
end = mid;
} else {
start = mid;
}
} else if (nums[start] > nums[mid]) {
if (nums[mid] <= target && target <= nums[end]) {
start = mid;
} else {
end = mid;
}
} else if (nums[start] == nums[mid]) {
start++;
}
}
if (nums[start] == target || nums[end] == target) {
return true;
}
return false;
}
}