劍指offer面試題12:矩陣中的路徑(Java實現)
阿新 • • 發佈:2019-01-06
題目:請設計一個函式,用來判斷在一個矩陣中是否存在一條包含某字串所有字元的路徑。路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。如果一條路徑經過了矩陣中的某一個格子,則該路徑不能再進入該格子。 例如 a b c e s f c s a d e e 矩陣中包含一條字串”bcced”的路徑,但是矩陣中不包含”abcb”路徑,因為字串的第一個字元b佔據了矩陣中的第一行第二個格子之後,路徑不能再次進入該格子。
思路:
這是一個可以用回朔法解決的典型題。
- 首先,在矩陣中任選一個格子作為路徑的起點。如果路徑上的第i個字元不是ch,那麼這個格子不可能處在路徑上的第i個位置。如果路徑上的第i個字元正好是ch,那麼往相鄰的格子尋找路徑上的第i+1個字元。除在矩陣邊界上的格子之外,其他格子都有4個相鄰的格子。重複這個過程直到路徑上的所有字元都在矩陣中找到相應的位置。
- 由於回朔法的遞迴特性,路徑可以被開成一個棧。當在矩陣中定位了路徑中前n個字元的位置之後,在與第n個字元對應的格子的周圍都沒有找到第n+1個字元,這個時候只要在路徑上回到第n-1個字元,重新定位第n個字元。
- 由於路徑不能重複進入矩陣的格子,還需要定義和字元矩陣大小一樣的布林值矩陣,用來標識路徑是否已經進入每個格子。 當矩陣中座標為(row,col)的格子和路徑字串中相應的字元一樣時,從4個相鄰的格子(row,col-1),(row-1,col),(row,col+1)以及(row+1,col)中去定位路徑字串中下一個字元
- 如果4個相鄰的格子都沒有匹配字串中下一個的字元,表明當前路徑字串中字元在矩陣中的定位不正確,我們需要回到前一個,然後重新定位。
- 一直重複這個過程,直到路徑字串上所有字元都在矩陣中找到合適的位置
測試用例:
- 功能測試:在多行多列矩陣中存在或者不存在路徑。
- 邊界測試:矩陣只有一行或一列;矩陣和路徑中是所有字母都是相同的。
- 負面測試:輸入空指標。
public class test_twelve { public boolean hasPath(char[] matrix, int rows, int cols, char[] str){ if(matrix == null || rows<=0 || cols<=0 || str == null)return false; if(str.length == 0)return true; boolean[] visited = new boolean[matrix.length]; //用來識別路徑是否已經進入每個格子 for(int i=0; i<rows;i++){ //兩個for迴圈遍歷矩陣 for(int j=0;j<cols;j++){ if(findPath(matrix,rows,cols,i,j,str,0,visited)) //呼叫尋找路徑的函式 return true; } } return false; } //定義findPath函式,通過遞迴的方式來遍歷每一個字元上下左右四個字元 private boolean findPath(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, boolean[] visited) { if(i<0 || i>=rows ||j<0 || j>=cols || matrix[i*cols+j]!=str[k] || visited[i*cols+j]){ return false; } if(k == str.length-1){ return true; } if(findPath(matrix,rows,cols,i-1,j,str,k+1,visited) //通過遞迴的方式尋找下一個字元 || findPath(matrix,rows,cols,i,j-1,str,k+1,visited) || findPath(matrix,rows,cols,i+1,j,str,k+1,visited) || findPath(matrix,rows,cols,i,j+1,str,k+1,visited) ){ return true; } visited[i*cols+j] = false; return false; } }