Rust:二分查找

507 阅读4分钟

1. 什么是二分查找算法

二分查找算法(Binary Search Algorithm)是一种在有序数组中查找特定元素的高效算法。

它的基本思想是将查找区间不断缩小,每次将区间缩小一半,直到找到目标元素或确定目标元素不存在。

2. 二分查找算法的原理

二分查找算法的原理很简单。首先,我们需要确定查找区间的左右边界。然后,我们计算区间的中间位置,并检查中间位置的元素是否为目标元素。如果是,则返回该位置;如果不是,则根据中间位置的元素与目标元素的大小关系,更新查找区间的左右边界,并重复上述过程,直到找到目标元素或确定目标元素不存在。

3. 如何实现二分查找算法

下面是一个简单的二分查找算法的 Rust 代码实现:

fn binary_search(arr: &[i32], target: i32) -> Option<usize> {
    let mut left = 0;
    let mut right = arr.len() - 1;
    while left <= right {
        let mid = left + (right - left) / 2;
        if arr[mid] == target {
            return Some(mid);
        } else if arr[mid] < target {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    None
}

在这段代码中,我们定义了一个 binary_search 函数,它接受一个整数数组 arr 和一个目标值 target 作为输入,并返回目标值在数组中的位置(如果存在)。我们使用两个变量 left 和 right 来表示查找区间的左右边界,并使用 while 循环来不断缩小查找区间。在每次循环中,我们计算区间的中间位置 mid,并检查 arr[mid] 是否为目标值。如果是,则返回 mid;如果不是,则根据 arr[mid] 与 target 的大小关系更新查找区间的左右边界。

当然了,也可以直接调用Vec自带的方法:

impl Solution {
   pub fn search(nums: Vec<i32>, target: i32) -> i32 {
       match nums.binary_search(&target) {
           Ok(i) => i as i32,
           Err(_) => -1
       }
   }
}  

函数的实现使用了 Rust 标准库中的 binary_search 方法,该方法在有序数组中执行二分查找。如果查找成功,则返回目标值的位置;否则,返回一个错误。 使用了 match 表达式来处理查找结果。如果查找成功,则返回目标值的位置;否则,返回 -1

impl Solution {
   pub fn search(nums: Vec<i32>, target: i32) -> i32 {
       nums.binary_search(&target).map_or(-1, |x| x as i32)
   }
}

这段代码使用了 map_or 方法来处理查找结果。如果查找成功,则返回目标值的位置;否则,返回 -1,什么是map_or呢?下面详细介绍

Result 类型表示一个可能失败的计算结果。它有两个变体:Ok(T) 表示成功的结果,其中 T 是成功时的值;Err(E) 表示失败的结果,其中 E 是失败时的错误信息。

Result 类型提供了一些方法来处理可能失败的计算结果。其中之一就是 map_or 方法。 允许我们在处理 Result 值时提供一个默认值,以便在 Result 值为 Err(E) 时使用。 下面是一个简单的例子,演示如何在 Result 类型中使用 map_or 方法:

let x: Result<i32, &str> = Ok(3);
let y = x.map_or(0, |v| v * 2);
println!("{}", y); // 输出 6

let x: Result<i32, &str> = Err("error");
let y = x.map_or(0, |v| v * 2);
println!("{}", y); // 输出 0

在这个例子中,我们定义了两个 Result<i32, &str> 类型的变量 x 和 y。对于第一个变量 x,它的值为 Ok(3)。我们使用 map_or 方法将其映射为一个新值,并将结果存储在变量 y 中。由于 x 的值不为 Err(E),因此 map_or 方法会调用传入的函数,并将其返回值作为结果。因此,变量 y 的值为 6。

对于第二个变量 x,它的值为 Err("error")。我们同样使用 map_or 方法将其映射为一个新值,并将结果存储在变量 y 中。由于 x 的值为 Err(E),因此 map_or 方法不会调用传入的函数,而是直接返回默认值。因此,变量 y 的值为 0。

4. 二分查找算法的时间复杂度

二分查找算法的时间复杂度为 O(log n),其中 n 是数组的长度。这意味着,对于一个长度为 n 的数组,二分查找算法最多需要执行 log n 次循环才能确定目标元素是否存在。

5. 二分查找算法的应用场景

二分查找算法通常用于在有序数组中快速查找特定元素。它也可以用于解决一些其他问题,例如求解方程的根、确定一个数是否为完全平方数等。

6. 二分查找算法的优缺点

二分查找算法具有以下优点:

  • 时间复杂度低:对于一个长度为 n 的数组,二分查找算法最多需要执行 log n 次循环才能确定目标元素是否存在。
  • 空间复杂度低:二分查找算法只需要常数级别的额外空间。

但是,二分查找算法也有以下缺点:

  • 只能用于有序数组:如果数组不是有序的,则无法使用二分查找算法。

  • 对于动态数组不太友好:如果数组经常发生插入和删除操作,则维护数组的有序性会带来额外的开销。from刘金,转载请注明原文链接。感谢!