二分查找中的停止条件和移动边界情况总结

1. 停止条件

停止条件决定何时退出二分查找循环。在大多数二分查找中,循环的停止条件是通过比较左右边界来决定的。

  • 常见的停止条件

    • l <= r(通常用于查找目标值是否存在,典型的查找形式):循环会在 lr 相遇或 r 小于 l 时结束。
    • l < r(用于查找满足特定条件的边界,如找到某个值的第一个或最后一个出现位置):此条件用于确保在退出时能够保留最后一个检查的元素,适合寻找边界位置。
  • 示例

    • 查找目标值时,我们通常使用 l <= r
    • 查找某个值的边界时(如第一个或最后一个出现位置),通常使用 l < r,这样可以避免在跳出循环后还需要多一步判断。

2. 移动条件

移动条件是根据中间值 mid 的比较结果决定的,分为两种情况:

  • 向左移动:即缩小右边界 r
  • 向右移动:即增大左边界 l
常见移动条件
  1. 标准二分查找(寻找目标值)

    • if nums[mid] < target:目标值在右侧,左边界右移 l = mid + 1
    • if nums[mid] > target:目标值在左侧,右边界左移 r = mid - 1

    在这种查找中,如果 nums[mid] == target,通常会直接返回或进行其他处理。

  2. 寻找左边界(第一个等于目标值的位置)

    • nums[mid] == target 时,我们不应该立即返回,而是将右边界左移 r = mid,因为我们希望继续在左半部分查找,直到找到第一个目标值。
    • if nums[mid] >= target:缩小右边界 r = mid,使得搜索范围向左靠拢。
    • if nums[mid] < target:左边界右移 l = mid + 1
  3. 寻找右边界(最后一个等于目标值的位置)

    • nums[mid] == target 时,不应该立即返回,而是继续向右查找,移动左边界 l = mid + 1,以找到最后一个目标值。
    • if nums[mid] > target:右边界左移 r = mid - 1
    • if nums[mid] <= target:左边界右移 l = mid + 1

3. 代码示例

让我们通过代码说明这些不同情况的设计:

3.1. 标准二分查找(查找目标值)
 

func binarySearch(nums []int, target int) int {
    l, r := 0, len(nums) - 1
    for l <= r {
        mid := l + (r - l) / 2
        if nums[mid] == target {
            return mid
        } else if nums[mid] < target {
            l = mid + 1
        } else {
            r = mid - 1
        }
    }
    return -1 // 如果没找到目标值
}
  • 停止条件:l <= r,意味着当左右边界相等或交错时停止。
  • 移动条件:根据 nums[mid]target 的比较结果,移动 lr
3.2. 查找第一个等于目标值的位置
 
func findFirst(nums []int, target int) int {
    l, r := 0, len(nums) - 1
    for l < r { // 注意是 l < r
        mid := l + (r - l) / 2
        if nums[mid] >= target { // 尽量向左缩小范围
            r = mid
        } else {
            l = mid + 1
        }
    }
    if nums[l] == target {
        return l
    }
    return -1 // 如果没找到目标值
}
  • 停止条件:l < r,确保最后一个可能的候选位置还在范围内。
  • 移动条件:当 nums[mid] >= target 时,缩小右边界,确保找到第一个目标值。
3.3. 查找最后一个等于目标值的位置
func findLast(nums []int, target int) int {
    l, r := 0, len(nums) - 1
    for l < r {
        mid := l + (r - l) / 2
        if nums[mid] > target { // 缩小右边界
            r = mid - 1
        } else {
            l = mid + 1 // 向右寻找
        }
    }
    if nums[l-1] == target { // 退出循环后 l-1 是最后一个等于 target 的位置
        return l - 1
    }
    return -1 // 如果没找到目标值
}
  • 停止条件:l < r,以确保能够查找范围的最后一个位置。
  • 移动条件:当 nums[mid] <= target 时,移动左边界,继续查找最后一个目标值。

总结

  • 停止条件:根据你需要的结果选择使用 l <= rl < r
    • l <= r:通常用于简单查找。
    • l < r:通常用于查找边界,如寻找第一个或最后一个等于目标值的位置。
  • 移动条件:根据你的查找目的来调整移动逻辑。
    • 查找目标值:移动逻辑直接根据与目标值的比较。
    • 查找边界:移动逻辑需要确保不断缩小边界,直到找到最左或最右的位置。

通过这些设计,你可以根据具体需求灵活调整二分查找的停止条件和移动条件,从而高效、准确地完成查找任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值