[leetCode]剑指 Offer 56 - II. 数组中数字出现的次数 I、II

在这里插入图片描述

解法

有两个数字只出现一次,其余数字出现两次,那么出现两次的数字异或之后为0相互抵消,剩下两个出现一次的数字由于一定不相同,所以异或之后肯定有一位为1。所以可以通过该位是否为1将数组划分为两个子数组,每个数字都只有一个数字出现一次,这样就能通过异或分别找到每个数组中只出现一次的数字了。

class Solution {
    public int[] singleNumbers(int[] nums) {
        if (nums == null) return null;
        if (nums.length < 2) return new int[]{nums[0],0};
        int resultExclusiveOR = 0;
        for (int i = 0; i < nums.length; i ++) 
            resultExclusiveOR ^= nums[i];
        int indexOf1 = findFirstBitIs1(resultExclusiveOR);
        int[] ans = new int[2];
        for (int i = 0; i < nums.length; i++) {
            if (isBit1(nums[i], indexOf1)) {
                ans[0] ^= nums[i];
            } else {
                ans[1] ^= nums[i];
            }
        }
        return ans;
    }

    private int findFirstBitIs1(int num) {
        int indexBit = 0;
        while (((num & 1) == 0) && (indexBit < 32)) {
            num = num >> 1;
            ++indexBit;
        }
        return indexBit;
    }

    private boolean isBit1(int num, int index) {
        num = num >> index;
        return ((num & 1) == 1);
    }
}

在这里插入图片描述

解法

 由于除了只出现一次的数字之外其余数字都出现三次,那么把出现三次的数字每一位加起来肯定能被3整除。所以我们可以把数组中所有的数字每一位都加起来,如果某一位能被3整除则说明只出现一次的数字在该位为0,否则为1。

class Solution {
    public int singleNumber(int[] nums) {
        if (nums == null || nums.length == 0) return 0;
        // 长度为32的辅助数组,用于记录数字每一位的和
        int[] bitSum = new int[32];
        for (int i = 0; i < nums.length; i++) {
            int bitMask = 1;
            for (int j = 31; j >= 0; j--) {
                int bit = nums[i] & bitMask;
                if (bit != 0) {
                    ++bitSum[j];
                }
                bitMask = bitMask << 1;
            }
        }
        int result = 0;
        for (int i = 0; i < 32; i++) {
            result = result << 1;
            result += bitSum[i] % 3; 
        }
        return result;
    }
}
posted @ 2020-09-20 11:39  消灭猕猴桃  阅读(76)  评论(0编辑  收藏  举报