本期我们来继续探索如何从100W注彩票中选择出现次数最少的注。
首先重新梳理下题目。
每一注彩票分两类,一类是从1-33中抽取6个不同的数字,一类是从1-16中抽取1个数字,将这7个数字作为一注。计算机生成100W注彩票号码,对这些注号码的出现次数(7个数字全相等)进行排序,将出现次数最少的输出。
下面就来看一下这个一个可以打成百上千个的方法。
- 我们先看一下第一类数字,从1-33中抽取6个不同的数字,相当于有6个维度的信息,如何将这6个维度的信息融合在一起呢?这里就可以用到二进制的思想了,我们设置1-33位,如果抽中了某一个数字,就将对应的位置为1。比如抽中的6个数字是1,2,3,4,5,6,那融合后的数字为:63=1<<(1-1)|1<<(2-1)|1<<(3-1)|1<<(4-1)|1<<(5-1)|1<<(6-1)
- 然后再看一下第二类数字,从1-16中抽取1个数字,那这个就可以按数字本身来保存,不再需要任何变换。
- 接下来就是要讲第一类数字和第二类数字融合,依然还是二进制的逻辑,将刚才得到的两个新数字作为两个维度,又可以继续用上面的逻辑,即【第二类数字<<33|第一类数字】。
基于上述逻辑,我们只要发现融合后的最终数字相同,则说明抽取的7个数字相同,计数加一即可。
又有了思路,就继续开干!
写完了代码,我们来测试一下,先用1000注测一下,用时0.002s;再用10000注测一下,用时0.016s,哎呀.....这个运算效率妥妥的;再测一下10W注,用时0.17s,没问题;最后测一下100W注,1.7s,速度杠杠滴。
与上一篇文章中的方法做个简单的对比。
暴力 | 二进制 | |
0.1W | 0.06s | 0.002s |
1W | 7s | 0.016s |
10W | 10分钟未返回结果 预测需要700s | 0.17s |
100W | 未测试 预测需要70000s | 1.7s |
从上表可以看出,二进制方法比暴力破解的方法效率提升了成百上千,甚至是几万倍。
至此,终于从码农的暴力破解升级到了程序员的比较像样的解决方法了。当然这个方法还可以继续优化,包括内存占用、CPU利用率等,大家是否有更好的思路呢?欢迎大家留言讨论。