请教一个二维数组排列组合的问题。

993356686 2018-03-21 02:26:56
C#问题:
例如数组
List0={{0},{1},{2},{3}},三三组合:012,013,123,023,共有4种组合方式。
List1={{1,2},{3},{5},{1}},三三组合:135,131,235,231,151,251,351,共有7种组合方式。
List1={{1,2},{3,4},{5},{1}},三三组合:135,131,235,231,151,251,351,145,141,245,241,451共有12种组合方式。
请问该如何计算此类数组的组合方式的个数。
数组里子项的长度不固定,可能为{{0},{1},{2},{3}},也可能为{{0,1,2,3,4},{1},{2},{3}}也可能为{{0,1,2,3,4},{0,1,2,3,4},{2,4},{3}}

-------------------------------------------------------------------------------
上面List子项有4项,如果List子项有5项怎么求。
...全文
276 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
993356686 2018-03-21
  • 打赏
  • 举报
回复
引用 4 楼 xuzuning 的回复:
        static void Main(string[] args)
        {
            var List0 = new int[][]
            {
                new int[] {1, 2},
                new int[] {3, 4},
                new int[] {5},
                new int[] {1}
            };
            foreach (var c in List0.Combination(3))
            {
                foreach (var x in c.CartesianProduct())
                {
                    Console.WriteLine(string.Join(",", x));
                }
            }
        }
此方法完美可行,我也想到了另外的计算方式了。两种都OK!感谢!
xuzuning 2018-03-21
  • 打赏
  • 举报
回复
对集合的扩展是 Linq 提供的,需引用 Linq(using System.Linq;) 如果你的开发环境不支持 Linq,可改写我的代码,或到网上去搜这两个算法的代码(很多的,就 CSND 也至少有 10 个版本)
xuzuning 2018-03-21
  • 打赏
  • 举报
回复
不会吧?我用的好好的 报什么错?
993356686 2018-03-21
  • 打赏
  • 举报
回复
引用 9 楼 xuzuning 的回复:
不会吧?我用的好好的 报什么错?
没问题,谢谢啦,我验证一下
993356686 2018-03-21
  • 打赏
  • 举报
回复
引用 3 楼 xuzuning 的回复:
        static void Main(string[] args)
        {
            var List0 = new int[][]
            {
                new int[] {0},
                new int[] {1},
                new int[] {2},
                new int[] {3}
            };
            foreach (var c in List0.Combination(3))
            {
                foreach (var x in c.CartesianProduct())
                {
                    Console.WriteLine(string.Join(",", x));
                }
            }
        }
定义了一个扩展类
    static class Extend
    {
        /// <summary>
        /// 笛卡尔积
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sequences"></param>
        /// <returns></returns>
        public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
        this IEnumerable<IEnumerable<T>> sequences)
        {
            IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
            return sequences.Aggregate(
              emptyProduct,
              (accumulator, sequence) =>
                from accseq in accumulator
                from item in sequence
                select accseq.Concat(new[] { item }));
        }
        /// <summary>
        /// 组合
        /// </summary>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="values"></param>
        /// <param name="num"></param>
        /// <returns></returns>
        public static IEnumerable<IEnumerable<TValue>> Combination<TValue>(
            this IEnumerable<TValue> values,
            //            Int32 count,
            Int32 num)
        {
            var t = Enumerable.Range(0, num).ToList();
            do
            {
                yield return values.Where((x, i) => t.Contains(i));
            }
            while (NextCombination(t, values.Count(), num));
        }
        /// <summary>
        /// C(n,m) 的下一项
        /// </summary>
        /// <param name="ar"></param>
        /// <param name="num"></param>
        /// <param name="k"></param>
        /// <returns></returns>
        public static bool NextCombination(List<int> ar, int n, int m)
        {
            if (ar.Count() != m) ar = Enumerable.Range(0, m).ToList();
            bool changed = false, finished = false;
            if (m > 0)
            {
                for (int i = m - 1; !changed && !finished; i--)
                {
                    if (ar[i] < (n - 1) - (m - 1) + i)
                    {
                        ar[i]++;
                        if (i < m - 1)
                        {
                            for (int j = i + 1; j < m; j++)
                            {
                                ar[j] = ar[j - 1] + 1;
                            }
                        }
                        changed = true;
                    }
                    finished = (i == 0);
                }
            }
            return changed;
        }
    }
亲,扩展类报错,请问一下如何使用扩展类。
大鱼> 2018-03-21
  • 打赏
  • 举报
回复
引用 6 楼 xuzuning 的回复:
开玩笑吧? List1={{1,2},{3,4},{5},{1}} 展开成一维数组是 {1,,2,3,,4,5,1} 那么 3 和 4就可能分到一组了,答案这是题意不允许的 的确是最笨的方法:把问题搞得一踏遭了
引用 5 楼 qq_17486399 的回复:
最笨最好理解的办法是将二维数组拆成一维数组,然后遍历一维数组进行组合。
你理解错了,我说的是拆成一维数组而不是合并成一维数组。
xuzuning 2018-03-21
  • 打赏
  • 举报
回复
开玩笑吧? List1={{1,2},{3,4},{5},{1}} 展开成一维数组是 {1,,2,3,,4,5,1} 那么 3 和 4就可能分到一组了,答案这是题意不允许的 的确是最笨的方法:把问题搞得一踏遭了
引用 5 楼 qq_17486399 的回复:
最笨最好理解的办法是将二维数组拆成一维数组,然后遍历一维数组进行组合。
大鱼> 2018-03-21
  • 打赏
  • 举报
回复
最笨最好理解的办法是将二维数组拆成一维数组,然后遍历一维数组进行组合。
xuzuning 2018-03-21
  • 打赏
  • 举报
回复
        static void Main(string[] args)
{
var List0 = new int[][]
{
new int[] {0},
new int[] {1},
new int[] {2},
new int[] {3}
};
foreach (var c in List0.Combination(3))
{
foreach (var x in c.CartesianProduct())
{
Console.WriteLine(string.Join(",", x));
}
}
}

定义了一个扩展类
    static class Extend
{
/// <summary>
/// 笛卡尔积
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sequences"></param>
/// <returns></returns>
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
this IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] { item }));
}
/// <summary>
/// 组合
/// </summary>
/// <typeparam name="TValue"></typeparam>
/// <param name="values"></param>
/// <param name="num"></param>
/// <returns></returns>
public static IEnumerable<IEnumerable<TValue>> Combination<TValue>(
this IEnumerable<TValue> values,
// Int32 count,
Int32 num)
{
var t = Enumerable.Range(0, num).ToList();
do
{
yield return values.Where((x, i) => t.Contains(i));
}
while (NextCombination(t, values.Count(), num));
}
/// <summary>
/// C(n,m) 的下一项
/// </summary>
/// <param name="ar"></param>
/// <param name="num"></param>
/// <param name="k"></param>
/// <returns></returns>
public static bool NextCombination(List<int> ar, int n, int m)
{
if (ar.Count() != m) ar = Enumerable.Range(0, m).ToList();
bool changed = false, finished = false;
if (m > 0)
{
for (int i = m - 1; !changed && !finished; i--)
{
if (ar[i] < (n - 1) - (m - 1) + i)
{
ar[i]++;
if (i < m - 1)
{
for (int j = i + 1; j < m; j++)
{
ar[j] = ar[j - 1] + 1;
}
}
changed = true;
}
finished = (i == 0);
}
}
return changed;
}
}
xuzuning 2018-03-21
  • 打赏
  • 举报
回复
        static void Main(string[] args)
{
var List0 = new int[][]
{
new int[] {1, 2},
new int[] {3, 4},
new int[] {5},
new int[] {1}
};
foreach (var c in List0.Combination(3))
{
foreach (var x in c.CartesianProduct())
{
Console.WriteLine(string.Join(",", x));
}
}
}
993356686 2018-03-21
  • 打赏
  • 举报
回复
引用 1 楼 xuzuning 的回复:
对 List0 有 123 但无 231、321,所以不存在排列 先求 C(m, 3) (m 是第一维的长)的组合序列 在对 组合序列 的每一成员求 笛卡尔积
List0={{0},{1},{2},{3}},三三组合:012,013,123,023,共有4种组合方式。 需求按此排序,并且排后的内容无法靠前,例如对 List0 有 123 但无 231、321,1在2前,2在3前,1在3前,所以无法排231、321、312等顺序。 已核实问题描述,无误。笛卡尔积无法满足此需求!
xuzuning 2018-03-21
  • 打赏
  • 举报
回复
对 List0 有 123 但无 231、321,所以不存在排列 先求 C(m, 3) (m 是第一维的长)的组合序列 在对 组合序列 的每一成员求 笛卡尔积

110,534

社区成员

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

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

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