我有一些固定的整数集,每个集合中的distict值增加,例如:
{1, 2, 4}, {1, 3}, {2, 4}, {2, 7}, {3, 6}, {5, 6}, {3, 5, 7}.
是否有任何算法或更好的C#代码,从给定集合生成所有可能的组合,但不重复其内部整数,即
[{1, 2, 4}, {3, 6}] < all integers are unique
[{1, 2, 4}, {3, 5, 7}] < all integers are unique
[{1, 3}, {2, 4}, {5, 6}] <– all integers are unique.
等等。
====================================
这可能是输入数据的组织:
var set1 = new HashSet<int>() { 1, 2, 4 };
var set2 = new HashSet<int>() { 1, 3 };
var set3 = new HashSet<int>() { 2, 4 };
var set4 = new HashSet<int>() { 2, 7 };
var set5 = new HashSet<int>() { 3, 6 };
var set6 = new HashSet<int>() { 5, 6 };
var set7 = new HashSet<int>() { 3, 5, 7 };
var inputList = new List<HashSet<int>>();
inputList.Add(set1);
inputList.Add(set2);
inputList.Add(set3);
inputList.Add(set4);
inputList.Add(set5);
inputList.Add(set6);
inputList.Add(set7);
我需要从inputList获取所有可能列表(即组合)的列表(或集合),每个内部列表(组合)中都有唯一的整数。
这个问题被标记为重复,并且这个问题在这里已经有了答案: “生成所有可能的组合(8个答案)”。但是,在我看来,它本质上是一个不同的问题:
输入数据不是两个长度相同的数组,而是每个集合中具有不同元素数量的集合列表;
相同的元素可能存在于不同的集合中。
答案 0 :(得分:0)
我个人认为这是一个两部分问题:
编辑/更正
因此,深入研究问题的目的是找到SETS的组合而不是这些组中的个别数字(正如我上面最初指出的那样)。考虑到这一点,我会做以下事情:
我相信这应该有效。我(可能)稍后在这里创建一个例子!
守则
重要提示:这在任何意义上都不是很好或优化,但它确实有效,它确实说明了解决这个问题的方法。一个简单的优化是将布尔数组传递到生成组合的递归步骤,并在生成冲突时立即停止递归。这将节省大量的时间和计算能力。也就是说,我会将其作为练习留给读者。
只需将以下内容粘贴到新的控制台应用程序中即可。祝你好运!
static void Main(string[] args)
{
// create/read sets here
var integers = new List<int[]>(){new []{1,2,4}, new []{1,3}, new []{2, 4}, new []{2, 7}, new []{3, 6}, new []{5, 6}, new []{2, 5, 7}};
// allocate/populate booleans - loop may be able to be refined
var conflicts = new bool[integers.Count, integers.Count];
for (var idx = 0; idx < integers.Count; idx++)
for (var cmpIdx = 0; cmpIdx < integers.Count; cmpIdx++)
conflicts[idx, cmpIdx] = integers[idx].Any(x => integers[cmpIdx].Contains(x));
// find combinations (index combinations)
var combinations = GetCombinations(integers.Count);
// remove invalid entries
for (var idx = 0; idx < combinations.Count; idx++)
if (HasConflict(combinations[idx], conflicts))
combinations.RemoveAt(idx--);
// print out the final result
foreach (var combination in combinations) PrintCombination(combination, integers);
// pause
Console.ReadKey();
}
// get all combinatins
static List<Combination> GetCombinations(int TotalLists)
{
var result = new List<Combination>();
for (var combinationCount = 1; combinationCount <= TotalLists; combinationCount++)
result.AddRange(GetCombinations(TotalLists, combinationCount));
return result;
}
static List<Combination> GetCombinations(int TotalLists, int combinationCount)
{
return GetCombinations(TotalLists, combinationCount, 0, new List<int>());
}
// recursive combinatorics - loads of alternatives including linq cartesian coordinates
static List<Combination> GetCombinations(int TotalLists, int combinationCount, int minimumStart, List<int> currentList)
{
// stops endless recursion - forms final result
var result = new List<Combination>();
if (combinationCount <= 0)
{
if ((currentList ?? new List<int>()).Count > 0)
{
result.Add(new Combination() { sets = currentList });
return result;
}
return null;
}
for (var idx = minimumStart; idx <= TotalLists - combinationCount; idx++)
{
var nextList = new List<int>();
nextList.AddRange(currentList);
nextList.Add(idx);
var combinations = GetCombinations(TotalLists, combinationCount - 1, idx + 1, nextList);
if (combinations != null) result.AddRange(combinations);
}
return result;
}
// print the combination
static void PrintCombination(Combination value, List<int[]> sets)
{
StringBuilder serializedSets = new StringBuilder();
foreach (var idx in value.sets)
{
if (serializedSets.Length > 0) serializedSets.Append(", ");
else serializedSets.Append("{");
serializedSets.Append("{");
for (var setIdx = 0; setIdx < sets[idx].Length; setIdx++)
{
if (setIdx > 0) serializedSets.Append(", ");
serializedSets.Append(sets[idx][setIdx].ToString());
}
serializedSets.Append("}");
}
serializedSets.Append("}");
Console.WriteLine(serializedSets.ToString());
}
static bool HasConflict(Combination value, bool[,] conflicts)
{
for (var idx = 0; idx < value.sets.Count; idx++)
for (var cmpIdx = idx + 1; cmpIdx < value.sets.Count; cmpIdx++)
if (conflicts[value.sets[idx], value.sets[cmpIdx]]) return true;
return false;
}
// internal class to manage combinations
class Combination { public List<int> sets; }