《算法零基础100讲》(第46讲) 位运算 (异或) 入门【学习报告】

目录

传送门

知识点

异或运算符的应用

1、标记位取反

 2、交换变量

课后习题

136.只出现一次的数字

190. 颠倒二进制位

461. 汉明距离

1486. 数组异或操作

477. 汉民距离总和

1720. 解码异或后的数组


传送门

《算法零基础100讲》(第46讲) 位运算 (异或) 入门_英雄哪里出来-CSDN博客异或,简单加密算法https://blog.csdn.net/WhereIsHeroFrom/article/details/121739055

知识点

位异或运算符   ^          a ^ b

 运算规则

0^0=0,1^0=1,0^1=1,1^1=0(同为0,异为1)

例如:

3 ^ 7 = 0000 0011                14 ^ 1 = 0000 1110

        |   0000 0111                          |  0000 0001

        =  0000 0100                         = 0000 1111

        = 4                                         = 15

        常用知识点

  1. 交换律:a ^ b ^ c <=> 情况a ^ c ^ b

  2. 任何数于0异或为任何数 0 ^ n = n

  3. 相同的数异或为0: n ^ n = 0

异或运算符的应用

1、标记位取反

例:给定数 x ,返回 x 的第 4 位(从左到右)取反后的数

int f(int x){
   return x ^= 0b1000;
}

 2、交换变量

例:给定两个数,交换其值

#include <stdio.h>
int main() {
    int a, b;
	while (scanf("%d %d", &a, &b) != EOF) {
	    a = a ^ b;   // a = a ^ b
	    b = a ^ b;   // b = a ^ b = (a^b)^b = a ^ 0 = a
	    a = a ^ b;   // a = a ^ b = (a^b)^a = b ^ 0 = b
	    printf("%d %d\n", a, b);
	}
	return 0;
}

课后习题

                        简单题我重拳出击!!!!!!!!!!!!!!

136.只出现一次的数字

136. 只出现一次的数字https://leetcode-cn.com/problems/single-number/

 题目描述:

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

思路:因为 n ^ n = 0; 0 ^ n = n。所有异或所有的数字,出现两次次的异或都为 0,最后与出现一次的数字异或

int singleNumber(int* nums, int numsSize){
    int ans = 0,i;
    for(i=0; i<numsSize; ++i){
        ans ^= nums[i];         // n^n = 0 且 n^0 = n
    }
    return ans;
}

190. 颠倒二进制位

190. 颠倒二进制位https://leetcode-cn.com/problems/reverse-bits/

 题目描述:

颠倒给定的 32 位无符号整数的二进制位。

思路:倒过来取位,设定位

int GetBit(int x,int i){
    return (x>>i) & 1;
}
void SetBit(int *x,int i,int v){
    *x |= ((long)v<<i); 
}
uint32_t reverseBits(uint32_t n) {
    uint32_t ret = 0;
    int i;
    for(i=0; i<=31; ++i){
        int v = GetBit(n,31-i);       //颠倒过来取位
        SetBit(&ret,i,v);             //设定位
    }
    return ret;
}

461. 汉明距离

461. 汉明距离https://leetcode-cn.com/problems/hamming-distance/

 题目描述:

两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。

给你两个整数 x 和 y,计算并返回它们之间的汉明距离。

思路:先异或,再统计1的个数

int hammingDistance(int x, int y){
    x ^= y;             //异或运算 不同的位则会置1
    int ans = 0;
    while(x){
        ++ans;
        x = x & (x-1);  //每次将最低位 的1消去
    }
    return ans;
}

1486. 数组异或操作

1486. 数组异或操作https://leetcode-cn.com/problems/xor-operation-in-an-array/

 题目描述:

给你两个整数,n 和 start 。

数组 nums 定义为:nums[i] = start + 2*i(下标从 0 开始)且 n == nums.length 。

请返回 nums 中所有元素按位异或(XOR)后得到的结果。

int xorOperation(int n, int start){
    int ans = 0;
    for(int i=0;i<n;++i)
        ans ^= (start + 2*i); //直接按题目要求来就行了
    return ans;
}

477. 汉民距离总和

477. 汉明距离总和https://leetcode-cn.com/problems/total-hamming-distance/

 题目描述:

两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量。

给你一个整数数组 nums,请你计算并返回 nums 中任意两个数之间 汉明距离的总和 。

在力扣找的一个解释

 思路是:
		比如有3个数(用二进制表示) (方向从右到左<-,分别为第1位、第2位...)
			第一个数 a: 1 0 0 1
			第二个数 b: 0 1 1 1
			第三个数 c: 0 0 1 1
		那么第一位上的汉明距离总和是0。
			为什么? 因为a、b、c该位全是"1",任意两个"1"的汉明距离是0,所以该位汉明距离总和是0。
		接下来看第二位,a的第二位是"0",b、c的是"1",此时该位的汉明距离就是2。
			为什么? 由上面我们可以得到,该位的"0"有1个,"1"有2个,而任意一个"0"都可以和任意一个"1"组合,
					 一对组合可以产生的汉明距离为1,所以问题转换为了算多少对01组合,那么怎么计算呢?
					 答案就是该位"0"的个数乘以"1"的个数。
		接下来看第三位,可以看出,此时"0"有2个,"1"有1个,所以可以产生的汉明距离为2。
		接下来看第四位,可以看出,此时"0"有2个,"1"有1个,所以可以产生的汉明距离为2。
		于是: 总的汉明距离就是 0 + 2 + 2 + 2 = 6
*/
int GitBit(int x,int i){
    return (x >> i) & 1;    //取位
}
int bits[32][2];
int totalHammingDistance(int* nums, int numsSize){
    int ret = 0,i,j;
    for(i=0; i<=31; ++i)
        bits[i][0] = bits[i][1] = 0;    //初始化
    for(i=0; i<numsSize; ++i){
        for(j=0; j<=31; ++j){
            int temp = GitBit(nums[i],j);   
            ++bits[j][temp];            //统计每个位上的 0 和 1 的个数
        }
    }
    int ans = 0;
    for(i=0; i<=31; ++i){
        ans += (bits[i][0] * bits[i][1]);   
    }
    return ans;
}

1720. 解码异或后的数组

1720. 解码异或后的数组https://leetcode-cn.com/problems/decode-xored-array/

 题目描述:

未知 整数数组 arr 由 n 个非负整数组成。

经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encoded[i] = arr[i] XOR arr[i + 1] 。例如,arr = [1,0,2,1] 经编码后得到 encoded = [1,2,3] 。

给你编码后的数组 encoded 和原数组 arr 的第一个元素 first(arr[0])。

请解码返回原数组 arr 。可以证明答案存在并且是唯一的。

思路:

看着这题感觉这定义好熟悉,总感觉和Gray码和二进制码转换一个意思

a^b = c , a^b^b = a, 即 c^b=a 同理 c^a =b

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* decode(int* encoded, int encodedSize, int first, int* returnSize){
    int *ans = (int*)malloc(sizeof(int)*(encodedSize+1));
    *returnSize = encodedSize+1;
    ans[0] = first;         //第一个元素first
    for(int i=1;i<encodedSize+1;++i){
        ans[i] = ans[i-1] ^ encoded[i-1];
    }
    return ans;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周日加一

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值