【LeetCode】只出现一次的数字 I II III 总结

本文详细解析了三种寻找数组中唯一出现一次的数字的算法,包括只出现一次、出现两次和出现三次的情况。通过异或操作和位运算,实现了线性时间和常数空间的高效解决方案。

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

136.只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

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

解答:每个整数与它本身异或(^)的结果为0,所以所有数异或的结果则为与众不同的那个数。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int res=0;
        for(int i=0;i<nums.size();i++)
            res ^= nums[i];
        return res;
    }
};

 

137. 只出现一次的数字 II

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。

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

解答:还是按位处理,除了多余的那个数字其余所有数字转换成二进制数之后的各位分别的和应该可以被3整除(因为每个数字有三个),这里定义一个32位的数组(int最多32位)表示每位的和,每次循环分别与1,2,4,8等进行与操作,判断每一位是否为1,若是bit[i]++,最后对这个bit数组的每一位mod3取余,再换算成十进制输出。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int n =  nums.size();
        int bit[32]={0};
        int step = 1;
        for(int i=0;i<n;i++){
            step = 1;
            for(int j=0;j<32;j++){
                if(nums[i]&step)
                    bit[j]++;
                step = step << 1;
            }
        }
        int res = 0;
        step = 1;
        for(int i=0;i<32;i++){
            res += bit[i]%3 * step;
            step = step << 1;
        }
        return res;
    }
};

 

260. 只出现一次的数字 III

给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。

注意:

  1. 结果输出的顺序并不重要,对于上面的例子, [5, 3] 也是正确答案。
  2. 你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?

解答:同样利用异或,所有数字异或相当于两个不重复的数字异或,结果必不为0,此时,取这个结果中的任意为1的一位,利用这个将原数组分为两类,其中一类是这一位是1的,其中一位是这一位为0的,易知,第一类所有数字的异或为第一个所求数字,第二类所有数字异或为第二个所求数字。

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        vector<int> res;
        if(nums.size()<2)
            return res;
        int n = nums.size();
        int resOR = 0;
        for(int i=0;i<n;i++)
            resOR ^= nums[i];
        int index = FirstBitOf1(resOR);
        int res1 = 0;
        int res2 = 0;
        for(int i=0;i<n;i++){
            if(judge(nums[i],index)){
                res1 ^= nums[i];
            }else{
                res2 ^= nums[i];
            }
        }
        res.push_back(res1);
        res.push_back(res2);
        return res;
    }
    int FirstBitOf1(int num){    //这个函数用来找从右往左数第一个1的位置
        int index = 0;
        while((num & 1) == 0){
            num = num >> 1;
            index++;
        }
        return index;
    }
    bool judge(int num,int index){    //这个函数用来判断num与2的index-1次方做与运算的结果,用来分类
        num = num >> index;
        return (num&1);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值