LeetCode-260. 只出现一次的数字 III

648 阅读2分钟

1.题目描述

给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

**进阶:**你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?

示例 1:

输入:nums = [1,2,1,3,2,5]
输出:[3,5]
解释:[5, 3] 也是有效的答案。

示例 2:

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

示例 3:

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

提示:

  • 2 <= nums.length <= 3 * 104
  • -231 <= nums[i] <= 231 - 1
  • 除两个只出现一次的整数外,nums 中的其他数字都出现两次

Tips: 力扣地址:leetcode-cn.com/problems/si…

2. 思路分析

这一类题有一个统一的简单解决方法就是下面方式1(和之前的一样):

方式1:整个最容易想到的方法解决就是通过额外空间,定义一个HashMap,key为元素,value为元素出现的次数。这个是实现最容易想到的解决方案,遍历整个数组然后将数组的次数统计出来到map的value中。

下面来看看方式2:

方式2:这个题目和《136. 只出现一次的数字》这个比较相似,不同的是有两个数据只出现一次,假设为a,b。根据异或的特点,将数组遍历异或得到的值就是a^b的值c。接下来只需要从c的值中分离出来a和b就可以了。然后将c的值再一次与数组进行异或就可以了

3. AC代码

class Solution {
    public int[] singleNumber(int[] nums) {
int[] a = new int[2];
        Map<Integer, Integer> map = new HashMap<>(3*10000);
        for(int item : nums){
            map.put(item, map.getOrDefault(item, 0)+1);
        }
        List<Integer> collect = map.entrySet().stream().filter(item -> item.getValue() == 1).map(item -> item.getKey())
            .collect(Collectors.toList());
        a[0] = collect.get(0);
        a[1] = collect.get(1);
        return a;
    }
}


class Solution {
    public int[] singleNumber(int[] nums) {
		int c = 0;
        for (int num : nums) {
            c ^= num;
        }
        int e = (c == Integer.MIN_VALUE ? c : c & (-c));
        int a = 0, b = 0;
        for (int num : nums) {
            if ((num & e) != 0) {  
                a ^= num;
            } else {
                b ^= num;
            }
        }
        return new int[]{a, b};
    }
}

4. 总结

这一类问题通过Hash表来求解是最直观最简单的。位运算求解需要对位运算有较深的了解

我是蚂蚁背大象,文章对你有帮助点赞关注我,文章有不正确的地方请您斧正留言评论~谢谢