C# 值列表的所有可能组合
我的C#程序中有一个整数列表C# 值列表的所有可能组合,c#,algorithm,combinations,C#,Algorithm,Combinations,我的C#程序中有一个整数列表list。但是,我只知道在运行时列表中的项目数 让我们说,为了简单起见,我的列表是{1,2,3} 现在我需要生成所有可能的组合,如下所示 {1, 2, 3} {1, 2} {1, 3} {2, 3} {1} {2} {3} 有人能帮忙吗?首先,给定一组n个元素,计算出其中k个元素的所有组合(nCk)。您必须将k的值从1更改为n以满足您的要求 有关生成组合的C#代码,请参见此 如果您对自己开发组合算法感兴趣,请在有大量相关资料链接的地方检查此项。尝试以下方法: sta
list
。但是,我只知道在运行时列表中的项目数
让我们说,为了简单起见,我的列表是{1,2,3}
现在我需要生成所有可能的组合,如下所示
{1, 2, 3}
{1, 2}
{1, 3}
{2, 3}
{1}
{2}
{3}
有人能帮忙吗?首先,给定一组n个元素,计算出其中k个元素的所有组合(nCk)。您必须将k的值从1更改为n以满足您的要求 有关生成组合的C#代码,请参见此 如果您对自己开发组合算法感兴趣,请在有大量相关资料链接的地方检查此项。尝试以下方法:
static void Main(string[] args)
{
GetCombination(new List<int> { 1, 2, 3 });
}
static void GetCombination(List<int> list)
{
double count = Math.Pow(2, list.Count);
for (int i = 1; i <= count - 1; i++)
{
string str = Convert.ToString(i, 2).PadLeft(list.Count, '0');
for (int j = 0; j < str.Length; j++)
{
if (str[j] == '1')
{
Console.Write(list[j]);
}
}
Console.WriteLine();
}
}
static void Main(字符串[]args)
{
getcomposition(新列表{1,2,3});
}
静态void getcomposition(列表)
{
double count=Math.Pow(2,list.count);
对于(inti=1;i另一个使用Linq和递归的解决方案
static void Main(string[] args)
{
List<List<long>> result = new List<List<long>>();
List<long> set = new List<long>() { 1, 2, 3, 4 };
GetCombination<long>(set, result);
result.Add(set);
IOrderedEnumerable<List<long>> sorted = result.OrderByDescending(s => s.Count);
sorted.ToList().ForEach(l => { l.ForEach(l1 => Console.Write(l1 + " ")); Console.WriteLine(); });
}
private static void GetCombination<T>(List<T> set, List<List<T>> result)
{
for (int i = 0; i < set.Count; i++)
{
List<T> temp = new List<T>(set.Where((s, index) => index != i));
if (temp.Count > 0 && !result.Where(l => l.Count == temp.Count).Any(l => l.SequenceEqual(temp)))
{
result.Add(temp);
GetCombination<T>(temp, result);
}
}
}
static void Main(字符串[]args)
{
列表结果=新列表();
列表集=新列表(){1,2,3,4};
获取组合(集合、结果);
结果:添加(集合);
IOrderedEnumerable sorted=result.OrderByDescending(s=>s.Count);
sorted.ToList().ForEach(l=>{l.ForEach(l1=>Console.Write(l1+));Console.WriteLine();});
}
私有静态void getcomposition(列表集、列表结果)
{
for(int i=0;i索引!=i));
if(temp.Count>0&&!result.Where(l=>l.Count==temp.Count).Any(l=>l.SequenceEqual(temp)))
{
结果。添加(温度);
获取组合(临时、结果);
}
}
}
对于涉及字符串或整数的组合/置换问题,我们可以使用递归
public static void Main(string[] args)
{
IntegerList = new List<int> { 1, 2, 3, 4 };
PrintAllCombination(default(int), default(int));
}
public static List<int> IntegerList { get; set; }
public static int Length { get { return IntegerList.Count; } }
public static void PrintAllCombination(int position, int prefix)
{
for (int i = position; i < Length; i++)
{
Console.WriteLine(prefix * 10 + IntegerList[i]);
PrintAllCombination(i + 1, prefix * 10 + IntegerList[i]);
}
}
publicstaticvoidmain(字符串[]args)
{
整数列表=新列表{1,2,3,4};
PrintAllCombination(默认值(int)、默认值(int));
}
公共静态列表整数列表{get;set;}
公共静态整数长度{get{return IntegerList.Count;}}
公共静态void PrintAllCombination(int位置,int前缀)
{
for(int i=位置;i<长度;i++)
{
Console.WriteLine(前缀*10+整数列表[i]);
PrintAllCombination(i+1,前缀*10+整数列表[i]);
}
}
这里有两个针对强类型列表的通用解决方案,它们将返回列表成员的所有唯一组合(如果您能用更简单的代码解决这个问题,我向您致敬):
//递归
公共静态列表GetAllCombos(列表)
{
列表结果=新列表();
//头
结果.添加(新列表());
result.Last().Add(列表[0]);
如果(list.Count==1)
返回结果;
//尾巴
List tailCombos=GetAllCombos(List.Skip(1.ToList());
tailCombos.ForEach(combo=>
{
结果.添加(新列表(组合));
combo.Add(列表[0]);
结果.添加(新列表(组合));
});
返回结果;
}
//迭代,使用“i”作为位掩码选择每个组合成员
公共静态列表GetAllCombos(列表)
{
int comboCount=(int)Math.Pow(2,list.Count)-1;
列表结果=新列表();
对于(int i=1;i>j)%2!=0)
result.Last().Add(list[j]);
}
}
返回结果;
}
//示例用法
List combos=GetAllCombos(新的int[]{1,2,3}.ToList());
这里有一个使用递归的通用解决方案
public static ICollection<ICollection<T>> Permutations<T>(ICollection<T> list) {
var result = new List<ICollection<T>>();
if (list.Count == 1) { // If only one possible permutation
result.Add(list); // Add it and return it
return result;
}
foreach (var element in list) { // For each element in that list
var remainingList = new List<T>(list);
remainingList.Remove(element); // Get a list containing everything except of chosen element
foreach (var permutation in Permutations<T>(remainingList)) { // Get all possible sub-permutations
permutation.Add(element); // Add that element
result.Add(permutation);
}
}
return result;
}
公共静态ICollection排列(ICollection列表){
var result=新列表();
if(list.Count==1){//如果只有一个可能的置换
result.Add(list);//添加并返回
返回结果;
}
foreach(列表中的var元素){//对于该列表中的每个元素
var remainingList=新列表(列表);
remainingList.Remove(element);//获取一个包含除所选元素之外的所有内容的列表
foreach(置换中的var置换(remainglist)){//获取所有可能的子置换
permutation.Add(元素);//添加该元素
结果。添加(排列);
}
}
返回结果;
}
我知道这是一篇老文章,但有人可能会觉得这很有帮助。这个答案使用了与ojlovecd相同的算法,并且(对于他的迭代解)jaolho。我唯一要添加的是一个选项,用于过滤组合中最少数量的项目的结果。例如,如果您只对包含至少两个项目的组合感兴趣,这可能会很有用
编辑:根据@user3610374的请求,已添加最大项数的筛选器
编辑2:正如@stannius所建议的,该算法已被更改,以使其在不需要所有组合的情况下更有效
/// <summary>
/// Method to create lists containing possible combinations of an input list of items. This is
/// basically copied from code by user "jaolho" on this thread:
/// http://stackoverflow.com/questions/7802822/all-possible-combinations-of-a-list-of-values
/// </summary>
/// <typeparam name="T">type of the items on the input list</typeparam>
/// <param name="inputList">list of items</param>
/// <param name="minimumItems">minimum number of items wanted in the generated combinations,
/// if zero the empty combination is included,
/// default is one</param>
/// <param name="maximumItems">maximum number of items wanted in the generated combinations,
/// default is no maximum limit</param>
/// <returns>list of lists for possible combinations of the input items</returns>
public static List<List<T>> ItemCombinations<T>(List<T> inputList, int minimumItems = 1,
int maximumItems = int.MaxValue)
{
int nonEmptyCombinations = (int)Math.Pow(2, inputList.Count) - 1;
List<List<T>> listOfLists = new List<List<T>>(nonEmptyCombinations + 1);
// Optimize generation of empty combination, if empty combination is wanted
if (minimumItems == 0)
listOfLists.Add(new List<T>());
if (minimumItems <= 1 && maximumItems >= inputList.Count)
{
// Simple case, generate all possible non-empty combinations
for (int bitPattern = 1; bitPattern <= nonEmptyCombinations; bitPattern++)
listOfLists.Add(GenerateCombination(inputList, bitPattern));
}
else
{
// Not-so-simple case, avoid generating the unwanted combinations
for (int bitPattern = 1; bitPattern <= nonEmptyCombinations; bitPattern++)
{
int bitCount = CountBits(bitPattern);
if (bitCount >= minimumItems && bitCount <= maximumItems)
listOfLists.Add(GenerateCombination(inputList, bitPattern));
}
}
return listOfLists;
}
/// <summary>
/// Sub-method of ItemCombinations() method to generate a combination based on a bit pattern.
/// </summary>
private static List<T> GenerateCombination<T>(List<T> inputList, int bitPattern)
{
List<T> thisCombination = new List<T>(inputList.Count);
for (int j = 0; j < inputList.Count; j++)
{
if ((bitPattern >> j & 1) == 1)
thisCombination.Add(inputList[j]);
}
return thisCombination;
}
/// <summary>
/// Sub-method of ItemCombinations() method to count the bits in a bit pattern. Based on this:
/// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
/// </summary>
private static int CountBits(int bitPattern)
{
int numberBits = 0;
while (bitPattern != 0)
{
numberBits++;
bitPattern &= bitPattern - 1;
}
return numberBits;
}
//
///方法创建包含项目输入列表的可能组合的列表。这是
///基本上是从用户“jaolho”在此线程上的代码复制的:
/// http://stackoverflow.com/questions/7802822/all-possible-combinations-of-a-list-of-values
///
///输入列表中项目的类型
///项目清单
///生成的组合中需要的最小项目数,
///如果为零,则包括空组合,
///默认值为1
///生成的组合中需要的最大项数,
///默认值没有最大限制
///输入项可能组合的列表列表
公共静态列表项组合(列表输入列表,int最小项=1,
int maximumItems=int.MaxValue)
{
int nonEmptyCombinations=(int)Math.Pow(2,inputList.Count)-1;
List listOfLists=新列表(非空组合+1);
//优化空com的生成
/// <summary>
/// Method to create lists containing possible combinations of an input list of items. This is
/// basically copied from code by user "jaolho" on this thread:
/// http://stackoverflow.com/questions/7802822/all-possible-combinations-of-a-list-of-values
/// </summary>
/// <typeparam name="T">type of the items on the input list</typeparam>
/// <param name="inputList">list of items</param>
/// <param name="minimumItems">minimum number of items wanted in the generated combinations,
/// if zero the empty combination is included,
/// default is one</param>
/// <param name="maximumItems">maximum number of items wanted in the generated combinations,
/// default is no maximum limit</param>
/// <returns>list of lists for possible combinations of the input items</returns>
public static List<List<T>> ItemCombinations<T>(List<T> inputList, int minimumItems = 1,
int maximumItems = int.MaxValue)
{
int nonEmptyCombinations = (int)Math.Pow(2, inputList.Count) - 1;
List<List<T>> listOfLists = new List<List<T>>(nonEmptyCombinations + 1);
// Optimize generation of empty combination, if empty combination is wanted
if (minimumItems == 0)
listOfLists.Add(new List<T>());
if (minimumItems <= 1 && maximumItems >= inputList.Count)
{
// Simple case, generate all possible non-empty combinations
for (int bitPattern = 1; bitPattern <= nonEmptyCombinations; bitPattern++)
listOfLists.Add(GenerateCombination(inputList, bitPattern));
}
else
{
// Not-so-simple case, avoid generating the unwanted combinations
for (int bitPattern = 1; bitPattern <= nonEmptyCombinations; bitPattern++)
{
int bitCount = CountBits(bitPattern);
if (bitCount >= minimumItems && bitCount <= maximumItems)
listOfLists.Add(GenerateCombination(inputList, bitPattern));
}
}
return listOfLists;
}
/// <summary>
/// Sub-method of ItemCombinations() method to generate a combination based on a bit pattern.
/// </summary>
private static List<T> GenerateCombination<T>(List<T> inputList, int bitPattern)
{
List<T> thisCombination = new List<T>(inputList.Count);
for (int j = 0; j < inputList.Count; j++)
{
if ((bitPattern >> j & 1) == 1)
thisCombination.Add(inputList[j]);
}
return thisCombination;
}
/// <summary>
/// Sub-method of ItemCombinations() method to count the bits in a bit pattern. Based on this:
/// https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
/// </summary>
private static int CountBits(int bitPattern)
{
int numberBits = 0;
while (bitPattern != 0)
{
numberBits++;
bitPattern &= bitPattern - 1;
}
return numberBits;
}
protected List<List<T>> AllCombos<T>(Func<List<T>, List<T>, bool> comparer, params T[] items)
{
List<List<T>> results = new List<List<T>>();
List<T> workingWith = items.ToList();
results.Add(workingWith);
items.ToList().ForEach((x) =>
{
results.Add(new List<T>() { x });
});
for (int i = 0; i < workingWith.Count(); i++)
{
T removed = workingWith[i];
workingWith.RemoveAt(i);
List<List<T>> nextResults = AllCombos2(comparer, workingWith.ToArray());
results.AddRange(nextResults);
workingWith.Insert(i, removed);
}
results = results.Where(x => x.Count > 0).ToList();
for (int i = 0; i < results.Count; i++)
{
List<T> list = results[i];
if (results.Where(x => comparer(x, list)).Count() > 1)
{
results.RemoveAt(i);
}
}
return results;
}
protected List<List<T>> AllCombos2<T>(Func<List<T>, List<T>, bool> comparer, params T[] items)
{
List<List<T>> results = new List<List<T>>();
List<T> workingWith = items.ToList();
if (workingWith.Count > 1)
{
results.Add(workingWith);
}
for (int i = 0; i < workingWith.Count(); i++)
{
T removed = workingWith[i];
workingWith.RemoveAt(i);
List<List<T>> nextResults = AllCombos2(comparer, workingWith.ToArray());
results.AddRange(nextResults);
workingWith.Insert(i, removed);
}
results = results.Where(x => x.Count > 0).ToList();
for (int i = 0; i < results.Count; i++)
{
List<T> list = results[i];
if (results.Where(x => comparer(x, list)).Count() > 1)
{
results.RemoveAt(i);
}
}
return results;
}
public class CombinationGenerator{
private readonly Dictionary<int, int> currentIndexesWithLevels = new Dictionary<int, int>();
private readonly LinkedList<List<int>> _combinationsList = new LinkedList<List<int>>();
private readonly int _combinationLength;
public CombinationGenerator(int combinationLength)
{
_combinationLength = combinationLength;
}
private void InitializeLevelIndexes(List<int> list)
{
for (int i = 0; i < _combinationLength; i++)
{
currentIndexesWithLevels.Add(i+1, i);
}
}
private void UpdateCurrentIndexesForLevels(int level)
{
int index;
if (level == 1)
{
index = currentIndexesWithLevels[level];
for (int i = level; i < _combinationLength + 1; i++)
{
index = index + 1;
currentIndexesWithLevels[i] = index;
}
}
else
{
int previousLevelIndex;
for (int i = level; i < _combinationLength + 1; i++)
{
if (i > level)
{
previousLevelIndex = currentIndexesWithLevels[i - 1];
currentIndexesWithLevels[i] = previousLevelIndex + 1;
}
else
{
index = currentIndexesWithLevels[level];
currentIndexesWithLevels[i] = index + 1;
}
}
}
}
public void FindCombinations(List<int> list, int level, Stack<int> stack)
{
int currentIndex;
InitializeLevelIndexes(list);
while (true)
{
currentIndex = currentIndexesWithLevels[level];
bool levelUp = false;
for (int i = currentIndex; i < list.Count; i++)
{
if (level < _combinationLength)
{
currentIndex = currentIndexesWithLevels[level];
MoveToUpperLevel(ref level, stack, list, currentIndex);
levelUp = true;
break;
}
levelUp = false;
stack.Push(list[i]);
if (stack.Count == _combinationLength)
{
AddCombination(stack);
stack.Pop();
}
}
if (!levelUp)
{
MoveToLowerLevel(ref level, stack, list, ref currentIndex);
while (currentIndex >= list.Count - 1)
{
if (level == 1)
{
AdjustStackCountToCurrentLevel(stack, level);
currentIndex = currentIndexesWithLevels[level];
if (currentIndex >= list.Count - 1)
{
return;
}
UpdateCurrentIndexesForLevels(level);
}
else
{
MoveToLowerLevel(ref level, stack, list, ref currentIndex);
}
}
}
}
}
private void AddCombination(Stack<int> stack)
{
List<int> listNew = new List<int>();
listNew.AddRange(stack);
_combinationsList.AddLast(listNew);
}
private void MoveToUpperLevel(ref int level, Stack<int> stack, List<int> list, int index)
{
stack.Push(list[index]);
level++;
}
private void MoveToLowerLevel(ref int level, Stack<int> stack, List<int> list, ref int currentIndex)
{
if (level != 1)
{
level--;
}
AdjustStackCountToCurrentLevel(stack, level);
UpdateCurrentIndexesForLevels(level);
currentIndex = currentIndexesWithLevels[level];
}
private void AdjustStackCountToCurrentLevel(Stack<int> stack, int currentLevel)
{
while (stack.Count >= currentLevel)
{
if (stack.Count != 0)
stack.Pop();
}
}
public void PrintPermutations()
{
int count = _combinationsList.Where(perm => perm.Count() == _combinationLength).Count();
Console.WriteLine("The number of combinations is " + count);
}
}
static void Main(string[] args)
{
Combos(new [] { 1, 2, 3 });
}
static void Combos(int[] arr)
{
for (var i = 0; i <= Math.Pow(2, arr.Length); i++)
{
Console.WriteLine();
var j = i;
var idx = 0;
do
{
if ((j & 1) == 1) Console.Write($"{arr[idx]} ");
} while ((j >>= 1) > 0 && ++idx < arr.Length);
}
}
static void Main(string[] args)
{
foreach (var vals in Combos(new[] { "0", "1", "2", "3" }).Where(v => v.Skip(1).Any() && !v.Skip(2).Any()))
Console.WriteLine(string.Join(", ", vals));
}
static IEnumerable<IEnumerable<T>> Combos<T>(T[] arr)
{
IEnumerable<T> DoQuery(long j, long idx)
{
do
{
if ((j & 1) == 1) yield return arr[idx];
} while ((j >>= 1) > 0 && ++idx < arr.Length);
}
for (var i = 0; i < Math.Pow(2, arr.Length); i++)
yield return DoQuery(i, 0);
}
public static IEnumerable<T[]> Combinations<T>(IEnumerable<T> source) {
if (null == source)
throw new ArgumentNullException(nameof(source));
T[] data = source.ToArray();
return Enumerable
.Range(0, 1 << (data.Length))
.Select(index => data
.Where((v, i) => (index & (1 << i)) != 0)
.ToArray());
}
var data = new char[] { 'A', 'B', 'C' };
var result = Combinations(data);
foreach (var item in result)
Console.WriteLine($"[{string.Join(", ", item)}]);
[]
[A]
[B]
[A, B]
[C]
[A, C]
[B, C]
[A, B, C]
public static List<List<int>> GetCombination(List<int> lst, int index, int count)
{
List<List<int>> combinations = new List<List<int>>();
List<int> comb;
if (count == 0 || index == lst.Count)
{
return null;
}
for (int i = index; i < lst.Count; i++)
{
comb = new List<int>();
comb.Add(lst.ElementAt(i));
combinations.Add(comb);
var rest = GetCombination(lst,i + 1, count - 1);
if (rest != null)
{
foreach (var item in rest)
{
combinations.Add(comb.Union(item).ToList());
}
}
}
return combinations;
}
List<int> lst= new List<int>(new int[]{ 1, 2, 3, 4 });
var combinations = GetCombination(lst, 0, lst.Length)
static void Main(string[] args)
{
GetCombination(new List<int> { 1, 2, 3 });
}
private static void GetCombination(List<int> list)
{
double count = Math.Pow(2, list.Count);
for (int i = 1; i <= count - 1; i++)
{
for (int j = 0; j < list.Count; j++)
{
int b = i & (1 << j);
if (b > 0)
{
Console.Write(list[j]);
}
}
Console.WriteLine();
}
}
private static List<string> GetCombinations(List<string> elements)
{
List<string> combinations = new List<string>();
combinations.AddRange(elements);
for (int i = 0; i < elements.Count - 1; i++)
{
combinations = (from combination in combinations
join element in elements on 1 equals 1
let value = string.Join(string.Empty, $"{combination}{element}".OrderBy(c => c).Distinct())
select value).Distinct().ToList();
}
return combinations;
}
List<string> elements = new List<string> { "1", "2", "3" };
List<string> combinations = GetCombinations(elements);
foreach (string combination in combinations)
{
System.Console.Write(combination);
}