【递归算法】找出所有子集的异或总和再求和

题目链接

文章摘要:

  • 本文介绍了LeetCode题目《所有子集异或总和之和》的解法。通过分析题目要求,提出三步解题思路:找出所有子集、计算子集异或值、求和异或值。采用决策树模型设计回溯算法,利用全局变量path和sum分别记录子集异或值和总和。详细讲解了dfs函数实现、回溯处理和递归出口等关键步骤,并给出Java代码实现。该方法通过异或运算特性简化回溯操作,高效计算所有子集的异或总和。

一、题目解析

题目定义了对数组的异或总和是怎么运算的。

给我们一个数组,要我们返回该数组的所有子集的异或和再求和。

简单来说,我们做这道题目有三个步骤:

  1. 找出数组的所有的子集
  2. 计算所有子集中的所有数字的异或值
  3. 将所有子集的异或值相加

虽然看起来挺麻烦的,但其实,解题步骤和子集那道题目差不多,我们可以把 2 和 3 的逻辑加入到 1 中。

二、算法原理 + 代码实现

决策树

我们第一步就是画出决策树,这里是找出数组的所有子集,与上一道题目的思路一致,有两种方法,这里采用第二种方法作决策树。

我们根据示例2来画:

决策树:

接下来,我们根据决策树来设计代码。

全局变量

我们这里需要计算的是子集中所有元素的异或值 以及异或值之和。因此定义两个 int 类型即可,path 用来记录子集中所有元素的异或值,ret 用来记录异或值之和。

dfs 函数

函数头

我们这里需要通过递归遍历题目所给数组nums,因此参数是数组 nums 和下标 pos。

函数体

在子集那道题目中,我们的 dfs 函数体中做的事情是 "从当前数字往后遍历",在这里也是一样的,只不过是修改的东西从集合类变成里基本数据类型。当拿到一个数字,就把它与 path 进行异或,然后基于这个再递归。

细节问题

回溯

这里我们也是要在回溯的时候恢复现场的,在函数体当中,递归回来的时候就恢复现场。这里可以利用异或的 "抵消" 性质,再次将 path 与当前数字异或,就可以恢复现场了。

剪枝

这里同样不涉及到剪枝操作。

递归出口

这里不需要设置递归出口。我们更新结果是一进入 dfs 函数就更新的,因为决策树的每一个节点都是结果。当函数体中的遍历结束,整个递归也就结束了。

代码实现

Java 复制代码
public class Solution {
    int sum;  // 记录异或值之和
    int path; // 记录子集中所有元素的异或值

    public int subsetXORSum(int[] nums) {
        dfs(nums, 0);
        return sum;
    }

    private 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];  // 回溯时恢复现场
        }
    }
}

文章到这里就告一段落啦,若有错误请尽管指出!

相关推荐
闲研随记2 分钟前
【文献阅读 ICLR 2026】RL算法:Co-Rewarding
算法
xcLeigh4 分钟前
Go入门:短变量声明的陷阱与最佳实践
java·redis·golang·教程·变量
青山木11 分钟前
Hot 100 --- 最小栈
java·数据结构·算法·leetcode
疯狂打码的少年14 分钟前
【数据结构】栈的应用:表达式求值(后缀表达式)
java·数据结构·笔记·算法
szephyr19 分钟前
腾讯云 ADP 智能体的 Skills 版本回滚总是回到旧配置,是缓存没清还是版本管理没开?
java·缓存·腾讯云
云烟成雨TD23 分钟前
Micrometer 系列【39】链路追踪:入门案例 | 环境准备
java·云原生·链路追踪
HiDev_25 分钟前
【非标自动化】plc执行顺序问题、扫描周期问题
深度学习·算法·机器学习
chuan.bai25 分钟前
Java RAG 实战(第 3 篇):从交互式聊天到多轮上下文
java·人工智能·macos·ai
9523639 分钟前
Sentinel
java·后端·spring·sentinel·springcloud
阿pin44 分钟前
Java随笔-JDK7 HashMap头插法为何能导致死循环?
java·开发语言·hashmap