leecode 解题总结:79. Word Search

来源:互联网 发布:数据散修txt下载 编辑:程序博客网 时间:2024/04/29 02:22
#include <iostream>#include <stdio.h>#include <vector>#include <string>using namespace std;/*问题: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 =[  ['A','B','C','E'],  ['S','F','C','S'],  ['A','D','E','E']]word = "ABCCED", -> returns true,word = "SEE", -> returns true,word = "ABCB", -> returns false.分析:这是明显的深度优先搜索问题。可以对当前位置(i,j)对应的字符,如果该字符等于给定字符串上对应位置的字符,说明找到了当前位置。后续进行上下左右4个位置的继续查找,一旦发现位置上的字符不等于给定单词对应位置字符,立即终止这个方向的搜索这个不应该是递归,应该是回溯,一旦碰到当前字符不等后,需要回溯到上一个结果。回溯的话只能判定当前,而不能像递归一样直接尝试下一个,回溯应该是先判定当前是否可能,如果不可能,再做输入:3(行数)  ABCCED(待查找字符串)ABCESFCSADEE3  SEEABCESFCSADEE3  ABCBABCESFCSADEE1 aa1 abcab1 ba2 cdbaabcd3  ABCESEEEFSABCESFESADEE输出:truetrue falsefalse关键:1 典型的回溯问题,罗列所有起点+回溯回溯:一开始就对当前遍历元素的正确和错误状态指出,访问标记一定要先设置,然后回溯结束,重置回溯开始部分会检查位置是否超出,则递归时无需再检查,这样是重复处理,而且会导致错误bool dfs(vector<vector<char>>& board, string word, int pos ,int curRow , int curCol , vector<vector<int>>& visited){//找到结果,返回trueif(pos == word.length()){return true;}int colMax = board.at(0).size();//x最大值为列数int rowMax = board.size();//y最大值为行数if(curRow < 0 || curRow >= rowMax || curCol < 0 || curCol >= colMax){return false;}if(board.at(curRow).at(curCol) != word.at(pos)){//需要回溯return false;}//说明当前是可以继续向下操作的,需要设置访问标记.但是如果是由字符不等,则不需要设置访问标记,因为后续还可能用到if(visited.at(curRow).at(curCol)){return false;}visited.at(curRow).at(curCol) = 1;//部分先成功后失败的字符访问标记可能会导致后续查找失败,这里需要重新设置bool isOk = dfs(board , word , pos + 1 , curRow + 1 , curCol , visited) || dfs(board , word , pos + 1 , curRow - 1 , curCol , visited) ||dfs(board , word , pos + 1 , curRow , curCol + 1 , visited) ||dfs(board , word , pos + 1 , curRow , curCol - 1 , visited);visited.at(curRow).at(curCol) = 0;//回溯需要return isOk;}*/int g_next[][2] = {{-1 , 0},//上{1 , 0},//下{0, -1},//左{0,1}//右}; class Solution {public://, vector< vector<int> >& visitedbool dfs2(vector<vector<char>>& board, string word, int pos ,int curRow , int curCol , vector<vector<int>>& visited){//找到结果,返回trueif(pos == word.length()){return true;}int row;int col;int colMax = board.at(0).size();//x最大值为列数int rowMax = board.size();//y最大值为行数if(curRow < 0 || curRow >= rowMax || curCol < 0 || curCol >= colMax){return false;}//是否访问过不能放在后续中,这是对当前元素判定的条件//如果以(x,y)处为起点的字符已经访问过,表示不可能,则直接跳过,因为一个元素只能用一次if(visited.at(curRow).at(curCol)){return false;}//说明当前位置不行,为了复用位置,需要重新设定该位置为未访问visited.at(curRow).at(curCol) = 1;bool isFind = true;//需要先选定一个字符,进行比较//对四个方向遍历//如果当前位置字符与pos位置上字符相等,就尝试从4个方向对下一个字符处理,否则,应该重新设定新的起始位置(也是4个方向,这个需要标记数组)if(board.at(curRow).at(curCol) != word.at(pos)){//需要回溯return false;}//当前字符与字符串中对应字符,不等,需要重新选定起点else{for(int i = 0 ; i < 4 ; i++){row = curRow + g_next[i][0];col = curCol + g_next[i][1];//范围校验不需要,//如果发现pos == word.length() - 1,也算正确,避免只有一行一列导致不能继续遍历情况,会导致有的情况不能处理//尝试继续访问bool isOk = dfs(board , word , pos + 1 , row , col ,visited);//如果从当前位置继续向下不可能,就应该换一个方向处理if(isOk){return true;}}}//说明当前位置不行,为了复用位置,需要重新设定该位置为未访问visited.at(curRow).at(curCol) = 0;//防止一行一列因为不能上下左右搜索而被误认为是找不到return false;}bool dfs(vector<vector<char>>& board, string word, int pos ,int curRow , int curCol , vector<vector<int>>& visited){//找到结果,返回trueif(pos == word.length()){return true;}int colMax = board.at(0).size();//x最大值为列数int rowMax = board.size();//y最大值为行数if(curRow < 0 || curRow >= rowMax || curCol < 0 || curCol >= colMax){return false;}if(board.at(curRow).at(curCol) != word.at(pos)){//需要回溯return false;}//说明当前是可以继续向下操作的,需要设置访问标记.但是如果是由字符不等,则不需要设置访问标记,因为后续还可能用到if(visited.at(curRow).at(curCol)){return false;}visited.at(curRow).at(curCol) = 1;//部分先成功后失败的字符访问标记可能会导致后续查找失败,这里需要重新设置bool isOk = dfs(board , word , pos + 1 , curRow + 1 , curCol , visited) || dfs(board , word , pos + 1 , curRow - 1 , curCol , visited) ||dfs(board , word , pos + 1 , curRow , curCol + 1 , visited) ||dfs(board , word , pos + 1 , curRow , curCol - 1 , visited);visited.at(curRow).at(curCol) = 0;//回溯需要return isOk;}    bool exist(vector<vector<char>>& board, string word) {if(board.empty() || word.empty()){return false;}int row = board.size();int col = board.at(0).size();//罗列所有可能的起始位置bool isOk;//设定访问标记vector< vector<int> > visited( row , vector<int>(col , 0) );vector< vector<int> > visitedTemp;int pos;for(int i = 0; i < row ; i++){for(int j = 0 ; j < col; j++){//每次重新除法,都需要重新设定访问标记visitedTemp = visited;pos = 0;isOk = dfs(board , word , pos , i , j , visitedTemp);if(isOk){return true;}}}return false;    }};void process(){ //vector<string> nums; string value; int num; Solution solution; vector<int> result; vector< vector<char> > chars; int len = 0; string word; while(cin >> num >> word ) { chars.clear(); for(int i = 0 ; i < num ; i++) { cin >> value; len = value.length(); vector<char> values; for(int j = 0 ; j < len ; j++) { values.push_back(value.at(j)); } chars.push_back(values); } bool isOk = solution.exist(chars , word); if(isOk) { cout << "true" << endl; } else { cout << "false" << endl; } }}int main(int argc , char* argv[]){process();getchar();return 0;}

0 0