LeetCode题解(Java实现)——33.Search in Rotated Sorted Array(循环有序数组)

前言

欢迎关注我的 Github 仓库 https://github.com/bigrotor187/awesome-java-notes ,如果觉得有帮助,请点个 star 哟,目前主要在更 leetcode题解(Java版)剑指offer题解(Java版),可以点个star

文本已收录至我的GitHub仓库,欢迎Star:awesome-java-notes

33. Search in Rotated Sorted Array

Description

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。

你的算法时间复杂度必须是 O(log n) 级别。

Example 1:

输入: nums = [4,5,6,7,0,1,2], 
target = 0
输出: 4

Example 2:

输入: nums = [4,5,6,7,0,1,2], 
target = 3
输出: -1

Example 3:

输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。

Tags: Array, Binary Search

思路 0

参考这里

循环链表中存在这样一个性质(事实):将数组从中间点劈开,会将数组分成两部分,分别是循环有序数组部分和有序数组部分。

为了找到目标元素 target,我们可以先找到数组的有序部分,然后再判断目标元素是否在有序数组部分中。

  • 如果首元素小于中间元素mid,那么前半部分是有序的,后半部分是循环有序数组(如 4 5 6 7 8 1 2 3);
  • 如果首元素大于中间元素 mid,那么后半部分是有序的,前半部分是循环有序数组(如 5 6 1 2 3 4);
  • 如果 target 在有序数组部分中,则对有序部分使用二分查找;
  • 如果目标元素在循环有序数组中,则重新设定数组边界后,重复上述步骤。

上述中,将数组 4 5 6 7 8 1 2 3 从中间元素 7(mid = 3) 劈开后分成了 4 5 6 的有序数组部分以及 8 1 2 3 的循环有序数组部分。

时间复杂度: O(logn)

空间复杂度: O(1)

public int search(int[] nums, int target) {
        int start = 0;
        int end  = nums.length - 1;
        while (start <= end) {
            int mid = start + ((end - start) >> 2);
            if (target == nums[mid]) {
                return mid;
            }
            // 前面部分有序
            // 千万要注意这里的条件是 `nums[start] <= nums[mid]`,而不是 `nums[start] < nums[mid]`
            if (nums[start] <= nums[mid]) {
                if (target >= nums[start] && target < nums[mid]) {
                   end = mid - 1;
                } else {
                    start = mid + 1;
                }
            // 后半部分有序
            } else {
                if (target > nums[mid] && target <= nums[end]) {
                    start = mid + 1;
                } else {
                    end = mid - 1;
                }
            }
        }
        return -1;
    }

结语

如果你同我一样想要征服数据结构与算法、想要刷 LeetCode,欢迎关注我 GitHub 上的 LeetCode 题解:awesome-java-notes

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章