|
发表于 2015-5-26 17:48
|
显示全部楼层
本楼为最佳答案
上代码和注释:
- Dim sj, a(9), b(), d, k&, m&, n&
- '定义递归需要的公用变量:
- ' 存放工作表数据区域的二维数组sj
- ' 记录数字是否重复的数组a
- ' 存放组合结果的数组b
- ' 用于删选排序后不重复结果的字典d
- ' 组合结果序号k
- ' 原始数据元素最大个数m (此处为最大行数)
- ' 原始数据列数n
- Sub MultiColumnCombin() 'by kagawa 代码主过程
- Dim tms#
- tms = Timer
-
- sj = [a1].CurrentRegion
- m = UBound(sj): n = UBound(sj, 2)
-
- k = m ^ n '计算组合结果最大可能数k
- ReDim b(k, 1 To n) '据此定义存放组合结果的数组b
- Set d = CreateObject("Scripting.Dictionary") '建立字典d
-
- k = 0: Call dgMN(1) 'k初始化 然后调用递归过程
-
- [a1].Offset(m + 2, n).CurrentRegion = "" '清空输出区域
- [a1].Offset(m + 2).Resize(k, n) = b '输出不重复组合结果
- [a1].Offset(m + 2, n + 1).Resize(d.Count) = WorksheetFunction.Transpose(d.keys)
- '输出数字排序后的不重复组合结果
- MsgBox Format(Timer - tms, "0.000s ") & k & "/" & d.Count
- '程序结束、对话框显示:程序耗时/组合结果总数k/排序不重复个数
- End Sub
- Sub dgMN(j&) '递归算法过程
- Dim i&, l&, t
- For i = 1 To m '遍历本列j列各行
- t = sj(i, j): If t = "" Then Exit For '如果该行元素为空则退出
- If a(t) = "" Then '如果该数字未被使用则继续 / 否则跳过
- a(t) = t '在数组a中标记该数字t已使用
- b(k, j) = t '在结果数组b的对应列中记录该数字t
- If j = n Then '如果组合个数达到n个则完成本次组合
- k = k + 1 '组合结果k+1
- For l = 1 To n - 1
- b(k, l) = b(k - 1, l) '复制、继承相同内容到下一行
- Next
- d(Join(a, "")) = "" '合并数组a中的结果得到从小到大排序的组合结果、用字典去重复
- Else '如组合个数<n 则继续递归
- Call dgMN(j + 1) 'j+1即可进入下一列
- End If
- a(t) = "" '本次递归计算后、退出时需要把数组a中的记录也清空,以便下一次新的组合可以使用
- End If
- Next
- End Sub
复制代码 以上,注释已经很详细了。 |
评分
-
查看全部评分
|