C# 字谜算法

C# 字谜算法,c#,algorithm,anagram,C#,Algorithm,Anagram,这是为文本生成字谜的最佳方式(最大长度为80个字符)。 例子: 输入:狗 输出狗dgo odg ogd gdo god 我只是在考虑一个回溯解决方案,但如果文本较长,则需要一段时间 另一个想法是建立字典中所有单词的索引,但问题并不要求真正的单词 有人能指出一个最小时间复杂度的解决方案吗 谢谢大家! 回溯是最快的方法,当你想要一个文本的所有字谜时,它意味着你需要所有的n!它的排列。因此,假设打印/生成每个置换至少需要O(1),那么您的算法无论如何都需要O(n!),因此您不能比回溯解决方案更快。这里

这是为文本生成字谜的最佳方式(最大长度为80个字符)。 例子: 输入:狗 输出狗dgo odg ogd gdo god

我只是在考虑一个回溯解决方案,但如果文本较长,则需要一段时间

另一个想法是建立字典中所有单词的索引,但问题并不要求真正的单词

有人能指出一个最小时间复杂度的解决方案吗


谢谢大家!

回溯是最快的方法,当你想要一个文本的所有字谜时,它意味着你需要所有的n!它的排列。因此,假设打印/生成每个置换至少需要O(1),那么您的算法无论如何都需要O(n!),因此您不能比回溯解决方案更快。

这里是一个简单的实现,以防您需要:

IEnumerable<List<T>> Permutations<T>(List<T> items)
{
    if (items.Count == 0) yield return new List<T>();

    var copy = new List<T>(items);
    foreach (var i in items)
    {
        copy.Remove(i);
        foreach (var rest in Permutations(copy))
        {
            rest.Insert(0, i);
            yield return rest;
        }
        copy.Insert(0, i);
    }

}

IEnumerable<string> Anagrams(string word)
{
    return Permutations(word.ToCharArray().ToList()).Select(x => new String(x.ToArray()));
}
IEnumerable置换(列表项)
{
如果(items.Count==0)产生返回新列表();
var副本=新列表(项目);
foreach(项目中的var i)
{
复制。删除(i);
foreach(变量剩余置换(副本))
{
其余。插入(0,i);
剩余收益率;
}
副本。插入(0,i);
}
}
IEnumerable字谜(字符串字)
{
返回置换(word.tocharray().ToList()).Select(x=>newstring(x.ToArray());
}

关于时间复杂性的答案给了阿迪提亚。要理解他们的答案,你必须知道有n!=n个项目的1*2*..*n排列。我的算法证明了这一点(或基于直接证明)

问题看起来像是生成排列列表;(字谜是排列的子集,构成有意义的单词)。N排列可以使用STL方法按时间顺序生成(每个排列的线性时间复杂度);您可以在这里找到对该算法的讨论:;STL的算法甚至可以处理重复的数据,而朴素的交换算法在这种情况下失败了


对于生成置换的深入讨论,您可以浏览Donald Knuth的TAOCP部分。

它类似于构建置换的词典顺序。数字指的是索引器。如果不是,请解释现实世界的需要。我很感兴趣@弗雷德里克,如果是,那又有什么关系呢?无论哪种方式,他都想学点东西。@Filip:如果是家庭作业的话,最好是提供指导而不是解决方案。在这个问题上有一些讨论:是的,O(80!)。。。几年!当输入字符串包含相同的字母时会发生什么:例如:input:aba output应该是:aab aba baa。我不需要复制品。我是否必须将当前结果与所有previos结果进行比较以避免重复?您可以使用包含已发现排列的哈希,或者如果重复太多,您可以构建trie,但在这里要小心一点。每个节点都会有一个映射到剩余出现次数的字符哈希映射,使用这些字符生成子节点,并在其哈希映射中减少子节点字符的计数器,如果计数为0,则删除键。根将具有所有唯一字符作为映射到其出现次数的键,而叶将具有空映射。现在,为您的解决方案打印叶的所有路径。若所有字符都相同,则需要O(n)。@Dan Dinu将所有结果存储在哈希表中,所以检查结果将为O(1)