对数器:
    就是自己写的一个验证方法
    一个需求,用两种不同思路实现,比较结果是否一样
    image.png

    二分法:
    image.png
    确定下标中间位置:
    R(右边值) - L(左边之) 确定距离
    除以2加L(左边值)就是中间位置
    带符号右移一位 相当于除以2 (位运算比出运算快)
    image.png
    拓展:
    N2 可以带符号左移1位 N<<1
    N
    2 + 1 可以或运算1位 (N<<1)| 1
    image.png

    image.png

    局部最小值问题:
    在 0 — 1 范围 如果0位置比1小 0位置就是局部最小值
    在 n-1 — n 范围 如过 n位置比 n-1位置小 n位置就是局部最小值
    在 中间 i 位置 i 要比两边都小 i 才是局部最小值

    有一个无序数组 任意两个相邻的数都不相等 返回一个局部最小的就可以

    分析判断趋势
    image.png
    可二分判断趋势 舍弃另一边 缩小范围 寻找局部最小值
    image.png

    image.png
    结论:
    只要有排他性出现就可以二分(两种可能性一定有)
    只要可以构建出排除另一边的逻辑就可以二分

    异或运算
    image.png

    image.png
    2)解释 :连续异或 a^b^c 和 c^a^b 结果一样(同样一批数 异或结果是一样的)

    如何不用额外变量 交换两个数的值 a = 甲 ; b = 乙
    a = a^b
    b = a^b
    a = a^b
    原理解析 :
    a = 甲 ^ 乙
    b = 甲 ^ 乙 ^ 乙 = 甲
    a = 甲 ^ 乙 ^ 甲 = 乙 完成交换
    注意 : 如果 a 和 b 在内存中指向一个地址 会出错;用异或完成交换 必须内存指向不同

    image.png
    思路:循环异或
    image.png
    提取出二进制中 最右侧的1 (结果中只有最右侧的1保留 其他位归0)
    image.png
    解析:
    N & ((~N) + 1) ; N 与上 N取反加1 ; 与(&)运算 相同取相同 不同取0
    image.png

    image.png

    image.png
    解析:
    循环异或,最后的结果一定是 两个为奇数个数的数 (a和b)
    假设二进制 任意一位(第8位) a和b一定不同 因为异或
    按第8位 1或0 分为两组 则a和b分开
    此时重新循环异或 eor’ 为第8位为1的数 则这个数是 a或b
    eor 再异或 eor’ 即可得到另外一个数
    image.png

    随意一个数字 得出 二进制中 1的个数
    不断提取最右侧的1 计数器+1
    再把最右侧的1抹去(原数 异或 提取最右侧1的数 直接抹去化0)

    1. public static int bit1counts(int N) {
    2. int count = 0;
    3. // 011011010000
    4. // 000000010000 1
    5. // 011011000000
    6. while(N != 0) {
    7. int rightOne = N & ((~N) + 1);
    8. count++;
    9. N ^= rightOne;
    10. // N -= rightOne
    11. }
    12. return count;
    13. }