【每日算法】查找算法1(中等)

简介: 查找算法(中等)

16fb98eea012ef0cb446588ddc50662.png

题目

剑指 Offer 11. 旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为 1。

注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

示例:

输入:numbers = [3,4,5,1,2]
输出:1
复制代码

分析

做这道题还是花了有点多时间的,踩坑无数,现在来一起复盘一下

首先这是一个半有序数组,可以优先考虑使用二分查找

之前有个误区,认为二分查找必须是有序数组才能使用,实际上只要满足一定的条件,就可以使用二分查找

二分查找本质是将查找区间由中间分为两份,只要能总结出,目标值在其中哪一部分,就可以使用二分查找

回到这道题中

需要我们分析出目标值在我们分割的区间中有什么特点

5770153093445a30cb6f415cbe2aa35.png

旋转点右侧元素大于旋转点左侧元素

如果使用二分法将数组切分,以 mid 为中点,把数组切成两部分

即 3 个端点:left = 0; right = numbers.length - 1; mid = (left + right) >> 1

[leff, mid)

[mid, right]

那么根据中间点 mid 的大小,会有三种情况

  • nums[mid] < nums[right]

最小值就在 [left, mid] 之间

  • nums[mid] > nums[right]

最小值就在 [mid, right]之间

  • 两者相等?

这个地方就有坑了,由于可能存在多个相同的值,无法直接确定就是最小值

这里就需要逐步逼近了,让右端点减1再继续迭代,这样最后的右端点就是我们所求的最小值

实现

function minArray(numbers: number[]): number {
    let l_idx: number = 0
    let r_idx: number = numbers.length - 1
    while(l_idx < r_idx) {
        const mid: number = (l_idx + r_idx) >> 1
        if (numbers[mid] < numbers[r_idx]) {
            // 【l_ridx - mid】
            r_idx = mid
        } 
        else if (numbers[mid] > numbers[r_idx]) {
            // 【mid - r_idx】
            l_idx = mid + 1
        }
        else {
            r_idx --
        }
    }
    return numbers[r_idx]
};
相关文章
树的子结构(中等难度,好题目)
树的子结构(中等难度,好题目)
110 0
树的子结构(中等难度,好题目)
|
存储
二叉搜索树与双向链表(中等难度)(好题目)
二叉搜索树与双向链表(中等难度)(好题目)
130 0
二叉搜索树与双向链表(中等难度)(好题目)
|
存储 算法
全排列(中等难度)
全排列(中等难度)
95 0
全排列(中等难度)
|
算法 测试技术
全排列Ⅱ(中等难度,加入剪枝操作)
全排列Ⅱ(中等难度,加入剪枝操作)
143 0
全排列Ⅱ(中等难度,加入剪枝操作)
二叉搜索树的后序遍历序列(中等难度)
二叉搜索树的后序遍历序列(中等难度)
100 0
二叉搜索树的后序遍历序列(中等难度)
leetcode【栈与队列—中等】 347.前 K 个高频元素
leetcode【栈与队列—中等】 347.前 K 个高频元素
leetcode【栈与队列—中等】 347.前 K 个高频元素
二维数组中的查找(中等难度)
二维数组中的查找(中等难度)
99 0

热门文章

最新文章