龙猫12138 2018-05-14 13:46 采纳率: 0%
浏览 1129
已结题

java,算数字的补数,leetcode上面为什么以下的做法可以得到正确答案

输入:5
输出:2

 public int findComplement(int num) {  
        return (~num) & ((Integer.highestOneBit(num) << 1) - 1);  
    }  

只用一行代码就解决了,我的问题是,到底是怎么推导出或者说怎么想到是这样做的?

当num=5的时候,
原码是:00001010
反码是:11110101

输出2
原码是:00000101

也就是说得有个办法既可以去掉5的反码前面4位的1111,又可以得到后面的0101,
但是如果这样来想的话,就有4种方式可以得到结果
00000111(正确)
00000011
00000110
00000010(不可能)
换句话说,我只要能够构建出上面3个的bit位就可以得到结果了,但问题是,我该构建哪一个呢?
他们到底是怎么知道代码那样的做法就能够构建出00000111这个正确的bit呢?
希望大家不吝赐教!

  • 写回答

1条回答 默认 最新

  • threenewbee 2018-05-14 14:56
    关注
     我不是很清楚什么叫“补数”,我感觉是题目故意设置的概念,不去管它,我找到了题目
    
    给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。
    
    按照这个解释,00001010算一个补数的方式是,去掉前导的0,得到1010,然后取反,得到0101,也就是101
    
    然后看你的程序,00001010
    Integer.highestOneBit(num)
    这个得到最高位的1,其余位的1忽略,都是0
    也就是00001000
    (Integer.highestOneBit(num) << 1
    向左移动1位,低位补0
    因此得到 00010000
    再-1
    得到
    00001111
    注意这个1111的作用,它相当于过滤器,用and运算可以去掉num的前导0,因为0 and任意数都是0,1 and 1是1,所以用它和~num做 and,前面的1肯定就过滤了。
    而~num按照题目的意思,就是取反了。
    取反+去掉前导0,就是结果,这是题目规定的
    
    所以这个解法没有任何技巧可言,就是按照题目算的。
    
    评论

报告相同问题?

悬赏问题

  • ¥88 实在没有想法,需要个思路
  • ¥15 MATLAB报错输入参数太多
  • ¥15 python中合并修改日期相同的CSV文件并按照修改日期的名字命名文件
  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败