包含所有字母的字典中最短的单词

时间:2015-02-06 22:23:02

标签: algorithm

我在接受采访时被问到这个问题。

给定一个字符数组,找到包含所有字符的字典中的最短单词。此外,提出了一个优化此函数调用的字典实现。

例如char [] chars = {' R' ,' C' }。结果应该是" CAR"。

我无法想出任何能够合理快速运行的东西。我想通过构建一个哈希表来检索特定长度的所有单词来预处理字典。然后我只能想到以递增的长度顺序检索所有单词并检查所有单词中是否存在所需的字符(可能使用位掩码。)

6 个答案:

答案 0 :(得分:5)

这是一个常见的软件访谈问题,其解决方案是:按字母长度对字典进行排序,并按字母顺序对每个值进行排序。给出字符时,对它们进行排序并找到所需的字母。

答案 1 :(得分:2)

首先按照长度的升序对字典进行排序。

对于每个字母,构造包含该字母的单词字典中位置的位图。每个位图都很长,但不会很多。

对于每次搜索,请获取数组中字母的位图交集。结果中的第一位将位于与包含所有字母的最短单词的字典中的位置对应的索引处。

答案 2 :(得分:2)

其他答案更好,但我意识到这完全可以预先计算。

  • 每个单词
    • 对字母进行排序并删除重复项
    • 字母序列可视为位掩码,A = 0位,B = 1位... Z = 26位。根据这个单词中的字母设置掩码A的位。
    • 对于掩码A中的每个设置位组合,制作子集掩码B.
      • 如果已经有与此掩码B关联的单词
        • 这个词更短,用这个替换相关的词
        • 否则尝试下一个B
      • 如果没有与面具B相关联的单词
        • 将此词与面具B联系起来。

这将需要大量的设置时间,并且随后的关联存储将在1.7GB附近,但是您将能够在O(1)时间内找到包含字母超集的最短字。保证。

答案 3 :(得分:1)

明显的预处理是按字母长度和字母顺序重新排序对字典中的所有单词进行排序:例如,“dorw”下的“单词”。然后,您可以使用常规搜索算法(例如,正则表达式)来搜索您需要的字母。在最坏的情况下,高效(DFA)搜索只需要通过字典一次,如果第一次匹配很短,则需要更少。

答案 4 :(得分:0)

预处理

一个。将单词排序为字母char数组。保留从排序到原始单词的映射

湾按照建议的字长拆分字典

℃。按字母顺序对每个字长设置条目

在函数调用

  1. 按字母顺序排序字符数组
  2. 以与数组相同长度的组开始
  3. 循环测试字符的条目,直到字典中的第一个字母大于第一个字符,然后中断。如果匹配则返回原始单词(参见上面的映射)
  4. 返回2以获取下一个最长词组
  5. 有趣的扩展。多个单词可能映射到a中的相同条目。你应该返回哪一个......

答案 5 :(得分:0)

这是C#中的解决方案:

using System.Collections.Generic;
using System.Linq;

public class ShortestWordFinder
{
    public ShortestWordFinder(IEnumerable<string> dictionary)
    {
        this.dictionary = dictionary;
    }

    public string ShortestWordContaining(IEnumerable<char> chars)
    {
        var wordsContaining = dictionary.Where(s =>
        {
            foreach (var c in chars)
            {
                if (!s.Contains(c))
                {
                    return false;
                }

                s = s.Remove(s.IndexOf(c), 1);
            }

            return true;
        }).ToList();

        if (!wordsContaining.Any())
        {
            return null;
        }

        var minLength = wordsContaining.Min(word => word.Length);
        return wordsContaining.First(word => word.Length == minLength);
    }

    private readonly IEnumerable<string> dictionary;
}

简单测试:

using System.Diagnostics;
using Xunit;

public class ShortestWordFinderTests
{
    [Fact]
    public void Works()
    {
        var words = new[] { "dog", "moose", "gargoyle" };
        var finder = new ShortestWordFinder(words);
        Trace.WriteLine(finder.ShortestWordContaining("o"));
        Trace.WriteLine(finder.ShortestWordContaining("oo"));
        Trace.WriteLine(finder.ShortestWordContaining("oy"));
        Trace.WriteLine(finder.ShortestWordContaining("eyg"));
        Trace.WriteLine(finder.ShortestWordContaining("go"));
        Assert.Null(finder.ShortestWordContaining("ooo"));
    }
}