给出字典列表,给出字典

时间:2012-04-24 18:49:45

标签: java algorithm

我在接受采访时被问到这个问题。假设您有一个有序字典,并给出一个无序字符列表 - 您将如何按优先顺序排列这些字符?此词典包含保证显示所有26个字符的单词。但请注意,字典的大小可能是任何内容。字典可以小到几个单词,并且可能没有针对每个字符的单独部分,例如,可能没有以a开头的单词的部分;虽然a将作为另一个词的一部分出现,例如" bat"。

字典可能是"有序" (/讽刺)就像这样"斑马',"苹果","猫","粗鲁",如果你被给予列表{azr},正确的顺序为{zar}。因为" zebra"是在" apple"之前在字典中,我们知道z出现在a之前。因为" apple"来自" cat"之前,我们知道a出现在c之前。因为" cat"来自" crass",我们知道a出现在r之前。这个排序使cr留下了一个圆满的演讲,但由于字母列表是{azr},我们知道解决方案是{zar}。

3 个答案:

答案 0 :(得分:11)

使用带有26个顶点的有向图,每个顶点代表一个字符。从顶点A到顶点B的边缘表示字母B在A的前面。

第一步是建立只有顶点但没有边缘的图形。

其次,您逐字扫描输入字典。并将每个单词与前一个单词进行比较。您应该为扫描的每个单词找到确切的关系。因此,您在此图表中添加了一条边。假设字典是正确的,应该没有冲突。

完成字典后,按

输出字母
  1. 选择一个随机顶点,遍历其路径,直到找到一个指向任何内容的字符。这是字母表中的第一个字符。输出并从图表中删除它。
  2. 继续执行1直到删除所有顶点。
  3. 编辑: 为了更好地解释这个算法,让我们在你的样本输入上运行它。

    输入:{“zebra”,“apple”,“cat”,“crass”}

    Word 0和word 1,我们立即知道z在a之前,所以我们创建了一个边缘a-> z

    单词1和单词2,我们立即知道a出现在c之前,所以我们创建另一个边缘c-> a

    Word 2和Word 3,第一个字母是相同的“c”,但第二个字母不同,所以我们知道a在r之前,所以我们有另一个边r-> a

    现在阅读所有单词。通过随机拾取顶点来输出顺序(比如我们选择c),然后我们在图中有c-> a-> z。输出z并从图形中删除z(将其标记为NULL)。现在选择另一个(比如我们选择r),然后我们在图中找到r-> a。我们输出并删除图表。现在我们选择另一个(比如我们再次选择c),找不到路径,所以我们只输出c并删除它。现在我们选择最后一个,r,再没有路径,所以我们输出r并删除它。由于删除了所有顶点,因此算法已完成。

    输出为z,a,c,r。 “c”和“r”的排序是随机的,因为我们并不真正知道它们与输入的关系。

答案 1 :(得分:1)

来自&#34;斑马&#39; &LT; &#34;苹果&#34; &LT; &#34;猫&#34; &LT; &#34;粗鲁&#34;,导出每个字符关系的最有效方法是让循环考虑所有单词的第N个字符,其中N最初为0,产生关系&#34; z&#34; &LT; &#34;&#34; &LT; &#34; C&#34 ;.该循环可以递归地提取具有相同前缀的单词组的第(N + 1)个字符的关系(即,位置<= N的文本)。使用相同前缀&#34; cat&#34;为N == 1执行此操作和&#34;粗鲁&#34;产生关系&#34; a&#34; &LT; &#34; R&#34;

我们可以在x < y真值的二维数组中表示已知关系。

y\x a b c...r...z
a   -   N   N   Y
b     -
c   Y   -       Y
r   Y       -
z   N   N       -

蛮力方法是迭代输入列表中的所有字符对(即{a,z,r} - > az,ar,zr)查找表a<z,{{ 1}},a<r:如果这是假的,那么交换字符并重启整个she-bang。当您完成整个过程而无需交换任何其他字符时,输出将与规则一致地排序。这有点像做冒泡分类。

为了加快速度,我们可以更积极主动地在表格中填充隐含关系的单元格:例如,我们知道&#34; z&#34; &LT; &#34;&#34; &LT; &#34; C&#34;和&#34; a&#34; &LT; &#34; r&#34;,所以我们推断出&#34; z&#34; &LT; &#34; R&#34 ;.我们可以通过运行&#34;天真&#34;上面的表格可以找到我们对每个角色所知的一切(例如z<rz<a) - 然后查看我们对a和c的了解。为了避免过度深度的树,你可以按照这样的一个间接级别,然后重复直到表稳定。

答案 2 :(得分:-3)

根据您描述问题的方式,您的示例不正确。你的答案应该是{z,r,a}。然而,可能是,下面是解决问题的代码。您可以修改它以返回与我所假设的{z,r,a}不同的订单。

Set<Character> charPrecedence(List<String> dictionary, char[] letters){
    Set<Character> result = new HashSet<Character>();
    //since your characters are the 26 letters instead of the 256 chars
    // a bit vector won't do; you need a map or set
    Set<Character> alphabets = new HashSet<Character>();
    for(char c: letters)
       alphabets.add(c);

    //now get to work
    for(String word: dictionary){
       if(alphabets.isEmpty()) return result;
       for(char c: word.toCharArray()){
          if(alphabets.remove(c))
           result.add(c);
       }
    }
    //since the dictionary is guaranteed to contain all the 26 letters,
    //per the problem statement, then at this point your work is done.
    return result;
}

最佳案例O(1);最坏情况O(n)其中n是字典中的字符数,即一个特定字母只出现一次,是你检查的最后一个字符。