2023/10/14

176 阅读2分钟

136. 只出现一次的数字

算法掌握:

  • 位运算(异或 ^)
  • 常见的位运算操作:
    • 与运算(&):对两个操作数的每个对应比特位执行 AND 运算,只有当两个位都为 1 时,结果位才为 1。
    • 或运算(|):对两个操作数的每个对应比特位执行 OR 运算,只要其中一个位为 1,结果位就为 1。
    • 异或运算(^):对两个操作数的每个对应比特位执行 XOR 运算,当两个位不同时结果位为 1,否则为 0。
    • 取反运算(~):反转操作数的每个位,将 0 变为 1,将 1 变为 0。
    • 左移运算(<<):将操作数的比特位向左移动指定的位数,低位补 0。
    • 右移运算(>>):将操作数的比特位向右移动指定的位数,高位补符号位(负数补 1,正数补 0)。

解题思路:

如果不考虑 线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间 的情况。 直接开个hash表去重查询没有重复的即可,或者用排序后相邻前后比较即可 本题考查对位运算的异或

首先理解 什么是异或运算 -> 对两个操作数的每个对应比特位(二进制位)执行 XOR 运算,当两个位不同时结果位为 1,否则为 0。

异或运算有以下三个性质。

任何数和 0 做异或运算,结果仍然是原来的数,即 a ⊕ 0 = a

任何数和其自身做异或运算,结果是 0,即 a ⊕ a = 0

异或运算满足交换律和结合律, 即 a ⊕ b ⊕ a = b ⊕ a ⊕ a = b ⊕ (a ⊕ a) = b ⊕ 0 = b

根据 第一个性质和第二个性质 自身相互异或为 0,自身与 0 异或为本身,将所有的值都异或一遍,相同的都为0,剩下一个单独的一定是与 0 异或得本身

java code:

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

c++ code:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int res = 0;
        for(int num : nums) res ^= num;
        return res;
    }
};