劍指offer面試題12:矩陣中的路徑(Java版已在牛客網AC)

慕柏發表於2018-12-20

題目

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

思路

這是一個典型的回溯法應用例項,以題目中的例子為例:

  1. 首先在矩陣中任意選擇一個字元ch1作為起點,然後和待查詢的字串中的第i個字元進行比較
  2. 如果不相等,則繼續遍歷矩陣中ch1緊挨著的下一個元素
  3. 如果相等,則對ch1周圍的其他方向進行查詢和待查詢的字串中地i+1個字元相等的字元
  4. 重複上述過程直到待查詢的字串的每一個字元都在矩陣中找到,如果在矩陣中找到了待查詢的字串的前n個字元的位置後,在第n個字元的位置周圍無法找到待查詢字串的第n+1個字元,則需要回退到第n-1個字元的位置上重新選擇方向進行查詢。

注意

  • 除了矩陣邊界的格子外,其他格子都有4個相鄰的格子分別代表著相應的方向
  • 在該演算法中須有一個標誌陣列,用來標誌已經走過的路
  • 標誌陣列中標記走過的格子不能再訪問

程式碼實現

//matrix是一個一維陣列但用來表示二維的矩陣,是不是想問為啥不直接用二維陣列
//博主也想用二維陣列來表示矩陣,但是牛客網上給的引數就一維陣列,博主也很無奈
//row表示矩陣的行數 cols表示矩陣的列數 str表示的是帶查詢的字串
 public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
    {
        if(matrix==null||rows<1||cols<1||str==null)
        {
            return false;
        }
        //visted是一個標誌陣列用來標誌哪些格子已經被訪問過
        boolean[] visted=new boolean[rows*cols];
        //初始化標誌陣列
        for(int i=0;i<visted.length;i++)
        {
            visted[i]=false;
        }
        //用來表示待查詢字串在矩陣中已經找到的字元個數
        Integer pathLength=0;
        //雙重迴圈用來遍歷矩陣尋找待查詢字串的第一個字元 row表示矩陣的當前行數
        //col表示矩陣當前的列數
        for(int row=0;row<rows;row++)
        {
            for(int col=0;col<cols;col++)
            {
            //遞迴查詢待查詢的字串在矩陣中是否存在
                if(hasPathCore(matrix,rows,cols,row,col,str,pathLength,visted))
                {
                    return true;
                }
            }
        }

        return false;
    }
 
    private boolean hasPathCore(char[] matrix,int rows,int cols,int row,int col,char[] str,Integer pathLength,boolean[] visited)
    {
    //如果待查詢的字串的所有字元都在矩陣中找到
        if(pathLength==str.length)
        {
            return true;
        }
        //用來表示在在矩陣中的某一個格子附近是否還能找到待查詢字串的下一個字元
        boolean hasPath=false;
		//如果矩陣當前格子的位置的字元等於待查詢字串的下一個字元
       if(row>=0&&row<rows&&col>=0&&col<cols&&matrix[row*cols+col]==str[pathLength]&&!visited[row*cols+col])
        {
          
            ++pathLength;

            visited[row*cols+col]=true;
            //繼續在該位置的其他方向進行尋找下一個字元
            //左
            hasPath=hasPathCore(matrix,rows,cols,row,col-1,str,pathLength,visited)
            			//上
                    ||hasPathCore(matrix,rows,cols,row-1,col,str,pathLength,visited)
					//右                    
                    ||hasPathCore(matrix,rows,cols,row,col+1,str,pathLength,visited)
				//下
                    ||hasPathCore(matrix,rows,cols,row+1,col,str,pathLength,visited);
            //如果在某個位置上找不到待查詢字串的下一個字元
            if(!hasPath)
            {
            //回退到上一個位置
                --pathLength;
                visited[row*cols+col]=false;
            }
        }
        return hasPath;
    }

相關文章