原题链接
方法1:暴力(略)
无脑遍历,时间复杂度O(n),不符合题意
public int search(int[] nums, int target) {
int len = nums.length;
for (int i = 0; i < len; i++) {
if (nums[i] == target) {
return i;
}
}
return -1;
}
方法2:二分查找
本文参考原文
以 原数组 nums = [1,2,3,4,5,6,7] 为例。
数组在某个位置旋转之后,只会存在两种情况:
- 前半部分有序
这种情况的判定条件是:nums[start] <= nums[mid]
例如:原数组 nums = [1,2,3,4,5,6,7] ,以 1 为旋转点,将 1 及其前面的数字全都平移到数组末尾,也就变成了 nums = [2,3,4,5,6,7,1],则 nums[start] = 2,nums[mid] = 5,由 nums[start] <= nums[mid] 可判定是前半部分有序。 - 后半部分有序
这种情况的判定条件是:nums[start] > nums[mid]
例如:原数组 nums = [1,2,3,4,5,6,7] ,以 5 为旋转点,将 5 及其前面的数字全都平移到数组末尾,也就变成了 nums = [6,7,1,2,3,4,5],则 nums[start] = 6,nums[mid] = 2,由 nums[start] > nums[mid] 可判定是后半部分有序。
public int search2(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}
int start = 0;
int end = nums.length - 1;
int mid;
while (start <= end) {
mid = start + (end - start) / 2;
if (nums[mid] == target) {
return mid;
}
//前半部分有序,注意此处用小于等于
if (nums[start] <= nums[mid]) {
//如果target在前半部分
if (target >= nums[start] && target < nums[mid]) {
end = mid - 1;//则去前半部分继续找
} else {
start = mid + 1;//否则去后半部分
}
} else {//若是后半段有序
//如果target在后半部分
if (target <= nums[end] && target > nums[mid]) {
start = mid + 1;//则去后半段继续找
} else {
end = mid - 1;//否则去前半部分
}
}
}
return -1;
}