牛客-NC156-数组中只出现一次的数(其它数出现k次)

这篇博客介绍了如何在Java中找到数组中唯一出现一次的数字,当其他数字出现k(奇数)次时,提供了两种方法:HashMap法和位运算法。HashMap法通过统计每个数字出现的次数并遍历找出出现一次的数字;位运算法利用位运算的性质,通过对数组中所有数字的二进制位求和并判断余数来确定只出现一次的数字。两种方法的时间复杂度均为O(N),空间复杂度分别为O(N)和O(1)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NC156. 数组中只出现一次的数(其它数出现k次)(easy)


在这里插入图片描述

方法一:HashMap法

思路:这个解法是暴力解,直接统计每个数字出现的次数,再遍历返回出现一次的那个数即可。于是,可以写出以下代码:

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param arr int一维数组 
     * @param k int 
     * @return int
     */
    public int foundOnceNumber (int[] arr, int k) {
        // write code here
        HashMap<Integer, Integer> ret = new HashMap<>();
        for (int i = 0; i < arr.length; i++) {
            if (!ret.containsKey(arr[i])) {
                ret.put(arr[i], 1);
            } else {
                ret.put(arr[i], ret.get(arr[i]) + 1);
            }
        }
        Set<Map.Entry<Integer, Integer>> entries = ret.entrySet();
        Iterator<Map.Entry<Integer, Integer>> iterator = entries.iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, Integer> next = iterator.next();
            if (next.getValue() == 1) {
                return next.getKey();
            }
        }
        return -1;
    }
}

时间复杂度: O(N),N表示数组arr的长度。
空间复杂度: O(N),需要使用HashMap来对数字出现的次数进行存储。

方法二:位运算法

思路:出现k次我们不能再使用之前的异或方法进行解决,但仍可以利用位运算的思想去做。因为出现k(奇数)次的数字每个位(0或者1)也是出现k(奇数)次,因此可以每一位的和能够被k整除(对k取余为0)。所以如果把每个数的二进制表示的每一位加起来,对于每一位的和,如果能被k整除,那对应那个只出现一次的数字的那一位就是0,否则对应的那一位是1。我们需要用一个长度为32(int型二进制表示最多为32位,4字节)的数组bisum保存每一位的和。
具体来讲实现过程是,先初始化为0,然后对于每个数字,遍历它二进制表示的每一位,如果这一位是1,bisum对应的那一位就加1。得到bisum后,我们再次遍历bisum,如果某个二进制位不能被k整除,即 bisum[i] % k != 0,那么只出现一次的这个数字在当前二进制位上为1,此时要进行左移恢复,即1<<i

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param arr int一维数组 
     * @param k int 
     * @return int
     */
    public int foundOnceNumber (int[] arr, int k) {
        // write code here
        // 对所有数字的第i位,如果它们的和对k取余是0,则只出现一次的数字为0,否则为1。
        int[] bisum = new int[32];
        int n = arr.length;
        for (int i = 0; i < 32; i++) {
            int sum = 0;
            for (int j = 0; j < n; j++) {
                sum += (arr[j] & 1); // 统计当前数组元素的1的个数
                arr[j] = (arr[j] >> 1); // 让当前数组元素右移一位
            }
            bisum[i] = sum;
        }
        int ret = 0;
        for (int i = 0; i < 32; i++) {
            if (bisum[i] % k != 0) ret += (1<<i);
        }
        return ret;
    }
}

时间复杂度: O(N),N表示数组array的长度。
空间复杂度: O(1),额外空间不包含返回所需的空间ret。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值