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

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。

全部评论

相关推荐

01-16 18:34
四川大学 Java
欢迎加入AI:没有啥稳定不稳定,一切都源于业务快速发展还是收缩。我当年一开始去的央企,业务不赚钱,也贼卷,慢慢就开始优化了。。。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务