1. 题目解析
题目链接:1863. 找出所有子集的异或总和再求和
这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。
2.算法原理
算法思路与实现
为了求解给定整数数组的所有子集并将其异或和相加,我们可以采用递归的方式遍历所有可能的子集。由于每个元素都有两种选择——要么在子集中,要么不在,因此我们可以通过递归函数来模拟这个过程。
递归函数设计
我们定义一个递归函数dfs
,该函数接受两个参数:当前正在处理的元素下标idx
和待处理的整数数组nums
。函数的作用是遍历所有可能的子集选择,并计算这些子集的异或和。
返回值
该函数没有直接的返回值,因为它通过修改全局变量(如一个累加器)来累计异或和。
函数作用
函数的主要作用是:
- 在每个递归层级,决定当前元素
nums[idx]
是否应包含在当前的子集状态中。 - 如果包含,更新当前子集的异或和(与
nums[idx]
进行异或运算)。 - 递归调用自身,处理下一个元素(
idx+1
)。 - 如果不包含,保持当前子集的异或和不变,并递归调用自身处理下一个元素。
递归流程
-
递归结束条件:当
idx
等于数组nums
的长度时,说明已经处理完所有元素,此时将当前子集的异或和累加到总和中,并结束递归。 -
包含当前元素:在当前子集的异或和基础上,与
nums[idx]
进行异或运算,然后递归调用dfs(idx+1, nums)
处理下一个元素。 -
不包含当前元素:直接递归调用
dfs(idx+1, nums)
处理下一个元素,当前子集的异或和保持不变。
算法步骤
- 初始化一个变量来累计所有子集的异或和总和。
- 调用递归函数
dfs(0, nums)
,从数组的第一个元素开始处理。 - 在递归函数中,根据递归结束条件、包含当前元素和不包含当前元素三种情况,分别处理并更新当前子集的异或和,以及递归调用自身。
- 递归结束后,返回累计的异或和总和作为结果。
注意
- 由于异或操作满足交换律和结合律,因此不需要担心子集元素的顺序。
- 为了避免重复计算,我们使用递归而不是迭代,因为递归能够清晰地表示出所有可能的子集选择。
- 在递归过程中,通过更新全局变量或传递引用参数来累计异或和总和。
3.代码编写
class Solution
{
int sum = 0;
int path = 0;
public:
int subsetXORSum(vector<int>& nums)
{
dfs(nums, 0);
return sum;
}
void dfs(vector<int> nums, int pos)
{
sum += path;
for(int i = pos; i < nums.size(); i++)
{
path ^= nums[i];
dfs(nums, i + 1);
path ^= nums[i];
}
}
};
The Last
嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。
觉得有点收获的话,不妨给我点个赞吧!
如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~