一个List<int>集合,里面有33个元素,每次从中任意取6个元素,会有很多种提取方法。
要求把所有提取方法,所提取的6个元素为一组的List<int>(6个数字),放到一个大的List<List<int>>中。也就是说,假如有100种提取方法,那么,每次提取的6个数字组成一个List<int>,最后把100个List<int>,放到一个List<List<int>>中去。
我在网上摘得方法速度不是很快,谁搜藏有经典的算法
要求把所有提取方法,所提取的6个元素为一组的List<int>(6个数字),放到一个大的List<List<int>>中。也就是说,假如有100种提取方法,那么,每次提取的6个数字组成一个List<int>,最后把100个List<int>,放到一个List<List<int>>中去。
我在网上摘得方法速度不是很快,谁搜藏有经典的算法
因此任意拿6个元素的组合方法总共有33*32*31*30*29*28 = 797448960假设一组6个数字算6个字节(如果使用int还要大,为24个字节),即使不算List的开销,存放800兆的组合也要4.8G的内存。你要想想你的目的是什么,有没有必要"把所有提取方法...放到一个大的List..."。
调用方法就是:
ListCombinations(33, 6);
应该可以再调整优化,但思路就这样了,这个算法应该是比较快的了。C# Debug模式生成算出这个列表所有这些用了两三秒时间。没有测具体列表内容,但输出列表的长度的确是1107468(即33中取6的组合数)应该差不离了。也都打到内存里,算一下应该也就几十兆内存。
static List<List<int>> ListCombinations(int numTotal, int numSelected)
{
var result = new List<List<int>>();
var basePos = new int[numSelected+1];
for (var i = 0; i < numSelected; i++)
{
basePos[i] = i;
}
basePos[numSelected] = numTotal; for(var i = numSelected - 1; i>=0; )
{
result.Add(new List<int>(basePos));
basePos[i]++;
if (basePos[i] >= basePos[i + 1])
{
do
{
i--;
} while(i >= 0 && basePos[i] + numSelected - i >= numTotal);
if (i >= 0)
{
basePos[i]++;
for (var j = i + 1; j < numSelected; j++)
{
basePos[j] = basePos[j - 1] + 1;
}
i = numSelected - 1;
}
}
}
return result;
}
static void Main(string[] args)
{
int[] fom=new int[6]{0,0,0,0,0,0};
GetList(fom,1);
Console.Write(count);
Console.Read();
} static int count = 0; private static void GetList(int[] fomula, int current)
{
if (current == 7) {
count++;
//Console.WriteLine(fomula.Aggregate("",(one, two) => one +" "+ two));
return; }
int begin =fomula.Max() + 1;
int end = 33 - (6-current);
for (; begin <= end; begin++)
{
fomula[current-1]=begin;
GetList(fomula, current + 1);
fomula[current - 1] = 0;
}
}我没有写保存的部分,我感觉保存成位图的方式比较好
保存成一个33bit的,其中会有六个位是1,其他是0,选前6个就是1111110000000000
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<List<int>> result = Combo(33, 6).ToList();
Console.WriteLine(result.Count);
} static IEnumerable<List<int>> Combo(int m, int n)
{
var query = Enumerable.Range(1, m).Select(x => new List<int> { x });
for (int i = 1; i < n; i++)
{
query = query.SelectMany(x => Enumerable.Range(x.Last() + 1, m - x.Last()).Select(y =>
{
var r = x.ToList(); r.Add(y); return r;
}));
}
return query;
}
}
}1107568
http://bbs.csdn.net/topics/300076865我见到一款软件,其运算速度比较快,不知是怎么写的
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<List<int>> list = new List<List<int>>();
for (int i = 0; i < 1107568; i++)
{
List<int> l = new List<int>();
for (int j = 0; j < 6; j++)
l.Add(j);
list.Add(l);
}
}
}
}如果你固执地希望使用List<List<int>>,这是无论任何算法都不能超越的性能极限,因为它就是产生这么多个空的列表。我的算法也就比理论极限慢了50%。也就是说,你花无限大的努力,也就是最多把速度翻一倍。
我说了,性能原因在于你固执地坚持List<List<int>>这样的数据结构。你可以测试我14L的代码——它不做任何计算,就是产生这么多个固定的列表,也要大约耗费一半的时间。显然无论算法是什么,都不可能快过什么都不算。所以不能说我的算法性能不好,因为付出更多的努力,去找更快的算法在我看来是不值得的。
是在List<List<string>>中,任意取N个元素(这个N值又有很多种)是正确的,除去N个元素的的剩下都是错的。当中存在取合集,取交集,因此,需要运算速度。急用