【问题标题】:Printing all possible words from a 2D array of characters从二维字符数组中打印所有可能的单词
【发布时间】:2012-12-03 09:34:33
【问题描述】:

最近偶然发现了这个面试问题,

给定一个二维字符数组和一个字典,可以在O(1) 时间内搜索到一个单词。需要打印字典中存在的数组中的所有单词。单词可以在任何方向形成,但必须在数组的任何边缘结束。(不必太担心字典)

输入:

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”不是字典词,因为它没有在数组的边缘结束。

我以前见过类似的问题,但一直想不出一个好的算法来解决这类问题。任何关于如何解决这类问题(从字符数组形成单词)的帮助都会非常有帮助。

(我能想到的唯一方法是在二维数组中找到所有可能的字符排列,并检查它是否在数组的边缘结束,并检查排列是否是 O 中字典中的有效单词(1) 时间)

【问题讨论】:

  • 除了dict.contains(word),你还能用字典做什么?例如,您可以对其进行预处理以构建一些数据结构吗?
  • 您不能对字典进行任何预处理,您可以选择预处理数组。
  • 构词时是否允许多次使用同一个单元格?
  • 你能把同一个元素重复两次吗?如果是这样 - 假设无限字典 (ea)+ 和数组 [e,a] 你的答案是 ea,eaea,eaeaea,...(对于无穷大),所以基本上字典中没有任何信息的问题等同于 Halting Problem
  • 你怎么能被允许预处理一个而不是另一个?这是作业吗?

标签: arrays algorithm data-structures


【解决方案1】:

把数组变成一个图,这样每个单元格[i,j] 与它的 4 个邻居 [i+1,j], [i-1,j], [i,j+1], [i,j-1] 中的每一个共享一条边。 然后在每个 array-edge-cell 上运行 DFS 并继续检查字典是否 反面的词就在里面。

【讨论】:

  • 请注意,只有当您有限地返回每个元素有限次数时,该方法才可行。
【解决方案2】:

你没有提到一个字符只能使用一次 - 所以没有这个限制是“我们可以生成 k(或更多)不同的单词吗?”的问题。 无法确定1

(由于每个元素的“访问”数量受到限制,存在有限数量的可能性,因此声明和证明当然不成立。

证明:
众所周知,没有算法A 可以决定终止算法B 是否针对k 或更多不同的输入返回true。 (如果需要,稍后会查找此声明的引用,现在相信我)。

我们将展示给定一个算法 A,它表示是否有 k 或更多生成的单词 - 我们可以确定是否有 k 或更多不同的输入产生“真”:

  1. 让(终止)算法决定是否有k或 更多生成的词是M

  2. 不失一般性 - 假设二进制字母(我们可以用它来表示所有内容)。

  3. 让:

     array = 0 1 
             0 1
    

    注意我们可以在这个数组上行走时生成任何二进制字。

算法 A:
输入:算法B,自然数n
输出:当且仅当算法 B 对 n 个或更多不同的输入回答“真”时才为真。
算法
(1) 使用B(word) 作为黑盒字典——如果答案是真的,那么word 在字典中。
(2) 使用array 作为数组。
(3) 在 (array,dictionary,n) 上运行 M,然后像它一样回答。

请注意,如果 M 回答为真 -> 有 n 或更多接受的词 -> 有 n 或更多不同的 B 输入产生真(字典的定义,因为我们可以用数组生成每个输入) -> 问题的答案是正确的。
(如果算法回答错误,则证明类似)。

QED

结论:
如果我们可以重复数组中的一个字符不止一次(或者准确地说 - 无限次) - 那么如果没有字典上的任何信息,这个问题是无法解决的。


(1) 无法判定的问题是没有算法可以在 100% 的情况下正确回答 TRUE/FALSE 的问题 - 对于每种算法,在某些情况下,算法会“陷入”无限循环(或给出错误答案)。最常见的“不可判定”问题是 Halting Problem - 它表示 - 没有算法 A 可以采用任何算法 B 并回答如果 B 停止某些输入 w

【讨论】:

    【解决方案3】:

    我的解决办法是:

    我想我有一个 M*N 数组并且搜索单词没有限制。例如,“rood”和“door”是两个不同的词,因为它们是相互颠倒的。

    从第一个字母开始(左,上)。在这种情况下,它是“a”。并检查字典中是否有单词(假设有以'ae'和'af'开头的单词)检查它们是否已经是单词并且最后一个字母的索引是0或M-1或N-1 .如果没有,请将它们添加到队列中以便稍后查看。轮流检查所有排队的子字符串,并通过处理队列中的所有值来完成此阶段。然后检查第二个字母并继续到数组的最后一个成员。像这样,您将能够检查所有可能的单词。

    它适用于我的一个这样的问题,但我不确定你是否也在寻找复杂性。

    【讨论】:

    • 问题是 OP 说字典是黑盒子:你只能测试给定的单词是否出现在其中 - 所以不能测试是否存在带有给定前缀的单词。
    【解决方案4】:
    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);
                }
            }
        }
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2016-02-15
      • 2023-03-13
      • 1970-01-01
      • 2019-10-24
      • 2018-09-29
      • 1970-01-01
      • 1970-01-01
      • 2014-12-21
      • 2015-12-13
      相关资源
      最近更新 更多