leetcode260. Single Number III

本文介绍如何使用位运算解决数组中寻找唯一出现一次的元素问题,包括三种情况:一个元素出现一次,其余元素出现两次;一个元素出现一次,其余元素出现三次;两个元素各出现一次,其余元素出现两次。提供了详细的算法思路及C++实现。

先说第一种题

题目:

Given an array of integers, every element appears twice except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

我的解法:对数组排序,两个两个跳着比较直到找到不等的,时间复杂度O(NlogN)

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
        sort(nums.begin(),nums.end());
        int size = nums.size();
        if (size == 1)
            return nums[0];
            
        for (int i = 1; i < size; i += 2)
            if (nums[i] != nums[i - 1])
                return nums[i - 1];
                
        
        return nums[size -1];
    }
};

参考其他解法,知道了这类题考察的是位运算

AC解:

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
        int x = 0;
        int size = nums.size();
        for (int i = 0; i < size; i++)
            x ^= nums[i];
        return x;
    }
};
或者直接 return accumulate(nums.begin(),nums.end(),0,bit_xor<int>());

升级版题目:

Given an array of integers, every element appears three times except for one, which appears exactly once. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

用一个数组来存储所有元素每个位上1的个数,模3剩下的就是所有元素此位上的数字

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
        const int length = sizeof(int) * 8;
        int count[length];
        fill(count,count + length,0);
        int size = nums.size();
        
        for (int i = 0 ; i < size; i++)
            for (int j = 0; j < length; j++)
            {
                count[j] += (nums[i] >> j) & 0x1;
                count[j] %= 3;
            }
        
        int result = 0;
        for (int i = 0; i < length; i++)
            result += (count[i] << i);
        
        return result;
    }
};

再次升级版:

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].

AC解: 解法分两步,精妙之处在于diff

1.对所有数字进行异或运算,diff的值为要求的两个数进行异或运算的结果,再diff &= -diff,得到的结果为diff中从右到左第一个位为1的的数,例如0x1010 其负数为0x0110,与运算的结果为0x0010。并且可以知道这两个数的此位必定一个为0一个为1

2.根据此位是否为1将数分为了两部分,分别对两部分进行异或运算,因为相同的两个数异或操作后结果为0,所以两组数的最终结果就是所要求得的数

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
        //数组中所有位进行异或,diff为所求的两个数异或的结果
        int diff = accumulate(nums.begin(),nums.end(),0,bit_xor<int>());
        //取得从右到左第一个为1的位,并且这两个数的此位一定不同
        diff &= -diff;
        
        vector<int> ans(2,0);
        //分离两个数
        for (auto a : nums)
            if (a & diff)//当前元素的此位为1
                ans[0] ^= a;        //不算这两个数,当前位为0或1的数肯定是成对出现的
            else                    //相同的数异或操作后为0
                ans[1] ^= a;
        
        return ans;
    }
};




LeetCode的第260题中,题目被称为“只有一个公共元素的数组 II”。这是一道关于数组操作的数据结构和算法题目。给定两个已经排序的整数数组 nums1 和 nums2,你需要找出它们之间的一个共同的元素,这个元素在每个数组中都只出现一次。 该问题的目标是找到这样的一个公共元素,并返回它的值。例如,如果nums1 = [1, 2, 2, 4] 和 nums2 = [2, 2, 8, 10],那么唯一的公共单次出现的元素是2。 为了解决这个问题,你可以采用一种类似于双指针的方法。从两个数组的起始位置开始遍历,每次比较当前指针对应的元素。如果元素相等且在各自的数组中都是第一次出现(即前一个出现的位置比当前位置大),就将这个元素添加到结果中并继续向后移动指针。如果遇到不同的元素,则移动较小的那个指针的所在数组的指针。 Python 或 C++ 等语言中,可以实现一个循环或者递归的解决方案,直到找到共同的单次出现元素或遍历完其中一个数组。这里是一个简单的 Python 示例: ```python def singleNumber(nums1, nums2): i, j = 0, 0 count = {} while i < len(nums1) and j < len(nums2): if nums1[i] not in count or nums2[j] not in count: count[nums1[i]] = 1 i += 1 elif nums2[j] not in count: count[nums2[j]] = 1 j += 1 else: del count[nums1[i]] del count[nums2[j]] i += 1 j += 1 # 如果有一个数组没遍历完,剩下的最后一个元素就是公共唯一元素 return list(count.keys())[0] if i < len(nums1) else list(count.keys())[-1] ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值