搜索旋转排序数组II

LeetCode每日一题,81. 搜索旋转排序数组 II

先看题目描述

cNyQQs.png

算法和思路

二分查找

二分查找只可以用于有序的数组,但是这道题,数组本身并不是有序的,而是有序数组经过了旋转,仅保证了局部的有序性,还是可以使用二分查找的

我们可以在二分查找的时候查看当前 mid 为分割位置分割出来的两个部分,判断哪部分是有序的,再根据有序的部分判断 target 在不在这部分中,从而确定该如何改变二分查找的上下界

  • 由于数组中存在重复元素,若 nums[l] == nums[mid] == nums[r],此时无法判断哪部分是有序的,则将 l + 1,r - 1,再进行下一次循环
  • 若 nums[mid] 与 target 相等,直接返回 true 即可
  • 若 nums[l] <= nums[mid],则说明 [l,mid] 是有序部分,若 target 在 nums[l] 和 nums[mid] 之间,则 target 在左半部分即 [l,mid - 1]中,令 r = mid - 1;否则,target 在右半部分即 [mid + 1,r] 中,令 l = mid + 1
  • 若 nums[mid] <= nums[r],则说明 [mid,r] 是有序部分, 若 target 在 nums[mid] 和 nums[r] 之间,则 target 在右半部分即 [mid + 1,r] 中,令 l = mid + 1;否则,target 在左半部分即 [l,mid - 1] 中,令 r = mid - 1

最后没找到则返回 false

算法源码

二分查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public int search(int[] nums, int target) {
int n = nums.length;
int l = 0;
int r = n - 1;
while (l <= r) {
int mid = (l + r) / 2;
if (nums[mid] == target) {
return mid;
}
if (nums[l] <= nums[mid]) {
if (nums[l] <= target && target < nums[mid]) {
r = mid - 1;
} else {
l = mid + 1;
}
} else {
if (nums[mid] < target && target <= nums[r]) {
l = mid + 1;
} else {
r = mid - 1;
}
}
}
return -1;
}
}