Rust:带你写个二分查找,一学就会

  1. 二分查找详解

点击这里查看力扣题目,了解详细信息。

当你面对一个升序排列的整数数组 nums 并寻找一个特定目标值 target 时,你可以采用一种高效的搜索方法来定位这个目标值。如果目标值存在于数组中,那么就返回它的索引;如果不存在,就返回 -1 作为标记。

示例 1:

makefile 复制代码
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
说明: 目标值 9 在数组中的索引为 4

示例 2:

makefile 复制代码
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
说明: 目标值 2 并不在数组中,因此返回 -1

提示:

  • 数组 nums 中的元素是唯一的。
  • 数组的大小 n 范围在 [1, 10000]
  • 数组元素的值域是 [-9999, 9999]

方法探究

此题假定数组是有序且无重复元素的,这为二分查找提供了理想的应用条件。但是,要正确实现二分查找,关键在于如何处理搜索的边界条件,这往往是编码时最容易出错的地方。主要有两种方式来定义查找区间:左闭右闭 [left, right] 和左闭右开 [left, right)

二分查找的实现方法

  • 采用左闭右闭区间 [left, right]

    • 循环条件使用 while (left <= right),意味着 leftright 相等是有效的,需要被检查。
    • 如果发现 nums[middle] > target,则说明 target 不可能是 nums[middle],下一步 right 应该调整到 middle - 1
rust 复制代码
impl Solution {
    pub fn search(nums: Vec<i32>, target: i32) -> i32 {
        let (mut left, mut right) = (0_i32, nums.len() as i32 - 1);
        while left <= right {
            let mid = (left + right) / 2;
            match nums[mid as usize].cmp(&target) {
                Ordering::Less => left = mid + 1,
                Ordering::Greater => right = mid - 1,
                Ordering::Equal => return mid,
            }
        }
        -1
    }
}
  • 采用左闭右开区间 [left, right)

    • 循环条件改为 while (left < right),因为当 leftright 相等时,区间不再有效。

    • 如果 nums[middle] > target,那么 right 更新为 middle,因为 nums[middle] 已经被排除在外,接下来的搜索区间应该是左闭右开的 [left, middle)

rust 复制代码
use std::cmp::Ordering;
impl Solution {
    pub fn search(nums: Vec<i32>, target: i32) -> i32 {
        let (mut left, mut right) = (0_i32, nums.len() as i32);
        while left < right {
            let mid = (right + left) / 2;
            match nums[mid as usize].cmp(&target) {
                Ordering::Less => left = mid + 1,
                Ordering::Greater => right = mid,
                Ordering::Equal => return mid,
            }
        }
        -1
    }
};
  • 时间复杂度: 对于两种方法而言,都是 O(log n),因为每次查找都是将查找区间缩小到原来的一半。
  • 空间复杂度: O(1),我们只需要常数级别的额外空间。

深入理解二分查找

二分查找,作为一个经典而高效的搜索算法,之所以能够在有序数组中快速定位元素,是因为它每一步都将待搜索的区间减半,从而大幅减少了搜索所需的时间。但是,恰当地实现二分查找并非毫无挑战。很多时候,我们可能会遇到各种边界条件的处理问题,导致写出来的代码不符合要求,但是实际上,搞明白边界问题,二分查找就是手拿把掐,手到擒来!Pomelo_刘金,转载请注明原文链接。感谢!

相关推荐
leonkay3 小时前
Golang语言闭包完全指南
开发语言·数据结构·后端·算法·架构·golang
颜酱4 小时前
BFS 与并查集实战总结:从基础框架到刷题落地
javascript·后端·算法
casual~4 小时前
第?个质数(埃氏筛算法)
数据结构·c++·算法
仰泳的熊猫5 小时前
题目2308:蓝桥杯2019年第十届省赛真题-旋转
数据结构·c++·算法·蓝桥杯
hssfscv5 小时前
力扣练习训练2(java)——二叉树的中序遍历、对称二叉树、二叉树的最大深度、买卖股票的最佳时机
java·数据结构·算法
y = xⁿ6 小时前
【LeetCodehot100】二叉树大合集 T94:二叉树的中序遍历 T104:二叉树的最大深度 T226:翻转二叉树 T101:对称二叉树
后端·算法·深度优先
不想看见4046 小时前
Search a 2D Matrix II数组--力扣101算法题解笔记
数据结构·算法
IronMurphy6 小时前
【算法二十六】108. 将有序数组转换为二叉搜索树 98. 验证二叉搜索树
数据结构·算法·leetcode
jaysee-sjc6 小时前
【练习十二】Java实现年会红包雨小游戏
java·开发语言·算法·游戏·intellij-idea
im_AMBER6 小时前
Leetcode 141 最长公共前缀 | 罗马数字转整数
算法·leetcode