【33】搜索旋转排序数组

1. 题目描述

image.png

2. 题目链接

https://leetcode.cn/problems/search-in-rotated-sorted-array/

3. 思路

对于有序数组,可以使用二分查找的方法查找元素。但是这道题中,数组本身不是有序的,进行旋转后只保证了数组的局部是有序的,那我们还能进行二分查找吗?答案是可以的。

可以发现的是,我们将数组从中间分开成左右两部分的时候,一定有一部分的数组是有序的。拿示例来看,我们从【33、81、153、154】搜索旋转排序数组系列 - 图2这个位置分开以后数组变成了【33、81、153、154】搜索旋转排序数组系列 - 图3【33、81、153、154】搜索旋转排序数组系列 - 图4两个部分,其中左边【33、81、153、154】搜索旋转排序数组系列 - 图5这个部分的数组是有序的,其他也是如此。

这启示我们可以在常规二分查找的时候,查看以当前【33、81、153、154】搜索旋转排序数组系列 - 图6为分割位置分割出来的两个部分【33、81、153、154】搜索旋转排序数组系列 - 图7【33、81、153、154】搜索旋转排序数组系列 - 图8哪个部分是有序的,并根据有序的那个部分确定我们该如何改变二分查找的上下界,因为我们能够根据有序的那部分判断出【33、81、153、154】搜索旋转排序数组系列 - 图9在不在这个部分:

  • 如果【33、81、153、154】搜索旋转排序数组系列 - 图10恰好等于【33、81、153、154】搜索旋转排序数组系列 - 图11,则直接返回【33、81、153、154】搜索旋转排序数组系列 - 图12

  • 如果【33、81、153、154】搜索旋转排序数组系列 - 图13是有序数组,且【33、81、153、154】搜索旋转排序数组系列 - 图14的大小满足【33、81、153、154】搜索旋转排序数组系列 - 图15,则我们应该将搜索范围缩小至【33、81、153、154】搜索旋转排序数组系列 - 图16,否则在【33、81、153、154】搜索旋转排序数组系列 - 图17中寻找。

  • 如果【33、81、153、154】搜索旋转排序数组系列 - 图18是有序数组,且【33、81、153、154】搜索旋转排序数组系列 - 图19的大小满足【33、81、153、154】搜索旋转排序数组系列 - 图20,则我们应该将搜索范围缩小至【33、81、153、154】搜索旋转排序数组系列 - 图21,否则在【33、81、153、154】搜索旋转排序数组系列 - 图22中寻找。

image.png

4. 代码实现

  1. public int search(int[] nums, int target) {
  2. if (nums == null || nums.length == 0) {
  3. return -1;
  4. }
  5. if (nums.length == 1) {
  6. return nums[0] == target ? 0 : -1;
  7. }
  8. // 二分查找
  9. int left = 0, right = nums.length - 1;
  10. while (left <= right) {
  11. int mid = left + (right - left) / 2;
  12. if (nums[mid] == target) {
  13. return mid;
  14. }
  15. // [left,mid]是有序数组
  16. if (nums[mid] >= nums[0]) {
  17. // 判断target是否在[left,mid-1]区间内
  18. if (target >= nums[left] && target < nums[mid]) {
  19. right = mid - 1;
  20. } else {
  21. left = mid + 1;
  22. }
  23. }
  24. // [mid+1,right]是有序数组
  25. else {
  26. // 判断target是否在[mid+1,right]区间内
  27. if (target > nums[mid] && target <= nums[right]) {
  28. left = mid + 1;
  29. } else {
  30. right = mid - 1;
  31. }
  32. }
  33. }
  34. return -1;
  35. }
  • 时间复杂度:【33、81、153、154】搜索旋转排序数组系列 - 图24,其中【33、81、153、154】搜索旋转排序数组系列 - 图25【33、81、153、154】搜索旋转排序数组系列 - 图26数组的大小。整个算法的时间复杂度即为二分查找的时间复杂度,即【33、81、153、154】搜索旋转排序数组系列 - 图27
  • 空间复杂度:【33、81、153、154】搜索旋转排序数组系列 - 图28。我们只需要常数级别的空间存放变量。