1. 程式人生 > >劍指offer面試題12:矩陣中的路徑(Java實現)

劍指offer面試題12:矩陣中的路徑(Java實現)

題目:請設計一個函式,用來判斷在一個矩陣中是否存在一條包含某字串所有字元的路徑。路徑可以從矩陣中的任意一個格子開始,每一步可以在矩陣中向左,向右,向上,向下移動一個格子。如果一條路徑經過了矩陣中的某一個格子,則該路徑不能再進入該格子。 例如 a b c e s f c s a d e e 矩陣中包含一條字串”bcced”的路徑,但是矩陣中不包含”abcb”路徑,因為字串的第一個字元b佔據了矩陣中的第一行第二個格子之後,路徑不能再次進入該格子。

思路:

這是一個可以用回朔法解決的典型題。

  1. 首先,在矩陣中任選一個格子作為路徑的起點。如果路徑上的第i個字元不是ch,那麼這個格子不可能處在路徑上的第i個位置。如果路徑上的第i個字元正好是ch,那麼往相鄰的格子尋找路徑上的第i+1個字元。除在矩陣邊界上的格子之外,其他格子都有4個相鄰的格子。重複這個過程直到路徑上的所有字元都在矩陣中找到相應的位置。
  2. 由於回朔法的遞迴特性,路徑可以被開成一個棧。當在矩陣中定位了路徑中前n個字元的位置之後,在與第n個字元對應的格子的周圍都沒有找到第n+1個字元,這個時候只要在路徑上回到第n-1個字元,重新定位第n個字元。
  3. 由於路徑不能重複進入矩陣的格子,還需要定義和字元矩陣大小一樣的布林值矩陣,用來標識路徑是否已經進入每個格子。 當矩陣中座標為(row,col)的格子和路徑字串中相應的字元一樣時,從4個相鄰的格子(row,col-1),(row-1,col),(row,col+1)以及(row+1,col)中去定位路徑字串中下一個字元
  4. 如果4個相鄰的格子都沒有匹配字串中下一個的字元,表明當前路徑字串中字元在矩陣中的定位不正確,我們需要回到前一個,然後重新定位。
  5. 一直重複這個過程,直到路徑字串上所有字元都在矩陣中找到合適的位置

測試用例:

  1. 功能測試:在多行多列矩陣中存在或者不存在路徑。
  2. 邊界測試:矩陣只有一行或一列;矩陣和路徑中是所有字母都是相同的。
  3. 負面測試:輸入空指標。
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;
	}
}