Last Commit: 2023-09-16 17:23:28

views:

33. Search in Rotated Sorted Array

source: https://leetcode.com/problems/longest-palindromic-substring/

Question

There is an integer array nums sorted in ascending order (with distinct values).

Prior to being passed to your function, nums is possibly rotated at an unknown pivot index k (1 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed). For example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become [4,5,6,7,0,1,2].

Given the array nums after the possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.

You must write an algorithm with O(log n) runtime complexity.

初想法

好像涉及Binary Search的题目都看起来特别的简单,比如4题, 但是对于特定的时间复杂度,又必须要使用。

首先看一下最简单的思路:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function (nums, target) {
  return nums.findIndex((num) => num === target);
};

二分查找

这题的一个关键是要找到一个前提:

  • 数组旋转后,必然有一半是升序的

基于这一半的有序数组,去做二分查找:

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var search = function (nums, target) {
  let left = 0;
  let right = nums.length - 1;
  while (left <= right) {
    const mid = ~~((left + right) / 2);
    const v = nums[mid];
    // 找到目标
    if (v === target) return mid;
    // 数组左侧是升序
    if (v >= nums[left]) {
      // 目标在数组左侧, 缩小右边界
      if (target >= nums[left] && target < v) {
        right = mid - 1;
      } 
      // 目标不在数组左侧, 缩小左边界
      else {
        left = mid + 1;
      }
    }
    // 数组右侧是升序
    else {
      // 目标在数组右侧,缩小左边界
      if (target <= nums[right] && target > v) {
        left = mid + 1;
      }
      // 目标在数组左侧,缩小右边界
      else {
        right = mid - 1;
      }
    }
  }
  // 未找到
  return -1;
};

End

对于查找有序数组中某个元素的问题,可以优先考虑二分查找。