最接近的数(面试金典上的题)的一点思考

这是题目描述,实际上使用暴力搜索也不会很久,依然能够通过。

 

但是这里面有更深层的思考:这题一看就是二进制位操作题,但是怎么操作呢?

 

首先题目描述,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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值