doocs/leetcode 搜索算法大全:从二分查找到A*算法的完整指南

doocs/leetcode 搜索算法大全:从二分查找到A*算法的完整指南

【免费下载链接】leetcode 🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解 【免费下载链接】leetcode 项目地址: https://gitcode.com/doocs/leetcode

前言:为什么搜索算法如此重要?

在编程面试和算法竞赛中,搜索算法是最基础也是最核心的技能之一。无论是处理有序数据的二分查找,还是解决图论问题的广度优先搜索(BFS)和深度优先搜索(DFS),亦或是智能寻路的A*算法,掌握这些搜索技术将让你在解决复杂问题时游刃有余。

本文将带你深入探索doocs/leetcode项目中涵盖的各种搜索算法,通过详细的代码示例、算法模板和实战案例,帮助你构建完整的搜索算法知识体系。

📊 搜索算法分类总览

mermaid

🔍 一、二分查找:有序世界的利器

算法核心思想

二分查找的本质并非"单调性",而是"边界"。只要找到某种性质,使得整个区间一分为二,就可以用二分把边界点找出来。

两种经典模板

模板1:查找左边界
boolean check(int x) {
    // 检查条件函数
}

int search(int left, int right) {
    while (left < right) {
        int mid = (left + right) >> 1;
        if (check(mid)) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    return left;
}
模板2:查找右边界
boolean check(int x) {
    // 检查条件函数
}

int search(int left, int right) {
    while (left < right) {
        int mid = (left + right + 1) >> 1;
        if (check(mid)) {
            left = mid;
        } else {
            right = mid - 1;
        }
    }
    return left;
}

二分查找四步法

  1. 确定循环条件left < right
  2. 计算中间值:先写 mid = (left + right) / 2
  3. 选择模板
    • right = mid 则 else 写 left = mid + 1
    • left = mid 则 else 写 right = mid - 1,且 mid 计算要+1
  4. 处理结果:循环结束时 left 与 right 相等

实战例题

题目难度关键点
在排序数组中查找元素的第一个和最后一个位置中等左右边界二分
x的平方根简单浮点数二分
寻找峰值中等二分性质判断
第一个错误的版本简单标准二分应用

🚀 二、广度优先搜索(BFS):层层递进的探索

BFS算法框架

from collections import deque

def bfs(start, target):
    queue = deque([start])
    visited = set([start])
    steps = 0
    
    while queue:
        size = len(queue)
        for _ in range(size):
            current = queue.popleft()
            if current == target:
                return steps
            
            for neighbor in get_neighbors(current):
                if neighbor not in visited:
                    visited.add(neighbor)
                    queue.append(neighbor)
        steps += 1
    return -1

BFS变种与应用场景

1. 多源BFS

适用于多个起点同时扩散的场景,如"01矩阵"、"地图中的最高点"等题目。

2. 双向BFS

从起点和终点同时开始搜索,大幅减少搜索空间,适用于"打开转盘锁"、"单词接龙"等题目。

3. 0-1BFS

使用双端队列,边权为0或1时的优化BFS,适用于"网格中的最短路径"等题目。

BFS复杂度分析

场景时间复杂度空间复杂度
标准BFSO(V + E)O(V)
双向BFSO(b^(d/2))O(b^(d/2))
多源BFSO(V + E)O(V)

🌊 三、深度优先搜索(DFS):深入探索的艺术

DFS递归模板

def dfs(node, visited, path):
    if is_goal(node):
        # 处理结果
        return
    
    visited.add(node)
    for neighbor in get_neighbors(node):
        if neighbor not in visited:
            path.append(neighbor)
            dfs(neighbor, visited, path)
            path.pop()  # 回溯
    visited.remove(node)

DFS迭代模板

def dfs_iterative(start):
    stack = [start]
    visited = set([start])
    
    while stack:
        node = stack.pop()
        # 处理当前节点
        
        for neighbor in get_neighbors(node):
            if neighbor not in visited:
                visited.add(neighbor)
                stack.append(neighbor)

DFS高级技巧

1. 回溯算法

用于组合、排列、子集等问题,通过剪枝优化搜索效率。

2. 记忆化搜索

将中间结果缓存,避免重复计算,显著提升性能。

3. 剪枝策略
  • 可行性剪枝
  • 最优性剪枝
  • 重复性剪枝

DFS应用场景

问题类型典型题目技巧
组合问题组合总和回溯+剪枝
排列问题全排列回溯+去重
子集问题子集回溯
图遍历岛屿数量递归DFS
路径搜索单词搜索回溯+剪枝

⭐ 四、启发式搜索:A*算法

A*算法原理

A*算法结合了Dijkstra算法的最短路径保证和贪心最佳优先搜索的启发式引导,通过评估函数 f(n) = g(n) + h(n) 来选择最优路径。

A*算法实现

import heapq

def a_star(start, target):
    open_set = []
    heapq.heappush(open_set, (0 + heuristic(start, target), 0, start))
    g_score = {start: 0}
    came_from = {}
    
    while open_set:
        _, current_g, current = heapq.heappop(open_set)
        
        if current == target:
            return reconstruct_path(came_from, current)
            
        for neighbor in get_neighbors(current):
            tentative_g = current_g + cost(current, neighbor)
            if neighbor not in g_score or tentative_g < g_score[neighbor]:
                g_score[neighbor] = tentative_g
                f_score = tentative_g + heuristic(neighbor, target)
                heapq.heappush(open_set, (f_score, tentative_g, neighbor))
                came_from[neighbor] = current
                
    return None  # 无路径

启发函数设计原则

  1. 可采纳性:h(n) ≤ h*(n),从不高估实际成本
  2. 一致性:h(n) ≤ c(n, n') + h(n'),满足三角不等式
  3. 有效性:计算简单,能有效引导搜索方向

A*算法应用

题目启发函数特点
滑动谜题曼哈顿距离拼图游戏
访问所有节点的最短路径最小生成树代价图遍历优化
为高尔夫比赛砍树欧几里得距离路径规划

🎯 五、搜索算法选择指南

算法选择决策树

mermaid

性能对比表

算法时间复杂度空间复杂度适用场景
二分查找O(log n)O(1)有序数据查找
BFSO(V + E)O(V)最短路径、层次遍历
DFSO(V + E)O(h)路径存在性、回溯问题
A*O(b^d)O(b^d)启发式路径搜索
双向BFSO(b^(d/2))O(b^(d/2))已知起点终点的搜索

💡 六、实战技巧与优化策略

1. 状态压缩技巧

对于状态空间较大的问题,使用位运算、哈希等方式压缩状态表示。

2. 剪枝优化

  • 可行性剪枝:提前终止不可能达到目标的路径
  • 最优性剪枝:放弃非最优解路径
  • 对称性剪枝:避免重复计算对称状态

3. 记忆化搜索

使用字典或数组缓存中间结果,避免重复计算。

4. 迭代加深搜索

结合DFS的深度限制和BFS的完备性,适用于深度未知的问题。

🚀 七、进阶学习路径

初级 → 中级 → 高级

  1. 初级阶段:掌握二分查找、基础BFS/DFS

    • 练习:二分查找变种、迷宫问题、图遍历
  2. 中级阶段:学习回溯、记忆化搜索、双向BFS

    • 练习:组合问题、最短路径优化、状态压缩
  3. 高级阶段:掌握A算法、IDA、Meet in Middle

    • 练习:启发式搜索、折半搜索、复杂优化

📚 八、推荐练习题目

二分查找系列

    1. 在排序数组中查找元素的第一个和最后一个位置
    1. x的平方根
    1. 寻找峰值
    1. 第一个错误的版本

BFS系列

    1. 岛屿数量
    1. 打开转盘锁
    1. 单词接龙
    1. 二进制矩阵中的最短路径

DFS系列

    1. 单词搜索
    1. 全排列
    1. 子集
    1. 组合总和

A*系列

    1. 滑动谜题
    1. 访问所有节点的最短路径
    1. 为高尔夫比赛砍树

总结

搜索算法是算法领域的基石,从简单的二分查找到复杂的A*算法,每种算法都有其独特的应用场景和优化技巧。通过系统学习和大量练习,你将能够:

  1. 快速识别问题类型并选择合适的搜索算法
  2. 熟练运用各种模板解决经典问题
  3. 掌握优化技巧提升算法效率
  4. 灵活组合不同算法解决复杂问题

记住,算法学习的关键在于理解思想而非死记模板。多思考、多实践、多总结,你一定能成为搜索算法的高手!

下一步行动:选择2-3个感兴趣的题目,亲自动手实现代码,体会不同搜索算法的精妙之处。祝你编程之路越走越远!

【免费下载链接】leetcode 🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解 【免费下载链接】leetcode 项目地址: https://gitcode.com/doocs/leetcode

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值