一、问题描述
一个数组的 异或总和 定义为数组中所有元素按位 XOR
的结果;如果数组为 空 ,则异或总和为 0
。
- 例如,数组
[2,5,6]
的 异或总和 为2 XOR 5 XOR 6 = 1
。
给你一个数组 nums
,请你求出 nums
中每个 子集 的 异或总和 ,计算并返回这些值相加之 和 。
题目链接:所有子集的异或总和
二、题目要求
样例
输入: nums = [5,1,6] 输出: 28 解释: [5,1,6] 共有 8 个子集: - 空子集的异或总和是 0 。 - [5] 的异或总和为 5 。 - [1] 的异或总和为 1 。 - [6] 的异或总和为 6 。 - [5,1] 的异或总和为 5 XOR 1 = 4 。 - [5,6] 的异或总和为 5 XOR 6 = 3 。 - [1,6] 的异或总和为 1 XOR 6 = 7 。 - [5,1,6] 的异或总和为 5 XOR 1 XOR 6 = 2 。 0 + 5 + 1 + 6 + 4 + 3 + 7 + 2 = 28
考察
位运算、子集问题 建议用时20~40min
三、问题分析
本题是位运算的第8题,没了解过位运算相关知识点可以看这一篇文章,讲解比较详细:
想要完成这道题目,需要攻壳两个难点:
1.子集
依靠普通的方法遍历所有的子集肯定是不行的,之前我写个一篇利用位运算实现子集的,也算是为这一题做一个铺垫吧。
2.异或计算
子集求解之后,在循环内部进行异或运算就行了,运算规则如下:
符号:^
运算规则:两个二进制位相反为1,相同为0
示例:1001^0111=1110
四、编码实现
classSolution { public: intsubsetXORSum(vector<int>&nums) { inti,j,n=nums.size(),sum=0,ans;//初始化变量for(i=0;i<(1<<n);i++)//第一层for循环 { ans=0;//初始化for(j=0;j<n;j++)//第二层for循环 { if(i&(1<<j))//符合条件 { ans=ans^nums[j];//异或计算 } } sum+=ans;//叠加 } returnsum; } };