【忍者算法】探秘二分查找:一道温柔的算法入门题!|LeetCode 35「搜索插入位置」

探秘二分查找:一道温柔的算法入门题!

大家好,我是忍者算法。今天我想和大家聊一道特别适合入门的算法题 - LeetCode 35「搜索插入位置」。这道题虽然看起来简单,但它蕴含了二分查找的精髓,是我最喜欢用来教学的题目之一。

📚 从图书馆说起

想象你在图书馆整理书架。手里有一本新书要插入已经按编号排序的书架中。你会怎么做?相信大多数人不会从头到尾一本本对比,而是会先看看中间的书,判断新书应该放在左边还是右边,这样反复几次就能找到正确的位置。

这正是二分查找的思想,也是我们今天要解决的问题!

💡 问题解析

题目要求
给定一个排序数组和一个目标值,在数组中找到目标值并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

示例

输入: nums = [1,3,5,6], target = 5
输出: 2  // 5在数组中,返回其位置2

输入: nums = [1,3,5,6], target = 2
输出: 1  // 2不在数组中,应该插入到位置1

🤔 思路发展历程

让我们看看解决这个问题时,思维是如何逐步进化的:

1. 最直观的思路(新手常用)

// 从头到尾遍历一遍
for (int i = 0; i < nums.length; i++) {
    if (nums[i] >= target) {
        return i;
    }
}
return nums.length;

这种方法虽然直观,但时间复杂度是O(n),没有利用数组已排序的特性。

2. 二分查找思路(进阶方案)

既然数组已经排序,我们可以用二分查找将时间复杂度降到O(log n)。

🚀 优雅的解决方案

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        
        // 特殊情况处理:目标值比所有元素都大
        if (target > nums[right]) {
            return nums.length;
        }
        
        while (left <= right) {
            // 计算中间位置,避免整数溢出
            int mid = left + (right - left) / 2;
            
            if (nums[mid] == target) {
                return mid;  // 找到目标值
            } else if (nums[mid] < target) {
                left = mid + 1;  // 目标在右半部分
            } else {
                right = mid - 1;  // 目标在左半部分
            }
        }
        
        // 没找到目标值时,left就是插入位置
        return left;
    }
}

📝 代码详解

让我们一步步理解这个解法:

1. 初始化

  • left和right指针分别指向数组的开始和结束
  • 先处理特殊情况,如果目标值比所有元素都大

2. 二分查找过程

  • 每次取中间位置mid
  • 比较nums[mid]和target:
    • 相等:找到目标值,直接返回
    • nums[mid]小于target:说明目标在右边
    • nums[mid]大于target:说明目标在左边

3. 返回插入位置

  • 循环结束时,left就是正确的插入位置
  • 无需特别处理,因为left自然会停在正确位置

🎯 易错点分析

  1. 边界条件

    • while循环的条件是 left <= right 而不是 left < right
    • 这确保了不会漏掉任何一个位置
  2. 中间位置计算

    • 使用 left + (right - left) / 2 而不是 (left + right) / 2
    • 避免整数溢出的隐患
  3. 返回值选择

    • 最后返回left而不是right
    • left自然停在插入位置,而right总是在其左边

💡 举一反三

这道题的思路可以应用到很多类似场景:

  1. 查找第一个不小于目标值的位置

    • 这就是我们这道题的本质
  2. 查找最后一个不大于目标值的位置

    • 只需要稍微改变一下判断条件
  3. 在排序数组中查找元素的第一个和最后一个位置

    • LeetCode 34题,是这道题的进阶版

🌟 面试技巧

  1. 理解二分查找的本质

    • 不是简单的查找,而是在查找的过程中缩小范围
    • 每次都能排除一半的搜索空间
  2. 处理边界情况

    • 数组为空
    • 目标值在数组范围之外
    • 数组中有重复元素
  3. 代码优化

    • 考虑代码的简洁性和可读性
    • 处理好整数溢出问题

作者:忍者算法
公众号:忍者算法

🎁 回复【刷题清单】获取LeetCode高频面试题合集
🧑‍💻 回复【代码】获取多语言完整题解
💡 回复【加群】加入算法交流群,一起进步

#算法面试 #LeetCode #二分查找 #数组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忍者算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值