我已经看过许多获得给定字母集的所有排列的例子。递归似乎可以很好地得到一组字母的所有可能组合(尽管如果其中两个字母是相同的,它似乎没有考虑到。)
我想弄清楚的是,您是否可以使用linq(或不使用)来获得所有可能的字母组合,最多可达3个字母组合。
例如,给出字母:P I G G Y. 我想要一系列这些字母的所有可能的组合,以便我可以查看单词列表(拼字游戏?)并最终得到一个列表,列出你可以使用这些字母创建的所有可能的单词(从3个字母到总数,在此案例5个字母)。
答案 0 :(得分:9)
答案 1 :(得分:1)
这种方法似乎有效。它使用Linq和程序代码。
IEnumerable<string> GetWords(string letters, int minLength, int maxLength)
{
if (maxLength > letters.Length)
maxLength = letters.Length;
// Associate an id with each letter to handle duplicate letters
var uniqueLetters = letters.Select((c, i) => new { Letter = c, Index = i });
// Init with 1 zero-length word
var words = new [] { uniqueLetters.Take(0) };
for (int i = 1; i <= maxLength; i++)
{
// Append one unused letter to each "word" already generated
words = (from w in words
from lt in uniqueLetters
where !w.Contains(lt)
select w.Concat(new[] { lt })).ToArray();
if (i >= minLength)
{
foreach (var word in words)
{
// Rebuild the actual string from the sequence of unique letters
yield return String.Join(
string.Empty,
word.Select(lt => lt.Letter));
}
}
}
}
答案 2 :(得分:1)
搜索单词的所有排列的问题是计算绝对乱码所花费的工作量。生成所有排列是O(n!)并且sooo大部分都将被绝对浪费。这就是为什么我建议给予回答。
这是一个返回所有排列的递归linq函数:
public static IEnumerable<string> AllPermutations(this IEnumerable<char> s) {
return s.SelectMany(x => {
var index = Array.IndexOf(s.ToArray(),x);
return s.Where((y,i) => i != index).AllPermutations()
.Select(y => new string(new [] {x}.Concat(y).ToArray()))
.Union(new [] {new string(new [] {x})});
}).Distinct();
}
你可以找到你想要的单词:
"piggy".AllPermutations().Where(x => x.Length > 2)
然而:
警告:我不喜欢非常效率低下的答案
现在linq对我来说最大的好处就是它的可读性。尽管如此,我认为上述代码的意图并不清楚(我写了它!)。因此,linq(对我而言)的最大优势不在于上面,和它不如非linq解决方案那么有效。我通常原谅linq缺乏执行效率,因为它为编码时间,可读性和易维护性增加了效率,但我只是不认为linq解决方案最适合这里...方形挂钩,圆孔排序如果你愿意的话。
此外,还有我上面提到的复杂性问题。当然它可以在.2秒内找到153个三个字母或更多的“小猪”排列,但是给它一个像'簿记员'的单词,你将等待一个坚实的 1分39秒找到所有435,574个三个字母或更多的排列。那我为什么发布这么糟糕的功能呢?为了说明必须采取正确的方法。生成所有排列并不是解决这个问题的有效方法。
答案 3 :(得分:0)