• Leetcode刷题详解—— 找出所有子集的异或总和再求和


    1. 题目链接:1863. 找出所有子集的异或总和再求和

    2. 题目描述:

    一个数组的 异或总和 定义为数组中所有元素按位 XOR 的结果;如果数组为 ,则异或总和为 0

    • 例如,数组 [2,5,6]异或总和2 XOR 5 XOR 6 = 1

    给你一个数组 nums ,请你求出 nums 中每个 子集异或总和 ,计算并返回这些值相加之

    **注意:**在本题中,元素 相同 的不同子集应 多次 计数。

    数组 a 是数组 b 的一个 子集 的前提条件是:从 b 删除几个(也可能不删除)元素能够得到 a

    示例 1:

    输入:nums = [1,3]
    输出:6
    解释:[1,3] 共有 4 个子集:
    - 空子集的异或总和是 0 。
    - [1] 的异或总和为 1 。
    - [3] 的异或总和为 3 。
    - [1,3] 的异或总和为 1 XOR 3 = 2 。
    0 + 1 + 3 + 2 = 6
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    示例 2:

    输入: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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    示例 3:

    输入:nums = [3,4,5,6,7,8]
    输出:480
    解释:每个子集的全部异或总和值之和为 480 。
    
    • 1
    • 2
    • 3

    提示:

    • 1 <= nums.length <= 12
    • 1 <= nums[i] <= 20

    3. 解法(递归)

    算法思路:

    所有子集可以解释为:每个元素选择在或不在一个集合中(因此,子集有2^n个)。

    1. 定义两个变量pathsum,分别表示当前子集的异或和以及所有子集的异或和之和。
    2. subsetXORSum函数中,调用dfs函数进行深度优先搜索。传入参数为输入数组nums和起始位置0
    3. dfs函数是一个递归函数,用于遍历数组的所有子集并计算它们的异或和。
    4. dfs函数中,首先将当前子集的异或和path加入总和sum中。
    5. 然后,使用一个循环从当前位置pos开始遍历数组中的每个元素。
    6. 在循环中,对当前元素进行异或操作,更新当前子集的异或和path
    7. 接着,递归调用dfs函数,传入下一个位置i + 1作为起始位置。
    8. 递归返回后,执行回溯操作,恢复当前子集的异或和path
    9. 最后,当所有子集都被遍历完毕后,返回所有子集的异或和之和sum

    通过这种深度优先搜索的方式,可以遍历数组的所有子集,并计算它们的异或和之和。

    请添加图片描述

    C++算法代码:

    class Solution {
        int path; // 当前子集的异或和
        int sum; // 所有子集的异或和之和
    public:
        int subsetXORSum(vector& nums) {
            dfs(nums, 0); // 从第一个元素开始进行深度优先搜索
            return sum; // 返回所有子集的异或和之和
        }
        void dfs(vector& nums, int pos) {
            sum += path; // 将当前子集的异或和加入总和中
            for (int i = pos; i < nums.size(); i++) {
                path ^= nums[i]; // 对当前元素进行异或操作,更新当前子集的异或和
                dfs(nums, i + 1); // 继续递归搜索下一个元素
                path ^= nums[i]; // 回溯,恢复当前子集的异或和
            }
        }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    【目标检测】YOLOv5:640与1280分辨率效果对比
    固态硬盘有缓存和没缓存之间的区别在哪
    【无标题】
    [数据集][目标检测]纸箱子检测数据集VOC+YOLO格式8375张1类别
    黑马瑞吉外卖之删除分类
    C++ - STL 使用红黑树封装map set
    SpringBoot快速入门(黑马学习笔记)
    Windows 11再次迎来更新,支持1000多款Android应用程序
    队列的实现方式—Python数据结构(三)
    我的学校网页期末作业(纯html+css实现)
  • 原文地址:https://blog.csdn.net/weixin_51799303/article/details/134215140