位运算

给你两个二进制字符串 ab ,以二进制字符串的形式返回它们的和。

设置一个carry进位。从字符串的尾部进行比较累加。字符串长度不够的以0代替。

class Solution {
    public String addBinary(String a, String b) {

              StringBuffer ans = new StringBuffer();

        int n = Math.max(a.length(), b.length()), carry = 0;
        //倒着加
        for (int i = 0; i < n; ++i) {
            carry += i < a.length() ? (a.charAt(a.length() - 1 - i) - '0') : 0;
            carry += i < b.length() ? (b.charAt(b.length() - 1 - i) - '0') : 0;
            ans.append(carry % 2 );
            carry /= 2;
        }
        if (carry > 0) {
            ans.append('1');
        }
        ans.reverse();
        return ans.toString();
    }
}

解法2:

解法3:

  • 计算当前 x 和 y 的无进位相加结果:answer = x ^ y 相同数字异或=0,0和任何数字异或=数字本身

  • 计算当前 xy 的进位:carry = (x & y) << 1

颠倒给定的 32 位无符号整数的二进制位。

提示:

  • 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。

  • 在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在 示例 2 中,输入表示有符号整数 -3,输出表示有符号整数 -1073741825

解法:n&1 得到最低位,然后左移31-i位,跟rev做按位或。保留最高位。然后把n逻辑右移一位。重复得到结果。

解法2.位运算分治

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

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

解法:同样的数异或=0,0和任何数异或等于这个数本身。所以可以用异或操作。

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

你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。

解法1:同样是异或,但是判断出现的次数是否<=2

解法2.依次确定每一个二进制位

答案的第 i 个二进制位就是数组中所有元素的第 i 个二进制位之和除以 3 的余数。

给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。

解法1。使用Hash表。 ------没想到更好办法之前,就用最笨的办法

解法2.位运算,考虑136只出现一次的数字是通过异或操作做出来的。

如果能把数组中的两个只出现一次的数字分成两组。再做异或操作就能得到两个数字的值了。

因为x1不等于x2,我们找到异或后的最后一个1,那么x1或者x2跟这个值进行异或的结果是不同的。这样就可以把x1和x2分组。

x & -x 是一种常见的位运算操作,通常用于获取整数 x 的最低位的1。这个操作的原理基于补码表示。

具体来说,对于二进制数的补码表示,-x 可以通过 ~x + 1 得到。在补码表示中,x-x 在二进制中只有最低位的1是相同的,其他位都是互补的。

给你一个整数数组 nums ,返回 nums[i] XOR nums[j] 的最大运算结果,其中 0 ≤ i ≤ j < n

解法1.字典树

可以将数组中的元素看成长度为 31 的字符串,字符串中只包含 0 和 1。如果我们将字符串放入字典树中,那么在字典树中查询一个字符串的过程,恰好就是从高位开始确定每一个二进制位的过程。

如何求出 x 呢?我们可以从字典树的根节点开始进行遍历,遍历的「参照对象」为 ai。在遍历的过程中,我们根据 ai的第 x个二进制位是 0 还是 1,确定我们应当走向哪个子节点以继续遍历。假设我们当前遍历到了第 k 个二进制位:

如果 ai 的第 k 个二进制位为 0,那么我们应当往表示 1 的子节点走,这样 0⊕1=1,可以使得 x 的第 k 个二进制位为 1。如果不存在表示 1 的子节点,那么我们只能往表示 0 的子节点走,x 的第 k个二进制位为 0;

如果 ai的第 k 个二进制位为 1,那么我们应当往表示 0 的子节点走,这样 1⊕0=1,可以使得 x 的第 k 个二进制位为 1。如果不存在表示 0 的子节点,那么我们只能往表示 1 的子节点走,x 的第 k 个二进制位为 0。

由于字典树中的每个节点最多只有两个子节点,分别表示 0 和 1,因此本题中的字典树是一棵二叉树。在设计字典树的数据结构时,我们可以令左子节点 left 表示 0,右子节点 right 表示 1。

解法2.用hash表。从高位起,一位一位的进行处理。判断是否能够异或成为1

先处理最高位,我们的目标是结果尽可能多的1,我们把数字的最高位存入set,遍历的时候,判断最高位跟结果做异或操作,看是否存在set里面。如果有就说明可行。否则把结果减一。

DNA序列 由一系列核苷酸组成,缩写为 'A', 'C', 'G''T'.。

  • 例如,"ACGAATTCCG" 是一个 DNA序列

在研究 DNA 时,识别 DNA 中的重复序列非常有用。

给定一个表示 DNA序列 的字符串 s ,返回所有在 DNA 分子中出现不止一次的 长度为 10 的序列(子字符串)。你可以按 任意顺序 返回答案。

318.最大单词长度乘积

给你一个字符串数组 words ,找出并返回 length(words[i]) * length(words[j]) 的最大值,并且这两个单词不含有公共字母。如果不存在这样的两个单词,返回 0

解法:如果可以将判断两个单词是否有公共字母的时间复杂度降低到 O(1)?

由于单词只包含小写字母,共有 26个小写字母,因此可以使用位掩码的最低 26 位分别表示每个字母是否在这个单词中出现。将 a 到 z 分别记为第 0 个字母到第 25 个字母,则位掩码的从低到高的第 i 位是 1 当且仅当第 i 个字母在这个单词中,其中 0≤i≤25 。

用数组 masks 记录每个单词的位掩码表示。计算数组 masks 之后,判断第 i 个单词和第 j 个单词是否有公共字母可以通过判断 masks[i] & masks[j] 是否等于 0 实现,当且仅当 masks[i] & masks[j]=0 时第 i 个单词和第 j 个单词没有公共字母,此时使用这两个单词的长度乘积更新最大单词长度乘积。

给你两个整数 leftright ,表示区间 [left, right] ,返回此区间内所有数字 按位与 的结果(包含 leftright 端点)。

解法:找数字二进制的最长前缀。抹去最右边的1:

最后更新于

这有帮助吗?