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

题目链接

文章摘要:

  • 本文介绍了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];  // 回溯时恢复现场
        }
    }
}

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

相关推荐
甲方大人请饶命16 分钟前
SSM-基础
java·数据库·spring
谷雨不太卷21 分钟前
Linux基础IO
java·开发语言
小新同学^O^27 分钟前
简单学习 --> 文件IO
java·学习·文件io
洛水水33 分钟前
【力扣100题】29. 对称二叉树
算法·leetcode·职场和发展
大熊背41 分钟前
近期遇到的一些问题总结(四)
算法·拍照·白平衡·isp pipeline
吴声子夜歌43 分钟前
Java——Arrays
java·算法·排序算法
fanzhonghong1 小时前
javaWeb开发之Maven高级
java·开发语言·spring boot·spring cloud·私服
洛水水1 小时前
【力扣100题】26. 二叉树的中序遍历
算法·leetcode·深度优先
sheeta19981 小时前
LeetCode 每日一题笔记 日期:2026.05.11 题目:2553. 分割数组中数字的数位
笔记·算法·leetcode
xu_ws1 小时前
spring通过三级缓存解决循环依赖
java·spring·缓存·循环依赖