zoukankan      html  css  js  c++  java
  • 算法小技巧

    求2个数的中间值

    先说结论:int mid = (start + end) >>> 1

    二分查找中我们需要根据 start 和 end 求中点,正常情况下加起来除以 2 即可。

    int mid = (start + end) / 2

    但这样有一个缺点,我们知道int的最大值是 Integer.MAX_VALUE ,也就是2147483647。那么有一个问题,如果 start = 2147483645,end = = 2147483645,虽然 start 和 end都没有超出最大值,但是如果利用上边的公式,加起来的话就会造成溢出,从而导致mid计算错误。

    解决的一个方案就是利用数学上的技巧,我们可以加一个 start 再减一个 start 将公式变形。

    (start + end) / 2 = (start + end + start - start) / 2 = start + (end - start) / 2

    这样的话,就解决了上边的问题。

    然后当时和同学看到jdk源码中,求mid的方法如下

    int mid = (start + end) >>> 1

    它通过移位实现了除以 2,但。。。这样难道不会导致溢出吗?

    首先大家可以补一下 补码 的知识。

    其实问题的关键就是这里了>>> ,我们知道还有一种右移是>>。区别在于>>为有符号右移,右移以后最高位保持原来的最高位。而>>>这个右移的话最高位补 0。

    所以这里其实利用到了整数的补码形式,最高位其实是符号位,所以当 start + end溢出的时候,其实本质上只是符号位收到了进位,而>>>这个右移可以带着符号位右移,所以之前的信息没有丢掉。

    但>>有符号右移就会出现问题了,事实上 JDK6 之前都用的>>,这个 BUG 在 java 里竟然隐藏了十年之久。

    大小写转换

    结论:chars[i] ^= (1 << 5);

    使用异或运算转换字母大小写。

    我们发现大写字符与其对应的小写字符的 ASCII 的差为 32,32 这个值如果敏感的话,它是 2^5
    ,在编程语言中,可以表示为 1 << 5。而

    变换大小写这件事等价于:

    1、如果字符是小写字符,减去 32 得到大写字符;
    2、如果字符是大写字符,加上 32 得到小写字符。

    而这两者合并起来,就是给这个字符做一次不进位的加法,即异或上 1 << 5。

  • 相关阅读:
    转:WinCE驱动开发问题精华集锦
    转:WINCE6.0+S3C6410下的DM9000A驱动
    转:WinCE6.0 不重启修改IP地址
    前端小功能:canvas验证码
    前端小功能:canvas签名版
    JavaScript中数组的应用方式
    ES6--Promise
    wepy 语法高亮
    Javascript和JQuery获取浏览器窗口各种尺寸
    图片预加载
  • 原文地址:https://www.cnblogs.com/fanguangdexiaoyuer/p/11426281.html
Copyright © 2011-2022 走看看