1. 题⽬链接:1863.找出所有⼦集的异或总和再求和
2. 题⽬描述:
3. 解法(递归):
算法思路:
所有⼦集可以解释为:每个元素选择在或不在⼀个集合中(因此,⼦集有个)。本题我们需要求 出所有⼦集,将它们的异或和相加。因为异或操作满⾜交换律,所以我们可以定义⼀个变量,直接记 录当前状态的异或和。使⽤递归保存当前集合的状态(异或和),选择将当前元素添加⾄当前状态与 否,并依次递归数组中下⼀个元素。当递归到空元素时,表⽰所有元素都被考虑到,记录当前状态 (将当前状态的异或和添加⾄答案中)。
例如集合中的元素为[1,2],则它的⼦集状态选择过程如下:
递归函数设计:void dfs(int val, int idx, vector& nums)
参数:val(当前状态的异或和),idx(当前需要处理的元素下标,处理过程:选择将其添加⾄当前状 态或不进⾏操作);
返回值:⽆;
函数作⽤:选择对元素进⾏添加与否处理。
递归流程:
1. 递归结束条件:当前下标与数组⻓度相等,即已经越界,表⽰已经考虑到所有元素;
a. 将当前异或和添加⾄答案中,并返回;
2. 考虑将当前元素添加⾄当前状态,当前状态更新为与当前元素值的异或和,然后递归下⼀个元素;
3. 考虑不选择当前元素,当前状态不变,直接递归下⼀个元素;
C++算法代码:
class Solution
{
public:
int sum=0; //总异或和
int ret=0; //单个异或和
void dfs(vector<int>& nums,int temp)
{
//求和
sum+=ret;
for(int i=temp;i<nums.size();i++)
{
ret^=nums[i];
dfs(nums,i+1);
//恢复现场
ret^=nums[i];
}
}
int subsetXORSum(vector<int>& nums)
{
dfs(nums,0);
return sum;
}
};
Java算法代码:
class Solution
{
int path;
int sum;
public int subsetXORSum(int[] nums)
{
dfs(nums, 0);
return sum;
}
public void dfs(int[] nums, int pos)
{
sum += path;
for (int i = pos; i < nums.length; i++)
{
path ^= nums[i];
dfs(nums, i + 1);
path ^= nums[i]; // 恢复现场
}
}
}