一个List<int>集合,里面有33个元素,每次从中任意取6个元素,会有很多种提取方法。
要求把所有提取方法,所提取的6个元素为一组的List<int>(6个数字),放到一个大的List<List<int>>中。也就是说,假如有100种提取方法,那么,每次提取的6个数字组成一个List<int>,最后把100个List<int>,放到一个List<List<int>>中去。
我在网上摘得方法速度不是很快,谁搜藏有经典的算法

解决方案 »

  1.   

    拿第一个有33种方法,拿第二个则只有32种......
    因此任意拿6个元素的组合方法总共有33*32*31*30*29*28 = 797448960假设一组6个数字算6个字节(如果使用int还要大,为24个字节),即使不算List的开销,存放800兆的组合也要4.8G的内存。你要想想你的目的是什么,有没有必要"把所有提取方法...放到一个大的List..."。
      

  2.   

    做了一个,感觉应该不是很慢,忽略输出每一行的最后一个元素,它总是元素总和在这里就是33,那个是作为算法内部的守卫的。而前面几个数字是选择元素的index减1,所以例如选1,2,3,4,5,6这六个元素,List<int>中内容就是:0,1,2,3,4,5,33。
    调用方法就是:
    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;
    }
      

  3.   

    确实是1107568个private readonly int AllLength = 33;
            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
      

  4.   

    http://bbs.csdn.net/topics/300076865
      

  5.   

    using System;
    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
      

  6.   

    结果是没错,不过,速度不快,颌下面链接中的6楼的方法速度差不多
    http://bbs.csdn.net/topics/300076865我见到一款软件,其运算速度比较快,不知是怎么写的
      

  7.   

    using System;
    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%。也就是说,你花无限大的努力,也就是最多把速度翻一倍。
      

  8.   


    我说了,性能原因在于你固执地坚持List<List<int>>这样的数据结构。你可以测试我14L的代码——它不做任何计算,就是产生这么多个固定的列表,也要大约耗费一半的时间。显然无论算法是什么,都不可能快过什么都不算。所以不能说我的算法性能不好,因为付出更多的努力,去找更快的算法在我看来是不值得的。
      

  9.   

    我索取这个速度,是因为程序中有很多地方要进行下面这样的计算:在List<string>中,任意取N个元素(这个N值又有很多种)是正确的,除去N个元素的的剩下都是错的。当中存在取合集,取交集,因此,需要运算速度
      

  10.   

    更正一下,是在List<List<string>>中,任意取N个元素(这个N值又有很多种)是正确的,除去N个元素的的剩下都是错的。当中存在取合集,取交集,因此,需要运算速度。急用
      

  11.   

    http://www.cpdyj.com/html/soft/ssq/现在我的程序从开始运算到结束,需要大约40秒,显然是不行的。我索取这个速度,是因为程序中有很多地方要进行下面这样的计算:
    是在List<List<string>>中,任意取N个元素(这个N值又有很多种)是正确的,除去N个元素的的剩下都是错的。当中存在取合集,取交集,因此,需要运算速度。急用