(位运算) 剑指 Offer 56 - I. 数组中数字出现的次数 ——【Leetcode每日一题】

❓剑指 Offer 56 - I. 数组中数字出现的次数

难度:中等

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是 O ( n ) O(n) O(n),空间复杂度是 O ( 1 ) O(1) O(1)

示例 1:

输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]

示例 2:

输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]

限制

  • 2 <= nums.length <= 10000

思路:位运算

基础知识必知:一篇文章搞懂位运算!!!

两个相等的元素 异或 的结果为 0,而 0 与任意数 x 异或 的结果都为 x

对本题给的数组的所有元素执行异或操作,得到的是两个不存在重复的元素异或的结果。例如对于数组 [x,x,y,y,z,k]x^x^y^y^z^k = 0^y^y^z^k = y^y^z^k = 0^z^k = z^k

两个不相等的元素在位级表示上一定会有所不同,因此这两个元素异或得到的结果 diff 一定不为 0:

  • 使用 ans[0] = diff 先保存这两个数的结果;
  • 位运算 diff & -diff 能得到 diff 位级表示中 最右侧为 1 的位,令 diff = diff & -diff
  • diff 作为区分两个元素的依据,一定有一个元素对 diff 进行 运算的结果为 diff ,另一个结果为 0。

设不相等的两个元素分别为 xy,遍历数组所有元素,判断每一个元素与 diff 结果是否为 diff :

  • 如果是的话将元素与 x 进行 异或 并赋值给 ans[1]
  • 数组中相等的元素一定会同时与 x 异或操作,而且这些相等的元素异或的结果为 0,因此最后 只剩下 x 与 0 异或的结果;
  • 另一个元素 y = ans[0] ^ x

代码:(C++、Java)

C++

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        vector<int> ans(2);
        int diff = 0;
        for(int num : nums){//得到只出现一次的两个数的异或
            diff ^= num;
        }
        ans[0] = diff; //记录两个数的异或结果
        diff &= -diff; //得到最后一位1
        for(int num : nums){//得到其中一个数
            if((num & diff) == diff){
                ans[1] ^= num; 
            }
        }
        ans[0] ^= ans[1];//得到另一个数
        return ans;
    }
};

Java

class Solution {
    public int[] singleNumbers(int[] nums) {
        int[] ans = new int[2];
        int diff = 0;
        for(int num : nums){//得到只出现一次的两个数的异或
            diff ^= num;
        }
        ans[0] = diff; //记录两个数的异或结果
        diff &= -diff; //得到最后一位1
        for(int num : nums){//得到其中一个数
            if((num & diff) == diff){
                ans[1] ^= num; 
            }
        }
        ans[0] ^= ans[1];//得到另一个数
        return ans;
    }
}

运行结果:

(位运算) 剑指 Offer 56 - I. 数组中数字出现的次数 ——【Leetcode每日一题】_第1张图片

复杂度分析:

  • 时间复杂度 O ( n ) O(n) O(n),我们只需要遍历数组两次。
  • 空间复杂度 O ( 1 ) O(1) O(1),只需要常数的空间存放若干变量。

题目来源:力扣。

放弃一件事很容易,每天能坚持一件事一定很酷,一起每日一题吧!
关注我LeetCode主页 / CSDN—力扣专栏,每日更新!

注: 如有不足,欢迎指正!

你可能感兴趣的:(LeetCode,leetcode,算法,职场和发展)