这是一个需要针对时间进行优化的面试问题。
假设你有一个二维数组,并且你有一个字符串说"亚马逊"在数组内,使得各个字符可以从左到右,从右到左,从上到下,从下到上呈现。
我将用例子解释:
char[][] a = {
{B,B,A,B,B,N},
{B,B,M,B,B,O},
{B,B,A,B,B,Z},
{N,O,Z,B,B,A},
{B,B,B,B,B,M},
{B,B,B,B,B,A}
};
上面的Array有两个Amazon Strings。您需要返回此类字符串的数量。
答案 0 :(得分:2)
我做了一个简单的bfs,每次字符串toFind的第一个字符(在你的情况下是AMAZON)匹配2D数组中的一个字符。 一个简单的访问2D数组用于在一次迭代中检查标记的字符:
public class FindStrings {
private static int count = 0; // Final Count
public static void find(Character[][] a, String toFind) {
int rows = a.length;
int col = a[0].length;
boolean[][] visited = new boolean[a.length][a[0].length];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < col; j++) {
if (a[i][j] == toFind.charAt(0)) {
findUtil(visited, a, i, j, 0, toFind, new StringBuilder(), rows - 1, col - 1,new ArrayList<String>());
visited[i][j] = false;
}
}
}
}
private static void findUtil(boolean[][] visited, Character[][] a, int i, int j, int index, String toFind, StringBuilder result, int R, int C,ArrayList<String> list) {
result.append(a[i][j]);
//This list just prints the entire Path
list.add(i+"-"+j);
if (index == toFind.length() - 1 && result.toString().equals(toFind)) {
System.out.println(list.toString());
count++;
return;
}
visited[i][j] = true; // Just to mark the character so that one character is not visited twice for a string match
int nextIndex = index + 1; //Next index of the String to be compared
int nextR, nextC;
//Down
if (i + 1 >= 0 && j >= 0 && i + 1 <= R && j <= C && !visited[i + 1][j] && a[i + 1][j] == toFind.charAt(nextIndex)) {
nextR = i + 1;
nextC = j;
findUtil(visited, a, nextR, nextC, nextIndex, toFind, new StringBuilder(result), R, C,new ArrayList<>(list));
//Every time we are done with the next character in the 2D Array we mark it visited
visited[nextR][nextC] = false;
}
//Right
if (i >= 0 && j + 1 >= 0 && i <= R && j + 1 <= C && !visited[i][j + 1] && a[i][j + 1] == toFind.charAt(nextIndex)) {
nextR = i;
nextC = j + 1;
findUtil(visited, a, nextR, nextC, nextIndex, toFind, new StringBuilder(result), R, C,new ArrayList<>(list));
visited[nextR][nextC] = false;
}
//Left
if (i >= 0 && j - 1 >= 0 && i <= R && j - 1 <= C && !visited[i][j - 1] && a[i][j - 1] == toFind.charAt(nextIndex)) {
nextR = i;
nextC = j - 1;
findUtil(visited, a, nextR, nextC, nextIndex, toFind, new StringBuilder(result), R, C,new ArrayList<>(list));
visited[nextR][nextC] = false;
}
//Up
if (i - 1 >= 0 && j >= 0 && i - 1 <= R && j <= C && !visited[i - 1][j] && a[i - 1][j] == toFind.charAt(nextIndex)) {
nextR = i - 1;
nextC = j;
findUtil(visited, a, nextR, nextC, nextIndex, toFind, new StringBuilder(result), R, C,new ArrayList<>(list));
visited[nextR][nextC] = false;
}
}
public static int getCount() {
return count;
}
public static void main(String[] args) {
Character[][] a = new Character[][]{
{'B', 'B', 'A', 'B', 'B', 'N'},
{'B', 'B', 'M', 'B', 'B', 'O'},
{'B', 'B', 'A', 'B', 'B', 'Z'},
{'B', 'O', 'Z', 'O', 'N', 'A'},
{'B', 'B', 'O', 'Z', 'B', 'M'},
{'B', 'B', 'N', 'A', 'M', 'A'}
};
String toFind = "AMAZON";
find(a, toFind);
System.out.println(getCount());
}
答案 1 :(得分:1)
您可以从具有“A”的矩阵的每个单元格运行BFS,并计算可以构建Amazon的方式。最后将它们全部添加。
边缘: 如果相邻(上,下,左,右)节点(单元)包含亚马逊的下一个字符,则该节点(单元)具有来自当前节点(单元)的有向边。 例如,具有“N”的所有相邻节点具有来自具有“O”的节点的有向边缘。
答案 2 :(得分:1)
你只举了一个例子。如果:
然后你只需要计算那些不重复的字母中有多少。例如,使用&AMAZON&#39;,您只需计算多少&#39; Z&#39; (或者&#39; M&#39;或者&#39; O&#39;或者&#39; N&#39;)在数组中。
这不像路径寻找算法那么通用,但肯定更快。
答案 3 :(得分:1)
从矩阵[i,j]开始,尝试跟踪亚马逊&#39;使用所有四个方向
一个。您可以使用BFS或DFS
湾如果找到,将计数增加1
℃。如果没有找到,请继续
时间复杂度= O(N ^ 2 + N){使用DFS}
答案 4 :(得分:1)
制作一个三维表格,矩阵中的每个位置都指代一个表示字母表中每个字母的数组。从顶部,从左到右,从右到左,逐行执行两次迭代:如果字符串存在,您将遇到其第一个或最后一个字母(唯一可以遇到中间字母的方法是,如果您&#39;已经看过其连线比赛的第一部分或最后一部分了。汇总左右发现,但将下面元素的位置表示在表示下一个可能字符的索引处,该字符包含当前长度和方向。如果遇到表匹配,将其转换为完全匹配或另一部分匹配(每个此类字母+位置单元格可以保存多个匹配)。
答案 5 :(得分:0)
我编写了一个解决这个问题的java代码
但就时间复杂度而言,它是一种昂贵的解决方案
当我遍历2d阵列扫描时,A&#39;然后从那个元素我遍历4个方向扫描M然后A扫描等等
因此,如果我们假设阵列的1次扫描是n ^ 2,则最糟糕的情况 我们扫描的单词的长度是K
将是
O(N ^ 2 * K ^ 4)这里的4是我们要搜索的4个方向
这是完全运行的类
public class Treetest {
public static void main(String[] args) {
char[][] a = {
{'B', 'B', 'A', 'B', 'B', 'N'},
{'B', 'B', 'M', 'B', 'B', 'O'},
{'B', 'B', 'A', 'B', 'B', 'Z'},
{'N', 'O', 'Z', 'A', 'M', 'A'},
//{'N', 'O', 'Z', 'B', 'B', 'A'},
{'B', 'B', 'B', 'B', 'B', 'M'},
{'B', 'B', 'B', 'B', 'B', 'A'}
};
int vertical = 0;
int horiz = 0;
int solutioncount = 0;
for (char[] horizantal : a) {
for (char element : horizantal) {
if (element == 'A') {
if (findnextChar(horiz, vertical, "A", a))
solutioncount++;
}
horiz++;
}
horiz = 0;
vertical++;
}
System.out.println("Solution Count is : " + solutioncount);
}
public static boolean findnextChar(int posx, int posy, String currentFind, char[][] a) {
char nextchar = 0;
boolean checkMatch = false;
switch (currentFind) {
case "A":
nextchar = 'M';
break;
case "AM":
nextchar = 'A';
break;
case "AMA":
nextchar = 'Z';
break;
case "AMAZ":
nextchar = 'O';
break;
case "AMAZO":
nextchar = 'N';
checkMatch = true;
break;
}
String nextString = currentFind + String.valueOf(nextchar);
if (posx - 1 >= 0 && a[posy][posx - 1] == nextchar) {
if (checkMatch) {
return true;
}
return findnextChar(posx - 1, posy, nextString, a);
}
if (posx + 1 <= a[0].length - 1 && a[posy][posx + 1] == nextchar) {
if (checkMatch) {
return true;
}
return findnextChar(posx + 1, posy, nextString, a);
}
if (posy - 1 >= 0 && a[posy - 1][posx] == nextchar) {
if (checkMatch) {
return true;
}
return findnextChar(posx, posy - 1, nextString, a);
}
if (posy + 1 <= a[0].length - 1 && a[posy + 1][posx] == nextchar) {
if (checkMatch) {
return true;
}
return findnextChar(posx, posy + 1, nextString, a);
}
return false;
}
}