题目描述
分析
本文章基于以下这篇文章之理解
可以通过二分算法,进行加速查找
但要注意,由于未提及是否存在重复元素,所以对于重复元素是切割点的情况,需要特殊处理
算法
二分
过程
处理特殊情况 -> 找旋转点 -> 对两段分别查找
处理特殊情况
将 r 指向不同于 nums[0] 的元素
如果 nums[r] === nums[0],则递减 r
找旋转点
通过二分找旋转点
方法为找到从 nums[0] 开始的递增序列的最后一个元素
对两段分别查找
首先声明一个 idx,因为 l, r 在上一步之后均指向了左区间的最后一个元素,没发直接开始二分,因此需要一个新的指针来找到右区间的起始位置,然后对两个区间的二分
idx 指向右区间的第一个元素,因此它实际上就是现在的 l + 1 或 r + 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
}