81. Search in Rotated Sorted Array II

148 阅读1分钟

题目描述

leetcode-cn.com/problems/se…

分析

本文章基于以下这篇文章之理解

leetcode-cn.com/problems/se…

可以通过二分算法,进行加速查找

但要注意,由于未提及是否存在重复元素,所以对于重复元素是切割点的情况,需要特殊处理

算法

二分

过程

处理特殊情况 -> 找旋转点 -> 对两段分别查找

处理特殊情况

r 指向不同于 nums[0] 的元素

如果 nums[r] === nums[0],则递减 r

找旋转点

通过二分找旋转点

方法为找到从 nums[0] 开始的递增序列的最后一个元素

对两段分别查找

首先声明一个 idx,因为 l, r 在上一步之后均指向了左区间的最后一个元素,没发直接开始二分,因此需要一个新的指针来找到右区间的起始位置,然后对两个区间的二分

idx 指向右区间的第一个元素,因此它实际上就是现在的 l + 1r + 1

对两端分别二分,找结果

代码

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {boolean}
 */
var search = function (nums, target) {
  const n = nums.length
  let l = 0,
    r = n - 1
  while (l < r && nums[0] == nums[r]) r--
  while (l < r) {
    const mid = Math.floor((l + r + 1) / 2)
    if (nums[mid] >= nums[0]) {
      l = mid
    } else {
      r = mid - 1
    }
  }

  let idx = n
  if (nums[l] >= nums[0] && l + 1 < n) idx = l + 1
  let ans = find(nums, 0, idx - 1, target)
  if (ans !== -1) return true
  ans = find(nums, idx, n - 1, target)
  return ans === -1 ? false : true
}

function find(arr, l, r, target) {
  while (l < r) {
    const mid = Math.floor((l + r) / 2)
    if (arr[mid] >= target) {
      r = mid
    } else {
      l = mid + 1
    }
  }

  return arr[r] === target ? r : -1
}