矩阵中的路径
问题要求
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。
示例:
输入:board =
(“A”,“B”,“C”,“E”),
(“S”,“F”,“C”,“S”),
(“A”,“D”,“E”,“E”),
//board定义一个二维数组,此处( 等同于花括号,由于与markdown内置标签冲突,故使用括号代替花括号。
word = “ABCCED”
输出:true
问题分析
本问题是典型的矩阵搜索问题,可使用 深度优先搜索(DFS)+ 剪枝 解决。
算法原理
- 深度优先搜索: 可以理解为暴力法遍历矩阵中所有字符串可能性。DFS 通过递归,先朝一个方向搜到底,再回溯至上个节点,沿另一个方向搜索,以此类推。
- 剪枝: 在搜索中,遇到
这条路不可能和目标字符串匹配成功 的情况(例如:此矩阵元素和目标字符不同、此元素已被访问),则应立即返回,称之为 可行性剪枝 。
算法剖析
- 递归参数: 当前元素在矩阵 board 中的行列索引 i 和 j ,当前目标字符在 word 中的索引 k 。
- 终止条件:
返回 false : ① 行或列索引越界 或 ② 当前矩阵元素与目标字符不同 或 ③ 当前矩阵元素已访问过 (③ 可合并至 ② ) 。
返回 true : 字符串 word 已全部匹配,即 k = length(word) - 1 。
- 递推工作:
标记当前矩阵元素: 将 board[i][j]值暂存于变量 tmp ,并修改为字符 ‘/’ ,代表此元素已访问过,防止之后搜索时重复访问。 搜索下一单元格: 朝当前元素的 上、下、左、右 四个方向开启下层递归,使用 或 连接 (代表只需一条可行路径) ,并记录结果至 res 。 还原当前矩阵元素: 将 tmp 暂存值还原至 board[i][j] 元素。
- 回溯返回值: 返回
res ,代表是否搜索到目标字符串。
代码实现
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class Path_in_Mat { public boolean exists(char[][] boardpanel,String word){ char[] words=word.toCharArray(); for(int i=0;i<boardpanel.length;i++){ for(int j=0;j<boardpanel[0].length;j++){ if(dfs(boardpanel,words,i,j,0)) return true; } } return false; } public boolean dfs(char[][] boardpanel,char[] word,int i,int j,int k){ if(i<0||i>=boardpanel.length||j<0||j>=boardpanel[0].length||boardpanel[i][j]!=word[k]) return false; if(k==word.length-1) return true; char temp=boardpanel[i][j]; boardpanel[i][j]='/'; boolean res=dfs(boardpanel,word,i+1,j,k+1)||dfs(boardpanel,word,i-1,j,k+1)|| dfs(boardpanel,word,i,j+1,k+1)||dfs(boardpanel,word,i,j-1,k+1); boardpanel[i][j]=temp; return res; } public static void main(String[] args){ char[][] boardpanel={{'a','b','c','e'},{'s','f','c','s'},{'a','d','e','e'}}; String words="abcced"; Path_in_Mat path_in_mat=new Path_in_Mat(); System.out.println(path_in_mat.exists(boardpanel,words)); } }
|
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { public: bool exist(vector<vector<char>>& board, string word) { if(board.size() == 0) return false; for (int i=0;i<board.size();i++){ for(int j=0;j<board[0].size();j++){ if (dfs(board,word,i,j,0)){ return true; } } } return false; }
bool dfs(vector<vector<char>>& board, string& word, int i,int j,int length){ if(i>=board.size()||j>=board[0].size()||i<0||j<0||length>=word.size()||word[length]!=board[i][j]){ return false; } if(length==word.size()-1&&word[length]==board[i][j]){ return true; } char temp=board[i][j]; board[i][j]='0'; bool flag=dfs(board,word,i,j+1,length+1)||dfs(board,word,i,j-1,length+1)||dfs(board,word,i+1,j,length+1)||dfs(board,word,i-1,j,length+1); board[i][j]=temp; return flag; } };
|