【问题标题】:Using Binary Trees to find Anagrams使用二叉树查找字谜
【发布时间】:2011-04-12 15:40:57
【问题描述】:

我目前正在尝试创建一种方法,该方法使用二叉树来查找用户输入的单词的字谜。

如果树不包含单词的任何其他字谜(即,如果键不在树中或关联链表中的唯一元素是用户提供的单词),则消息“找不到字谜” "被打印出来 例如,如果键“opst”出现在树中,其关联的链表包含单词“spot”、“pots”和“tops”,并且用户给出了单词“spot”,程序应该打印“pots”和“tops”(但不是现货)。

public boolean find(K thisKey, T thisElement){
    return find(root, thisKey, thisElement);
}

public boolean find(Node current, K thisKey, T thisElement){
    if (current == null)
        return false;
    else{
        int comp = current.key.compareTo(thisKey);
        if (comp>0)
            return find(current.left, thisKey, thisElement);
        else if(comp<0)
            return find(current.right, thisKey, thisElement);
        else{
            return current.item.find(thisElement);
        }
    }
}

虽然我创建了这个方法来查找提供的元素是否在树中(以及关联的键),但我被告知不要重复使用此代码来查找字谜。

K 是泛型类型,扩展 Comparable 并表示 Key,T 是泛型类型,表示列表中的一项。

如果需要我已经完成的额外方法,我可以编辑这篇文章,但我完全迷失了。 (只需要指向正确方向的指针)

【问题讨论】:

  • 你写的方法,最好叫contains('是这棵树的关键吗?')。要使其成为find 方法,它应该返回找到的内容。

标签: java binary-tree


【解决方案1】:

有点不清楚到底是什么让你绊倒了(除了“我写了一个很好的 find 方法,但不允许使用它。”),所以我认为最好的办法是从头开始。

我想您会发现,一旦您以正确的方式构建数据,实际算法就会相对容易地遵循(许多计算机科学问题都具有此特征。)

你拥有三样东西:

1) 许多链表,每个链表都包含一组字母的字谜。我假设您可以根据需要生成这些列表。

2) 二叉树,将字符串(键)映射到从这些字符串生成的字谜列表。同样,我假设您能够对这些树状结构执行基本操作——添加元素、按键查找元素等。

3) 用户输入的字符串。

洞察:一组字母的字谜形成一个等价类。这意味着字谜列表的任何成员都可以用作与列表关联的键。此外,这意味着您不需要在树中存储指向同一个列表的多个键(假设我们在构建数据方面有点聪明;见下文)。

具体来说,没有必要将“spot”和“opts”作为指向同一个列表的树中的键,因为一旦你可以使用“spot”的任何变位词找到列表,你就会得到 所有“spot”的字谜。

巧妙地构建您的数据:根据我们的洞察力,假设我们的树恰好包含每个唯一字谜集的一个键。所以“opts”映射到{“opts”、“pots”、“spot”等}。如果我们的用户给了我们一个我们没有用作其字谜集的键的字符串,会发生什么?我们如何确定如果用户键入“spot”,我们应该找到以“opts”为键的列表?

答案是规范化我们数据结构中存储的数据。这是一种计算机科学的说法,即我们对如何存储数据执行任意规则。 (规范化数据是一种有用的技术,在许多不同的计算机科学领域中反复出现。)第一条规则是我们的树中只有一个键映射到给定的链表。其次,如果我们确保我们实际存储的每个键都是可预测的——也就是说,我们知道即使用户键入“spot”,我们也应该搜索“opts”?

有很多方法可以实现这种可预测性——一种简单的方法是确保每个键的字母都按字母顺序排列。然后,我们知道每组字谜将由按字母顺序排在第一位的(唯一!)成员键入。始终如一地执行此规则使得搜索树变得容易——我们知道,无论用户给我们什么字符串,我们想要的键都是根据用户输入的字母顺序形成的字符串。

放在一起:我将在此处提供高级算法以使其更加具体。

1) 从用户那里获取一个字符串(抓住这个字符串,我们稍后会用到它)

2) 将此字符串转换为遵循我们规范化方案的搜索键 (您可以在“K”类的构造函数中执行此操作,这样可以确保您的程序中任何地方都不会有非规范化键。)

3) 在树中搜索该键,并获取与其关联的链表。此列表包含用户输入字符串的每个字谜。

4) 打印列表中不是用户原始字符串的每个项目(看看我们为什么要把字符串放在手边?)


要点

通常,您的数据会具有一些让您变得聪明的特殊功能。在这种情况下,一个字谜列表的 任何 成员可以是我们为该列表存储的唯一键。

规范化您的数据可以让您获得可预测性,并让您能够有效地对其进行推理。如果每个键都可以是其字谜列表中的任意成员,那么“查找”算法的难度会增加多少?

推论:让您的数据结构完全正确(我要存储什么?这些部分是如何连接的?它是如何表示的?)将使您的算法更容易编写。

【讨论】:

    【解决方案2】:

    如何对单词中的字符进行排序,然后进行比较。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-05
      • 1970-01-01
      • 2012-10-12
      • 1970-01-01
      • 2021-01-01
      • 1970-01-01
      相关资源
      最近更新 更多