这是题目描述,实际上使用暴力搜索也不会很久,依然能够通过。
但是这里面有更深层的思考:这题一看就是二进制位操作题,但是怎么操作呢?
首先题目描述,1,0个数是肯定得相同了。
如果是暴力搜素,那么无非就是一个递减,一个递增,然后计算位个数而已。
但是考虑一下,如何把一个01序列,在01个数不变情况下“调大/调小”呢?
比如序列 :1001 0010 1001 0011 (随便写的)
把从后往前出现0的部分换成1:1001 0010 1001 0110这样就把这个数字调大了,简而言之这里面最后一个01 变成了10,因为1越往前数字越大,所以这个数字被调大了。
我们想,为了保持个数不变,事实上可以交换任意次数的0,1。但是我们现在要把它变大,然后变化的差值尽可能的小。
首先为了把它变大,那么找到的0的位置后面必须有1,所以第一步:找到从后往前第一个01的位置
在例子就是:1001 0010 1001 0011这两位,然后为了变大,交换位置:1001 0010 1001 0101
现在我们看变大了多少呢?(其实只看后三位即可)变大了2.
现在再看一个例子,假如:1001 0010 0111 0000。
显然步骤是,找到最后一个‘01’:1001 0010 0111 0000
交换:1001 0010 1011 0000 :这样变化了多少呢? 10110000-01110000,应该是一个挺大的数字,我就不算了。
为了让这个差值尽可能的小,有没有办法呢?有,把10后面的11挪到最后,就可以减小不少。
那么按照这个思路,步骤就是:找到最后一个01,变成10,这后面的1全部后移至最低位。
很好,变大的步骤有了,变小就与之类似:
找到最后一个10变成01,把后面的1全部提前到01(原10)后面即可。
代码如下:
class CloseNumber:
def getCloseNumber(self, x):
arr=list(bin(x)[2:])//构造二进制序列的List[str]形式
i=j=-1
for k in range(len(arr)-1):
if arr[k]=='0'and arr[k+1]=='1':
i=k# 找到最后的 '01'
if arr[k]=='1' and arr[k+1]=='0':
j=k#找到最后的 '10'
n1=arr[:]//构造两个副本
n2=arr[:]
n1[i],n1[i+1]=n1[i+1],n1[i]
n1=n1[:i+2]+sorted(n1[i+2:])//1后移到后面
n2[j],n2[j+1]=n2[j+1],n2[j]
n2=n2[:j+2]+sorted(n2[j+2:],reverse=True)//1移动到前面
n1=int(''.join(n1),2)
n2=int(''.join(n2),2)
return [n2,n1]
这里面用了极其偷懒的一种写法,没办法谁让python 就是方便呢哈哈哈哈。。。o(╥﹏╥)o