What is an efficient code for generating n binary digit numbers with k bits set as one?

安稳与你 提交于 2019-12-13 17:25:01

问题


Is there any efficient code to generate numbers with n digits in their binary representation with exactly r bits set as one?

Also is this a good strategy to generate masks for finding NcR combinations of a set?

I've thought about generating all 2^n numbers and counting their bits but counting bits seems to be O(nlogn).


回答1:


Well, if we are given a number with K bits set, how can we find the next largest number with K bits set? If we do this repeatedly we can generate all of them.

Generating the next one breaks down to a couple simple rules:

  1. The highest bit that changes must change from 0 to 1. Otherwise the new number would be smaller than the given one.
  2. The highest bit that changes must be the lowest one possible. Otherwise there would be other valid numbers between the current one and the new one. When we change a bit from 0 to 1, we have to change another bit from 1 to 0, and this bit has to be smaller, so the high bit we want to change from 0 to 1 is the lowest 0 bit with a 1 bit in a lower position.
  3. The remaining lower bits must be set to their smallest valid configuration. Otherwise there would again be other valid numbers between the current one and the new one. The smallest valid configuration for the lower bits is the one with all the 1 bits in the lowest positions.

It turns out that there are little binary math tricks that implement all these rules easily. Here it is in python:

N = 6 # length of numbers to generate
K = 4 # number of bits to be set

cur = (1<<K)-1  #smallest number witk K bits set

while cur < (1<<N):

    print format(cur,'b')

    #when you subtract 1, you turn off the lowest 1 bit
    #and set lower bits to 1, so we can get the samallest 1 bit like this:
    lowbit = cur&~(cur-1)

    #when you add lowbit, you turn it off, along with all the adjacent 1s
    #This is one more than the number we have to move into lower positions
    ones = cur&~(cur+lowbit)

    #cur+lowbit also turns on the first bit after those ones, which
    #is the one we want to turn on, so the only thing left after that
    #is turning on the ones at the lowest positions
    cur = cur+lowbit+(ones/lowbit/2)

You can try it out here: https://ideone.com/ieWaUW

If you want to enumerate NcR combinations using bitmasks, then this is a good way to do it. If you would prefer to have, say, an array of indexes of the chosen items, then it would be better to use a different procedure. You can make 3 rules like the above for incrementing that array too.



来源:https://stackoverflow.com/questions/46023719/what-is-an-efficient-code-for-generating-n-binary-digit-numbers-with-k-bits-set

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!