Leetcode 79 Word search

题意:给定一个m*n的矩阵,求在矩阵中是否能搜索到这个单词

https://leetcode.com/problems/word-search/description/

Input: board = \["A","B","C","E","S","F","C","S","A","D","E","E"], word = "ABCCED"

Output: true

解答:遇到第一个匹配的开头(比如例子中的A),开始搜索,用dfs来搜索四个方向,并用vis数组确保已经访问过的节点不会被访问,用一个变量来记录我当前搜索到哪一个位置了

cpp 复制代码
class Solution {
public:
    bool ret;
    bool exist(vector<vector<char>>& board, string word) {
        if(!word.size()) {
            return true;
        }
        int m = board.size();
        int n = board[0].size();
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(board[i][j] == word[0]) {
                    vector<vector<int>> vis(m, vector<int>(n,0));
                    vis[i][j] = 1;
                    dfs(board, 1, i, j, vis, word);
                    if(ret) {
                        return true;
                        }
                    }
                }
            }
            return false;
        }

    void dfs(vector<vector<char>>& board, int st, int x, int y, vector<vector<int>>& vis, string word) {
        int m = board.size();
        int n = board[0].size();
        if(st == word.size()) {
            ret = true;
            return;
        }
        
        int dk[] = {-1, 0, 1, 0, -1};
        for(int i = 0; i < 4; i++) {
            int dx = x + dk[i];
            int dy = y + dk[i+1];
            if(dx >= 0 && dx < m && dy >= 0 && dy < n && !vis[dx][dy] && board[dx][dy] == word[st]) {
                vis[dx][dy] = 1;
                dfs(board, st+1, dx, dy, vis, word);
                vis[dx][dy] = 0;
            }
        }
    }
};

question:为什么下面的代码过不了?以及有哪些不好的地方?

cpp 复制代码
class Solution {
public:
    bool ret;
    bool exist(vector<vector<char>>& board, string word) {
        if(!word.size()) {
            return true;
        }
        int m = board.size();
        int n = board[0].size();
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(board[i][j] == word[0]) {
                    vector<vector<int>> vis(m, vector<int>(n,0));
                    vis[i][j] = 1;
                    dfs(board, 1, i, j, vis, word);
                    if(ret) {
                        return true;
                        }
                    }
                }
            }
            return false;
        }

    void dfs(vector<vector<char>>& board, int st, int x, int y, vector<vector<int>> vis, string word) {
        int m = board.size();
        int n = board[0].size();
        if(st == word.size()) {
            ret = true;
            return;
        }
        
        int dk[] = {-1, 0, 1, 0, -1};
        for(int i = 0; i < 4; i++) {
            int dx = x + dk[i];
            int dy = y + dk[i+1];
            if(dx >= 0 && dx < m && dy >= 0 && dy < n && !vis[dx][dy] && board[dx][dy] == word[st]) {
                vis[dx][dy] = 1;
                dfs(board, st+1, dx, dy, vis, word);
                vis[dx][dy] = 0;
            }
        }
    }
};

为什么过不了?因为vis数组产生了copy,这个开销是MN的,你的答案的算法复杂度会变成M 2N 2

并且这个ret完全没必要,你完全可以通过dfs的返回值消掉这个ret

而且vis数组其实可以写在里面的

question:为什么这个会有问题?因为board[dx][dy] == word[st+1] 会有越界问题的,要想输入dfs(board, 0, i, j, vis, word,我必须每次进入的时候判定,而不是说每一次for循环中去判定

cpp 复制代码
class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        if(!word.size()) {
            return true;
        }
        int m = board.size();
        int n = board[0].size();
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(board[i][j] == word[0]) {
                    vector<vector<int>> vis(m, vector<int>(n,0));
                    if(dfs(board, 0, i, j, vis, word)) {
                        return true;
                        }
                    }
                    
                }
            }
            return false;
        }

    bool dfs(vector<vector<char>>& board, int st, int x, int y, vector<vector<int>>& vis, string word) {
        int m = board.size();
        int n = board[0].size();
        vis[x][y] = 1;
        if(st == word.size()) {
            return true;
        }
        int dk[] = {-1, 0, 1, 0, -1};
        for(int i = 0; i < 4; i++) {
            int dx = x + dk[i];
            int dy = y + dk[i+1];
            if(dx >= 0 && dx < m && dy >= 0 && dy < n && !vis[dx][dy] && board[dx][dy] == word[st+1]) {
                if(dfs(board, st+1, dx, dy, vis, word)) {
                    return true;
                }
            }
        }
        vis[x][y] = 0;
        return false;
    }


};

最为简洁的写法,写的时候注意,先判断true,再来false

cpp 复制代码
class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        if(!word.size()) {
            return true;
        }
        int m = board.size();
        int n = board[0].size();
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < n; j++) {
                if(board[i][j] == word[0]) {
                    vector<vector<int>> vis(m, vector<int>(n,0));
                    if(dfs(board, 0, i, j, vis, word)) {
                        return true;
                        }
                    }
                    
                }
            }
            return false;
        }

    bool dfs(vector<vector<char>>& board, int st, int x, int y, vector<vector<int>>& vis, string word) {
        int m = board.size();
        int n = board[0].size();
        if(st == word.size()) {
            return true;
        }
        if(x < 0 || x >= m || y < 0 || y >= n) {
            return false;
        }
        if(vis[x][y] || board[x][y] != word[st]) {
            return false;
        }
        vis[x][y] = 1;
        int dk[] = {-1, 0, 1, 0, -1};
        for(int i = 0; i < 4; i++) {
            int dx = x + dk[i];
            int dy = y + dk[i+1];
                if(dfs(board, st+1, dx, dy, vis, word)) {
                    return true;
                }
            }
        vis[x][y] = 0;
        return false;
        }

};

算法复杂度(MN 3^L)

MN是因为第一个大循环,第二个dfs相当于搜索长度为L的字符串,有3个方向可以搜索(去除了回退哪一个)

相关推荐
青 春 记 忆7 分钟前
LeetCode 53. 最大子数组和|Python 解法详解
python·算法·leetcode
星轨初途6 小时前
LeetCode 热题 100——day6 三数之和
数据结构·c++·算法·leetcode·职场和发展
鹿角片ljp6 小时前
LeetCode 53. 最大子数组和
算法·leetcode·职场和发展
mifengxing16 小时前
LeetCode 41.缺失的第一个正数|Hard题O(n)+O(1)最优解法深度解析
java·算法·leetcode·排序算法
hanlin0320 小时前
动态规划专练:力扣第121、122题
笔记·算法·leetcode
To_OC21 小时前
LC 74 搜索二维矩阵:换皮的二分查找,我居然一开始没看出来
javascript·算法·leetcode
玖玥拾21 小时前
LeetCode 189 轮转数组
算法·leetcode
Tisfy1 天前
LeetCode 3345.最小可整除数位乘积 I:暴力枚举(从n开始尝试)
数学·算法·leetcode·题解·枚举
青山木1 天前
Hot 100 --- 在排序数组中查找元素的第一个和最后一个位置
java·数据结构·算法·leetcode
mifengxing1 天前
LeetCode 238 除自身以外数组的乘积|无除法O(n)时间+O(1)空间双解法
java·算法·leetcode