剑走偏锋-leetcode中的奇技淫巧

本文作者通过做LeetCode题目,总结了位运算在解决编程问题中的巧妙应用,如快速求解问题、实现加法、查差、进制转换等。同时,作者还探讨了如何利用Java 8的Stream API进行高效集合操作,并分享了二叉树问题和逻辑推理问题的解题策略。文章旨在揭示编程思维的模式化及其在实际问题中的转化,提醒读者在解决问题时保持开放和创新的思维。
摘要由CSDN通过智能技术生成

断断续续做leetcode,已然数月有余。
做得多了,一种切身感受油然而生:每个人思考问题的方式和角度都是有道可循的,也就是说,一道题上次你用这样的方式解决,这次让你做,即使你已经忘记了上次做过这道题,最终形成的做法和上次大同小异。暂且称之为“思维固定模式论”。
映射到生活中也是如此,这次遇到同样的问题,你使用解决办法了A,并且成功解决了办法,那么下次遇到同样的问题你多半还会使用A办法。这是好事也是坏事,好事是因为A其实就是我们生活的经验,这些经验能够指导我们更好更便捷的处理事情;坏事是因为,这些经验容易让人不假思索,而错过了一些更好更高效的解释办法。
比如:leetcode的discuss区,当我看着着别人的高票解决问题之道,好似看着一道智慧之光,又能隐隐约约听到解题人狡黠的笑声,并沉头低语道:没想到吧!

1.0[位运算] trick one -制作某num的全“1”mask(例如:5-101-111)

学会使用二进制的思维来解决问题
学会使用Integer.highestOneBit(num)方法
见识到简洁代码的威力了吧

例题:476. Number Complement
Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation.
大意为求一个数的二进制取反的int值,例如(5-101-010-2 即返回2)

my solution:
step one:构造表示二进制的字符串
step two:根据二进制字符串一次取反并求值

源码:

 public int findComplement(int num) {
        String binStr=Integer.toBinaryString(num);
        char[] binaStr=binStr.toCharArray();
        String compNum="";
        for(int i=0;i<binStr.length();i++)
        {
            String temp=String.valueOf(binaStr[i]);
            if(temp.equals("1"))
            {
                compNum+=0;
            }
            else {
                compNum+=1;
            }
        }
        return getIntFromBinString(compNum);
    }
    public static int getIntFromBinString(String str)
    {
        char[] temp=str.toCharArray();
        int res=0;
        int j=0;
        for(int i=temp.length-1;i>0;i--)
        {
            String st=String.valueOf(temp[i]);
            if(st.equals("1"))
            {
                res+=Math.pow(2, j);
            }
            j++;
        }
        return res;
    }

better solution:
step one:构造mask,找到highestOneBit
step two:对num取反
step three:上述两个数AND
源码:

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

Integer.highestOneBit(num)的详细介绍
简言之就是取到这个数二进制的最高位

1.1[位运算] trick one -为重复而生的异或^运算-无视顺序-高效解决
所有偶数个的重复问题都可以通过异或运算求解
百度面试题

例题:136. Single Number
Given an array of integers, every element appears twice except for one. Find that single one.
很简单的一道题,直接的解题步骤:
两重循环全遍历,时间复杂度:O(n)=n^2

better solution:
对所有数值进行异或运算
源码:

public class Solution {
    public int singleNumber(int[] nums) {
        int result = 0;
        for (int i = 0; i<nums.length; i++)result ^=nums[i];
        return result;
        }
    }

原理就不在多说了
first , we have to know the bitwise XOR in java

0 ^ N = N
N ^ N = 0

无关乎顺序,就酱

题外衍生一下,之前遇到的百度面试题也是类似的解法,题目如下
箱子里有100个黑球和100个白球,每次取出(不放回)两个球,如果取出的两个球是同色则放回一个黑球,如果取出的两个球是不同颜色则放回一个白球,问最后剩一个黑球的概率是多少?
类似的,所谓同色放黑,异色放白,也就是一种异或运算。此处取黑色为“0”,白色为“1”
黑^黑=白^白=1^1=0^0
白^黑=黑^白=1^0
故一百个白球和一百个黑球异或也就是:
1^1^1^1^1^1^1^1^1^1^1^……^0^0^0^0^0^0^0^0^0^0^=0^0=0
所以最后剩一个黑球的概率必然是100%

1.2[位运算] trick one -异或^移位<<与&运算实现加法
从就计算机的角度看基本操作-加减乘除都是基本的寄存器中数据到运算器中运算的复杂化,同样的其他的负责操作又可以由加减乘除复杂化得来。把握底层的实现细节是件好事

例题:371. Sum of Two Integers
Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.
不用+或-实现加减法

better solution:
step one :^实现a和b的各位相加,&和<<运算实现进位
step two:进位后如果进位数不为0,则循环step one

源码:

public class Solution {
    public int getSum(int a, int b) {
    return b==0? a:getSum(a^b, (a&b)<<1); //be careful about the terminating condition;
    }
}

以上题为例,
a^b实现各位相加(比如:5+6 a^b=1001^1010=0011)
(a&b)<<1实现进位(比如 :5+6 a&b<<1=10000)
由于b不等于零,然后将b&到前面的a^b中即得到了:10011=11;

1.3 [位运算]trick one -异实现字符的查差
做题时,要有一种将字母和数字,将数字和二进制位统一起来的意识
举个栗子:看到”a’的时候要能够看到它其实是一个八位的ascall码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值