260. Single Number III

本文介绍了一种高效的算法,用于从大量重复数字中找出仅出现一次的两个数字。通过使用异或运算,巧妙地解决了这一问题,并对比了不同实现方法对运行效率的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.

For example:

Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].

 

解题思路:

题目要求给定数组,数组中有且只有两个元素只出现一次,其他元素都重复出现2次,返回只出现一次的元素。

首先遍历数组,使用异或操作得到一个数tmp,由于有两个元素只出现一次,因此异或出来的结果一定不为0。而这两个只出现一次的元素进行异或一定不为0,即至少有1个位一个元素为0,另一个元素为1tmp的二进制中为1的位置即可区分两个元素,从tmp中提取出一个1得到的数作为掩码,遍历数组,与掩码进行与操作,若为0,则与元素1异或,否则与元素2异或,这样即可将两个只出现一次的元素分开,同时,重复出现的元素会被分到同一类中,当进行异或时,对结果无影响。

影响运行效率的地方:

tmp中提取出一个1的方法:

1、首先使用tmp&(tmp-1)得到tmp去掉最低位1的数,再与tmp异或即得到该数(tmp&(tmp-1)^tmptmp^(tmp&(tmp-1)),这两个书写方式不同,运行所花费的时间也不同,前者相比于后者快些)

2tmp&(~(tmp-1))也是取最后一个1的,运行所花费的时间与tmp^(tmp&(tmp-1)相同。

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
    int n=nums.size();
    if(n==2)return nums;
    vector<int>res=vector<int>(2,0);
    int a=0,b=0;
    int tmp=0;
    for(int i=0;i<n;i++){
        tmp^=nums[i];
    }
    // 20ms
    //tmp&=(~(tmp-1));
    // 20ms
    tmp=tmp^(tmp&(tmp-1));
    // 18ms
    // tmp=tmp&(tmp-1)^tmp;
    for(int i=0;i<n;i++){
        if(nums[i]&tmp)res[0]^=nums[i];
        else
            res[1]^=nums[i];
    }
    return res;
    }
};

保存中间变量所使用的变量类型:

1、在开始时就新建vector对象,中间变量保存到vector数组中

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
    int n=nums.size();
    if(n==2)return nums;
    // 18ms
    vector<int>res=vector<int>(2,0);
    int tmp=0;
    for(int i=0;i<n;i++){
        tmp^=nums[i];
    }
    tmp=tmp&(tmp-1)^tmp
    for(int i=0;i<n;i++){
        if(nums[i]&tmp)res[0]^=nums[i];
        else
            res[1]^=nums[i];
    }
    return res;
    }
};

2、先使用int类型保存中间变量,最后使用vector<int>{a,b}的方式保存最后结果,该方法比1要快写。

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
    int n=nums.size();
    if(n==2)return nums;
    // 16ms
    int a=0,b=0;
    int tmp=0;
    for(int i=0;i<n;i++){
        tmp^=nums[i];
    }
    tmp=tmp&(tmp-1)^tmp
    for(int i=0;i<n;i++){
        if(nums[i]&tmp)a^=nums[i];
        else
            b^=nums[i];
    }
    return vector<int>{a,b};
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值