minimum number of steps to reduce number to 1

后端 未结 6 2015
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-07 12:53

Given any number n, and three operations on n:

  1. add 1
  2. subtract 1
  3. divide by 2 if the number is even

I want to find the minimum n

6条回答
  •  既然无缘
    2020-12-07 13:30

    I like the idea by squeamish ossifrage of greedily looking (for the case of odd numbers) whether n + 1 or n - 1 looks more promising, but think deciding what looks more promising can be done a bit better than looking at the total number of set bits.

    For a number x,

    bin(x)[:: -1].index('1')
    

    indicates the number of least-significant 0s until the first 1. The idea, then, is to see whether this number is higher for n + 1 or n - 1, and choose the higher of the two (many consecutive least-significant 0s indicate more consecutive halving).

    This leads to

    def min_steps_back(n):
        count_to_1 = lambda x: bin(x)[:: -1].index('1')
    
        if n in [0, 1]:
            return 1 - n
    
        if n % 2 == 0:
            return 1 + min_steps_back(n / 2)
    
        return 1 + (min_steps_back(n + 1) if count_to_1(n + 1) > count_to_1(n - 1) else min_steps_back(n - 1))
    

    To compare the two, I ran

    num = 10000
    ms, msb = 0., 0.
    for i in range(1000):
        n =  random.randint(1, 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999)
    
        ms += min_steps(n)
        msb += min_steps_back(n)
    
    print ms / num, msb / num
    

    Which outputs

    57.4797 56.5844
    

    showing that, on average, this does use fewer operations (albeit not by that much).

提交回复
热议问题