求C#实现数组各元素0至对应最大值的全组合生成函数
求C#实现数组各元素0至对应最大值的全组合生成函数
嘿,我懂你的痛点——之前用通用组合生成函数的话,确实会产出一大堆超出每个位置上限的无效结果,还要额外过滤,太折腾了。其实你要的这个需求,本质上是个多进制计数问题,每个位置的“进制数”就是对应最大值加1(因为要包含0嘛),咱们直接按这个思路实现就好,完全不用生成无效组合。
实现思路
把你的数组看成一个自定义进制的数:比如数组[5,8,3,4,9],每个位置的可选范围是0-5、0-8、0-3、0-4、0-9,对应的“进制”就是6、9、4、5、10。我们只需要从0开始,数到(6*9*4*5*10)-1,把每个数字转换成这个自定义进制的数,就能得到所有符合要求的组合了。
完整C#代码
using System; using System.Collections.Generic; using System.Linq; public class RangeCombinationGenerator { /// <summary> /// 生成每个位置从0到对应max值的所有组合 /// </summary> /// <param name="maxValues">每个位置的最大值数组</param> /// <returns>所有符合要求的组合枚举</returns> public static IEnumerable<int[]> Generate(int[] maxValues) { // 计算总组合数,提前判断是否为空 long totalCombinations = maxValues.Aggregate(1L, (accumulator, currentMax) => accumulator * (currentMax + 1)); if (totalCombinations == 0) yield break; for (long count = 0; count < totalCombinations; count++) { var combination = new int[maxValues.Length]; long currentNumber = count; // 从最后一位往前计算,模拟进制转换 for (int index = maxValues.Length - 1; index >= 0; index--) { int baseValue = maxValues[index] + 1; combination[index] = (int)(currentNumber % baseValue); currentNumber /= baseValue; } yield return combination; } } // 测试示例 public static void Main() { int[] testMaxValues = { 5, 8, 3, 4, 9 }; foreach (var combo in Generate(testMaxValues)) { Console.WriteLine(string.Join(",", combo)); } } }
这个实现的优势
- 无无效结果:直接按每个位置的上限生成,不需要事后过滤,效率拉满
- 懒加载特性:用
yield return返回枚举,不会一次性把所有组合塞进内存,就算数组很大也不会爆内存 - 逻辑直观:完全对应进制转换的思路,读代码的时候一眼就能明白是怎么回事,后续维护也方便
对比你之前用的通用组合方法,那个是从给定列表里选非递减元素,天生就不贴合你“每个位置有独立上限”的需求,所以才会有大量无效输出。这个方法就精准匹配你的场景啦。
备注:内容来源于stack exchange,提问作者Scott Englert
相关产品推荐
相关产品推荐

