《算法零基础100讲》(第47讲) 位运算 (异或) 进阶
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法零基础100讲》(第47讲) 位运算 (异或) 进阶相关的知识,希望对你有一定的参考价值。
零、写在前面
这是《算法零基础100讲》 专栏打卡学习的第四十六天了。
每天打卡的题,做不出来没关系,因为困难的题涉及知识点较多,后面还是会开放出来的,就像昨天的 最大公约数 那道题今天还是会有,所以不要着急,内容能看懂,能自己分析,能做出简单题,就可以打卡。
在刷题的过程中,总结自己遇到的坑点,写出 「 解题报告 」 供他人学习,也是一种自我学习的方式。这就是经典的帮助他人的同时,成就自己。目前, 「 万人千题 」 社区 每天都会有五六篇高质量的 「 解题报告 」 被我 「 加精 」。如果觉得自己有能力的,也可以来发布你的 「 解题报告 」。千万级流量,你我共同拥有。
一、概念定义
有关异或运算的概念,我们已经在 《算法零基础100讲》(第46讲) 位运算 (异或) 入门 学得差不多了,这一章节重要来看下,异或有哪些应用点。
二、题目描述
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。请利用线性复杂度来完成问题。
三、算法详解
首先,只有两个数出现一次,其他数都出现两次,所以所有数异或的结果一定为非零值,并且一定是这两个数的异或结果,即 sum = a XOR b
。
那么在sum
的二进制位中找到一个为 1
的位,假设第
i
i
i 位为1
,则用
2
i
2^i
2i 作为掩码;
将所有数和
2
i
2^i
2i进行位与,得到结果不为零的归为一组,异或以后的到a
,再用a
求得b = sum XOR a
。
四、源码剖析
int* singleNumber(int* nums, int numsSize, int* returnSize)
int i, j;
int sum = 0;
int *ret = (int *)malloc( sizeof(int) * 2 ); // (1)
*returnSize = 2;
for(i = 0; i < numsSize; ++i ) // (2)
sum ^= nums[i];
ret[0] = ret[1] = 0;
for(i = 0; i < 32; ++i)
if( sum & ((unsigned int)1<<i) ) // (3)
for(j = 0; j < numsSize; ++j)
if(nums[j] & ((unsigned int)1<<i)) // (4)
ret[0] ^= nums[j];
else
ret[1] ^= nums[j]; // (5)
break;
return ret;
- ( 1 ) (1) (1) 申请两个数的空间;
-
(
2
)
(2)
(2) 将所有数异或后得到
sum
。 -
(
3
)
(3)
(3) 如果
sum
第 i i i 位为1
,则取 2 i 2^i 2i 作为掩码; - ( 4 ) (4) (4) 和掩码 位与 结果非零的,异或完的结果就是其中一个数;
- ( 5 ) (5) (5) 否则,异或完结果就是另一个数;
五、推荐专栏
六、习题练习
序号 | 题目链接 | 难度 |
---|---|---|
1 | 只出现一次的数字 III | ★★☆☆☆ |
2 | 翻转矩阵后的得分 | ★★★☆☆ |
3 | 形成两个异或相等数组的三元组数目 | ★★★☆☆ |
以上是关于《算法零基础100讲》(第47讲) 位运算 (异或) 进阶的主要内容,如果未能解决你的问题,请参考以下文章