我找到了许多解决方案,它们在所有可能的顺序中组合了一个集合元素,但它们在每个结果中只使用一次元素,而我需要将它们视为可重用的。
例如,如果输入元素为{“a”,“b”,“c”}且数字为2,则输出为{“a”,“a”},{“a”,“b” },{“a”,“c”},{“b”,“a”},{“b”,“b”},{“b”,“c”},{“c”,“a” },{“c”,“b”},{“a”,“c”}。
答案 0 :(得分:1)
假设你有N个输入元素,你想要一个K-long组合。
您需要做的就是计算基数N,当然还要计算所有带有K位数的数字。
所以,假设N = {n0,n1,... nN}
你从数字[n0 n0 ... n0]开始,一直计数到[nN nN ... nN]
如果您希望了解如何计算其他基数,请获取here
您计算的每个数字都映射到您需要的K长组合之一。
我认为一个例子可以帮助
我会用你的价值观。 N = {a,b,c} 所以我们想要算在3号基数。 由于我们需要2长组合,我们只关心2位数字。 最小的2位数基数3是00,所以我们从那里开始。通过计算基数3,我们得到:
00
01
02
10
11
12
20
21
22
好的,现在将这些数字转换为组合。
请记住,我们的设置为{a,b,c}
所以每当我们看到0时,它就意味着1.无论我们在哪里看到1,它都意味着2,我相信你能猜出2意味着什么:)
00 aa
01 ab
02 ac
10 0 => a ba
11 1 => b bb
12 2 => c bc
20 ca
21 cb
22 cc
答案 1 :(得分:1)
您可以使用depth first search:
class Program
{
private static string[] letters = {"a", "b", "c"};
private static void dfs(string accum, int depth)
{
if (depth == 0)
{
System.Console.WriteLine(accum);
return;
}
foreach (string c in letters)
dfs(accum + c, depth - 1);
}
public static void Main()
{
int depth = 2; //Number of letters in each result
dfs("", depth);
System.Console.ReadLine();
}
}
输出:
aa
ab
ac
ba
bb
bc
ca
cb
cc
答案 2 :(得分:1)
Eric Lippert介绍了一种通用方法,可以从任意数量的序列which he blogs about here生成笛卡尔积。
他写了一个如下所示的扩展方法:
public static class Combinations
{
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat<T>(new[] { item }));
}
}
鉴于扩展方法,原始问题的解决方案可以这样做:
var items = new[] { "a", "b", "c" };
int numInEachSelection = 2;
var combs = Enumerable.Repeat(items, numInEachSelection).CartesianProduct();
foreach (var comb in combs)
Console.WriteLine(string.Join(", ", comb));
请注意combs
是IEnumerable<IEnumerable<string>>
- 它是一系列枚举,每个都是代表一个组合的序列。
如果您不需要这样的通用方法,并且您乐意将每个组合放在一个单独的对象中,该对象具有两个组合项目Item1
和Item2
的属性,那么最简单方式是这样的:
var items = new[] { "a", "b", "c" };
var combs = from Item1 in items from Item2 in items select new {Item1, Item2};
foreach (var comb in combs)
Console.WriteLine(comb);
答案 3 :(得分:0)
简单 - 你算一算。如果您有3个元素,如您的示例所示,并且想要所有双元素组合,则只需从0到8(3 ^ 2 - 1)计数,并将结果视为基数为3的数字,并将元素作为数字
如果您有15个元素并且需要8个元素组合,则从0到15 ^ 8-1计数并将结果视为基数为15的数字。
答案 4 :(得分:0)
你要求的是排列而不是组合。通过遍历n个元素的k,可以找到唯一的组合。如果你想要n个n个唯一元素,那么答案是1