搜索算法详解

学习提示

搜索算法是编程中最常用的基础算法之一。掌握它们能显著提升你的问题解决能力。

一、搜索的重要性 🔎

在信息爆炸的时代,如何快速找到需要的数据成为关键技能。搜索算法就是解决这个问题的核心工具。

想象一下:

这些场景都离不开高效的搜索算法。

搜索的应用领域

数据库查询
SQL 查询优化、索引查找都依赖高效搜索算法。
网络爬虫
搜索引擎需要快速检索海量网页内容。
文件系统
操作系统通过搜索算法快速定位文件。

二、线性搜索 - 最简单的方法 📏

线性搜索(Linear Search)是最直观的搜索方法,它逐个检查列表中的每个元素,直到找到目标或遍历完整个列表。

算法原理

代码实现

python
def linear_search(arr, target):
    """
    线性搜索算法
    :param arr: 待搜索的数组
    :param target: 目标值
    :return: 目标值的索引,未找到返回 -1
    """
    for i in range(len(arr)):
        if arr[i] == target:
            return i
    return -1

# 使用示例
numbers = [5, 3, 8, 1, 9, 2, 7]
result = linear_search(numbers, 9)
print(f"找到目标,位置: {result}")  # 输出: 找到目标,位置: 4
javascript
function linearSearch(arr, target) {
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] === target) {
            return i;
        }
    }
    return -1;
}

// 使用示例
const numbers = [5, 3, 8, 1, 9, 2, 7];
const result = linearSearch(numbers, 9);
console.log(`找到目标,位置: ${result}`); // 输出: 找到目标,位置: 4

性能分析

O(n)
时间复杂度
O(1)
空间复杂度
无需排序
前置条件
注意

线性搜索虽然简单,但在大数据量下效率较低。当数据有序时,应该优先考虑二分搜索。

三、二分搜索 - 高效的搜索策略 🎯

二分搜索(Binary Search)是一种在有序数组中查找目标值的高效算法。它每次将搜索范围缩小一半,因此速度非常快。

核心思想

迭代实现

二分搜索迭代版本
def binary_search(arr, target):
    """
    二分搜索算法(迭代版本)
    """
    left, right = 0, len(arr) - 1
    
    while left <= right:
        mid = left + (right - left) // 2  # 防止整数溢出
        
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return -1

# 测试
sorted_arr = [1, 3, 5, 7, 9, 11, 13, 15]
print(binary_search(sorted_arr, 7))   # 输出: 3
print(binary_search(sorted_arr, 6))   # 输出: -1

递归实现

二分搜索递归版本
def binary_search_recursive(arr, target, left=0, right=None):
    """
    二分搜索算法(递归版本)
    """
    if right is None:
        right = len(arr) - 1
    
    # 基本情况:搜索范围为空
    if left > right:
        return -1
    
    mid = left + (right - left) // 2
    
    if arr[mid] == target:
        return mid
    elif arr[mid] < target:
        return binary_search_recursive(arr, target, mid + 1, right)
    else:
        return binary_search_recursive(arr, target, left, mid - 1)

性能对比

算法 最好情况 平均情况 最坏情况 适用场景
线性搜索 O(1) O(n) O(n) 无序小数据集
二分搜索 O(1) O(log n) O(log n) 有序大数据集
二分搜索效率(100万元素)95%
线性搜索效率(100万元素)30%

四、二分搜索的变体 🔧

二分搜索不仅用于精确匹配,还可以解决许多变种问题。

查找第一个出现位置

python
def find_first_occurrence(arr, target):
    """查找目标值第一次出现的位置"""
    left, right = 0, len(arr) - 1
    result = -1
    
    while left <= right:
        mid = left + (right - left) // 2
        
        if arr[mid] == target:
            result = mid
            right = mid - 1  # 继续在左侧搜索
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return result

查找最后一个出现位置

python
def find_last_occurrence(arr, target):
    """查找目标值最后一次出现的位置"""
    left, right = 0, len(arr) - 1
    result = -1
    
    while left <= right:
        mid = left + (right - left) // 2
        
        if arr[mid] == target:
            result = mid
            left = mid + 1  # 继续在右侧搜索
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return result

查找插入位置

python
def search_insert_position(arr, target):
    """查找目标值应该插入的位置(保持有序)"""
    left, right = 0, len(arr) - 1
    
    while left <= right:
        mid = left + (right - left) // 2
        
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    
    return left  # 返回插入位置

五、实际应用案例 💡

案例一:字典查找

电子词典通常使用二分搜索来快速查找单词释义。

为什么字典适合二分搜索?

字典具有以下特点:

  • 单词按字母顺序排列(有序)
  • 数据量庞大(数十万词条)
  • 查询频率高(用户频繁查找)
  • 更新频率低(词典内容相对稳定)

这些特性使二分搜索成为理想选择,能在毫秒级时间内完成查找。

bash
# Git bisect 命令使用二分搜索
git bisect start
git bisect bad          # 标记当前版本有问题
git bisect good v1.0    # 标记 v1.0 版本正常
# Git 会自动二分查找问题提交

案例二:版本控制

Git 等版本控制系统使用二分搜索来定位引入 bug 的提交。

案例三:数值计算

在科学计算中,二分搜索用于求解方程的根。

牛顿法 vs 二分法

六、常见问题与陷阱 ⚠️

整数溢出问题

在计算 mid = (left + right) / 2 时,如果 leftright 很大,可能会溢出。

解决方案:使用 mid = left + (right - left) / 2

这个公式在数学上等价,但避免了溢出风险。

边界条件处理

二分搜索的边界条件容易出错,特别是:

  • while left <= right 还是 while left < right
  • right = mid - 1 还是 right = mid
  • left = mid + 1 还是 left = mid

建议:统一使用 left <= right 和相应的更新逻辑,保持一致性。

非整数除法

在某些语言中,(left + right) / 2 可能产生浮点数。

解决方案:使用整数除法 //(Python)或 (left + right) >> 1(位运算)。

七、练习与挑战 🏆

经典练习题

LeetCode 704. 二分查找
给定一个 n 个元素有序的整型数组和一个目标值,写一个函数搜索目标值,如果存在返回下标,否则返回 -1。 难度:⭐ 简单 通过率:65%
LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组,和一个目标值。找出给定目标值在数组中的开始位置和结束位置。 难度:⭐⭐ 中等 通过率:42%

八、总结 📝

搜索算法是编程的基础技能,掌握它们对提升编程能力至关重要。

线性搜索

简单直观,适用于小规模或无序数据。

二分搜索

高效快速,适用于大规模有序数据。

继续探索更多算法

搜索算法只是冰山一角,还有树搜索、图搜索等更多内容等待你探索!

查看图搜索算法 下载完整代码

© 2026 AI未来实验室 · 用 AI 探索无限可能
站点地图 | Robots.txt | 关于