解题思路
能进则进,进不了则退,退不了则换,典型的回溯法思想。只是在矩阵中寻找路径使得这道题变得复杂了,那么我们就从先从简单的地方入手,一层一层的剥开这道题的套路。
(1)寻找返回条件: 在矩阵中找到一条路径上的字符组合和目标字符串相同时,则查找成功,如果有一次查找成功,则返回true,停止进行查找。两种方法:
①可以设置一个StringBuilder,每次找到一个匹配的字符便添加该字符,同时记录当前目标字符串的查找位置index,每匹配到一个字符便令index++;
②因为每当递归深度增加一层,就说明匹配到了一个字符,可以用一个count来记录当前的递归深度,当count=目标字符串长度时(count初始化为1,若count初始化为0,则条件为count=目标字符串长度-1),则证明已匹配到全部字符,查找成功。
这里我们采用第二种方法。
(2)寻找匹配条件: 假设当前位置为board[i][j],目标字符串(word)的查找位置为index,那么匹配条件就是board[i][j]=word.charAt(index)。
(3)寻找递归路径: 每次站在一个新的起点,在你面前都会有四条路可以选择,上、下、左、右,这就意味着每一次你都需要做四次选择。
设起点为board[i][j],下一步可以是board[i-1][j],board[i+1][j],board[i][j-1],board[i][j+1]
但是你要保证两点:①好马不走回头路;②不能撞墙(边界问题)。
对于①,
可以用一个和board同样大小的布尔类型数组flag来记录board[i][j]是否已被访问,起点为board[i][j],将flag[i][j]设为true(初始化都为false),把匹配条件改成
(board[i][j]==word.charAt(index)&&flag[i][j])
还可以将board[i][j]的字符替换成永远不会在目标字符串中出现的字符,这样便可以避免走回头路了。
对于②,在进行选择前设置一些边界条件就可以了:
(i-1>=0)–>board[i-1][j],
(i+1<board.length)–>board[i+1][j],
(j-1>=0)–>board[i][j-1],
(j+1<board[0].length)–>board[i][j+1]
(4)撤销选择: 在选择完路径后,一定要记得把之前做的改变改回去,对于利用flag记录该位置是否被访问过的方法,将flag[i][j]恢复为false;对于直接改变board[i][j]的方法,要改回原来的值。
(5)递归函数dfs的返回值: 当有一条路径可以匹配到目标字符串时,返回true;当该路径不可再进行时返回false。(通过这前五步,就