The Ruby Way 之幂集

Hal Fulton 的《Ruby之道》里面有一个输出幂集的程序。

  1. class Array

  2.   def powerset
  3.     num = 2**size
  4.     ps = Array.new(num, [])
  5.     self.each_index do |i|
  6.       #print "i := #{i}/n"
  7.       a = 2**i
  8.       b = 2**(i+1) - 1
  9.       j = 0
  10.       while j < num-1
  11.       #print "j := #{j}, (#{j+a}..#{j+b})/n"
  12.         for j in j+a..j+b
  13.           ps[j] += [self[i]]
  14.           #print "ps[#{j}] = #{ps[j]}/n"
  15.         end
  16.         #print "j := #{j}/n"
  17.         j += 1
  18.       end
  19.     end
  20.     ps
  21.   end

  22. end

  23. x = [1, 2, 3, 4]
  24. y = x.powerset
  25. print "{"
  26. for i in 0 ... y.size-1
  27.   print "{#{y[i].join("")}}, "
  28. end
  29. print "{#{y[-1].join("")}}}/n"
  30. # y is now:
  31. #   [[], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3]]
  32. # print {{}, {1}, {2}, {1, 2}, {3}, {1, 3}, {2, 3}, {1, 2, 3}, {4}, {1, 4}, {2, 4}, {1, 2, 4}, {3, 4}, {1, 3, 4}, {2, 3, 4}, {1, 2, 3, 4}}
看了老半天都没看明白,所以加了几条输出,发现了如下规律:
其实它采用的是递归的思想(只不过把递归展开了而已) ,有一半的集合含有某个元素,另一半不含。

为了验证,写了一个递归版本的程序:

  1. class Array
  2.   def divide_and_conquer(ps, i, j, level)
  3.     print "level #{level}: (#{i}..#{j})/n"
  4.     if level == 0
  5.       ps[j-1] += [self[0]]
  6.     else
  7.       half = (j - i)/2
  8.       divide_and_conquer(ps, i, i+half, level-1)
  9.       divide_and_conquer(ps, i+half, j, level-1)
  10.       for i in i+half ... j
  11.         ps[i] += [self[level]]
  12.       end
  13.     end
  14.   end
  15.   
  16.   def powerset
  17.     num = 2**size
  18.     ps = Array.new(num, [])
  19.     self.divide_and_conquer(ps, 0, num, size-1)
  20.     ps
  21.   end
  22. end
  23. x = [1, 2, 3, 4]
  24. y = x.powerset
  25. for i in 0 ... y.size
  26.   print "#{y[i]}/n"
  27. end
  28. print "{"
  29. for i in 0 ... y.size-1
  30.   print "{#{y[i].join("")}}, "
  31. end
  32. print "{#{y[-1].join("")}}}/n"
  33. # y is now:
  34. #   [[], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3]]
  35. # print {{}, {1}, {2}, {1, 2}, {3}, {1, 3}, {2, 3}, {1, 2, 3}, {4}, {1, 4}, {2, 4}, {1, 2, 4}, {3, 4}, {1, 3, 4}, {2, 3, 4}, {1, 2, 3, 4}}


不由得感叹:大师的算法学得这么好!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值