五月集训(第10天) —— 位运算

Posted 英雄哪里出来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了五月集训(第10天) —— 位运算相关的知识,希望对你有一定的参考价值。

文章目录

前言

        此为《英雄算法联盟:算法集训》的内容,具体内容详见:知识星球:英雄算法联盟。加入星球后,即可享用星主 CSDN付费专栏 免费阅读 的权益。
        欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
        希望大家先自己思考,如果实在没有想法,再看下面的算法思路,如果有思路但是写不出来,可以参考朋友圈中其他人的代码,总有一款是适合你的,关注一下他,取其之长,补给之短。
        今天集训的内容是:位运算
        前三题较为简单,第四题有一些技巧,想出来以后就会很有成就感,建议想一想。

一、练习题目

题目链接难度
191. 位1的个数★☆☆☆☆
461. 汉明距离★☆☆☆☆
136. 只出现一次的数字★☆☆☆☆
137. 只出现一次的数字 II★★★☆☆

二、算法思路

1、位1的个数

        (1)把一个数想象成二进制,先判断最低位是多少(可以用 位与),并且累加到结果上;
        (2)将这个数右移一位,继续 (1) 的判断,直到这个数为 0 为止。
        (3)思考:位与1·相当于 模2;右移一位相当于 除2

int hammingWeight(uint32_t n) 
    int ans = 0;
    while(n) 
        ans += (n & 1);
        n >>= 1;
    
    return ans;

2、汉明距离

        (1)对于两个数来说,如果相同位置的二进制位相同,则对应汉明距离为 0,否则为 1;和异或的性质不谋而合,所以可以将两个数异或以后,求异或结果的 位1的个数

int hammingWeight(uint32_t n) 
	// 复用第一题的代码


int hammingDistance(int x, int y)
    return hammingWeight(x^y);

3、只出现一次的数字

        (1)任意两个数异或的结果为 0,所以只要偶数个数异或,结果都为 0;
        (2)异或满足交换律和结合律,所以把所有数异或以后,得到的数就是我们要求的那个只出现一次的数。

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

4、只出现一次的数字 II

        (1)这题将原本的两个数变成了三个数,于是用异或就行不通了;
        (2)将每个数转换成二进制以后排列起来;
        (3)对于每个位进行分别计算,如果加起来是3的倍数,说明只出现一次的数的对应位是0;否则,是1;

int singleNumber(int* nums, int n)
    int ret = 0;
    for(int i = 0; i < 32; ++i) 
        int ans = 0;
        for(int j = 0; j < n; ++j) 
            ans += (nums[j] >> i) & 1;
        
        ans %= 3;
        if(ans) 
            ret += ((unsigned int)1<<i);
        
    
    return ret;

2022深度学习开发者峰会 5月20日13:00让我们相聚云端,共襄盛会!

以上是关于五月集训(第10天) —— 位运算的主要内容,如果未能解决你的问题,请参考以下文章

七月集训(第10天) —— 位运算

七月集训(第10天) —— 位运算

五月集训(第18天) —— 树

五月集训(第14天) —— 栈

五月集训(第24天) —— 线段树

五月集训(第31天) —— 状态压缩