You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LeetCode单词搜索问题:为何采用回溯而非常规DFS?

关于Word Search中回溯与DFS的疑问解答

嘿,这个问题问得特别到位!其实你猜的方向完全没错——回溯本质上就是带「状态重置」的DFS,咱们来把这层关系拆解清楚,你就能明白为什么在这个问题里回溯(或者说带状态管理的DFS)是最合理的选择了。

先理清楚核心概念:常规DFS vs 回溯

  • 常规DFS一般用于遍历所有可达节点(比如找图的连通分量),这类场景里每个节点只需要访问一次,不需要撤销访问标记,走到底就行。
  • 但在Word Search问题中,我们需要尝试不同的路径组合:比如从某个单元格出发,往右走没找到目标单词,就得退回来,再尝试往下走。这时候必须把之前标记为「已访问」的单元格重新设为「未访问」——这就是回溯的核心:尝试路径→失败→回滚状态→再尝试其他路径。

关于visited矩阵:它本身就是回溯的实现方式!

你提到的用visited矩阵替代的思路完全可行,但这其实就是回溯的一种写法啊!举个代码例子你就能明白:

def exist(board, word):
    rows, cols = len(board), len(board[0])
    visited = [[False]*cols for _ in range(rows)]
    
    def backtrack(i, j, current_idx):
        # 找到完整单词,直接返回成功
        if current_idx == len(word):
            return True
        # 越界、已访问、字符不匹配,直接返回失败
        if i < 0 or i >= rows or j <0 or j >= cols or visited[i][j] or board[i][j] != word[current_idx]:
            return False
        
        # 标记当前单元格为已访问(进入分支前的状态变更)
        visited[i][j] = True
        # 尝试四个方向的路径
        found = backtrack(i+1,j,current_idx+1) or backtrack(i-1,j,current_idx+1) or backtrack(i,j+1,current_idx+1) or backtrack(i,j-1,current_idx+1)
        # 回溯:撤销标记(退出分支后重置状态)
        visited[i][j] = False
        
        return found
    
    # 遍历所有单元格作为起始点
    for i in range(rows):
        for j in range(cols):
            if backtrack(i,j,0):
                return True
    return False

这里的visited[i][j] = False就是典型的回溯操作——如果当前路径走不通,就得把状态改回去,让其他可能的路径还能使用这个单元格。要是只做DFS不回溯,一旦标记了某个单元格为已访问,后续所有路径都用不了它,肯定会漏掉正确的解。

额外小技巧:不用visited矩阵也能回溯

甚至可以不用单独的visited矩阵,直接修改原board的字符(比如把当前单元格改成#这种特殊字符),回溯的时候再改回原字符,这样能节省额外的空间,本质还是回溯的思路。

总结

你说的「常规DFS」是没有状态回滚的DFS,在这个问题里根本行不通——因为我们需要探索多条独立的路径,每条路径的访问状态不能互相干扰。而用visited矩阵的方式,本质就是带状态回溯的DFS,这正是解决这类路径探索问题的标准姿势。两者不是对立的,回溯是DFS针对「需要尝试多种路径、必须回滚状态」场景的特殊应用~

内容的提问来源于stack exchange,提问作者J. Doe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:09:19