C# 获取集合的所有子集
我正在尝试创建一个方法,该方法将返回集合的所有子集 例如,如果我有集合C# 获取集合的所有子集,c#,algorithm,set,subset,C#,Algorithm,Set,Subset,我正在尝试创建一个方法,该方法将返回集合的所有子集 例如,如果我有集合10,20,30,我希望得到以下输出 return new List<List<int>>() { new List<int>(){10}, new List<int>(){20}, new List<int>(){30}, new List
10,20,30
,我希望得到以下输出
return new List<List<int>>()
{
new List<int>(){10},
new List<int>(){20},
new List<int>(){30},
new List<int>(){10,20},
new List<int>(){10,30},
new List<int>(){20,30},
//new List<int>(){20,10}, that substet already exists
// new List<int>(){30,20}, that subset already exists
new List<int>(){10,20,30}
};
返回新列表()
{
新列表(){10},
新列表(){20},
新列表(){30},
新列表(){10,20},
新列表(){10,30},
新列表(){20,30},
//新列表(){20,10},该子集已存在
//新列表(){30,20},该子集已存在
新列表(){10,20,30}
};
因为集合也可以是字符串的集合,例如,我想创建一个泛型方法。这就是我所做的
static void Main(字符串[]args)
{
Foo(新int[]{10,20,30});
}
静态列表Foo(T[]集)
{
//初始化列表
列表子集=新列表();
//在单个元素上循环
for(int i=1;i
编辑 对不起,这是错误的,我仍然得到重复
static List<List<T>> GetSubsets<T>(IEnumerable<T> Set)
{
var set = Set.ToList<T>();
// Init list
List<List<T>> subsets = new List<List<T>>();
subsets.Add(new List<T>()); // add the empty set
// Loop over individual elements
for (int i = 1; i < set.Count; i++)
{
subsets.Add(new List<T>(){set[i - 1]});
List<List<T>> newSubsets = new List<List<T>>();
// Loop over existing subsets
for (int j = 0; j < subsets.Count; j++)
{
var newSubset = new List<T>();
foreach(var temp in subsets[j])
newSubset.Add(temp);
newSubset.Add(set[i]);
newSubsets.Add(newSubset);
}
subsets.AddRange(newSubsets);
}
// Add in the last element
subsets.Add(new List<T>(){set[set.Count - 1]});
//subsets.Sort();
return subsets;
}
静态列表GetSubset(IEnumerable集合)
{
var set=set.ToList();
//初始化列表
列表子集=新列表();
subsets.Add(new List());//添加空集
//在单个元素上循环
for(int i=1;i
然后我可以将该方法称为:
如果不想返回一组列表,则需要使用java的集合类型。Set已经完成了您正在寻找的部分工作,它只保存了每种类型的一个唯一元素。例如,你不能再加20次。这是一种无序类型,因此您可以编写一个组合函数,创建一组集合,然后返回一个包含这些集合列表的列表。这是一个基本算法,我使用下面的技术制作了一个单人拼字解算器(报纸上的) 让您的集合具有
n
元素。将从0开始的整数递增到2^n
。对于每个生成器编号,位掩码为整数的每个位置。如果整数的i
th位置为1
,则选择集合的i
th元素。对于从0
到2^n
的每个生成的整数,执行上述比特排序和选择将获得所有子集
这里有一个帖子:我知道这个问题有点老了,但我一直在寻找答案,在这里没有找到任何好的答案,所以我想分享这个解决方案,这是在这个博客中找到的一个改编: 我仅将该类转换为泛型类:
public class SubSet<T>
{
private IList<T> _list;
private int _length;
private int _max;
private int _count;
public SubSet(IList<T> list)
{
if (list== null)
throw new ArgumentNullException("lista");
_list = list;
_length = _list.Count;
_count = 0;
_max = (int)Math.Pow(2, _length);
}
public IList<T> Next()
{
if (_count == _max)
{
return null;
}
uint rs = 0;
IList<T> l = new List<T>();
while (rs < _length)
{
if ((_count & (1u << (int)rs)) > 0)
{
l.Add(_list[(int)rs]);
}
rs++;
}
_count++;
return l;
}
}
公共类子集
{
私有IList_列表;
私有整数长度;
私人国际最大值;
私人国际单位计数;
公共子集(IList列表)
{
if(list==null)
抛出新的ArgumentNullException(“lista”);
_列表=列表;
_长度=_list.Count;
_计数=0;
_max=(int)数学功率(2,_长度);
}
公共IList Next()
{
如果(\u计数=\u最大值)
{
返回null;
}
uint-rs=0;
IList l=新列表();
while(rs<\u长度)
{
如果(_计数和(1u 0)
{
l、 添加(_list[(int)rs]);
}
rs++;
}
_计数++;
返回l;
}
}
要使用此代码,您可以执行以下操作:
List<string> lst = new List<string>();
lst.AddRange(new string[] {"A", "B", "C" });
SubSet<string> subs = new SubSet<string>(lst);
IList<string> l = subs.Next();
while (l != null)
{
DoSomething(l);
l = subs.Next();
}
List lst=new List();
lst.AddRange(新字符串[]{“A”、“B”、“C”});
子集subs=新子集(lst);
IList l=subs.Next();
while(l!=null)
{
剂量测定法(l);
l=subs.Next();
}
请记住:此代码仍然是O(2^n),如果您在列表中传递20个元素,您将得到2^20=1048576子集
编辑:
正如Servy sugest我添加了一个带有interator块的实现以用于Linq an foreach,新类如下所示:
private class SubSet<T> : IEnumerable<IEnumerable<T>>
{
private IList<T> _list;
private int _length;
private int _max;
private int _count;
public SubSet(IEnumerable<T> list)
{
if (list == null)
throw new ArgumentNullException("list");
_list = new List<T>(list);
_length = _list.Count;
_count = 0;
_max = (int)Math.Pow(2, _length);
}
public int Count
{
get { return _max; }
}
private IList<T> Next()
{
if (_count == _max)
{
return null;
}
uint rs = 0;
IList<T> l = new List<T>();
while (rs < _length)
{
if ((_count & (1u << (int)rs)) > 0)
{
l.Add(_list[(int)rs]);
}
rs++;
}
_count++;
return l;
}
public IEnumerator<IEnumerable<T>> GetEnumerator()
{
IList<T> subset;
while ((subset = Next()) != null)
{
yield return subset;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
List<string> lst = new List<string>();
lst.AddRange(new string[] {"A", "B", "C" });
SubSet<string> subs = new SubSet<string>(lst);
foreach(IList<string> l in subs)
{
DoSomething(l);
}
私有类子集:IEnumerable
{
私有IList_列表;
私有整数长度;
私人国际最大值;
私人国际单位计数;
公共子集(IEnumerable列表)
{
if(list==null)
抛出新的ArgumentNullException(“列表”);
_列表=新列表(列表);
_长度=_list.Count;
_计数=0;
_max=(int)数学功率(2,_长度);
}
公共整数计数
{
获取{return\u max;}
}
私有IList Next()
{
如果(\u计数=\u最大值)
{
List<string> lst = new List<string>();
lst.AddRange(new string[] {"A", "B", "C" });
SubSet<string> subs = new SubSet<string>(lst);
foreach(IList<string> l in subs)
{
DoSomething(l);
}
public static IEnumerable<IEnumerable<T>> Subsets<T>(IEnumerable<T> source)
{
List<T> list = source.ToList();
int length = list.Count;
int max = (int)Math.Pow(2, list.Count);
for (int count = 0; count < max; count++)
{
List<T> subset = new List<T>();
uint rs = 0;
while (rs < length)
{
if ((count & (1u << (int)rs)) > 0)
{
subset.Add(list[(int)rs]);
}
rs++;
}
yield return subset;
}
}
public static IEnumerable<IEnumerable<T>> GetPermutations<T>(IEnumerable<T> list, int length) where T : IComparable
{
if (length == 1) return list.Select(t => new T[] { t });
return GetPermutations(list, length - 1).SelectMany(t => list.Where(e => t.All(g => g.CompareTo(e) != 0)), (t1, t2) => t1.Concat(new T[] { t2 }));
}
public static IEnumerable<IEnumerable<T>> GetOrderedSubSets<T>(IEnumerable<T> list, int length) where T : IComparable
{
if (length == 1) return list.Select(t => new T[] { t });
return GetOrderedSubSets(list, length - 1).SelectMany(t => list.Where(e => t.All(g => g.CompareTo(e) == -1)), (t1, t2) => t1.Concat(new T[] { t2 }));
}
List<int> set = new List<int> { 1, 2, 3 };
foreach (var x in GetPermutations(set, 3))
{
Console.WriteLine(string.Join(", ", x));
}
Console.WriteLine();
foreach (var x in GetPermutations(set, 2))
{
Console.WriteLine(string.Join(", ", x));
}
Console.WriteLine();
foreach (var x in GetOrderedSubSets(set, 2))
{
Console.WriteLine(string.Join(", ", x));
}
1, 2, 3
1, 3, 2
2, 1, 3
2, 3, 1
3, 1, 2
3, 2, 1
1, 2
1, 3
2, 1
2, 3
3, 1
3, 2
1, 2
1, 3
2, 3
class Program
{
static HashSet<List<int>> SubsetMaker(int[] a, int sum)
{
var set = a.ToList<int>();
HashSet<List<int>> subsets = new HashSet<List<int>>();
subsets.Add(new List<int>());
for (int i =0;i<set.Count;i++)
{
//subsets.Add(new List<int>() { set[i]});
HashSet<List<int>> newSubsets = new HashSet<List<int>>();
for (int j = 0; j < subsets.Count; j++)
{
var newSubset = new List<int>();
foreach (var temp in subsets.ElementAt(j))
{
newSubset.Add(temp);
}
newSubset.Add(set[i]);
newSubsets.Add(newSubset);
}
Console.WriteLine("New Subset");
foreach (var t in newSubsets)
{
var temp = string.Join<int>(",", t);
temp = "{" + temp + "}";
Console.WriteLine(temp);
}
Console.ReadLine();
subsets.UnionWith(newSubsets);
}
//subsets.Add(new List<int>() { set[set.Count - 1] });
//subsets=subsets.;
return subsets;
}
static void Main(string[] args)
{
int[] b = new int[] { 1,2,3 };
int suma = 6;
var test = SubsetMaker(b, suma);
Console.WriteLine("Printing final set...");
foreach (var t in test)
{
var temp = string.Join<int>(",", t);
temp = "{" + temp + "}";
Console.WriteLine(temp);
}
Console.ReadLine();
}
}
private static List<List<int>> GetPowerList(List<int> a)
{
int n = a.Count;
var sublists = new List<List<int>>() { new List<int>() };
for (int i = 0; i < n; i++)
{
for (int j = i; j < n; j++)
{
var first = a[i];
var last = a[j];
if ((j - i) > 1)
{
sublists.AddRange(GetPowerList(a
.GetRange(i + 1, j - i - 1))
.Select(l => l
.Prepend(first)
.Append(last).ToList()));
}
else sublists.Add(a.GetRange(i,j - i + 1));
}
}
return sublists;
}