56 - II. 数组中数字出现的次数 II


comments: true
difficulty: 中等
edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9856%20-%20II.%20%E6%95%B0%E7%BB%84%E4%B8%AD%E6%95%B0%E5%AD%97%E5%87%BA%E7%8E%B0%E7%9A%84%E6%AC%A1%E6%95%B0%20II/README.md

面试题 56 - II. 数组中数字出现的次数 II

题目描述

在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。

 

示例 1:

输入:nums = [3,4,3,3]
输出:4

示例 2:

输入:nums = [9,1,7,9,7,9,7]
输出:1

 

限制:

  • 1 <= nums.length <= 10000
  • 1 <= nums[i] < 2^31

 

解法

方法一:位运算

我们用一个长度为 32 的数组 c n t cnt cnt统计所有数字的每一位中 1 1 1 的出现次数。如果某一位的 1 1 1 的出现次数能被 3 3 3 整除,那么那个只出现一次的数字二进制表示中对应的那一位也是 0 0 0【说明一定不属于非重复数字的位】;否则,那个只出现一次的数字二进制表示中对应的那一位是 1 1 1

时间复杂度 O ( n × C ) O(n \times C) O(n×C),空间复杂度 O ( C ) O(C) O(C)。其中 n n n 是数组的长度;而 C C C 是整数的位数,本题中 C = 32 C=32 C=32

【LeetCode刷题力扣题解 | 剑指Offer56 - II. 数组中数字出现的次数 II | 画图算法思路讲解及C++代码实现】 https://www.bilibili.com/video/BV1ZP4y1x7N3/?share_source=copy_web&vd_source=ed4a51d52f6e5c9a2cb7def6fa64ad6a
核心:重复数字对应为1的位 的个数统计一定为2的倍数。如果不是,就说明 非重复数字 在该位为1。
在这里插入图片描述

Python3
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        cnt = [0] * 32
        for x in nums:
            for i in range(32):
                cnt[i] += x & 1
                x >>= 1
        return sum(1 << i for i in range(32) if cnt[i] % 3)
Java
class Solution {
    public int singleNumber(int[] nums) {
        int[] cnt = new int[32];
        for (int x : nums) {
            for (int i = 0; i < 32; ++i) {
                cnt[i] += x & 1;
                x >>= 1;
            }
        }
        int ans = 0;
        for (int i = 0; i < 32; ++i) {
            if (cnt[i] % 3 == 1) {
                ans |= 1 << i;
            }
        }
        return ans;
    }
}
C++
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int cnt[32]{};
        for (int& x : nums) {
            for (int i = 0; i < 32; ++i) {
                cnt[i] += x & 1;
                x >>= 1;
            }
        }
        int ans = 0;
        for (int i = 0; i < 32; ++i) {
            if (cnt[i] % 3) {
                ans |= 1 << i;
            }
        }
        return ans;
    }
};
Go
func singleNumber(nums []int) (ans int) {
	cnt := [32]int{}
	for _, x := range nums {
		for i := range cnt {
			cnt[i] += x & 1
			x >>= 1
		}
	}
	for i, v := range cnt {
		if v%3 == 1 {
			ans |= 1 << i
		}
	}
	return
}
Rust
impl Solution {
    pub fn single_number(nums: Vec<i32>) -> i32 {
        let mut counts = [0; 32];
        for num in nums.iter() {
            for i in 0..32 {
                counts[i] += (num >> i) & 1;
            }
        }
        let mut res = 0;
        for count in counts.iter().rev() {
            res <<= 1;
            res |= count % 3;
        }
        res
    }
}
JavaScript
/**
 * @param {number[]} nums
 * @return {number}
 */
var singleNumber = function (nums) {
    const cnt = new Array(32).fill(0);
    for (let x of nums) {
        for (let i = 0; i < 32; ++i) {
            cnt[i] += x & 1;
            x >>= 1;
        }
    }
    let ans = 0;
    for (let i = 0; i < 32; ++i) {
        if (cnt[i] % 3) {
            ans |= 1 << i;
        }
    }
    return ans;
};
C#
public class Solution {
    public int SingleNumber(int[] nums) {
        int[] cnt = new int[32];
        foreach(int x in nums) {
            int v = x;
            for (int i = 0; i < 32; ++i) {
                cnt[i] += v & 1;
                v >>= 1;
            }
        }
        int ans = 0;
        for (int i = 0; i < 32; ++i) {
            if (cnt[i] % 3 == 1) {
                ans |= 1 << i;
            }
        }
        return ans;
    }
}
Swift
class Solution {
    func singleNumber(_ nums: [Int]) -> Int {
        var bitCounts = [Int](repeating: 0, count: 32)

        for num in nums {
            var x = num
            for i in 0..<32 {
                bitCounts[i] += x & 1
                x >>= 1
            }
        }

        var result = 0
        for i in 0..<32 {
            if bitCounts[i] % 3 == 1 {
                result |= 1 << i
            }
        }

        return result
    }
}
  • 14
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值