异或位运算

异或

异或是一种基于二进制的位运算,XOR或者^表示,它的运算法则是对运算符两侧数的每一个二进制位,同值取0,异值取1。可以理解为不进位的加法。1+1=0, 0+0=0, 1+0=1

异或的性质

  1. 交换律:a XOR b = b XOR a;
  2. 结合律:a XOR b XOR c = a XOR ( b XOR c )
  3. 对于任何数x:都有x^x = 0, x ^ 0 = x;
  4. 自反性:a ^ b ^ b = a ^ 0 = a

异或的应用

  1. 交换两个元素的值
int a = 1, b = 2;
a = a ^ b;
b = b ^ a;
a = a ^ b;
  1. 找出多余的一个数字
    数字1-n放入容量为n+1的数组arr中,只有唯一一个数重复,找出该重复的数
    step1:对1-n进行异或得T1,对arr中所有元素进行异或得T2
    step2: 重复的数为T1^T2

子数组亦或查询

题目出处:https://leetcode-cn.com/problems/xor-queries-of-a-subarray/
在这里插入图片描述
在这里插入图片描述
方法一:暴力(超时)

class Solution {
public:
    vector<int> xorQueries(vector<int>& arr, vector<vector<int>>& queries) {
        int n = queries.size();
        int index = 0;
        vector<int> ans(n);
        for(auto & query : queries){
            int l = query[0];
            int r = query[1];
            int res = arr[l];
            for(int i = l+1; i <= r; ++i){
                res ^= arr[i];
            }
            ans[index++] = res;
        }

        return ans;
    }
};

方法二:前缀和

class Solution {
public:
    vector<int> xorQueries(vector<int>& arr, vector<vector<int>>& queries) {
        int n = arr.size();
        vector<int> nSum(n+1, 0);
        for(int i = 1; i <= n; ++i){  //求前缀亦或值
            nSum[i] = nSum[i-1]^arr[i-1];
        }
    
        int index = 0;
        vector<int> ans(queries.size());
        for(auto & query : queries){
           int l = query[0];
           int r = query[1];
           ans[index++] = nSum[l]^nSum[r+1];   //l+1到r+1的异或值
        }

        return ans;
    }
};

解码异或后的排列

题目出处:https://leetcode-cn.com/problems/decode-xored-permutation/
在这里插入图片描述
思路:若得到原数组的第一个元素,就可解码数组。数组的第一个元素可以由前n个正整数的异或除了数组第一个元素外的所有元素的异或得到。

class Solution {
public:
    vector<int> decode(vector<int>& encoded) {
        int n = encoded.size() + 1;
        int total = 0;
        for (int i = 1; i <= n; i++) {
            total ^= i;
        }
        int odd = 0;
        for (int i = 1; i < n - 1; i += 2) {
            odd ^= encoded[i];
        }
        vector<int> perm(n);
        perm[0] = total ^ odd;
        for (int i = 0; i < n - 1; i++) {
            perm[i + 1] = perm[i] ^ encoded[i];
        }
        return perm;
    }
};
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值