不重复的单词组合
Posted
技术标签:
【中文标题】不重复的单词组合【英文标题】:Words combinations without repetition 【发布时间】:2011-07-05 04:51:14 【问题描述】:我有 10 个单词。如何获得 5 个单词 (n=10, k=5)
的所有可能组合。顺序无关紧要。
例如:"A", "B", "C", if k=2 (n=3 in this case)
,表示 AB、BC 和 AC。也许您知道一些有用的代码或示例。
附:对不起,如果我不够正确,因为我的英语不太好。
【问题讨论】:
【参考方案1】:您要做的是获取集合的所有排列。
Unique permutations of list permutations of k objects from a set of n algorithm这里是sn-p的代码:
static void Main(string[] args)
var list = new List<string> "a", "b", "c", "d", "e" ;
var result = GetPermutations(list, 3);
foreach (var perm in result)
foreach (var c in perm)
Console.Write(c + " ");
Console.WriteLine();
Console.ReadKey();
static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> items, int count)
int i = 0;
foreach (var item in items)
if (count == 1)
yield return new T[] item ;
else
foreach (var result in GetPermutations(items.Skip(i + 1), count - 1))
yield return new T[] item .Concat(result);
++i;
输出:
a b c
a b d
a b e
a c d
a c e
a d e
b c d
b c e
b d e
c d e
【讨论】:
在数学上更正确。你称这种组合(顺序不重要)没有重复(一个项目最多可能出现 1 次或更少)。 mathsisfun.com/combinatorics/combinations-permutations.html “最多 1 次”不是暗示“或更少”吗?【参考方案2】:这是我整理的:
static class LinqExtensions
public static IEnumerable<IEnumerable<T>> CombinationsWithoutRepetition<T>(
this IEnumerable<T> items,
int ofLength)
return (ofLength == 1) ?
items.Select(item => new[] item ) :
items.SelectMany((item, i) => items.Skip(i + 1)
.CombinationsWithoutRepetition(ofLength - 1)
.Select(result => new T[] item .Concat(result)));
public static IEnumerable<IEnumerable<T>> CombinationsWithoutRepetition<T>(
this IEnumerable<T> items,
int ofLength,
int upToLength)
return Enumerable.Range(ofLength, Math.Max(0, upToLength - ofLength + 1))
.SelectMany(len => items.CombinationsWithoutRepetition(ofLength: len));
...
foreach (var c in new[] "a","b","c","d".CombinationsWithoutRepetition(ofLength: 2, upToLength: 4))
Console.WriteLine(string.Join(',', c));
产生:
a,b
a,c
a,d
b,c
b,d
c,d
a,b,c
a,b,d
a,c,d
b,c,d
a,b,c,d
请注意,这很简洁但效率低下,不应该用于大型集合或内部循环。值得注意的是,短数组会被多次重新创建并且可以被记忆,而IEnumerable
会被多次迭代,如果不注意可能会导致意外的工作。
此外,如果输入包含重复项,则输出也将包含重复项。要么先使用.Distinct().ToArray()
,要么使用包含相等性检查的其他解决方案,并且大概采用IEqualityComparer
作为通用性。
【讨论】:
【参考方案3】:public IActionResult Index()
var list = new List<string> "a", "b", "c", "d", "e" ;
List<string> ret = GetAllCombinations(list).OrderBy(_ => _).ToList();
return View();
static IEnumerable<string> GetAllCombinations(IEnumerable<string> list)
return list.SelectMany((mainItem, mi) => list.Where((otherItem, oi) => mi < oi)
.Select(otherItem => mainItem + otherItem));
输出:
ab
ac
ad
ae
bc
bd
be
cd
ce
de
【讨论】:
欢迎来到 Stack Overflow。虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。 How to Answer。亲切的问候。【参考方案4】:更实用的解决方案怎么样
var list = new List<string> "a", "b", "c", "d", "e" ;
GetAllCombinations(list).OrderBy(_ => _).ToList().ForEach(Console.WriteLine);
static IEnumerable<string> GetAllCombinations(IEnumerable<string> list)
return list.SelectMany(mainItem => list.Where(otherItem => !otherItem.Equals(mainItem))
.Select(otherItem => mainItem + otherItem));
输出:
ab
ac
ad
ae
ba
bc
bd
be
ca
cb
cd
ce
da
db
dc
de
ea
eb
ec
ed
【讨论】:
OP指定顺序无关紧要,因此出现在该代码结果中的“ab”和“ba”是相同的。以上是关于不重复的单词组合的主要内容,如果未能解决你的问题,请参考以下文章