最近偶然发现了这个面试问题,
给定一个二维字符数组和一个可以在O(1)
时间内搜索单词的字典。需要打印字典中存在的数组中的所有单词。 Word可以在任何方向形成,但必须在数组的任何边缘结束。(不用担心字典)
输入:
a f h u n
e t a i r
a e g g o
t r m l p
输出:
after
hate
hair
air
eat
tea
注意:这里“egg”不是字典单词,因为它不在数组的边缘结束。
我以前见过类似的问题,但从来没有想过一个好的算法来解决这些问题。任何有关如何解决这些问题的帮助(从字符数组中形成单词)都将非常有用。
(我能想到的唯一方法是找到2D数组中所有可能的字符排列,并检查它是否在数组的边缘结束,并检查排列是否是O中字典中的有效字。 (1)时间)
答案 0 :(得分:3)
将数组转换为图形,以便每个单元格[i,j]
与其4个邻居[i+1,j], [i-1,j], [i,j+1], [i,j-1]
中的每一个共享一条边。
然后在每个数组边缘单元格运行DFS,并继续检查字典是否
相反的词就在其中。
答案 1 :(得分:2)
你没有提到关于一个角色只能使用一次的事情 - 所以没有这个限制是“我们能生成k(或更多)不同的词吗?”的问题。是不可判断。 1 。
(对每个元素的“访问次数”进行约束,存在有限数量的可能性,并且声明和证明当然不成立。)
<强>证明:强>
众所周知,没有算法A
可以决定终止算法B
是否为true
或更多不同的输入返回k
。 (如果需要,将在以后寻找此声明的引用,暂时相信我)。
我们将展示给定一个算法A
,说明是否有k
个或更多生成的字 - 我们可以决定是否有k
个或更多不同的输入产生“真” :
让(终止)算法决定是否有k
或
更多生成的单词为M
。
不失一般性 - 假设二进制字母表(我们可以用它代表一切)。
让:
array = 0 1
0 1
请注意,我们可以在此阵列上行走时生成任何二进制字。
算法A:
输入:算法B,自然数n
输出:当且仅当算法B对n个或更多不同输入回答“真”时才为真。
算法:
(1)使用B(word)
作为黑匣子字典 - 如果答案为真,则word
在字典中。
(2)使用array
作为数组。
(3)运行M on(array,dictionary,n),并按照它回答。
请注意,如果M回答为真 - >有n
个或更多可接受的单词 - &gt;对于B,有n
个或更多不同的输入产生true(字典的定义,因为我们可以用数组生成每个输入) - &gt;这个问题的答案是真的。
(如果算法回答错误,则证据类似)。
<强> QED 强>
<强>结论:强>
如果我们可以重复一次数组中的一个字符(或者更确切地说 - 无限次数) - 那么如果没有关于字典的任何信息,问题就无法解决。
(1)一个不可抗拒的问题是没有算法可以在100%的情况下正确回答TRUE / FALSE的问题 - 对于每种算法,在某些情况下算法将被“卡住”在无限的情况下循环(或给出错误的答案)。最常见的“不可判断的”问题是Halting Problem - 其中说 - 没有算法A
可以采用任何算法B
并在B
停止某些输入时回答w
。
答案 2 :(得分:0)
我的解决方案是:
我想我有一个M * N数组,搜索单词没有限制。例如,'rood'和'door'是两个不同的单词,彼此相反。
从第一个字母开始(左上角)。在这种情况下,它是'a'。如果字典中有任何单词,则检查邻接(假设有以'ae'和'af'开头的单词)检查它们是否已经是单词,最后一个字母的索引是0还是M-1或N-1 。如果没有,请将它们添加到队列中以便稍后查看。轮流检查所有排队的子串,并通过对队列中的所有值进行处理来完成此阶段。然后检查第二个字母并继续到数组的最后一个成员。像这样,你将能够检查所有可能的单词。
它适用于我的一个问题,但我不确定你是否也在寻找复杂性。
答案 3 :(得分:0)
import java.util.HashSet;
import java.util.Set;
/**
* Given a 2-dimensional array of characters and a
* dictionary in which a word can be searched in O(1) time.
* Need to print all the words from array which are present
* in dictionary. Word can be formed in any direction but
* has to end at any edge of array.
* (Need not worry much about the dictionary)
*/
public class DictionaryWord {
private static char[][] matrix = new char[][]{
{'a', 'f', 'h', 'u', 'n'},
{'e', 't', 'a', 'i', 'r'},
{'a', 'e', 'g', 'g', 'o'},
{'t', 'r', 'm', 'l', 'p'}
};
private static int dim_x = matrix.length;
private static int dim_y = matrix[matrix.length -1].length;
private static Set<String> wordSet = new HashSet<String>();
public static void main(String[] args) {
//dictionary
wordSet.add("after");
wordSet.add("hate");
wordSet.add("hair");
wordSet.add("air");
wordSet.add("eat");
wordSet.add("tea");
for (int x = 0; x < dim_x; x++) {
for (int y = 0; y < dim_y; y++) {
checkAndPrint(matrix[x][y] + "");
int[][] visitedMap = new int[dim_x][dim_y];
visitedMap[x][y] = 1;
recursion(matrix[x][y] + "", visitedMap, x, y);
}
}
}
private static void checkAndPrint(String word) {
if (wordSet.contains(word)) {
System.out.println(word);
}
}
private static void recursion(String word, int[][] visitedMap, int x, int y) {
for (int i = Math.max(x - 1, 0); i < Math.min(x + 2, dim_x); i++) {
for (int j = Math.max(y - 1, 0); j < Math.min(y + 2, dim_y); j++) {
if (visitedMap[i][j] == 1) {
continue;
} else {
int[][] newVisitedMap = new int[dim_x][dim_y];
for (int p = 0; p < dim_x; p++) {
for (int q = 0; q < dim_y; q++) {
newVisitedMap[p][q] = visitedMap[p][q];
}
}
newVisitedMap[i][j] = 1;
checkAndPrint(word + matrix[i][j]);
recursion(word + matrix[i][j], newVisitedMap, i, j);
}
}
}
}
}