• 算法小技巧


    求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。

  • 相关阅读:
    【 SSH 配置参考】
    【 SSH 实例】使用ssh开发的简单项目
    【 Hibernate 】Hibernate的session更新和删除失败问题
    【 SSH 整合】Spring、Struts、Hibernate基本整合
    Tower是个不错的项目管理开放平台
    随便写写,四年多了第一次在博客园上发表
    asp.net获取服务器绝对路径和相对路径
    342. 4的幂
    283. 移动零
    268. 缺失数字
  • 原文地址:https://www.cnblogs.com/fanguangdexiaoyuer/p/11426281.html
Copyright © 2020-2023  润新知