剑指 offer day21-22 位运算

剑指 Offer 15. 二进制中1的个数

题目:

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数。

题解1:

直接调用Integer.bitCount()函数

public int hammingWeight(int n) {
        return Integer.bitCount(n);
    }

题解2(逐位判断):

位运算,清晰图解

1.若n&1=0,则证明最右一位是0;反之若n&1=1,则证明最后一位是1,则返回值+1;

2.使得n右移一位,继续与1进行&操作,注意: Java 中无符号右移为 “>>>”

public int hammingWeight(int n) {
        int res = 0;
        while (n!=0){
            if ((n&1)==1) res++;
            n>>>=1;//不是n>>=1  三个“>”号
        }
        return res;
    }

剑指 Offer 65. 不用加减乘除做加法

题目:

写一个函数,求两个整数ab之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。

题解:

位运算,清晰图解

1.不要考虑a(i)、b(i)以及i-1位置是否进位三者的关系,会有很多种情况太复杂,换一种角度;

2.如下图所示,a(i)和b(i)是第i个位置a和b的值,假如二者均为1,则进一位之后落下0,进位的需要*2即执行左移操作;

3.n(i)异或操作,c(i+1)操作,则a+b=n+c(比如把1+1 转换为2+0,进位就是左移);

4.通过不断的循环,使得a+b转换成0+d,返回d即可;

5.通过一个例子可以发现进位在求&操作时会出现等于0的情况,因此循环结束的条件为进位为0

在这里插入图片描述

public int add(int a, int b) {

        while (b!=0){
            int c = (a&b)<<1;//c是进位
             a = a^b; //a是无进位和
             b=c;//b是进位
        }
        return a;

    }

剑指 Offer 56 - I. 数组中数字出现的次数

题目:

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

题解:

1.两个相同数字的异或操作值为0,0和任何数字的异或操作的结果均为其本身。

2.假设出现1次的两个数字是a和b,则数组中的全部数取异或操作的结果即为a和b的异或操作的结果;

例如:假设数组中的数字为{4,4,3,3,2,1} ,则4和4取异或为0,3和3取异或为0,最后只剩下2和1;

3.由于a和b不相等,则异或操作的结果中肯定有1的存在,找到结果中任意一个1,假设是p,按照该位置对数组中的数字重新进行划分,即a带着所有第i位为1的数字,b带着所有第i位为0的数字(或者二者颠倒)

  • 如果nums[i]&p==0,证明第i位为0,则被分到组1;
  • 如果nums[i]&p==1 ,证明第i位为1,则被分到组2;
  • 各个组内再次进行异或操作,得到的最终结果返回即可。
public int[] singleNumbers(int[] nums) {
     //定义数组中全部数字的异或结果为xor
        int xor = 0;
        for (int n:nums){
            xor=xor^n;
        }
        //在xor中自右向左查找1
        int p = 1;
        while ((p&xor)==0){
            p=p<<1;
        }
        //定义两个最终的返回值
        int res1=0,res2=0;
        for (int n:nums){
            //如果第i位为0,则为组1,组内进行异或
            if ((n&p)==0){
                res1 = res1^n;
            }else  //如果第i位为1,则为组2,组内进行异或
                res2 = res2^n;
        }
        int[] res = {res1,res2};
        return res;
    }

剑指 Offer 56 - II. 数组中数字出现的次数

题目:

在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。

题解1:

1.如果在数组中取出某一个出现三次的数字,并不会影响最后的与操作的结果,因为a&a==a;但是如果取出数组中出现一次的数字则会影响最后的与操作的结果。

2.步骤:

  • 对数组中所有的数字进行与操作,记作and
  • 剔除数组中的某一个数字,将剩下的数字进行与操作,记为and2
  • 如果andand2不相等,返回结果即可

3. 代码提交是错误的
错误原因: 数组中全部的数字取与操作最后的结果大概率是0,造成一些奇奇怪怪的结果

 public static int singleNumber(int[] nums) {
        //定义返回值res
        int res = 0;
        //定义nums数组中全部数字的与操作结果
        int and = nums[0];
        for (int i:nums){
           and = and & i;
        }
        //假设num[n]为出现一次的数字
        for (int n=0;n<nums.length;n++){
            res = nums[n];
            int and2 = Integer.MAX_VALUE;
            for (int i=0;i<n;i++){
                and2 = and2 & nums[i];
            }
            if (n!=nums.length-1){
                for (int i= n+1;i<nums.length;i++){
                    and2 = and2 & nums[i];
                }
            }
            if (and2!=and){
               break;
            }
        }
        return res;
    }

题解2:

1.遍历将数组中的数出现的次数存储在map集合中;

2.遍历map,寻找出现次数为1的key值,返回结果。

    public static int singleNumber(int[] nums) {

        int res = 0;
        Map<Integer,Integer> map = new HashMap<>();
        //通过遍历将数组中的数出现的次数存储在map集合中
        for (int i:nums){
            if (!map.containsKey(i)){
                map.put(i,1);
            }else {
                int times = map.get(i);
                map.remove(i);
                map.put(i,times+1);
            }
        }
        //遍历map,寻找出现次数为1的key值,返回结果
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
           if (entry.getValue()==1){
               res = entry.getKey();
           }
        }
        return res;
    }

我昨晚好像睡着了哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值