剑指Offer:只出现一次的数(三)

这篇博客介绍了如何在Java中解决一个数组中只有一个数字出现一次,其他数字出现三次的问题。提供了两种解题方法:一是利用哈希表统计每个数字出现的次数,二是通过位运算统计每一位上1出现的次数并判断能否被3整除。这两种方法的时间复杂度均为O(n),空间复杂度分别为O(n)和O(1)。
摘要由CSDN通过智能技术生成

题目描述

在一个数组 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

来源:力扣Leetcode

两种解题方法

import java.util.HashMap;

/**
 * 在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。
 * 请找出那个只出现一次的数字。
 * @author IT00ZYQ
 * @date 2021/5/26 9:13
 **/
public class 数组中只出现一次的数 {
    /**
     * 解法1:哈希表
     * 时间复杂度:O(n)
     * 空间复杂度:O(n)
     */
    public static int singleNumber1(int[] nums) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            Integer count = map.get(num);
            if (count != null) {
                if (count == 2) {
                    map.remove(num);
                } else {
                    map.put(num, 2);
                }
            } else {
                map.put(num, 1);
            }
        }
        Integer[] res = new Integer[1];
        map.keySet().toArray(res);
        return res[0];
    }

    /**
     * 解法2:统计每一个二进制位上1出现的次数,判断是否能被3整除
     * 空间复杂度:O(1)
     * 时间复杂度:O(n)
     */
    public static int singleNumber2(int[] nums) {
        int[] bits = new int[32];
        for (int i = 0; i < nums.length; i++) {
            for (int j = 0; j < 32; j++) {
                // (nums[i] & 1),最低位为1时返回1,最低位为0时返回0
                bits[j] += (nums[i] & 1);
                // 无符号右移
                nums[i] = nums[i] >>> 1;
            }
        }
        int res = 0;
        // 将不能被3整除的位置累加到res
        for (int i = 0; i < 32; i++) {
            if (bits[i] % 3 != 0) {
                res += (1 << i);
            }
        }
        return res;
    }

    public static void main(String[] args) {
        int[] nums = {9,1,7,9,7,9,7};
        System.out.println(singleNumber1(nums));
        System.out.println(singleNumber2(nums));
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

it00zyq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值