【LeetCode】35. 搜索插入位置

leetcode

 

算法思路

  1. 初始化区间
    采用左闭右闭区间 [left, right],初始时 left=0right=len(nums)-1。

  2. 循环条件
    使用 left <= right 作为循环条件,确保区间有效性(当 left == right 时仍需要检查最后一个元素)。 

  3. 中间值计算
    通过 middle = left + (right - left)/2 计算中间索引,避免整数溢出。 

  4. 分支判断

    • 若 nums[middle] == target:直接返回当前索引
    • 若 nums[middle] > target:调整右边界为 middle-1(排除右侧区间)
    • 若 nums[middle] < target:调整左边界为 middle+1(排除左侧区间)
  5. 插入位置确定
    当循环结束时,left 指向第一个大于 target 的元素位置,即为插入位置。

     

Golang 实现

func searchInsert(nums []int, target int) int {
    left, right := 0, len(nums)-1
    for left <= right {
        middle := left + (right - left)/2 // 防止溢出
        if nums[middle] == target {
            return middle
        } else if nums[middle] > target {
            right = middle - 1 // 缩小至左区间
        } else {
            left = middle + 1  // 缩小至右区间
        }
    }
    return left // 未找到时返回插入位置
}

 

代码解析

  • 时间复杂度:O(log n),每次循环排除一半元素,满足题目要求。
  • 空间复杂度:O(1),仅使用常量空间存储索引值。
  • 边界处理
    • 当 target 大于所有元素时,循环结束后 left = len(nums),直接返回该值作为插入位置。
    • 当 target 需要插入数组中间时,left 自动指向正确位置(如示例2中的 2 插入到索引1)。

示例验证

fmt.Println(searchInsert([]int{1,3,5,6}, 5))  // 2(示例1)
fmt.Println(searchInsert([]int{1,3,5,6}, 2))  // 1(示例2)
fmt.Println(searchInsert([]int{1,3,5,6}, 7))  // 4(示例3)

 

关键点总结

  1. 循环条件选择:左闭右闭区间必须用 left <= right,否则会漏查边界情况。
  2. 插入位置推导:二分查找结束后,left 的物理意义是「数组中第一个大于 target 的元素位置」,这个特性天然支持插入位置的确定。
  3. 溢出保护:通过 left + (right-left)/2 代替 (left+right)/2,规避大数相加的溢出风险。
posted @ 2025-03-12 17:46  云隙之间  阅读(33)  评论(0)    收藏  举报