LeetCode-033-搜索旋转排序数组

给你一个整数数组 nums ,和一个整数 target 。

该整数数组原本是按升序排列,但输入时在预先未知的某个点上进行了旋转。(例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

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

示例 1:

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

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

输入:nums = [1], target = 0
输出:-1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array

解题思路

采用二分法的思想, 并结合旋转数组的特性, 在[left, mid][mid, right]中找出哪一段是递增的
并利用递增的特性判断目标数是否在该递增区间

  • 每轮找出中间数值, 如果左端的数小于中间的数, 则该[left, mid]是递增区间
    • 如果目标刚好在该递增区间内, 则区间右端指针往中间移动
    • 不在该区间内则左端指针往中间移动
  • 另一种情况就是递增区间在[mid, right]
    • 如果目标刚好在该递增区间内, 则区间左端指针往中间移动
    • 不在该区间则右端指针往中间移动
  • 跳出循环后需要判断左边界的值是否等于目标值, 因为循环中更新查找区间时可能左右指针重叠然后跳出循环, 如果指针所指刚好是目标值, 则需要单独处理

代码

class Solution {
    public int search(int[] nums, int target) {
        // 左右指针
        int i = 0, j = nums.length - 1;
        while (i < j) {
            // 中间指针
            int mid = (i + j) >> 1;
            // 中间数等于目标时返回
            if (nums[mid] == target) {
                return mid;
            }
            // 如果左端的数小于中间的数, 则该区间是递增区间
            if (nums[i] <= nums[mid]) {
                // 如果目标刚好在递增区间内
                if (nums[i] <= target && target < nums[mid]) {
                    // 区间右端往中间移动
                    j = mid - 1;
                } else { // 不在递增区间内则左端往中间移动
                    i = mid + 1;
                }
            } else { // 递增区间在右边
                // 如果目标在递增区间内
                if (nums[mid] < target && target <= nums[j]) {
                    i = mid + 1;
                } else {
                    j = mid - 1;
                }
            }
        }
        return nums[i] == target ? i : -1;
    }
}

你可能感兴趣的:(LeetCode-033-搜索旋转排序数组)