8.3 第一次做,无法 AC
8.4 无法 AC
8.5 无法 AC
8.6 一次 AC

题目描述


原题链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/

解题思路


K 神题解:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/solution/

8.5 心得:

  • 其它数字出现了三次,所以不能用异或!

  • 统计!!!!下面第16行代码得用 += !!!!

    1. class Solution {
    2. public int singleNumber(int[] nums) {
    3. // 我们知道,每个数字都只有一个二进制数
    4. // 则每个 int 类型就有唯一一个 32 位的二进制数
    5. // 我们用一个长度为 32 的数组来存储这些 int 型数字的二进制表示中出现 1 的次数
    6. // 这样的话,只要某个数字出现了三次,那么该数组的某位就是 3
    7. // 我们再对 3 取余就可以将为 3 的位给清 0
    8. // 这样这个数组剩下的要么是 1 要么是 0
    9. // 其实结果就是我们要的只出现一次的数的二进制表示形式
    10. // 统计出各个32位二进制数字中每一位的数量,重点是可以统计出各个数字的各个 1
    11. int[] counts = new int[32];
    12. for(int num : nums) {
    13. for(int i = 0; i < 32; i++) {
    14. // 数组的最低位存储的是二进制中的最低位
    15. counts[i] += num & 1; // & 运算只能涉及到最右一位,所以下面得用无符号右移
    16. num >>>= 1; // 无符号右移一位
    17. }
    18. }
    19. // 将数组中的每一位对 3 取余后恢复到一个 int 型数字中,该数字就是我们要的答案
    20. int res = 0;
    21. for(int i = 0; i < 32; i++) {
    22. res <<= 1; // 每次都得先左移一位,一开始的 0 没事,反正也会被32位给限制住最后消失
    23. res |= counts[31 - i] % 3; // res 首先恢复的肯定是最左边的,最左边的恢复后用左移就可以恢复该数右边;那么数组肯定也要先从最高位开始恢复; res 最右一位一开始肯定是 0 ,所以只能用或运算
    24. }
    25. return res;
    26. }
    27. }