416. 分割等和子集

2023-11-09

题目描述:

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

示例 1:

输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。
示例 2:

输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。
 

提示:

1 <= nums.length <= 200
1 <= nums[i] <= 100

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/partition-equal-subset-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析:

        我能想到前一半的思路。即,先计算整个数组的和sum,如果sum为奇数,那么必不可能分为两个相等的子集(例如,数组和为11,则两个子集和为5.5,而数组中全是整数,因此不可能)。如果数组中最大元素>sum/2,则也不可能分为两个相等子集。如果以上情况都不存在,那么,该问题就转化为了,一个数组中是否存在和为sun/2的子集。

        我想到的办法是回溯,但回溯的时间复杂度太大了,就没有去真的写。去看了看题解,背包问题的转化版,即面对一个数字,有选择或者不选择该数字两种方法,他们能够组成的所有情况,通过数组dp进行递推。

        bool数组dp[i][j]代表,从0~i个元素中选取若干个,他们的和能否为j。

        初始情况下,dp全为false。然后考虑nums[0],只有一个元素nums[0]的情况下,dp[0][0]代表,从第0个元素中,选取若干个,和能否为0,当然可以,不选nums[0],那么和就为0;因此dp[0][0]=true。还有一种情况,那就是选取nums[0],在这种情况下,dp[0][nums[0]]为true,即选取第0个元素,和为nums[0]。

        递推公式显而易见了:

        dp[i][j]=dp[i-1][j] || dp[i-1][j-nums[i]]

        即如果前i-1个元素的和已经为j,那么前i个元素的和,也必定能够为j。如果之前i-1个元素的和为j-nums[i],那么选取当前元素,加上nums[i],也刚好能够构成和为j。除此之外,其他情况为false。       

详细分析请见官方题解:

https://leetcode-cn.com/problems/partition-equal-subset-sum/solution/fen-ge-deng-he-zi-ji-by-leetcode-solution/

代码如下:

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        // 计算nums长度
        int len=nums.size();
        if(len<1) return false;
        int sum=0;
        for(int i=0;i<len;i++)
        sum+=nums[i];
        // 和为奇数,返回false
        if(sum%2==1) return false;
        sort(nums.begin(),nums.end());
        // 最大元素>sum/2,返回false
        if(nums[len-1]>sum/2) return false;
        // dp[i][j]代表0~i个元素的和是否为j
        // 205和sum+5是为了防止数组越界

        // 两种方式声明二维数组并赋初始值
        bool dp[205][sum+5];
        memset(dp,false,sizeof(dp));

        // vector<vector<bool>> dp(205,vector<bool>(sum+5,false));

        // 初始化面对第0个元素时的情况
        dp[0][0]=true;
        dp[0][nums[0]]=true;
        // 通过递推方程求解之后的dp
        for(int i=1;i<len;i++)
        {
            for(int j=0;j<=sum/2;j++)
            {
                // 之前的和已经为j,那么不选取该元素
                if(i-1>=0&&dp[i-1][j])
                dp[i][j]=true;
                // 之前的和为j-nums[i],那么选取该元素
                else if(i-1>=0&&j-nums[i]>=0&&dp[i-1][j-nums[i]])
                dp[i][j]=true;
                // 其他情况均为false
                else dp[i][j]=false;
            }
        }
        return dp[len-1][sum/2];

    }
};

tips:

1.声明数组时尽量初始化

        本来使用bool dp[205][sum+5]这种方式声明二维数组,但是这种声明没有办法在声明数组的时候给数组内所有元素赋初始值,必须通过for循环赋值。

        我并没有给每个元素都赋了初始值,在运行时报错了:

runtime error: load of value 128, which is not a valid val

 去网上查说是没有初始化的问题,于是只好放弃这种做法,改为使用vector来声明二维bool数组。

2.声明数组并初始化的方法

        1.使用memset

   bool flag[200][50];

   memset(flag,false,sizeof(flag))

        2.使用vector

 vector<vector<bool>> flag(200,vector<bool> (50,false));

3.vector声明数组并赋初始值的几种方式

        1.vector<int> a;

        声明一维数组a,长度为0,没有初始值

        2.vector<int> a(5)

        声明一维数组a,长度为5,没有初始值

        3.vector<int> a(5,10)

        声明一维数组a,长度为5,初始值均为10

        4.vector<vector<int>> a(20,vector<int>(10,100))

        声明二维数组a,行为20,列为10,初始值均为100

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

416. 分割等和子集 的相关文章

随机推荐

  • 【漏洞复现】JDWP远程命令执行漏洞

    0x01 简介 JPDA Java Platform Debugger Architecture 即Java平台调试体系架构 Java虚拟机设计的专门的API接口供调试和监控虚拟机使用 JPDA按照抽象层次 又分为三层 分别是 JVM TI
  • IP地址和子网掩码

    本科的时候其实修过计算机网络 但是现在基本上都还给老师了 在这里重新学习一下IP地址的相关内容 1 IP地址的分类 A类 000 127 默认子网掩码 255 0 0 0 B类 128 191 默认子网掩码 255 255 0 0 C类 1
  • 在修复小型森林道路的过程中使用无人机估算土方工程量的可能性

    小规模道路施工作业 主要是土方作业 通常发生在斜坡上 需要有更多的空间进行临时土壤储存 有必要在有限的区域内反复挖掘 临时放置和填充土壤 因此 很难预测和量化进行的土方工程量 因为仅仅通过比较施工前的土壤形状和已完成地面的形状很难确定所有进
  • Ubuntu 20.04从0到跑通yolov5 v6.0

    Ubuntu 20 04 安装与卸载 一 卸载ubuntu 参考 双系统下完全卸载ubuntu 哔哩哔哩 bilibili 二 安装ubuntu 电脑配置 r7000p 3050ti 步骤 制作启动盘 win 下 磁盘管理 压缩卷 压缩多少
  • 公有云和ChatGPT关系不大

    前段时间要过年 休养身体 写长篇 所以公众号停更了两个月 本文解释了AI云为什么不会成为云厂商的重要营收途径 延伸分析了一些云产品的本质 1 流量密码不是财富密码 这两个月才突然热议ChatGPT的朋友 其实技术嗅觉有点迟钝 见识有点落伍
  • IDEA创建java项目src下没有办法创建包文件/MAVEN模块名变灰且模块多道横杠

    1 IDEA中的java项目src下无法创建包文件 原因 这是因为该项目的src文件夹不是源文件夹 解决方法 需右键该文件夹 选择标记 源根 2 MAVEN模块名变灰且模块多道横杠 原因 api项目的pom xml文件被设置在maven忽略
  • 日志框架:slf4j、log4j和logback的基本使用

    slf4j是日志框架的标准 即通用接口 实现了日志框架一些通用的api 而log4j和logback是众多日志框架中的几种 log4j和logback可以单独的使用 也可以绑定slf4j一起使用 1 单独使用时分别调用框架自己的方法来输出日
  • Multi-level Attention Networks for Visual Question Answering阅读笔记

    Multi level Attention Networks 这个模型可以同时提取高级语义信息和空间信息 模型框架如下所示 该模型分为三个部分 分别是Semantic Attention Context aware Visual Atten
  • 云计算的快速发展,未来主要的发展趋势是什么?

    1 云计算的分工将会变得更加细化 随着云计算产业生态链不断完善 行业分工逐渐细化 在未来年 云计算的分工更加细化 行业云将成为云计算领域的发展热点 2 Iaas将迎来更大的降价风潮 万物互联对云计算带来更大的需求 在行业竞争和规模效应的驱动
  • 张飞硬件第四部(二)

    文章目录 第一章 项目背景 第二章 项目条件 第三章 项目实现 第一节 涉及知识点 1 1 三级管的放大作用 1 1 1 原理 1 1 2 正反馈与负反馈 1 1 3 共模干扰与差模干扰 1 1 4 差模放大 1 1 5 运算放大器 第一章
  • ESP8266EX使用SDK开发串口调试乱码

    目录 问题如图所示 问题分析 问题解决 问题如图所示 问题分析 有输出信号 说明有数据产生 可能原因 波特率不匹配 时钟频率不对 问题解决 不断调整串口调试助手的波特率9600 115200 不管用 把ESP8266的默认波特率改为9600
  • Maven使用指南(超详细)

    Maven高级 目标 理解并实现分模块开发 能够使用聚合工程快速构建项目 能够使用继承简化项目配置 能够根据需求配置生成 开发 测试环境 并在各个环境间切换运行 了解Maven的私服 1 分模块开发 1 1 分模块开发设计 1 按照功能拆分
  • 关于微信公众号获取token值和模板推送接口对接问题

    今天做了一个关于微信的接口 由于以前没有接触过关于微信的问题 现在碰到了查了很多资料 下面总结一下 1 获取token值 微信获取公众号token值需要公众号的appid和secret 这两个值是微信提供的 是不会变的 获取token值地址
  • 动力节点Java17最新零基础视频-第三章 Java基础语法

    标识符 掌握 什么是标识符 在Java中 标识符是用来给变量 方法 类和包等命名的字符序列 标识符由字母 数字 下划线和美元符号组成 但是第一个字符必须是字母 下划线或美元符号 标识符不能包含空格或其他特殊字符 也不能与Java关键字相同
  • gojs 节点(node)/线(link)的动态添加及样式(nodeTemplate / linkTemplateMap)

    1 创建节点及节点样式 节点样式可以是多种的 你阔以 可以 给不同的节点设置不同的样式 或者是直接设置一个通用的样式 比如 var CreateNode key getNextKey 设置key的方法 每个节点最好是有自己独立的key ca
  • 使用vector迭代器实现二分查找

    vector二分查找 include stdafx h include
  • macOS 视频格式转换:ffmpeg + shell 脚本【最优方案】【免费 + 高效】

    效果完美 开始转换 成功输出 ffmpeg 下载 github 开源下载 下载地址 https ffmpeg org download html shell 脚本 你的用户名 替换成你得自己的对应路劲 比如你下载的 ffmpeg 躲在路劲
  • windows的磁盘操作之七——获取当前所有的物理磁盘号

    有了前几节的基础后 本节给出一个更复杂但却非常实用的例子 很多情况下 我们想知道当前系统下安装了多少块磁盘 他们的物理驱动器号都是多少 每一块磁盘上有多少个分区 分区号怎么分布 每个分区大小是多少 这就类似于我们打开windows 的磁盘管
  • c++的工程文件的编译顺序

    以前一直以为 vs在编译c 文件时候是从头文件开始编译的 而每个头文件对应的源文件只是头文件定义中的一些实现而已 源文件不参与编译 今天经过同学指点并实践之后才发现 其实不是这样的 从中受益颇多 c 编译的时候实际上只编译源文件 而不编译头
  • 416. 分割等和子集

    题目描述 给你一个 只包含正整数 的 非空 数组 nums 请你判断是否可以将这个数组分割成两个子集 使得两个子集的元素和相等 示例 1 输入 nums 1 5 11 5 输出 true 解释 数组可以分割成 1 5 5 和 11 示例 2