LeetCode476:数字的补数

代码

        我这人比较直白,喜欢先上答案(给你也看不懂):

 

调皮

        怎么样?看不懂吧,现在就能看得懂这篇代码的明天中午找我,我请你一根冰棍。哦,明天好像要降温,那就请一根烤肠吧。大家注意明天出门披个褂子啊,忽冷忽热易感冒,冒,冒!!!(喊得够大声了吧) 

细说由来


中午2点左右闲来无事,打开了LeetCode题库:https://leetcode-cn.com/problemset/all/ 
随机点了一道题,题目要求:


输入一个十进制数,转化为二进制数
输出该二进制对应的反码的十进制数 
例如:输入5 -->二进制:101 -->转为反码:010 -->输出十进制:2



就是这么一个题,用编程语言实现,我从两点开始想,想了一下午。首先我想的问题是:

拎起键盘就敲——十进制转二进制算法

就是辗转相除法,实现输入一个十进制正整数,转化为二进制数

  1. 需要输入一个数
  2. 如果这个数对2取余 其结果只有1/0 两种情况 将余数存入一个数组
  3. 让这个数 除以2 得到商
  4. 若商为1 将1也存入数组 停止
  5. 若商不为1 ,用商执行 1.2.3.4步 直到停止

然后转反码: 
if(arr[i]==1){arr[i]=0} 
else{arr[i]=1} 
最后就是倒着遍历输出数组中的每一个数,然后按权值与2相乘,得到十进制数,完美。 
        人类能看懂的自然语言很简单,可是转化为计算机能理解的语言,可不容易。我只是在算法上实现了
十进制转二进制,并且还没有成功输出。 

实在觉得麻烦了——赏析答案


        这里要声明一点,’看答案‘和’赏析答案‘是有区别的,’看‘这个动词,几乎不带感情;’赏析‘就不一样了,
这是怀揣着对大师作品的无上崇高的敬仰的欣赏。 
        我上CSDN搜索了一下,看到一篇像是答案的文章,点进去一看,只有两三行代码: 
public static void main(String[] args){
    int num = 5;
    System.out.println(~num & (Integer.highestOneBit(num) - 1));
}

        当时我心里就骂街了,又是一篇垃圾文章,随便写写就发布了来浪费别人时间,可是,当我复制粘贴
运行了一下看到答案之后,实在我是坐着,要是换做站着,估计当场我就跪那了。让我想了一下午的代码,

案竟然精简到只有三两行。接下来我就以我的方式细说一下这个代码:

public static void main(String[] args){
    int num = 5;
    System.out.println(~num & (Integer.highestOneBit(num) - 1));
}

以上各个符号的作用:
/*		 
 *       Integer.highestOneBit(num) :取num的二进制数最左边的最高位,且高位后面全部补零,
 *                                    最后返回int型的结果。
 *       -1:因为经过上面的步骤,只有最高位为 1 其余位都为 0 这样再减一  就会导致借位 直到借到最高位  
 *           结果得到 最高位为0 其余位都为1  相当于取反了
 *       &:对两个二进制数进行按位与运算,例     101          101
 *       			             &   010       &  111
 *                                        得     000      得  101
 *       ~ :对一个数的二进制取反
 */

首先定义一个 int 型的num,在计算机中占2字节,1字节 = 8 位 ,也就是说, 5 在计算机中存储的方式是: 00000000 00000101

所以实际上就是计算这个二进制的反码, ~num 的意思就是取反,即得到 11111111 11111010    ;结合题意,要求是不要前导数的:我们要的结果是:00000000 00000010    

现在问题就是如何让11111111 11111010 转化为 00000000 00000010 ,当然笨方法有很多,大师的答案就是:~num & (Integer.highestOneBit(num) - 1) 

首先Integer.highestOneBit(num)   取5的不含前导位的二进制的最高位,即101  取1,其他位都补0;得到100 减一之后变为 011 ,这时再和 ~num 进行与运算, 因为011 位数不够,所以需要填补0,即 

~num:11111111 11111010

   &       00000000 00000011

    得     00000000 00000010    即十进制的 2

完了。

如果你难过,我肩膀最辽阔,帮你带走乌云满布的天空,陪你一起度过平淡的生活,只需要你还我一个灿烂的笑容,我也会学着像你一样舔一舔上虎牙望着放晴的天空露出八颗皓齿。

    免责声明:文章部分内容引自

 https://blog.csdn.net/qq_24696917/article/details/51912706
 http://jackey25.iteye.com/blog/497213
 https://blog.csdn.net/yuzhi829/article/details/45647921 

   特别声明:文章关键逻辑由  -热忱  点拨

    著作权归作者所有。商业转载请联系作者获得免费授权,非商业转载请随意爱咋咋地。