Algo to Solve填字游戏

时间:2013-02-05 09:53:10

标签: algorithm data-structures

我刚刚解决了这个问题,除了暴力之外,我想不出更好的方法给出一个二维数组的字符和一个有效单词的原始列表。 1)查找数组中的所有有效单词。从数组中的每个元素,您可以向上,向下,向右或向左移动。 例如,

g o d b o d y
t a m o p r n 
u i r u s m p

来自上述2D阵列的有效单词 - >上帝,山羊,神体,爱情,......

3 个答案:

答案 0 :(得分:1)

您应该将此列表预先处理为前缀树,而不是在前缀树上的2D数组中使用强力搜索。

您也可以对已经处理过的数组路径和单词部分的类似输入

使用memoization

记事本示例:

RecursiveMatch(i,j,wordPart)

 if ((i,j,wordPart) in cache) 
   print cache[i,j,wordPart]
   return;
 if a[i,j] on the prefixTreePath){
   cache[i,j,wordPart]+=RecursiveMatch(i+1,j,wordPart[1:])
   cache[i,j,wordPart]+=RecursiveMatch(i-1,j,wordPart[1:])
   cache[i,j,wordPart]+=RecursiveMatch(i,j+1,wordPart[1:])
   cache[i,j,wordPart]+=RecursiveMatch(i,j-1,wordPart[1:])
   print cache[i,j,wordPart]
 }

我还没有添加任何结束案例,例如边框,很容易添加。 我的目的是给你一般的想法。

答案 1 :(得分:1)

确保您有按字母顺序排序的有效单词列表。你可以在nlg n时间内构建它。

现在你有了这个排序列表,你可以验证一个字符序列是否是lg n时间内正确单词的开头。

使用一组有效单词来验证字母序列是否是有效单词(在固定时间内)。

现在为每个起始位置调用getWords(input,startX,startY,new ArrayList(),“”)并合并生成的列表:

public List<String> getWords(char[][] input, int x, int y, List<String> result, String current){
    if(isValidWord(current))
         result.add(current);

    if(isValidStartOfWord(current)){
         // call getWords recursively for all valid directions, concatenating the char to current
    }

    return result;
 }

通过这种方式,您可以在O(x ^ 2 * y ^ 2 * lg w)时间内找到答案,其中包含char数组的x和y维度,以及w有效单词列表的大小。这并不比最坏的情况好(鉴于lg w验证),但这对我来说似乎不太可能。预期的运行时间更好。

如果有效单词列表很小,您还可以为正确单词的所有有效开头构建一个集合。在这种情况下,你可以在恒定的时间内验证你是否正在前往正确的单词,最坏的情况是减少到O(x ^ 2 * y ^ 2)。

祝你好运。

答案 2 :(得分:0)

一种算法依赖于称为前缀树或tree的合适数据结构。

第一步是预处理有效单词的词典并将其放入trie中。 这使您可以有效地回答如下问题:

给定的前缀是否是有效的前缀?

您可以使用trie在O(lenght of the prefix)时间内回答此问题。

然后假设您选择了一个单词的起始正方形。您现在需要在4个方向上遍历网格,并检查到目前为止获得的前缀是否是有效前缀。如果不是那么你将不会在这个方向上进一步。另一方面,如果到目前为止前缀是一个有效的单词,你可以打印它。 遍历可以使用DFS或BFS完成(并不重要)。 重要的是使用trie快速检查有效的前缀和有效的单词。