史上最詳細深度優先搜尋遍歷(DFS)程式碼,力扣(LeetCode)刷題第79題:單詞搜尋!
阿新 • • 發佈:2020-12-11
技術標籤:力扣刷題筆記演算法javaleetcode資料結構dfs
文章目錄
前言
一、題目介紹
給定一個二維網格和一個單詞,找出該單詞是否存在於網格中。
單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重複使用。
示例 1:
示例:
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
給定 word = "ABCCED", 返回 true
給定 word = "SEE", 返回 true
給定 word = "ABCB", 返回 false
二、解題思路
1.分析題目
針對題目給出的介紹和示例,可以分析,題目是想讓我們查詢一個矩陣中是否可以找到給出的單詞,也就是所謂的單詞搜尋,我們可以思考一下,其實也就是搜尋,我們把矩陣想象成圖,也就是從一個圖中搜索一個單詞,可以嘗試圖的搜尋演算法,深度和廣度優先搜尋遍歷。
2.思路與演算法
當確定完是搜尋的話,可以嘗試深度搜索遍歷。
我們可以嘗試從矩陣的每一個位置開始搜尋,如果當前位置的字元和單詞開始字元相同,則單詞字元後移一位,矩陣往下一個方位搜尋,一共有四個可供選擇的方向。如果一直下去都可以搜到對應的矩陣字元與單詞字元相匹配,則就返回true,如果有一個字元不匹配,則返回false,下次從下一個矩陣位置開始從0字元開始搜尋,一直遍歷完所有的矩陣位置。
對每次遍歷,如果當前位置已經遍歷過需要進行標記,可以使用一個同矩陣大小的標記矩陣visited[][]。
3.程式碼部分
Java程式碼詳細註釋
class Solution {
public boolean exist(char[][] board, String word) {
//使用深度優先搜尋遍歷
int row = board.length;
int low = board[0].length;//獲取陣列的大小
//設定一個判斷陣列,判斷當前陣列是否已經訪問過
boolean [][]visited = new boolean[row][low];//預設的是false
for(int i = 0;i<row;i++){
for(int j = 0;j<low;j++){
boolean flag = check(visited,board,i,j,word,0);//依次檢查當前節點
if (flag){//找到單詞的匹配,返回true
return true;
}
}
}
return false;//沒找到返回false
}
//檢查函式
public boolean check(boolean [][]visited,char[][]board,int i,int j,String word,int k){
//先檢查當前陣列所對應的節點是否存在單詞的字母
if(board[i][j]!=word.charAt(k)){
return false;
}
//如果當前已經遍歷到單詞的最後一個字母,則直接返回
else if(k == word.length()-1){
return true;//也就是單詞匹配成功
}
visited[i][j] = true;//已經比對過當前節點,而且說明當前點對應的字母匹配上了。
boolean result = false;//判斷引數
int[][] directions = {{0,1},{0,-1},{1,0},{-1,0}};//當遍歷到一個節點後,下次可以往四個方向查詢,{0,1}代表東邊,{0,-1}代表北邊,{1,0}代表南邊{-1,0}代表西邊。
//下一步,查詢四周的四個點是否存在匹配的字母
for(int[]dir:directions){//使用增強for,直接獲取當前directions中的資料,並不是獲取索引。
int newi = i + dir[0],newj = j + dir[1];//新的查詢節點
if(newi>=0 && newi<board.length &&newj>=0 && newj<board[0].length){//邊界判斷
if(visited[newi][newj]!=true){//判斷當前節點是否訪問,如果沒有在進行下一步判斷
boolean flag = check(visited,board,newi,newj,word,k+1);
if(flag){//如果返回的是true,說明是匹配的。
result = true;
break;
}
}
}
}
visited[i][j] = false;//檢查完當前節點需要把其重新變回false,便於下次檢查使用
return result;//返回結果
}
}
三、總結
提示:針對個別型別的題目,可以直接套用深度優先搜尋遍歷,其實可以總結出這種型別題目的模板,也就是深度優先搜尋遍歷的模板。
dfs(){
// 第一步,檢查下標是否滿足條件
// 第二步:檢查是否被訪問過,或者是否滿足當前匹配條件
// 第三步:檢查是否滿足返回結果條件
// 第四步:都沒有返回,說明應該進行下一步遞迴
// 標記
dfs(下一次)
// 回溯
}
main() {
for (對所有可能情況) {
dfs()
}
}
記錄時間:2020年12月8日