JZ12 矩陣中的路徑
描述
請設計一個函式,用來判斷在一個n乘m的矩陣中是否存在一條包含某長度為len的字串所有字元的路徑。路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。如果一條路徑經過了矩陣中的某一個格子,則該路徑不能再進入該格子。例如矩陣中包含一條字串"bcced"的路徑,但是矩陣中不包含"abcb"路徑,因為字串的第一個字元b佔據了矩陣中的第一行第二個格子之後,路徑不能再次進入該格子。
示例1
輸入:[[a,b,c,e],[s,f,c,s],[a,d,e,e]],"abcced"返回值:true
分析
先說一下這道題使用的方法是深度優先演算法dfs和回溯
dfs
深度優先演算法就是一種圖的遍歷演算法,簡單來說就是從某個頂點的分支開始,儘可能深沿圖的深度訪問沒有訪問過的節點直至此分支全都訪問完畢
解題
本人程式碼使用非遞迴實現了dfs+回溯,其中,一開始需要尋找矩陣中所有符合初始節點的字元位置,通過兩個while迴圈完成演算法
程式碼
/**
* 程式碼中的類名、方法名、引數名已經指定,請勿修改,直接返回方法規定的值即可
*
*
* @param matrix char字元型二維陣列
* @param word string字串
* @return bool布林型
*/
public boolean hasPath (char[][] matrix, String word) {
/**
* 訪問節點物件
*/
class HasPathNode{
char letter;
int x;
int y;
//標誌其節點周圍是否訪問過
boolean visitUp = false;
boolean visitDown = false;
boolean visitLeft = false;
boolean visitRight = false;
HasPathNode(char letter,int x,int y) {
this.letter = letter;
this.x = x;
this.y = y;
//給出邊界節點的判定
if (x == 0){
this.visitUp = true;
}
//給出邊界節點的判定
if (y == 0) {
this.visitLeft = true;
}
//給出邊界節點的判定
if (x == matrix.length -1) {
this.visitDown = true;
}
//給出邊界節點的判定
if (y == matrix[0].length -1) {
this.visitRight = true;
}
}
}
// write code here
char words[] = word.toCharArray();
//把需要判斷的字元放入連結串列
LinkedList<Character> wordsQueue = new LinkedList<>();
for (char item : words) {
wordsQueue.offer(item);
}
//已經經過判斷的字元
Stack<Character> usedWords = new Stack<>();
//符合條件的初始節點
Queue<HasPathNode> firstLetterQueue = new LinkedList<>();
//尋找符合條件的初始節點
for (int i = 0;i<matrix.length;i++) {
for (int j = 0;j<matrix[0].length;j++) {
if (matrix[i][j] == wordsQueue.peek()) {
HasPathNode node = new HasPathNode(matrix[i][j],i,j);
firstLetterQueue.offer(node);
}
}
}
//如果沒有符合的則返回false
if (firstLetterQueue.size() == 0)
return false;
//初始節點放入已使用
usedWords.push(wordsQueue.poll());
while (firstLetterQueue.size() >0) {
Stack<HasPathNode> nodeStack = new Stack<>();
nodeStack.push(firstLetterQueue.poll());
while (nodeStack.size() >0) {
if (nodeStack.peek().visitUp == false && matrix[nodeStack.peek().x - 1][nodeStack.peek().y] == wordsQueue.peek()) {
//上
HasPathNode node = new HasPathNode(wordsQueue.peek(),nodeStack.peek().x - 1,nodeStack.peek().y);
nodeStack.peek().visitUp = true;
nodeStack.push(node);
nodeStack.peek().visitDown = true;
usedWords.push(wordsQueue.poll());
}else if (nodeStack.peek().visitDown == false && matrix[nodeStack.peek().x + 1][nodeStack.peek().y] == wordsQueue.peek()) {
//下
HasPathNode node = new HasPathNode(wordsQueue.peek(),nodeStack.peek().x + 1,nodeStack.peek().y);
nodeStack.peek().visitDown = true;
nodeStack.push(node);
nodeStack.peek().visitUp = true;
usedWords.push(wordsQueue.poll());
}else if (nodeStack.peek().visitLeft == false && matrix[nodeStack.peek().x][nodeStack.peek().y - 1] == wordsQueue.peek()) {
//左
HasPathNode node = new HasPathNode(wordsQueue.peek(),nodeStack.peek().x,nodeStack.peek().y - 1);
nodeStack.peek().visitLeft = true;
nodeStack.push(node);
nodeStack.peek().visitRight = true;
usedWords.push(wordsQueue.poll());
}else if (nodeStack.peek().visitRight == false && matrix[nodeStack.peek().x][nodeStack.peek().y + 1] == wordsQueue.peek()) {
//右
HasPathNode node = new HasPathNode(wordsQueue.peek(),nodeStack.peek().x,nodeStack.peek().y + 1);
nodeStack.peek().visitRight = true;
nodeStack.push(node);
nodeStack.peek().visitLeft = true;
usedWords.push(wordsQueue.poll());
}else {
nodeStack.pop();
if (usedWords.size() != 1) {
wordsQueue.addFirst(usedWords.pop());
}
}
if (wordsQueue.size() == 0)
return true;
}
}
return false;
}