刷题笔记

98 阅读2分钟

一、单词搜索问题

1. 问题描述

在一个二维字符数组  grid  中,判断是否存在给定的目标字符串  target  ,可以从任意位置开始,按照上下左右四个方向进行搜索,每个位置的字符只能使用一次。

2. 代码实现

class Solution {
public:
    bool wordPuzzle(vector<vector<char>>& grid, string target) {
        rows = grid.size();
        cols = grid[0].size();
        for(int i = 0; i < rows; i++) {
            for(int j = 0; j < cols; j++) {
                if(dfs(grid, target, i, j, 0)) return true;
            }
        }
        return false;
    }
private:
    int rows, cols;
    bool dfs(vector<vector<char>>& grid, string target, int i, int j, int k) {
        if(i >= rows || i < 0 || j >= cols || j < 0 || grid[i][j] != target[k]) return false;
        if(k == target.size() - 1) return true;
        grid[i][j] = '\0';
        bool res = dfs(grid, target, i + 1, j, k + 1) || 
                   dfs(grid, target, i - 1, j, k + 1) || 
                   dfs(grid, target, i, j + 1, k + 1) || 
                   dfs(grid, target, i, j - 1, k + 1);
        grid[i][j] = target[k];
        return res;
    }
};

3. 代码分析

  • wordPuzzle函数中,遍历二维数组的每个位置,从每个位置开始调用  dfs  函数进行深度优先搜索。

  •  dfs函数中:

  • 首先通过一系列条件判断( i >= rows || i < 0 || j >= cols || j < 0 || grid[i][j] != target[k] )检查当前位置是否越界或字符不匹配,若满足则返回  false 。

  • 当  k  等于  target.size() - 1  时,说明已经匹配到目标字符串的最后一个字符,返回  true 。

  • 将当前位置字符标记为  '\0' ,表示已访问,防止重复访问。

  • 向上下左右四个方向递归调用  dfs  函数继续搜索,并使用逻辑或  ||  组合结果。

  • 搜索完成后,将当前位置字符恢复为原来的值( grid[i][j] = target[k]; ),以便后续其他路径的搜索。

二、深度优先搜索(DFS)

1. 定义

深度优先搜索是一种用于遍历或搜索图或树的算法。它从某个起始节点开始,沿着一条路径尽可能深地探索下去,直到无法继续或达到目标节点,然后回溯到上一个节点,继续探索其他路径。

2. 适用场景

  • 迷宫问题:寻找从起点到终点的路径。

  • 图的遍历:如连通分量的查找、拓扑排序等。

  • 回溯算法:在搜索过程中需要记录路径和状态,并且可以回溯到之前状态的问题,如八皇后问题、数独求解等。

3. 实现方式

  • 递归实现:通过递归函数不断调用自身,实现深度优先搜索。每次递归时,处理当前节点,并递归处理相邻节点。

  • 栈实现:使用栈数据结构模拟递归过程,将节点入栈和出栈,实现深度优先搜索。

4. 特点

  • 优点:

  • 能够快速找到解,特别是在解的深度较浅的情况下。

  • 对于某些问题(如树的遍历),实现简单直观。

  • 缺点:

  • 可能会陷入无限循环(在没有正确处理的情况下)。

  • 在搜索空间较大时,可能会消耗大量的内存(递归深度过深)。