【回溯专题】剑指 Offer 12. 矩阵中的路径

本问题对应课程链接:剑指offer刷题第七期

要求:

1、请打卡你的解题代码,如果能简单说一下思路则简单说一下思路。
2、给出你代码所用的时间复杂度和空间复杂度

共以下 9 个回答

  • lQl 永久会员 2025年1月18日 上午11:01
    class Solution {
        public boolean wordPuzzle(char[][] grid, String target) {
            int m = grid.length;// 行数
            int n = grid[0].length;// 列数
            char[] words = target.toCharArray();
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    if (dfs(grid, words, i, j, 0))
                        return true;
                }
            }
            return false;
        }
    
        boolean dfs(char[][] grid, char[] words, int i, int j, int k) {
            if (i >= grid.length || i < 0 || j >= grid[0].length || j < 0 || grid[i][j] != words[k])
                return false;
            if (k == words.length - 1)
                return true;
            grid[i][j] = '\0';
            boolean res = dfs(grid, words, i + 1, j, k + 1) || dfs(grid, words, i - 1, j, k + 1)
                    || dfs(grid, words, i, j + 1, k + 1) || dfs(grid, words, i, j - 1, k + 1);
            grid[i][j] = words[k];
            return res;
        }
    }
    

    时间复杂度O(mn4^l)
    空间复杂度O(l)

    0 赞同 0 条回复
  • 陆狗陆狗 普通 2024年12月23日 下午11:45

    解题思路
    – 1、把字符串分割成字符数组
    – 2、把grid的每个位置作为起点去尝试匹配字符
    – 如何匹配字符呢?按照上下左右的顺序去匹配
    – 哪些表示匹配失败了呢?超过grid的上下限了 或者 匹配到已经匹配的单元格 或者 匹配上不相等
    – 最终结束的标识?target的长度=已经匹配的长度
    【题解1】

    class Solution {
        public boolean wordPuzzle(char[][] grid, String target) {
            // 1、把字符串分割成字符数组
            // 2、把grid的每个位置作为起点去尝试匹配字符
            // 如何匹配字符呢?按照上下左右的顺序去匹配
            // 哪些表示匹配失败了呢?超过grid的上下限了 或者 匹配到已经匹配的单元格 或者 匹配上不相等
            // 最终结束的标识?target的长度=已经匹配的长度
    
            // 把字符串分割成字符数组
            char[] charArray = target.toCharArray();
            // 把grid的每个位置作为起点去尝试匹配字符
            for (int i = 0; i < grid.length; i++) {
                // 【错误点】写成了i<grid[0].length,双重循环一定要注意i和j,不要弄混了
                for (int j = 0; j < grid[0].length; j++) {
                    // 执行dps搜索
                    if (dfs(grid, charArray, i, j, 0)) {
                        return true;
                    }
                }
            }
            // 【错误】全部没有匹配到就返回false,不要忘记
            return false;
    
        }
    
        public boolean dfs(char[][] grid, char[] charArray, int i, int j, int k) {
            // 超过边界
            if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length) {
                return false;
            }
            // 值不相等
            if (grid[i][j] != charArray[k]) {
                return false;
            }
            // 如果值相等,且是最后一个字符了
            if (k == charArray.length - 1) {
                return true;
            }
            // 值相等但是不是最后一个字符,就需要从上下左右找下一个字符
            // 先标记一下当前已经被占用的的点,防止后续遍历再占用
            // 【错误点】字符而不是字符串
            grid[i][j] = '\0';
            boolean other = dfs(grid, charArray, i - 1, j, k + 1) || dfs(grid, charArray, i + 1, j, k + 1)
                    || dfs(grid, charArray, i, j - 1, k + 1) || dfs(grid, charArray, i, j + 1, k + 1);
            // 标记还原
            grid[i][j] = charArray[k];
            return other;
        }
    }
    
    • 错误点1:写成了i<grid[0].length,双重循环一定要注意i和j,不要弄混了
    • 错误点2:全部没有匹配到就返回false,不要忘记
    • 错误点3:字符而不是字符串,所以不能用””,要用’\0′
    0 赞同 0 条回复
  • Xiang. 永久会员 2024年12月22日 下午8:23
    class Solution {
        int m;
        int n;
        boolean[][] visited;
        public boolean wordPuzzle(char[][] grid, String target) {
            this.m=grid.length;
            this.n=grid[0].length;
            visited=new boolean[m][n];
            for(int i=0;i<m;i++){
                for(int j=0;j<n;j++){
                    if(find(grid,i,j,target,0)){
                        return true;
                    }
                }
            }
            return false;
        }
    
        public boolean find(char[][] grid,int i,int j,String target,int k){
            if(i<0||i>=m||j<0||j>=n||visited[i][j]||grid[i][j]!=target.charAt(k)) return false;
            if(k==target.length()-1) return true;
            visited[i][j]=true;   //目的是防止下一步搜索在进行回溯时被重复使用
            boolean res=find(grid,i,j+1,target,k+1)||
                        find(grid,i+1,j,target,k+1)||
                        find(grid,i,j-1,target,k+1)||
                        find(grid,i-1,j,target,k+1);
            visited[i][j]=false;
            return res;
        }
    }
    时间复杂度:O(mn)
    空间复杂度:O(n)
    
    0 赞同 0 条回复
  • 秋山丽奈 普通 2024年12月18日 下午8:17

    思路:回溯

    class Solution {
        boolean[][] flag;
    
        public boolean wordPuzzle(char[][] grid, String target) {
            // 行数 
            int row = grid.length;
            // 列数 
            int col = grid[0].length;
    
            this.flag =  new boolean[row][col];
    
            for(int i = 0; i < row; i ++){
                for(int j = 0; j < col; j ++){
                    this.flag =  new boolean[row][col];
                    if(check(grid, i, j, target.toCharArray(), 0)){
                        return true;
                    }
                }
            }
    
            return false;
        }
    
        public boolean check(char[][] grid, int index_row, int index_col, char[] target, int index_t){
            if(index_t == target.length){
                return true;
            }
    
            if(index_col >= grid[0].length || index_row >= grid.length || index_col < 0 || index_row < 0){
                return false;
            }
    
            if(this.flag[index_row][index_col] == true){
                return false;
            }
    
            if(grid[index_row][index_col] == target[index_t]){
                // 找到 当前字母
                this.flag[index_row][index_col] = true;
                boolean result =  check(grid, index_row, index_col-1, target, index_t+1) || check(grid, index_row, index_col+1, target, index_t+1) || check(grid, index_row+1, index_col, target, index_t+1) || check(grid, index_row-1, index_col, target, index_t+1);
                this.flag[index_row][index_col] = false;
                return result;
            }else{
                return false;
    
            }
        }
    }
    
    0 赞同 0 条回复
  • Kisara 普通 2024年12月18日 下午7:43

    回溯算法

    class Solution {
        public boolean wordPuzzle(char[][] grid, String target) {
            char[] words=target.toCharArray();
            for(int i=0;i<grid.length;i++)
                for(int j=0;j<grid[0].length;j++)
                    if(dfs(grid,words,i,j,0)) return true;
    
            return false;
        }
    
        public boolean dfs(char[][] grid,char[] target,int i,int j,int k){
            if(i>=grid.length||i<0||j>=grid[0].length||j<0||target[k]!=grid[i][j]) return false;
            if(k==target.length-1) return true;
    
            grid[i][j]='\0';
            boolean 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;
        }
    }
    
    0 赞同 0 条回复
  • 苯庸 普通 2024年12月18日 下午3:29

    class Solution {
    public boolean wordPuzzle(char[][] grid, String target) {
    for(int i = 0; i < grid.length; i++){
    for(int j = 0; j < grid[0].length; j++){
    if(grid[i][j] target.charAt(0)){
    if(dfs(grid, 0, target, i, j)){
    return true;
    }
    }
    }
    }
    return false;
    }

    int[] dir = {-1, 0, 1, 0, -1};
    boolean dfs(char[][] grid, int idx, String target, int x, int y){
        if(x < 0 || x >= grid.length || y < 0 || y >= grid[0].length || grid[x][y] != target.charAt(idx)){
            return false;
        }
        if(idx == target.length() - 1){
            return true;
        }
        grid[x][y] = '.';
        boolean res = dfs(grid, idx+1, target, x+1, y) || dfs(grid, idx+1, target, x-1, y) ||
                        dfs(grid, idx+1, target, x, y+1) || dfs(grid, idx+1, target, x, y-1);
    
        grid[x][y] = target.charAt(idx);
        return res;
    
    }
    

    }
    时间:O(mn)
    空间:O(mn)

    0 赞同 0 条回复
  • Aatorx 永久会员 2024年12月18日 下午2:45
    class Solution {
    public:
        bool wordPuzzle(vector<vector<char>>& grid, string target) {
            int m = grid.size();
            int n = grid[0].size();
            vector<vector<bool>> visit(m, vector<bool>(n, false));
            for (int x = 0; x < m; x++) {
                for(int y = 0; y < n; y++) {
                    if (recur(grid, visit, x, y, target, 0, m, n)) {
                        return true;
                    }
                }
            }
            return false;
        }
        bool recur(vector<vector<char>>& grid, vector<vector<bool>>& visit, int x, int y, string target, int k, int m, int n) {
            if(x >= m || y >= n || x < 0 || y < 0 || grid[x][y] != target[k] || visit[x][y] == true) {
                return false;
            }
            if(k == target.size() - 1) {
                return true;
            }
            visit[x][y] = true;
            bool res = recur(grid, visit, x + 1, y, target, k + 1, m, n) || recur(grid, visit, x, y + 1, target, k + 1, m, n) ||
                        recur(grid, visit, x - 1, y, target, k + 1, m, n) || recur(grid, visit, x, y - 1, target, k + 1, m, n);
            visit[x][y] = false;
            return res;
        }
    };
    

    回溯算法,用visit数组记录是否访问过。
    时间复杂度O(M∗N),空间复杂度O(M∗N)。

    0 赞同 0 条回复
  • 月下足迹 普通 2024年12月18日 下午12:48

    class Solution {
    int n;
    int m;
    int len;

    public boolean wordPuzzle(char[][] board, String word) {
        this.n = board.length;
        this.m = board[0].length;
        this.len = word.length();
    
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (dfs(board, i, j, word, 0)) {
                    return true;
                }
            }
        }
    
        return false;
    }
    
    // DFS 搜索
    boolean dfs(char[][] board, int i, int j, String word, int k) {
        // 判断越界或字符不匹配
        if (i < 0 || i >= n || j < 0 || j >= m || board[i][j] != word.charAt(k)) {
            return false;
        }
    
        // 如果已经到达最后一个字符
        if (k == len - 1) {
            return true;
        }
    
        // 临时标记为已访问
        char temp = board[i][j];
        board[i][j] = '\n';  // 标记当前字符为访问过
    
        // 四个方向递归搜索
        boolean res = dfs(board, i, j + 1, word, k + 1) ||
                      dfs(board, i + 1, j, word, k + 1) ||
                      dfs(board, i, j - 1, word, k + 1) ||
                      dfs(board, i - 1, j, word, k + 1);
    
        // 恢复当前字符
        board[i][j] = temp;
    
        return res;
    }
    

    }

    0 赞同 0 条回复
  • Jerry 普通 2024年12月17日 下午10:02
    class Solution {
    public:
        vector> valid;
        bool wordPuzzle(vector>& grid, string target) {
            bool res = false;
            vector> tmp(grid.size() , vector(grid[0].size(), 1));
            valid = tmp;
            for(int i = 0; i < grid.size(); i++){
                for(int j = 0; j < grid[i].size(); j++){
                    if(grid[i][j] == target[0]){
                        res = dfs(grid, target, i, j, 0);
                        if(res) return true;
                    }
                }
            }
            return res;
        }
        bool dfs(vector>& grid, string& target, int i, int j, int start){
            if(start == target.size()) return true;
            if(i<0 || i>=grid.size()) return false;
            if(j<0 || j>=grid[i].size()) return false;
            if(valid[i][j] == 0) return false;
            if(grid[i][j] != target[start]) return false;
    
            valid[i][j] = 0;
            bool res = dfs(grid, target, i-1, j, start+1)||
                    dfs(grid, target, i+1, j, start+1)||
                    dfs(grid, target, i, j-1, start+1)||
                    dfs(grid, target, i, j+1, start+1);
            valid[i][j] = 1;
            return res;
        }
    
    };
    

    时间o(mn3叉树节点个数) 这个咋算?矩阵每个节点都遍历一遍树。
    o(mn
    3^L)L是target的长度.
    空间o(mn)
    注意点:时间复杂度的计算。o(mn*3^L)L是target的长度。
    除了第一次是4个方向外,之后都是3个方向,因为有来时路,valid=0。

    0 赞同 0 条回复

# 回答此问题

后才能回答