• 【每日一题】只出现一次的数字 III


    Tag

    位运算】【数组】【2023-10-16】


    题目来源

    260. 只出现一次的数字 III


    题目解读

    找出数组中恰好只出现一次的连个元素,其余的所有元素均出现两次。要求算法的时间复杂度为线性的,空间复杂度为常量级别的。


    解题思路

    方法一:位运算

    我们先对数组 nums 中的虽有元素进行一次异或操作,得到的值 x 是数组中仅仅出现过一次的两个数的异或值,即 x = x 1 ⨁ x 2 x = x_1 \bigoplus x_2 x=x1x2 x 1 x_1 x1 x 2 x_2 x2 分别表示数组中仅仅出现过一次的两个数。

    显然,这个 x x x 的值不会等于 0,因为一旦等于 0,那么说明 x 1 = x 2 x_1 = x_2 x1=x2,这样 x 1 x_1 x1 x 2 x_2 x2 就不是仅出现一次的数了。

    现在使用位运算 KaTeX parse error: Expected 'EOF', got '&' at position 3: x &̲ -x 可以得到 x x x 的二进制表示位中最低位的 1,设其为第 i,也就表示 x 1 x_1 x1 x 2 x_2 x2 中的某一个数的二进制表示的第 i 位为 0,另一个数的第 i 位为 1,我们可以据此来将数组中的所有元素分类:

    • i 位为 1 的为一类;
    • i 位为 0 的为一类;

    根据以上分类,我们知道 x 1 x_1 x1 x 2 x_2 x2 分属在以上两个类中。每个类中出现的数有一个数是仅出现一次的数,其他的数都是出现两次的。于是,我们对每一个类中的元素进行异或和操作,就得到了该类中仅出现一次的元素。对这两个类分别进行异或和操作就得到了数组 nums 中仅出现了一次的两个数。

    实现代码

    class Solution {
    public:
        vector<int> singleNumber(vector<int>& nums) {
            int sum = 0;
            for(auto &num : nums){
                sum ^= num;
            }
            
            // 防止溢出
            int lst = ((sum == INT_MIN) ? sum : sum & (-sum));
            
            int num1 = 0, num2 = 0;
            for(auto &num : nums){
                if(lst & num){
                    num1 ^= num;
                }
                else{
                    num2 ^= num;
                }
            }
            return {num1, num2};
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    复杂度分析

    时间复杂度: n n n 是数组 nums 的长度。

    空间复杂度 O ( 1 ) O(1) O(1)


    其他语言

    c

    /**
     * Note: The returned array must be malloced, assume caller calls free().
     */
    int* singleNumber(int* nums, int numsSize, int* returnSize){
        int xorsum = 0;
        for (int i = 0; i < numsSize; ++i) {
            xorsum ^= nums[i];
        }
    
        int lsb = (xorsum == INT_MIN ? xorsum : xorsum & (-xorsum));
        int x1 = 0, x2 = 0;
        for (int i = 0; i < numsSize; ++i) {
            int num = nums[i];
            if (num & lsb) {
                x1 ^= num;
            }
            else {
                x2 ^= num;
            }
        }
    
        int *res = (int *)malloc(sizeof(int) * 2);
        res[0] = x1;
        res[1] = x2;
        *returnSize = 2;
        return res;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    python3

    class Solution:
        def singleNumber(self, nums: List[int]) -> List[int]:
            xorsum = 0
            for num in nums:
                xorsum ^= num
            
            lsb = xorsum & (-xorsum)
            x1, x2 = 0, 0
            for num in nums:
                if num & lsb:
                    x1 ^= num
                else:
                    x2 ^= num
            return [x1, x2]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    写在最后

    如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

    如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

    最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

  • 相关阅读:
    中小团队的技术负责人如何做好技术团队建设
    OceanBase 单机租户最多能支持多少分区?
    viewerjs -v 11 动态获取图片(ajax),以及重复初始化问题。
    docker本机启动多台容器导致出现后续容器启动失败
    PHP物业收费管理小程序系统源码
    幂级数求和难吗?细节很重要
    食品制造业SCM系统供应商管理模块提升企业采购管理效率,数字化升级供应链
    基于单片机的感应自动门系统
    (29)Blender源码分析之顶层菜单的system菜单分析
    ESD 静电标准分类
  • 原文地址:https://blog.csdn.net/weixin_54383080/article/details/133855853