有十个元素,按不同位置进行组合,元素不得重复,一共有多少种可能?

hailan_li 2017-08-18 12:01:53
元素:1,2,3,4,5,6,7,8,9,10
把这10个元素进行组合,组合成10个元素为一组的组合,组合元素的位置可以不相同,但每个元素只能取一次,请问一共有多少种组合可能性?并在控制台打印输出,代码如何实现呢?谢谢!
1,2,3,4,5,6,7,8,9,10
1,2,4,3,5,6,7,8,9,10
1,2,5,4,3,6,7,8,9,10
1,2,6,5,4,3,7,8,9,10
1,2,7,6,5,4,3,8,9,10
1,2,8,7,6,5,4,3,9,10
1,2,9,8,7,6,5,4,3,10
1,2,10,9,8,7,6,5,4,3
.........
1,2,3,4,5,6,7,8,10,9
1,2,3,4,5,6,7,10,9,8
1,2,3,4,5,6,7,9,8,10
...........
10,9,8,7,6,5,4,3,2,1
10,8,7,6,5,4,3,2,1,9
............................

我大概举例了下,我在网上用排列组合计算器计算了下,一共3628800种组合可能,但我想用代码实现,并输出每一种可能性








...全文
742 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
hailan_li 2017-08-19
  • 打赏
  • 举报
回复
引用 15 楼 sp1234 的回复:
c# 是很优雅的语言,关键其实还要看你的数学和算法知识是否具备,如果基础知识不理解那么语法也就肤浅,如果基础知识足够那么c#语法才有意义:
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var source = new int[] { 1, 2, 8, 9 };
            var cnt = 0;
            foreach (var x in 排列(source))
            {
                Console.Write("{0}:\t", ++cnt);
                foreach (var y in x)
                    Console.Write("{0} ", y);
                Console.WriteLine();
            }
            Console.WriteLine("...............按任意键退出");
            Console.ReadKey();
        }

        private static IEnumerable<List<int>> 排列(int[] arr)
        {
            return 排列(arr, arr.Length);
        }

        private static IEnumerable<List<int>> 排列(int[] arr, int len)
        {
            if (len <= 1)
                yield return new List<int> { arr[0] };
            else if (len <= arr.Length)
            {
                var 最右边元素 = arr[len - 1];
                foreach (var x in 排列(arr, len - 1))
                    for (var i = 0; i <= x.Count; i++)
                    {
                        var clone = x.ToList();
                        clone.Insert(i, 最右边元素);
                        yield return clone;
                    }
            }
        }
    }
}
不好意思,没注意到您的回复,不然也应该给您一定比例分值,实在抱歉,大神
  • 打赏
  • 举报
回复
而根本先把所有计算做完了才筛选结果 --> 而根本不是先把所有计算做完了才筛选结果 对这类问题容易纠结在什么数据、集合上。其实真正实用中,你需要的能力是把 query 预编译为一个委托而不断重复调用,你需要的能力是延迟计算能力,你需要的能力是把筛选表达式推入这个 query 内部深处的能力,你需要的是 Take(10) 这样的能力.......
  • 打赏
  • 举报
回复
你需要注意的是,简单清晰的编程模式,延迟计算和提前筛选(而根本先把所有计算做完了才筛选结果),等等编程能力。
  • 打赏
  • 举报
回复
注意,重点其实并不是纠结代码行数的多少,而是编程模式应用。 比如说,我们要得到“1~9中其中有3连数,并且数字与下标的乘积之和不大于100”的组合,最多只要10个就够了,那么就直接写
var source = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var query = from x in 排列(source)
            from p in Enumerable.Range(0, 7)
            let a = x[p]
            let b = x[p + 1]
            let c = x[p + 2]
            where a + 1 == b && b + 1 == c
            let s = from n in Enumerable.Range(0, source.Length)
                    select x[n] + n
            where s.Sum() <= 100
            select x;
var result = query.Take(10).ToArray();
这种能力才是我们要的。如果只会一小段计算代码,而不放到宽广的应用背景中,你就会错失 c# 的很多内容。
hailan_li 2017-08-19
  • 打赏
  • 举报
回复

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;


namespace NUMBER10
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            StreamWriter sw = new StreamWriter(@"E:\Services\PK10\PK10\PK10\obj\Debug\all.txt");
            DateTime startDate = DateTime.Now;
            sw.WriteLine(string.Join(",", a));
            int counts = 1;
            while (NextPermutation(a))
            {
                sw.WriteLine(string.Join(",", a));
                counts++;
            }
            sw.Close();
            sw.Dispose();
            TimeSpan ts = DateTime.Now.Subtract(startDate);
            Console.WriteLine(counts.ToString() + " items");
            Console.WriteLine(ts.TotalMilliseconds.ToString() + " mill seconds");
            Console.ReadKey();
        }

        public static bool NextPermutation(int[] a)
        {
            int first = 0;
            int last = a.Length;
            int c, j, m, n;

            int i = last;
            i--;
            while (true)
            {
                var t = i;
                i--;
                if (a[i] < a[t])
                {
                    j = last;
                    while (!(a[i] < a[--j])) ;
                    c = a[i];
                    a[i] = a[j];
                    a[j] = c;
                    m = t;
                    n = last - 1;
                    while (m < n)
                    {
                        c = a[n];
                        a[n] = a[m];
                        a[m] = c;
                        m++;
                        n--;
                    }
                    return true;
                }
                if (i == first)
                {
                    m = first;
                    n = last - 1;
                    while (m < n)
                    {
                        c = a[n];
                        a[n] = a[m];
                        a[m] = c;
                        m++;
                        n--;
                    }
                    return false;
                }
            }
        }
    }
}

output 3628800 items 3450 mill seconds
  • 打赏
  • 举报
回复
c# 是很优雅的语言,关键其实还要看你的数学和算法知识是否具备,如果基础知识不理解那么语法也就肤浅,如果基础知识足够那么c#语法才有意义:
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var source = new int[] { 1, 2, 8, 9 };
            var cnt = 0;
            foreach (var x in 排列(source))
            {
                Console.Write("{0}:\t", ++cnt);
                foreach (var y in x)
                    Console.Write("{0} ", y);
                Console.WriteLine();
            }
            Console.WriteLine("...............按任意键退出");
            Console.ReadKey();
        }

        private static IEnumerable<List<int>> 排列(int[] arr)
        {
            return 排列(arr, arr.Length);
        }

        private static IEnumerable<List<int>> 排列(int[] arr, int len)
        {
            if (len <= 1)
                yield return new List<int> { arr[0] };
            else if (len <= arr.Length)
            {
                var 最右边元素 = arr[len - 1];
                foreach (var x in 排列(arr, len - 1))
                    for (var i = 0; i <= x.Count; i++)
                    {
                        var clone = x.ToList();
                        clone.Insert(i, 最右边元素);
                        yield return clone;
                    }
            }
        }
    }
}
hailan_li 2017-08-19
  • 打赏
  • 举报
回复
引用 8 楼 xuzuning 的回复:
算法很多,一搜一大把 推荐一个 这是从 C++ STL next_permutation 库函数移植过来的,没有缓存开销
        public static bool NextPermutation(int[] a)
        {
            int first = 0;
            int last = a.Length;
            int c, j, m, n;

            int i = last;
            i--;
            while (true)
            {
                var t = i;
                i--;
                if (a[i] < a[t])
                {
                    j = last;
                    while (!(a[i] < a[--j])) ;
                    c = a[i];
                    a[i] = a[j];
                    a[j] = c;
                    m = t;
                    n = last - 1;
                    while (m < n)
                    {
                        c = a[n];
                        a[n] = a[m];
                        a[m] = c;
                        m++;
                        n--;
                    }
                    return true;
                }
                if (i == first)
                {
                    m = first;
                    n = last - 1;
                    while (m < n)
                    {
                        c = a[n];
                        a[n] = a[m];
                        a[m] = c;
                        m++;
                        n--;
                    }
                    return false;
                }
            }
        }
调用
int[] a = {1,2,3,4,5,6,7,8,9,10};
while(NextPermutation(a))
{
........
}
这个算法没有包含自身的排列,比如 int[] a={1,2,3} output: 1,3,2 2,1,3 2,3,1 3,2,1 3,1,2 还差一个1,2,3自己没出来哈,不过这样已经满足了,能达到我的目前,真实大神呀
hailan_li 2017-08-18
  • 打赏
  • 举报
回复
比如 1,2,3 和 3,2,1 属于同一组合,但有位置排列要求,用C#代码如何循环得出所有可能性啊?大神们,帮帮忙写个示例吧
xuzuning 2017-08-18
  • 打赏
  • 举报
回复
10! 你这不是组合,而是排列 组合是不考虑位置的,比如 1,2,3 和 3,2,1 属于同一组合 由组合数公式 C(n,m) = n!/((n-m)!*m!) 可知 C(10,10) = 1 (0的阶乘为1)
闭包客 2017-08-18
  • 打赏
  • 举报
回复
呵呵,可以使用蒙地卡罗法,逻辑最简单。
hailan_li 2017-08-18
  • 打赏
  • 举报
回复
能写一段代码出来参考吗?
ilikeff8 2017-08-18
  • 打赏
  • 举报
回复
但是如果你是想打出具体内容,最笨最简单的办法就是10层循环,而且去掉重复的
ilikeff8 2017-08-18
  • 打赏
  • 举报
回复
C10,10的组合公式套用算一下即可,无法是N!用循环变量计算
hailan_li 2017-08-18
  • 打赏
  • 举报
回复
请问要如何循环得以实现呢?
hailan_li 2017-08-18
  • 打赏
  • 举报
回复
我试试你们的代码
by_封爱 版主 2017-08-18
  • 打赏
  • 举报
回复
这不就是排量组合吗? 百度一搜索一大堆. http://www.cnblogs.com/rogerwei/archive/2010/11/18/1880336.html
xuzuning 2017-08-18
  • 打赏
  • 举报
回复
a 是数组,直接打印不出来的 Console.WriteLine(string.Join(",",a));
拜一刀 2017-08-18
  • 打赏
  • 举报
回复
10!
hailan_li 2017-08-18
  • 打赏
  • 举报
回复
引用 8 楼 xuzuning 的回复:
算法很多,一搜一大把 推荐一个 这是从 C++ STL next_permutation 库函数移植过来的,没有缓存开销
        public static bool NextPermutation(int[] a)
        {
            int first = 0;
            int last = a.Length;
            int c, j, m, n;

            int i = last;
            i--;
            while (true)
            {
                var t = i;
                i--;
                if (a[i] < a[t])
                {
                    j = last;
                    while (!(a[i] < a[--j])) ;
                    c = a[i];
                    a[i] = a[j];
                    a[j] = c;
                    m = t;
                    n = last - 1;
                    while (m < n)
                    {
                        c = a[n];
                        a[n] = a[m];
                        a[m] = c;
                        m++;
                        n--;
                    }
                    return true;
                }
                if (i == first)
                {
                    m = first;
                    n = last - 1;
                    while (m < n)
                    {
                        c = a[n];
                        a[n] = a[m];
                        a[m] = c;
                        m++;
                        n--;
                    }
                    return false;
                }
            }
        }
调用
int[] a = {1,2,3,4,5,6,7,8,9,10};
while(NextPermutation(a))
{
........
}
Console.WriteLine(a); 这样就是我想要的具体每一种排列结果了,对吗?
xuzuning 2017-08-18
  • 打赏
  • 举报
回复
算法很多,一搜一大把 推荐一个 这是从 C++ STL next_permutation 库函数移植过来的,没有缓存开销
        public static bool NextPermutation(int[] a)
        {
            int first = 0;
            int last = a.Length;
            int c, j, m, n;

            int i = last;
            i--;
            while (true)
            {
                var t = i;
                i--;
                if (a[i] < a[t])
                {
                    j = last;
                    while (!(a[i] < a[--j])) ;
                    c = a[i];
                    a[i] = a[j];
                    a[j] = c;
                    m = t;
                    n = last - 1;
                    while (m < n)
                    {
                        c = a[n];
                        a[n] = a[m];
                        a[m] = c;
                        m++;
                        n--;
                    }
                    return true;
                }
                if (i == first)
                {
                    m = first;
                    n = last - 1;
                    while (m < n)
                    {
                        c = a[n];
                        a[n] = a[m];
                        a[m] = c;
                        m++;
                        n--;
                    }
                    return false;
                }
            }
        }
调用
int[] a = {1,2,3,4,5,6,7,8,9,10};
while(NextPermutation(a))
{
........
}

110,566

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧