知耻而后勇,自己琢磨的排列组合生成算法
之前写了一个排列组合生成算法,主要思路是补集,然而实际上算补集太麻烦而且消耗时间太多。后面写概率模拟的时候下定决心重新写了一遍,结果效率还挺好。我只是一名菜鸟,很多博客关于排列组合算法的科普其实我看得不太懂,我也不知道下面这个的思路是怎样的(忘记了……)
# 使用哈希去重 def permlist_iter(n, m, &pr) # 求递增的排列数组 list = (1..m).to_a info = {} (1..m).each do |x| info[x] = true end ((m+1)..n).each do |x| info[x] = nil end pos = 1 loop do pr.call(list, pos) pos += 1 # 修改排列数组 i = m-1 #~ puts "info=#{info}" while (i>=1) k = list[i]+1 while (k<=n) if info[k]==nil info[list[i]] = nil info[k] = true list[i] = k break end k += 1 end if (k<=n) #~ # 修改右边 last = 1 ((i+1)..(m-1)).each do |j| (last..n).each do |k| if (info[k]==nil) info[k] = true list[j] = k last = k+1 break end end end break end info[list[i]] = nil i -= 1 end if (i==0) break if list[0]==n info[list[0]] = nil info[list[0]+1] = true list[0] += 1 last = 1 (1..(m-1)).each do |j| (last..n).each do |k| if (info[k]==nil) info[k] = true list[j] = k last = k+1 break end end end end end return end def comblist_iter(n, m, &pr) # 求递增的组合数组 list = (1..m).to_a info = {} (1..m).each do |x| info[x] = true end ((m+1)..n).each do |x| info[x] = nil end pos = 1 loop do pr.call(list, pos) pos += 1 # 修改组合数组 i = m-1 #~ puts "info=#{info}" while (i>=1) k = list[i]+1 while (k<=n) if info[k]==nil info[list[i]] = nil info[k] = true list[i] = k break end k += 1 end if (k<=n) #~ 修改右边 ((i+1)..(m-1)).each do |j| info[list[j]] = nil end last = k+1 ((i+1)..(m-1)).each do |j| (last..n).each do |k| if (info[k]==nil) info[k] = true list[j] = k last = k+1 break end end end break end #~ info[list[i]] = nil i -= 1 end if (i==0) break if list[0]==(n-m+1) list.each do |x| info[x] = nil end info[list[0]+1] = true list[0] += 1 last = list[0]+1 (1..(m-1)).each do |j| (last..n).each do |k| if (info[k]==nil) info[k] = true list[j] = k last = k+1 break end end end end end return end =begin # 测试排列数组 count = 0 tn1 = Time.now permlist_iter(13, 8) do |list, pos| #puts "(#{pos})=>#{list}" #~ gets count += 1 end puts "time:#{Time.now-tn1}", count =end #~ =begin # 测试组合数组 count = 0 tn1 = Time.now comblist_iter(25, 14) do |list, pos| #~ puts "(#{pos})=>#{list}" #~ gets count += 1 end puts "time:#{Time.now-tn1}", count #=end

浙公网安备 33010602011771号