您的位置:首页 > 其它

[LeetCode] World Search(!!!!回溯&&char *代替string&&递归)

2015-08-24 15:50 316 查看
Word Search Given a 2D board and a word, find if the word exists in

the grid.

The word can be constructed from letters of sequentially adjacent

cell, where “adjacent” cells are those horizontally or vertically

neighboring. The same letter cell may not be used more than once.

For example, Given board =

[ [“ABCE”],

[“SFCS”],

[“ADEE”] ]

word = “ABCCED”, -> returns true,

word = “SEE”, -> returns true,

word = “ABCB”, -> returns false.

直接想到的思路就是DFS(回溯),先找到第一个和word[0]相同的字符i,j,从ij开始递归。

在递归的过程中,先找到ij相邻的四个位置,存在pr[4]中,如果相邻的某一个ik,jk等于word[len],则将board[ik][jk]加到当前的string,继续递归,递归返回时,看时候string.size()==word.size()相等则返回,不用判断下面的ik,jk,不相等,则说明这个ik,jk虽然等于word[len]但是不可行,从string中移除board[ik][jk],跳到下一个ik,jk继续处理。

由于元素不能重复使用,所以发现满足的ik,jk时就让标记为访问过了,跳出时在恢复为未访问过。

class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
vector<vector<bool>> visited(board.size(),vector<bool>(board[0].size(),false));
int i ,j,len=0;
string s;
for(i = 0; i < board.size(); ++i)
for(j = 0; j < board[0].size(); ++j){
if(board[i][j]==word[0]){
visited[i][j]=true;
s+=board[i][j];
recuicv_find(visited, board, i,j,len+1,s, word);
visited[i][j]=false;
}

if(s.size()==word.size())
return true;
else
s="";
}
return false;
}

void recuicv_find(vector<vector<bool>> &visited, vector<vector<char>>& board, int i, int j, int len, string &s, string& word){
if(s.size()==word.size())
return ;
pair<int, int>  pr[4];
pr[0] = make_pair(i,j-1);
pr[1] = make_pair(i,j+1);
pr[2] = make_pair(i-1,j);
pr[3] = make_pair(i+1,j);
int ik,jk;
for(int k = 0; k <4; ++k){
ik = pr[k].first;jk = pr[k].second;
if(ik>=0&&ik<board.size()&&jk>=0&&jk<board[0].size()&&visited[ik][jk]==false&&board[ik][jk]==word[len]){
visited[ik][jk]=true;
s.insert(s.size(),1,board[ik][jk]);
recuicv_find(visited, board, ik,jk,len+1, s, word);
if(s.size()==word.size())
return;
else{
visited[ik][jk]=false;
s.erase(s.size()-1,1);
}
}
if(s.size()==word.size())
return;
}
}
};


72ms AC速度有点慢。。。

稍微调整下,这里使用pair来处理,速度上会有些慢,可以先定义一个private变量

step[4][2],ik,jk的更新通过step来操作

class Solution {
private:
int step[4][2];
public:
bool exist(vector<vector<char>>& board, string word) {
vector<vector<bool>> visited(board.size(),vector<bool>(board[0].size(),false));
int i ,j,len=0;
step[0][0] = 1;
step[0][1] = 0;
step[1][0] = -1;
step[1][1] = 0;
step[2][0] = 0;
step[2][1] = 1;
step[3][0] = 0;
step[3][1] = -1;
string s;
for(i = 0; i < board.size(); ++i)
for(j = 0; j < board[0].size(); ++j){
if(board[i][j]==word[0]){
visited[i][j]=true;
s+=board[i][j];
recuicv_find(visited, board, i,j,len+1,s, word);
visited[i][j]=false;
}

if(s.size()==word.size())
return true;
else
s="";
}
return false;
}

void recuicv_find(vector<vector<bool>> &visited, vector<vector<char>>& board, int i, int j, int len, string &s, string& word){
if(s.size()==word.size())
return ;
int ik,jk;
for(int k = 0; k <4; ++k){
ik = i + step[k][0]; jk = j + step[k][1];
if(ik>=0&&ik<board.size()&&jk>=0&&jk<board[0].size()&&visited[ik][jk]==false&&board[ik][jk]==word[len]){
visited[ik][jk]=true;
s.insert(s.size(),1,board[ik][jk]);
recuicv_find(visited, board, ik,jk,len+1, s, word);
if(s.size()==word.size())
return;
else{
visited[ik][jk]=false;
s.erase(s.size()-1,1);
}
}
if(s.size()==word.size())
return;
}
}
};


进一步比较会发现在处理返回值是,比较的是string的size()和word的size(),所以没有比较处理string s这个临时变量

class Solution {
private:
int step[4][2];
public:
bool exist(vector<vector<char>>& board, string word) {
vector<vector<bool>> visited(board.size(),vector<bool>(board[0].size(),false));
int i ,j;
step[0][0] = 1;
step[0][1] = 0;
step[1][0] = -1;
step[1][1] = 0;
step[2][0] = 0;
step[2][1] = 1;
step[3][0] = 0;
step[3][1] = -1;
bool flag = false;
for(i = 0; i < board.size(); ++i)
for(j = 0; j < board[0].size(); ++j){
if(board[i][j]==word[0]){
visited[i][j]=true;
recuicv_find(visited, board, flag, i,j, 1 ,word);
if(flag)
return true;
visited[i][j]=false;
}
}
return false;
}

void recuicv_find(vector<vector<bool>> &visited, vector<vector<char>>& board, bool &flag,int i, int j, int len, string& word){
if(len ==word.size()){
flag = true;
return ;
}
if(flag)
return;
int ik,jk;
for(int k = 0; k <4; ++k){
ik = i + step[k][0]; jk = j + step[k][1];
if(ik>=0&&ik<board.size()&&jk>=0&&jk<board[0].size()&&visited[ik][jk]==false&&board[ik][jk]==word[len]){
visited[ik][jk]=true;
recuicv_find(visited, board, flag, ik,jk,len+1,word);
visited[ik][jk]=false;
if(flag)    return;
}
}
}
};


44ms AC

之前的方法都是使用一个标记flag或是string判断是否找到。这里可以直接递归的return true or false来判断。

当前的i,j ,他有四个邻域,它们四个可以同时递归,如果递归的结果都是false则return false。否则就说明至少有一个返回true,则return true.

每一次递归的开始,判断下标是否越界(越界返回false),是否被使用了(使用过返回false),是否相等word[len] (不相等返回false)

如果这些都满足,那么就判断是否len是否等于word.size()如果相等,则返回true。

如果并不等于word.size(),则将这个数标记为已经访问过了,要更新i,j继续递归

class Solution {
public:
bool exist(vector<vector<char> > &board, string word) {
m=board.size();
n=board[0].size();
for(int x=0;x<m;x++)
for(int y=0;y<n;y++)
{
if(isFound(board,word.c_str(),x,y))
return true;
}
return false;
}
private:
int m;
int n;
bool isFound(vector<vector<char> > &board, const char* w, int x, int y)
{
if(x<0||y<0||x>=m||y>=n||board[x][y]=='\0'||*w!=board[x][y])
return false;
if(*(w+1)=='\0')
return true;
char t=board[x][y];
board[x][y]='\0';
if(isFound(board,w+1,x-1,y)||isFound(board,w+1,x+1,y)||isFound(board,w+1,x,y-1)||isFound(board,w+1,x,y+1))
return true;
board[x][y]=t;
return false;
}
};


16ms AC。。还有0.15%的人12ms AC,怎么做的。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: