LeetCode琅琊榜第二十一层-只出现一次的数字

LeetCode琅琊榜第二十一层-只出现一次的数字(二进制算法)

题目

题目浏览

在这里插入图片描述

关键信息提取

  • 除了某一个元素仅出现过一次之外,其他都出现三次
  • 2e-31 <= nums[i] <= 2e31 - 1
  • 算法的时间复杂度应该是线性

题目信息解读

  • 在数组中,只可能出现两个情况
    • 某一个元素出想过三次
    • 某一个元素出想过一次
  • 每一个元素的取值范围都在一个int范围内

算法概述

哈希计数法

  • 哈希计数法主要有两种
    • 通过HashSet集合来计数,一般该集合处理的是出想过多次的元素
    • 通过HashMap集合来计数,一般该集合处理的是只出现过一次的元素
    • 很明显,这里采用的是**HashMap**集合来计数

二进制求解法

算法详解

算法思想

哈希计数法

  • 我们先遍历一次nums数组,通过一个HashMap来记录每一个元素出现的个数
  • 再遍历一次HashMap,找到只出现过一次的元素

二进制求解法

在这里插入图片描述

解析
  1. 该算法的突破口是我们的二进制位,因此我们先得到其每一个元素的二进制位,并将其位置对正
  2. 针对于出现过三次的元素,他们的二进制位一定是一样的,即对应的二进制位上会出现以下两种情况
    1. 1 + 1 + 1 = 3 % 3 = 0
    2. 0 + 0 + 0 = 0 % 3 = 0
  3. 不论是哪一种情况都是3的倍数,同理推理到所有出现过三次的元素,只要该元素出现过三次对应的二进制位上%3一定会等于0
  4. 如果最后求出来的结果(res = sum % 3) != 0, 说明,这个res一定是出现一次的二进制位,将这些二进制位记录下来即可获取出现过一次的数字

代码实现与分析

哈希计数法

class Solution {
    public int singleNumber(int[] nums) {
        var map = new HashMap<Integer,Integer>();
        var target = 0;
        for (var num : nums) {
            // 如果该元素不存在,就赋值为0+1,否则是原来的大小+1
            map.put(num,map.getOrDefault(num,0) + 1);
        }
        for (var res : map.entrySet()) {
            if (res.getValue() == 1) {
                target = res.getKey();
                break;
            }
        }
        return target;
    }
}

二进制求解法

class Solution {
    public int singleNumber(int[] nums) {
        // target 用于记录最终的结果
        var target = 0;
        // 每一个元素都在int范围内,所以一共有32个bit位,循环32次
        for (int i = 0; i < 32; i++) {
            // 记录每一个二进制位的和
            var sum = 0;
            for (var num : nums) {
                // 获取每一个二进制位的和,详情请看解析1
                sum += (num >> i) & 1;
            }
            // 详情请看解析2 
            if (sum % 3 != 0) {
                target |= (1 << i);
            }
        }
        // 返回结果即可
        return target;
    }
}

解析1

  1. 当我们想获取某一个二进制位的时候最简单的方法就是移位操作符 >> 或 <<,第一次移动i = 0位,第二次移动i = 1位,正好把 第一个和第二个二进制位取到,后面同理
  2. 在这个基础上,我们需要对结果&1,可以把前面可能有1的二进制位去掉,只留对应的那一位
  3. 叠加即可

解析2

  1. 出现过一次的元素的二进制情况也只能有两个,即0和1
    1. 如果是0,结果sum % 3 == 0成立,这个二进制位默认是0,不需要改变
    2. 如果是1,结果sum % 3 == 0不成立,这个二进制位默认是0,需要改变成1,所以最终只要改变是1的情况
  2. 1<<i就可以得到对应的二进制位

算法结论

二进制求解法是优于哈希计数法的,不信你可以验证一下

二进制求解法不仅可以用于本题,还能运用于力扣二十层中!

猜你喜欢

转载自blog.csdn.net/JOElib/article/details/125125010