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

创建时间: November 25, 2021 3:15 PM
最后编辑时间: November 25, 2021 3:17 PM
标签: 位运算, 数组
网址: https://leetcode-cn.com/problems/WGki4K/
难度: 中等

题目

输入一个整数数组,数组中只有一个数字出现了一次,而其他数字都出现了3次。请找出那个只出现一次的数字。例如,如果输入的数组为[0,1,0,1,0,1,100],则只出现一次的数字是100。

分析

哈希表

本题一个直观的想法是使用哈希表来统计数字出现的次数,再遍历value,找到key

class Solution {
    public int singleNumber(int[] nums) {
        Map<Integer, Integer> freq = new HashMap<Integer, Integer>();
        for (int num : nums) {
            freq.put(num, freq.getOrDefault(num, 0) + 1);
        }
        int ans = 0;
        for (Map.Entry<Integer, Integer> entry : freq.entrySet()) {
            int num = entry.getKey(), occ = entry.getValue();
            if (occ == 1) {
                ans = num;
                break;
            }
        }
        return ans;
    }
}

使用位运算

先来看一个简化的版本

输入数组中除一个数字只出现一次之外其他数字都出现两次,请找出只出现一次的数字

异或tip
任何一个数字异或它自己的结果都是0
任何一个数字异或0的结果都是它自己
a ^ a=0,a ^ 0=a,a ^ a ^ a=a

如果将数组中所有数字进行异或运算,那么最终的结果就是那个只出现一次的数字。

再看本题,因为其他数字出现了三次,一个数字异或自己两次得到的数字还是自己本身,因此不能采用异或法

一个整数是由32个0或1组成的。我们可以将数组中所有数字的同一位置的数位相加。如果将出现3次的数字单独拿出来,那么这些出现了3次的数字的任意第i个数位之和都能被3整除。因此,如果数组中所有数字的第i个数位相加之和能被3整除,那么只出现一次的数字的第i个数位一定是0;如果数组中所有数字的第i个数位相加之和被3除余1,那么只出现一次的数字的第i个数位一定是1。这样只出现一次的任意第i个数位可以由数组中所有数字的第i个数位之和推算出来。当我们知道一个整数任意一位是0还是1之后,就可以知道它的数值。

class Solution {
    public int singleNumber(int[] nums) {
        int ans = 0;
        for (int i = 0; i < 32; ++i) {
            int total = 0;
            for (int num: nums) {
                total += ((num >> i) & 1);
            }
            if (total % 3 != 0) {
                ans |= (1 << i);
            }
        }
        return ans;
    }
}

核心代码是total += ((num >> i) & 1);ans |= (1 << i);

(num >> i) & 1 是取num的第i个二进制位

ans |= (1 << i) 是将ans的第i个二进制位置1

数字电路设计优化

官方题解居然能想到用数字电路的方式来求解本题,也是我没想到的,过程没有看懂,但是代码是真的简洁,这里也贴一下

class Solution {
    public int singleNumber(int[] nums) {
        int a = 0, b = 0;
        for (int num : nums) {
            b = ~a & (b ^ num);
            a = ~b & (a ^ num);
        }
        return b;
    }
}

你可能感兴趣的:(剑指Offer(专项突破版),java)