LeetCode从低效到高效,点击
一、题目描述:
题目要求
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
来源:力扣(LeetCode)链接
示例
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false
二、思路分析:
这是一道DFS,并且需要回溯的题目,这道题恶心在可以从这个二维矩阵中找任意的点作为开始,经过这道题的暴打,我发现回溯算法最好将判断提到最前面判断,然后回溯的时候啥都不判断直接扔进去所有可能性,然后将修改回溯。
三、AC 代码:
这个写法中的has的作用非常明显,可以在发现有解的时候结束递归,但是还有优化空间
// 236ms 11mb 勉强过了
void backtrack(vector<vector<char>>& board,string &word,vector<vector<bool>> &flag,int idx,int i,int j,bool &has){
if(i<0||has||i>=board.size()||j<0||j>=board[0].size()||flag[i][j]||board[i][j]!=word[idx]){
return;
}
if(idx== word.size()-1){
has = true;
return;
}
flag[i][j] = true;
backtrack(board,word,flag,idx+1,i+1,j,has);
backtrack(board,word,flag,idx+1,i-1,j,has);
backtrack(board,word,flag,idx+1,i,j+1,has);
backtrack(board,word,flag,idx+1,i,j-1,has);
flag[i][j] = false;
}
bool exist(vector<vector<char>>& board, string word) {
bool has = false;
int m = board.size(), n = board[0].size();
vector<vector<bool>> flag(m,vector<bool>(n,false));
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
backtrack(board,word,flag,0,i,j,has);
if(has){
return true;
}
}
}
// backtrack(board,word,flag,0);
return has;
}
去除标记数组,利用char只是用了7个比特 用另一个比特存东西
// 236ms 11mb 勉强过了
// 184 ms 10.6MB
void backtrack(vector<vector<char>>& board,string &word,int idx,int i,int j,bool &has){
if(i<0||has||i>=board.size()||j<0||j>=board[0].size()||board[i][j]!=word[idx]){
return;
}
if(idx== word.size()-1){
has = true;
return;
}
board[i][j] ^=0x80;
backtrack(board,word,idx+1,i+1,j,has);
backtrack(board,word,idx+1,i-1,j,has);
backtrack(board,word,idx+1,i,j+1,has);
backtrack(board,word,idx+1,i,j-1,has);
board[i][j] ^=0x80;
}
bool exist(vector<vector<char>>& board, string word) {
bool has = false;
int m = board.size(), n = board[0].size();
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
backtrack(board,word,0,i,j,has);
if(has){
return true;
}
}
}
// backtrack(board,word,flag,0);
return has;
}
四、总结:
本题中有两个重要的策略,一个是发现有解尽快停止搜索,另一个就是尽量减少标记数组的使用,在本题中利用char类型的特点将标记直接存储到了board中
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情