ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

剑指Offer专项训练 位运算 001. 整数除法 & 002. 二进制加法 & 003. 前 n 个数字二进制中 1 的个数 & 004. 只出现一次的数字 & 005. 单词长度的最大乘积

2022-01-01 16:58:29  阅读:81  来源: 互联网

标签:数字 nums 二进制 Offer int 字符串 除法


位运算

剑指 Offer II 001. 整数除法

题目

给定两个整数 a 和 b ,求它们的除法的商 a/b ,要求不得使用乘号 ‘*’、除号 ‘/’ 以及求余符号 ‘%’

(不用乘除实现除法)

注意:

整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2

假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231−1]。本题中,如果除法结果溢出,则返回 231 − 1

分析

每次 通过左移(x2) 找到最大可以减去的数,循环直至不可以减为止

代码

class Solution {
    public int divide(int a, int b) {
        //特殊情况会溢出,负数能表示的比正数多一,当取最小负数与-1时会溢出
        if(a==Integer.MIN_VALUE&&b==-1)return Integer.MAX_VALUE;

        //记录答案符号 同号为正
        boolean sign = (a>0&&b>0||a<0&&b<0);
        
        //Java中 负数能表示的比正数多一 因此全部转换为负数计算可避免过程中溢出
        if(a>0)a=-a;
        if(b>0)b=-b;

        //使用最小负数的半值 可以避免 左移 运算的溢出
        int overFlow = Integer.MIN_VALUE>>1;
        int cnt = 0;

        //循环减去每次能减去最大的2次幂数 降低时间复杂度
        while(a<=b){
            int base = 1;
            int t=b;
            
            //在避免溢出的同时 尽可能的寻找可以减去的最大二次幂
            while(a<=(t<<1)&&overFlow<=t){
                t<<=1;
                base<<=1;
            }

            a-=t;
            cnt+=base;
        }
		
        return sign?cnt:-cnt;
    }
}

剑指 Offer II 002. 二进制加法

题目

给定两个 01 字符串 a 和 b ,请计算它们的和,并以二进制字符串的形式输出。

输入为 非空 字符串且只包含数字 10

(二进制字符串加法)

每个字符串仅由字符 ‘0’ 或 ‘1’ 组成。

1 <= a.length, b.length <= 10^4

字符串如果不是 “0” ,就都不含前导零。

分析

从低位(右)到高位(左)依次二进制加

代码

public String addBinary(String a, String b) {
    //StringBuilder添加字符效率高 且有翻转函数reverse()
    StringBuilder res = new StringBuilder();
    int carry = 0;//进位值
    int l1 = a.length() - 1;
    int l2 = b.length() - 1;
    //从字符串右边(数的低位)向左(数的高位)遍历
    while (l1 >= 0 || l2 >= 0) {
        int x = l1 < 0 ? 0 : a.charAt(l1) - '0';
        int y = l2 < 0 ? 0 : b.charAt(l2) - '0';

        int sum = x + y + carry;

        res.append(sum & 1);//%2 奇偶
        carry = sum >> 1;//2、3->进位 0、1->不进位

        l1--; l2--;//向高位移动
    }
    if (carry != 0) res.append(carry);
    return res.reverse().toString();
}

剑指 Offer II 003. 前 n 个数字二进制中 1 的个数

题目

给定一个非负整数 n ,请计算 0 到 n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。

(输出每个数的二进制1的数量)

5 -> [0,1,1,2,1,2]

​ 0 1 2 3 4 5

分析

一个数[i]的二进制1数a[i]=去除最高位1的该数[i-highBit]的二进制1数a[i-highBit]+1

​ [00110]{2} = [00010]{1} + 1

highBit需要动态维护

i&(i-1)可以获取i去除最低位1后的数i-lowBit(也可以用i-(i&(-i)))

若此时i-lowBit0说明i2的幂(只含一个二进制1)它即是当前的highBit

代码

class Solution {
    public int[] countBits(int n) {
        int[]a = new int[n+1];
        a[0]=0;
        int higBit = 0;
        for(int i=1;i<=n;i++){
            if((i&(i-1))==0)higBit=i;
            a[i]=a[i-higBit]+1;
        }
        return a;
    }
}

剑指 Offer II 004. 只出现一次的数字

题目

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 **三次 。**请你找出并返回那个只出现了一次的元素。

1 <= nums.length <= 3 * 104

-231 <= nums[i] <= 231 - 1

nums中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次

分析

计算每个位上的 比特数 最后对3取余

代码

class Solution {
    public int singleNumber(int[] nums) {
        int ans = 0;
        for(int i=0;i<32;i++){//对int的32个位都进行遍历相加 O(32n)
            int total = 0;
            for(int num:nums){//遍历整个数组
                total += (num >> i) & 1;//当前数字的当前位是否为1
            }
            if((total % 3) != 0)
                ans |= 1 << i;//确定结果的当前位
        }
        return ans;
    }
}

剑指 Offer II 005. 单词长度的最大乘积

题目

给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。

(无重复字符的两个字符串的最大长度积)

分析

使用二进制的比特代表某种字符是否存在

a & b == 0则代表两个字符串没有重复的字符

代码

class Solution {
    public int maxProduct(String[] words) {
        //int 32 位,可以存储26个字母的情况
        int[] bits = new int[words.length];
        int ans=0;
        //用二进制表示各个字母是否出现
        for(int i=0;i<words.length;i++)
            for(int j=0;j<words[i].length();j++)
                bits[i] |= (1 << (words[i].charAt(j) - 'a'));
        //对比二进制,如果没有相交(a & b == 0),则说明不含相同字符
        for(int i=0;i<bits.length-1;i++)
            for(int j=i+1;j<bits.length;j++)
                if((bits[i] & bits[j]) == 0)
                    ans = Math.max(ans,words[i].length() * words[j].length());
        return ans;
    }
}

标签:数字,nums,二进制,Offer,int,字符串,除法
来源: https://blog.csdn.net/Ctrl_kun/article/details/122268753

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有