返回

精益求精,事半功倍:破解搜索插入位置算法的奥秘

前端

前言

在 LeetCode 这座题海之中,算法高手们不断磨砺技艺,寻求更快、更高效的解题之路。第 35 题「搜索插入位置」正是一道考验算法功底的经典题型,它要求我们在 O(log n) 的时间复杂度内找到目标数字的插入位置。本文将深入剖析这道题目的解法,带你领略算法的精髓。

逐层递进,缩小范围

这道题的关键在于巧用二分查找法。我们从有序数组的中间位置出发,将数组划分为左右两半,依次与目标值比较。如果目标值大于中间值,则目标一定在右半部分;否则,目标一定在左半部分。通过这种不断缩小范围的方式,我们可以快速逼近目标值。

二分查找算法步骤:

  1. 初始化左边界为 0,右边界为数组长度 n - 1。
  2. while 循环,只要左边界小于等于右边界:
    • 计算中间位置 mid = (left + right) // 2。
    • 如果 nums[mid] 等于目标值,则返回 mid。
    • 如果 nums[mid] 小于目标值,则更新 left = mid + 1。
    • 如果 nums[mid] 大于目标值,则更新 right = mid - 1。
  3. 返回 left。

实例演示

假设我们有一个有序数组 nums = [1, 3, 5, 6, 7, 8, 9, 11],目标值为 10。

  • 第一次迭代:mid = (0 + 7) // 2 = 3,nums[mid] = 5 < 10,因此更新 left = 4。
  • 第二次迭代:mid = (4 + 7) // 2 = 5,nums[mid] = 8 < 10,因此更新 left = 6。
  • 第三次迭代:mid = (6 + 7) // 2 = 6,nums[mid] = 9 < 10,因此更新 left = 7。
  • 第四次迭代:left = 7,已经大于 right = 6,因此跳出循环。
  • 返回 left = 7。

进一步优化

为了进一步优化时间复杂度,我们可以采用变种二分查找法,即在缩小范围时,判断目标值位于左半部分还是右半部分,并直接更新相应的边界。

代码实现

public int searchInsert(int[] nums, int target) {
    int left = 0, right = nums.length - 1;
    while (left <= right) {
        int mid = (left + right) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return left;
}

总结

通过二分查找法,我们可以高效地解决「搜索插入位置」问题,其时间复杂度为 O(log n)。这道题体现了算法思维的重要性,通过巧妙地缩小搜索范围,我们可以快速找到目标值。希望本文能够帮助你深入理解这道题目的解法,助你提升算法技能,在 LeetCode 的题海中乘风破浪。