題目描述:
請設計一個函數,用來判斷在一個矩陣中是否存在一條包含某字符串所有字符的路徑。路徑可以從矩陣中任意一格開始,
每一步可以在矩陣中向左右上下移動一格。如果一條路徑經過了矩陣的某一格,那麼該路徑不能再次進入該格子。
例如,在下面的3x4的矩陣中包含一條字符串“bcced"的路徑。但該矩陣中不包含字符串"abcd",的路徑,
因爲字符串的第一個字符b佔據了矩陣中的第一行第二個格子後,路徑不能再次進入這個格子。
a b c e
s f c s
a d e e
輸入描述:請輸入矩陣的行數:
3
請輸入矩陣的列數:
4
請輸入一個矩陣字符串,不包含空格:
abcesfcsadee
請輸入要查詢的字符串:
bcced
程序輸出:矩陣中是否包含該字符串:
true
思路:
利用回溯法。首先對所整個矩陣遍歷,找到第一個字符,然後向上下左右查找下一個字符,由於每個字符都是相同的判斷方法(先判斷當前字符是否相等,再向四周查找),因此採用遞歸函數。由於字符查找過後不能重複進入,所以還要定義一個與字符矩陣大小相同的布爾值矩陣,進入過的格子標記爲true。如果不滿足的情況下,需要進行回溯,此時,要將當前位置的布爾值標記回false。(所謂的回溯無非就是對使用過的字符進行標記和處理後的去標記)
代碼:
package offer01;
import java.util.Arrays;
public class TestNo66 {
public static void main(String[] args) {
//字符串轉爲字符數組,使用toCharArray()方法
char[] matrix = "ABTGCFCSJDEH".toCharArray();
int rows = 3;
int cols = 4;
char[] str = "BFCTB".toCharArray();
if(!new TestNo66().hasPath(matrix,rows,cols,str))
System.out.println("true");
else
System.out.println("false");
}
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
if(rows <= 0 || str.length <= 0)
return true;
//初始化一個和矩陣大小一樣的boolean矩陣,爲了記錄是否走過
boolean[] visited = new boolean[rows * cols];
Arrays.fill(visited,false);
int index = 0;
for(int i = 0;i<rows;i++){
for(int j = 0;j<cols;j++){
if(path(matrix,visited,rows,cols,i,j,str,index)){
return true;
}
}
}
return false;
}
public boolean path(char[] matrix,boolean[] visited,int rows,int cols,int i,int j,char[] str,int index){
//遞歸退出條件若能達到字符串末尾,則說明訪問序列正確
if(index == str.length)
return true;
boolean hashpath = false;
//1、i,j不能越界 2、結點未訪問過 3、結點字母與字符串需要的字母一致
if(i >= 0 && i<rows && j<cols && j>=0 && !visited[i*cols + j] && matrix[i*cols +j] == str[index]){
index++;
//二維數組下標的計算:row*cols+col,
visited[i*cols + j] = true;
hashpath = path(matrix,visited,rows,cols,i+1,j,str,index)||
path(matrix,visited,rows,cols,i-1,j,str,index)||
path(matrix,visited,rows,cols,i,j+1,str,index)||
path(matrix,visited,rows,cols,i,j-1,str,index);
//回溯。若不存在該路徑,則需要將路徑點都重置
if(!hashpath){
index--;
visited[i*cols +j] =false;
}
}
return hashpath;
}
}