Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 10827|回复: 25

[已解决]枚举不重复排列的问题,我的方法效率低,求指点

[复制链接]
发表于 2012-10-30 15:38 | 显示全部楼层 |阅读模式
如图,A列给出任意字母,在D列将所有排列(不是组合)列举出来,所有字母全用上。我的方法在计算7个字母时,就达到5分钟了,请教高手,如何提高速度。代码如下:
  1. Option Explicit
  2. Dim h As Long
  3. Dim arr() As String, brr()
  4. Dim x As Long, z As Long, k As Long, w As Long
  5. Dim m As Long, n As Long, j As Long
  6. Dim dic

  7. Sub 排列改进()
  8. Dim t
  9. Dim y As Long
  10. t = Timer '计时
  11. Set dic = CreateObject("Scripting.Dictionary")
  12. m = Range("a65536").End(xlUp).Row '判断元素个数

  13. ReDim arr(1 To m * m) '数组重复生成m边,放入arr
  14. For x = 1 To m * m
  15. y = x Mod m
  16. If y = 0 Then
  17. arr(x) = Cells(m, 1)
  18. Else
  19. arr(x) = Range("a" & y)
  20. End If
  21. Next x

  22. w = 0 '用于减少递归次数
  23. pailie "", 1 '递归

  24. Range("d1").Resize(dic.Count) = Application.Transpose(dic.Keys)
  25. Range("b2") = "用时" & Timer - t & "秒"
  26. Range("b3") = "共" & dic.Count & "种排列"
  27. Erase arr, dic

  28. End Sub

  29. Function pailie(sr, n)
  30. If w < m Then '判断是否执行递归

  31. If Len(sr) = m Then '符合长度则执行语句
  32. If Len(Replace(sr, arr(m), "")) = 0 Then '如果sr均为最后一个元素,则往下不需执行
  33. w = m
  34. Exit Function
  35. Else
  36. For x = 1 To m '根据长度变化判断重复值
  37. k = Len(sr)
  38. h = Len(Replace(sr, arr(x), ""))
  39. j = k - h
  40. If j <> 1 Then '判断sr中是否有元素遗漏或重复
  41. Exit Function
  42. ElseIf x = m Then '循环是否到最后一个元素
  43. dic(sr) = ""
  44. Exit Function '存入字典,去重复值
  45. End If
  46. Next x
  47. End If
  48. End If

  49. If n > m * m Then '递归
  50. Exit Function
  51. Else
  52. pailie sr & arr(n), n + 1
  53. pailie sr, n + 1
  54. End If
  55. End If
  56. End Function
复制代码
最佳答案
2012-10-31 20:43
补上附件。


楼主你自己写的代码只能全部扔掉,完全没有实用性。

运行起来速度慢的惨不忍睹。

图1.jpg
发表于 2012-10-31 17:11 | 显示全部楼层
本帖最后由 香川群子 于 2012-10-31 20:52 编辑

递归和循环都可以……

其实循环比递归效率更高一些,但是代码会比较复杂。

所以递归代码会好一点。


我的代码计算运行时间是0.1秒。(不含写入单元格)
而如果是用数组循环,则计算时间只要0.06秒。比你的代码快了几千倍吧?

楼主你好好消化消化吧……我是排列组合方面的专家。
  1. Dim sj, jg(), m%, n%, k
  2. Sub kagawa_Permut()
  3.     tms = Timer
  4.     m = [a1].End(4).Row
  5.     sj = [a1].Resize(m)
  6.     n = [b1]
  7.     If n = 0 Or n > m Then n = m
  8.    
  9.     AP = WorksheetFunction.Permut(m, n)
  10.     ReDim jg(AP, n)
  11.     k = 0
  12.    
  13.     Call dgPL("", 0)
  14.     MsgBox Format(Timer - tms, "0.000s")
  15.     [b3] = AP
  16.     If k < 65536 Then [d1].CurrentRegion = "": [d1].Resize(AP, n + 1) = jg
  17. End Sub
  18. Sub dgPL(s, t)
  19.     If t = n Then
  20.         p = Split(s, ",")
  21.         For j = 1 To n
  22. '            jg(k, j) = sj(p(j), 1)
  23. '            jg(k, 0) = jg(k, 0) & "," & sj(p(j), 1)
  24.             jg(k, 0) = jg(k, 0) & sj(p(j), 1)
  25.         Next
  26. '        jg(k, 0) = Mid(jg(k, 0), 2)
  27.         k = k + 1
  28.         Exit Sub
  29.     End If
  30.     For j = 1 To m
  31.         If InStr(s & ",", "," & j & ",") = 0 Then Call dgPL(s & "," & j, t + 1)
  32.     Next j
  33. End Sub

复制代码

评分

参与人数 2 +19 收起 理由
xdwy81129 + 18 神马都是浮云
ybchxj2010 + 1 很给力!

查看全部评分

回复

使用道具 举报

发表于 2012-10-31 17:12 | 显示全部楼层
如果原始数据中本身有重复,然后需要不重复的排列结果……这种情形会更加复杂。

回复

使用道具 举报

发表于 2012-10-31 17:13 | 显示全部楼层
如果原始数据中本身有重复,然后需要不重复的排列结果……这种情形会更加复杂。

回复

使用道具 举报

发表于 2012-10-31 17:15 | 显示全部楼层
在A1开始的列中输入要排列的原始数据。
在B1单元格中可以输入n=1~m之间的数值。(如果B1不输入为空,则作n=m处理。)
按下按钮,即可得到任意Permut(m,n)的全部排列结果。
回复

使用道具 举报

发表于 2012-10-31 20:43 | 显示全部楼层    本楼为最佳答案   
补上附件。


楼主你自己写的代码只能全部扔掉,完全没有实用性。

运行起来速度慢的惨不忍睹。

dgPL.rar

19.49 KB, 下载次数: 47

评分

参与人数 1 +18 收起 理由
xdwy81129 + 18 学习排列专家的附件

查看全部评分

回复

使用道具 举报

发表于 2012-10-31 20:46 | 显示全部楼层
根本性错误在于算法设计有误。

生成全部m*m种组合,然后逐个字母检查是否有重复、遗漏,是很愚蠢的做法。

应该在进入递归之前就进行检查,重复的事先就pass、跳过。

回复

使用道具 举报

发表于 2012-10-31 20:54 | 显示全部楼层
另外,如果算法正确,是不需要用字典方法来排除重复的……因为好的算法不产生重复。
回复

使用道具 举报

发表于 2012-11-1 11:07 | 显示全部楼层
膜拜下高手... ...{:081:}又被打击了
回复

使用道具 举报

 楼主| 发表于 2012-11-2 18:29 | 显示全部楼层
真的被打击了 谢谢指点,认真学习中
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-4-26 21:15 , Processed in 0.371302 second(s), 18 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表