剑指 Offer II 004. 只出现一次的数字

187 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

一、题目描述:

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

示例 1:

输入:nums = [2,2,3,2] 输出:3 示例 2:

输入:nums = [0,1,0,1,0,1,100] 输出:100

提示:

1 <= nums.length <= 3 * 104 -231 <= nums[i] <= 231 - 1 nums 中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次

进阶:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

二、思路分析:

最先想到使用哈希表的方法,通过哈希中方法来查找只出现一次的元素 方法如下:

循环数组,将每个元素挨个加入哈希表中

遍历哈希表中的数据,查找哪个数字只出现了一次返回。

class Solution {
    public int singleNumber(int[] nums) {
        HashMap<Integer,Integer> map = new HashMap<>();
        for(int i = 0;i < nums.length;i++){
            map.put(nums[i],map.getOrDefault(nums[i],0) + 1);
        }
        int res = 0; 
        for(Map.Entry<Integer,Integer> entry : map.entrySet()){
            if(entry.getValue() == 1){
                res = entry.getKey();
                break;
            }
        }
        return res;
    }
}

题目比较简单,我们试试进阶的访问,不使用额外的空间来完成

由于整个数组除了目标数字,其余所有的数都出现了三次,因此可以考虑:按位求和 ,思路如下:

遍历数字的每一位,因为数据大小不超过整形范围,因此遍历在范围[0,31]即可。对数组中的每一个数进行右移同时与1进行与运行算,获得当前位数字加入到sum当中。同时在将和右移i位加入到结果当中。

三、AC 代码:

class Solution {
    public int singleNumber(int[] nums) {
        int ans = 0;
        for (int i = 0; i < 32; i++) {
            int sum = 0;
            for (int num : nums) {
                sum += ((num >>= i) & 1);
            }
            sum %= 3;
            ans += (sum << i);
        }
        return ans;
    }
}
​

四、总结:

\

掘友们,解题不易,如果觉得有用就留下个赞或评论再走吧!谢啦~ 💐