|
|
|
|
package class08;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 给定一个char[][] matrix,也就是char类型的二维数组,再给定一个字符串word,
|
|
|
|
|
* 可以从任何一个某个位置出发,可以走上下左右,能不能找到word?
|
|
|
|
|
* 比如:
|
|
|
|
|
* char[][] m = {
|
|
|
|
|
* { 'a', 'b', 'z' },
|
|
|
|
|
* { 'c', 'd', 'o' },
|
|
|
|
|
* { 'f', 'e', 'o' },
|
|
|
|
|
* };
|
|
|
|
|
* word = "zooe"
|
|
|
|
|
* 是可以找到的
|
|
|
|
|
*
|
|
|
|
|
* 设定1:可以走重复路的情况下,返回能不能找到
|
|
|
|
|
* 比如,word = "zoooz",是可以找到的,z -> o -> o -> o -> z,因为允许走一条路径中已经走过的字符
|
|
|
|
|
*
|
|
|
|
|
* 设定2:不可以走重复路的情况下,返回能不能找到
|
|
|
|
|
* 比如,word = "zoooz",是不可以找到的,因为允许走一条路径中已经走过的字符不能重复走
|
|
|
|
|
*
|
|
|
|
|
* 写出两种设定下的code
|
|
|
|
|
*
|
|
|
|
|
* */
|
|
|
|
|
public class Code03_FindWordInMatrix {
|
|
|
|
|
|
|
|
|
|
// 可以走重复的设定
|
|
|
|
|
public static boolean findWord1(char[][] m, String word) {
|
|
|
|
|
if (word == null || word.equals("")) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
char[] w = word.toCharArray();
|
|
|
|
|
int N = m.length;
|
|
|
|
|
int M = m[0].length;
|
|
|
|
|
int len = w.length;
|
|
|
|
|
// dp[i][j][k]表示:必须以m[i][j]这个字符结尾的情况下,能不能找到w[0...k]这个前缀串
|
|
|
|
|
boolean[][][] dp = new boolean[N][M][len];
|
|
|
|
|
for (int i = 0; i < N; i++) {
|
|
|
|
|
for (int j = 0; j < M; j++) {
|
|
|
|
|
dp[i][j][0] = m[i][j] == w[0];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (int k = 1; k < len; k++) {
|
|
|
|
|
for (int i = 0; i < N; i++) {
|
|
|
|
|
for (int j = 0; j < M; j++) {
|
|
|
|
|
dp[i][j][k] = (m[i][j] == w[k] && checkPrevious(dp, i, j, k));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < N; i++) {
|
|
|
|
|
for (int j = 0; j < M; j++) {
|
|
|
|
|
if (dp[i][j][len - 1]) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 可以走重复路
|
|
|
|
|
// 从m[i][j]这个字符出发,能不能找到str[k...]这个后缀串
|
|
|
|
|
public static boolean canLoop(char[][] m, int i, int j, char[] str, int k) {
|
|
|
|
|
if (k == str.length) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (i == -1 || i == m.length || j == -1 || j == m[0].length || m[i][j] != str[k]) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 不越界!m[i][j] == str[k] 对的上的!
|
|
|
|
|
// str[k+1....]
|
|
|
|
|
boolean ans = false;
|
|
|
|
|
if (canLoop(m, i + 1, j, str, k + 1) || canLoop(m, i - 1, j, str, k + 1) || canLoop(m, i, j + 1, str, k + 1)
|
|
|
|
|
|| canLoop(m, i, j - 1, str, k + 1)) {
|
|
|
|
|
ans = true;
|
|
|
|
|
}
|
|
|
|
|
return ans;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 不能走重复路
|
|
|
|
|
// 从m[i][j]这个字符出发,能不能找到str[k...]这个后缀串
|
|
|
|
|
public static boolean noLoop(char[][] m, int i, int j, char[] str, int k) {
|
|
|
|
|
if (k == str.length) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (i == -1 || i == m.length || j == -1 || j == m[0].length || m[i][j] != str[k]) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 不越界!也不是回头路!m[i][j] == str[k] 也对的上!
|
|
|
|
|
m[i][j] = 0;
|
|
|
|
|
boolean ans = false;
|
|
|
|
|
if (noLoop(m, i + 1, j, str, k + 1) || noLoop(m, i - 1, j, str, k + 1) || noLoop(m, i, j + 1, str, k + 1)
|
|
|
|
|
|| noLoop(m, i, j - 1, str, k + 1)) {
|
|
|
|
|
ans = true;
|
|
|
|
|
}
|
|
|
|
|
m[i][j] = str[k];
|
|
|
|
|
return ans;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static boolean checkPrevious(boolean[][][] dp, int i, int j, int k) {
|
|
|
|
|
boolean up = i > 0 ? (dp[i - 1][j][k - 1]) : false;
|
|
|
|
|
boolean down = i < dp.length - 1 ? (dp[i + 1][j][k - 1]) : false;
|
|
|
|
|
boolean left = j > 0 ? (dp[i][j - 1][k - 1]) : false;
|
|
|
|
|
boolean right = j < dp[0].length - 1 ? (dp[i][j + 1][k - 1]) : false;
|
|
|
|
|
return up || down || left || right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 不可以走重复路的设定
|
|
|
|
|
public static boolean findWord2(char[][] m, String word) {
|
|
|
|
|
if (word == null || word.equals("")) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (m == null || m.length == 0 || m[0] == null || m[0].length == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
char[] w = word.toCharArray();
|
|
|
|
|
for (int i = 0; i < m.length; i++) {
|
|
|
|
|
for (int j = 0; j < m[0].length; j++) {
|
|
|
|
|
if (process(m, i, j, w, 0)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 从m[i][j]这个字符出发,能不能找到w[k...]这个后缀串
|
|
|
|
|
public static boolean process(char[][] m, int i, int j, char[] str, int k) {
|
|
|
|
|
if (k == str.length) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (i == -1 || i == m.length || j == -1 || j == m[0].length || m[i][j] == 0 || m[i][j] != str[k]) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
m[i][j] = 0;
|
|
|
|
|
boolean ans = false;
|
|
|
|
|
if (process(m, i + 1, j, str, k + 1) || process(m, i - 1, j, str, k + 1) || process(m, i, j + 1, str, k + 1)
|
|
|
|
|
|| process(m, i, j - 1, str, k + 1)) {
|
|
|
|
|
ans = true;
|
|
|
|
|
}
|
|
|
|
|
m[i][j] = str[k];
|
|
|
|
|
return ans;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
char[][] m = { { 'a', 'b', 'z' }, { 'c', 'd', 'o' }, { 'f', 'e', 'o' }, };
|
|
|
|
|
String word1 = "zoooz";
|
|
|
|
|
String word2 = "zoo";
|
|
|
|
|
// 可以走重复路的设定
|
|
|
|
|
System.out.println(findWord1(m, word1));
|
|
|
|
|
System.out.println(findWord1(m, word2));
|
|
|
|
|
// 不可以走重复路的设定
|
|
|
|
|
System.out.println(findWord2(m, word1));
|
|
|
|
|
System.out.println(findWord2(m, word2));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|