剑指 Offer 56-I/56-II 数组中数字出现的次数C++

------------------------------------------------------二刷2021/2/4------------------------------------------------------

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        int tmp = 0;
        for(int num : nums) {
            tmp ^= num;
        }
        int digital = 1;
        //寻找tmp为1即两个只出现一次数字不同的二进制位
        while((tmp & digital) == 0) {
            digital <<= 1;
        }
        int ans1 = 0 , ans2 = 0;
        for(int num : nums){
            if(num & digital) ans1 ^= num;
            else ans2 ^= num;
        }
        return vector<int>{ans1, ans2};
    }
};

while((tmp & digital) == 0) {记得里面加括号,位运算优先级低于比较运算符


56-I

题目描述

在这里插入图片描述

思路 分组异或

假设题目里面只有一个唯一数字的时候,我们可以设一个0,逐次异或到数组结束

  		int ans= 0;
        for(int num : nums) {
            ans^= num;
        }
        return ans;

得到的结果就是那个唯一的数字。
ps:异或符号为^
原因有两个
1.相同的数字异或等于0
2.异或运算满足交换律
这两点自己试试就知道了
现在题目有两个数字怎么办? 思路很难想到,但是一旦知道就很容易记住
我们还是设一个0,逐次异或到数组结束,设得到的结果为temp很明显是两个唯一数字相异或的结果。
那么对这个结果的数字的每位二进制进行分析,设temp的某个位为 Ai
Ai = 1,两个数字该位不同
Ai = 0,两个数字该位相同
那么只需要找到Ai = 1,将所有的数字分成 Ai = 1组和 Ai = 0组,自然也会把两个唯一数字分卡,并且分的过程中成对的数字不会被拆散,对于这两组数字分别执行只有一个唯一数字的情况下的算法就可以得到解了。
唯一的难点在于怎么对于每个数字获得Ai的值呢
这里用一个dNum变量,初始值为1代表第一位,然后每次右移一位。 num ^ dNum 即是对应二进制位的值。

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        int temp = 0;
        for(int num : nums) {
            temp ^= num;
        }
        int dNum = 1;
        while((temp & dNum) == 0) dNum <<= 1;
        int ans1 = 0, ans2 = 0;//0异或任何数等于该数
        for(int num : nums){
            if(num & dNum)
                ans1 ^= num;
            else ans2 ^= num;
        }
        return vector<int> {ans1,ans2};
    }
};

在这里插入图片描述
时间复杂度O(n)
空间复杂度O(1)

56-II

题目描述

在这里插入图片描述
先试着想了一下异或和同或,发现完全没有思路,于是无脑哈希解一下。

解法 哈希表

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        unordered_map <int,int> hash;
        for(int num : nums) {
            hash[num] ++;
        }
        for(int num : nums) {
            if(hash[num] == 1)
            return num;
        }
        return 0;
    }
};

时间复杂度O(N)
空间复杂度O(N)

解法 位运算

拒绝反复造轮子
在这里插入图片描述
竟然是有限状态机,跳过!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值