力扣hot100:416.分割等和子集(组合/动态规划/STL问题)

893a7603c38744d3a8d19eb2d79e5588.png

组合数问题

我们思考一下,如果要把数组分割成两个子集,并且两个子集的元素和相等,是否等价于在数组中寻找若干个数使之和等于所有数的一半?是的!

因此我们可以想到,两种方式:

①回溯的方式找到target,但是回溯是阶乘级别的算法,这里会超时。

②从前往后遍历,形象说明:定义n个集合dp[i],dp[i]表示前i个数的可能组合值,则有dp[i]={dp[i-1],dp[i-1]+i},dp[i-1]+i指的是i加上dp[i-1]中的所有元素得到的集合。同时由于长度最长200,数值最大为100,因此数的范围最大为1<=i<=20000,因此最多只有20000个不同的数。因此dp最大为2W个数!所以我们可以用集合实现,并且时间复杂度满足要求O(nums.length*nums.length*max(nums[i]))!

class Solution {
public:bool canPartition(vector<int>& nums) {int sum=0;for(auto &i:nums) sum+=i;if(sum&1||nums.size()==1) return false;//只有偶数总和可以sum>>=1;unordered_set<int> Set;vector<int> temp;for(auto &i:nums){if(i==sum) return true;for(auto it=Set.cbegin();it!=Set.cend();++it){int cur=*it+i;if(cur==sum) return true;if(cur<sum) temp.emplace_back(cur);//>sum的没意义}for(auto & j:temp) Set.insert(j);temp.clear();Set.insert(i);}return false;}
};

遇到的问题:

        在循环遍历的过程中往容器中插入元素会导致容器迭代器end()和size(),时刻发生变化。与此同时,有的容器比如vector和string,往后面增加元素超过容量capacity可能会导致拷贝,从而整个迭代器失效。因此!在使用循环并且需要添加元素时,想使用迭代器需要额外注意!

比如本题是先将所需增加的放入到一个vector中的。

我们不能企图使用临时“指针”迭代器i=end(),然后遍历到it!=i,这是错误的!因为i一直指向的仍然是end(),而不是end()当时指向的位置,换句话说end()不是一个具体的位置,而是一个抽象的位置。

int tmp=Set.size();
for(auto it=Set.cbegin();tmp!=0;++it,--tmp){ int cur=*it+i;if(cur==sum) return true;temp.emplace_back(cur);Set.insert(cur);
}

这样做仍然是错误的,实际上我们在往非顺序容器中插入元素时,容器的数据结构会发生变化,因此导致++it可能并非按照原来的想法遍历,所以是错误的!

唯一正确且安全的方式是,如果需要在遍历的时候同时添加元素,最好不要使用迭代器!迭代器可以很好的遍历元素或者按迭代器范围赋值。但是边添加边遍历问题非常大。

因此对于无序容器只能使用迭代器的情况下,使用临时容器存储是非常必要的;对于顺序容器可以使用下标的情况下,使用下标更好。

动态规划

        这道题实际上和0-1背包问题很像,即从n个物品中拿出一部分使得其值刚好等于target。意识到这一点我们可以定义动态转移方程:

dp[i][k]=max(dp[i-1][k-nums[i]],dp[i-1][k]);

dp[0][nums[0]]=1;

//dp[i][k]表示拿前i个物品是否可以达到重量k。

        这实际上和方法一组合数问题是异曲同工的,方法一使用集合实现,那么如果方法一使用的是数组实现呢?那么数组中标记为1的实际上就是方法二的状态了!

class Solution {
public:bool canPartition(vector<int>& nums) {int sum=0;for(auto &i:nums) sum+=i;if(sum&1||nums.size()==1) return false;sum>>=1;vector<vector<int>> dp(nums.size(),vector<int>(sum+1,0));//超过sum实际上就不用看了if(nums[0]<=sum)dp[0][nums[0]]=1;for(int i=1;i<nums.size();++i){for(int j=1;j<=sum;++j){dp[i][j]=dp[i-1][j];if(j-nums[i]>=0)dp[i][j]=max(dp[i-1][j-nums[i]],dp[i-1][j]);}if(nums[i]<=sum)dp[i][nums[i]]=1;}return dp[nums.size()-1][sum];}
};

由于只用到前面的值,很显然我们可以降维优化。

class Solution {
public:bool canPartition(vector<int>& nums) {int sum=0;for(auto &i:nums) sum+=i;if(sum&1||nums.size()==1) return false;sum>>=1;vector<int> dp(sum+1,0);//超过sum实际上就不用看了if(nums[0]<=sum)dp[nums[0]]=1;for(int i=1;i<nums.size();++i){for(int j=sum;j>=nums[i];--j){dp[j]=max(dp[j],dp[j-nums[i]]);}}return dp[sum];}
};

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2868422.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

DC-DC电源管理芯片MC34063A介绍

MC34063A 为一单片 DC-DC 变换集成电路&#xff0c;内含温度补偿的参考电压源&#xff08;1.25V&#xff09;、比较器、能有效限制电流及控制工作周期的振荡器&#xff0c;驱动器及大电流输出开关管等。外配少量元件&#xff0c;就能组成升压、降压及电压反转型 DC-DC 变换器。…

计算机系统基础 2 Intel 中央处理器

Intel微处理器的发展史 INTegrated ELectronics&#xff08;集成电子&#xff09;的缩写 先后推出的中央处理器&#xff1a; Intel4004、Intel8008、Intel8080/8085、8086/8088、80186、80286、i386、i486 Pentium&#xff08;奔腾&#xff09;、Pentium II、Pentium III、Pen…

Android Studio实现内容丰富的安卓宠物用品商店管理系统

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动。 项目编号128 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.系统公告 3.宠物社区&#xff08;可发布宠物帖子&#…

php中 0 == ‘’(0等于任意字符串) 判断是否成立 返回true

php中不同类型变量之间比较大小 一、背景二、探究0是为什么&#xff1f;三、探究 0all是为什么&#xff1f;四、程序中如何判断0是否等于指定字符串 一、背景 最近在项目实际开发中&#xff0c;我需要判断前端传来的参数值是否等于一个字符串&#xff1b;然后发现当参数值是0时…

论文阅读——ViTAE

ViTAE: Vision Transformer Advanced by Exploring Intrinsic Inductive Bias ViTAE旨在将细胞神经网络中固有的IB引入视觉转换器。如图2所示&#xff0c;ViTAE由两种类型的细胞组成&#xff0c;即RC和NC。RC负责将多尺度上下文和局部信息嵌入到令牌中&#xff0c;NC用于进一步…

XXE漏洞原理和pikachu靶场实验

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、XXE漏洞原理 XXE全称&#xff1a;XML External Enti…

JUnit 面试题及答案整理,最新面试题

JUnit中的断言&#xff08;Assert&#xff09;有哪些类型&#xff1f; JUnit提供了多种断言类型来帮助测试代码的正确性。常见的断言类型包括&#xff1a; 1、assertEquals&#xff1a; 用于检查两个值是否相等。如果不相等&#xff0c;测试失败。 2、assertTrue和assertFal…

HarmonyOS NEXT应用开发—折叠屏音乐播放器方案

介绍 本示例介绍使用ArkUI中的容器组件FolderStack在折叠屏设备中实现音乐播放器场景。 效果图预览 使用说明 播放器预加载了歌曲&#xff0c;支持播放、暂停、重新播放&#xff0c;在折叠屏上&#xff0c;支持横屏悬停态下的组件自适应动态变更。 实现思路 采用MVVM模式进…

【消息队列开发】 实现消息垃圾回收

文章目录 &#x1f343;前言&#x1f38b;准备工作&#x1f38d;具体实现&#x1f6a9;创建一个新文件&#x1f6a9;读取有效对象&#x1f6a9;把有效消息写入新文件中&#x1f6a9;以旧换新&#x1f6a9;更新统计文件&#x1f6a9;特别注意&#x1f6a9;完整代码 ⭕总结 &…

2.1_5 数据交换方式

文章目录 2.1_5 数据交换方式&#xff08;一&#xff09;为什么要数据交换&#xff1f;&#xff08;二&#xff09;数据交换方式&#xff08;1&#xff09;电路交换&#xff08;Circuit Exchanging&#xff09;&#xff08;2&#xff09;报文交换&#xff08;Message Exchangin…

mybatis源码阅读系列(二)

前言 上一篇文章mybatis源码阅读系列&#xff08;一&#xff09;介绍了mybatis和原生jdbc的区别&#xff0c;并通过代码展示了两者的运行过程和结果&#xff0c;下面让我们继续详细了解下mybatis的执行过程&#xff1b; package com.wyl.mybatis.service;import com.wyl.mybat…

环形链表2(C++), test ok

1. 题目 2. 思路分析&#xff1a; 与环形链表1一样&#xff0c;我们需要定义慢指针和快指针&#xff0c;确定链表是否有环&#xff0c;如果链表没有环的话&#xff0c;直接置空即可。如果链表有环&#xff0c;则需要向环形链表1一样&#xff0c;让快指针不断追赶慢指针&#x…

NVENC 视频编码器 API 编程指南 ( 中文转译 )

基于 NVIDIA Kepler™ 和更高版本 GPU 架构的 NVIDIA GPU 包含基于硬件的 H.264/HEVC/AV1 视频编码器&#xff08;以下简称 NVENC&#xff09;。NVENC 硬件采用 YUV/RGB 作为输入&#xff0c;并生成符合H.264/HEVC/AV1 标准的视频比特流。可以使用 NVIDIA 视频编解码器 SDK 中提…

Learn OpenGL 15 面剔除

面剔除 尝试在脑子中想象一个3D立方体&#xff0c;数数你从任意方向最多能同时看到几个面。如果你的想象力不是过于丰富了&#xff0c;你应该能得出最大的面数是3。你可以从任意位置和任意方向看向这个球体&#xff0c;但你永远不能看到3个以上的面。所以我们为什么要浪费时间…

Avalonia学习1:下载通用皮肤SukiUI,并在windows上启动成功

目录 1、引言 2、碰到的问题 1、下载下拉VS2022老版本的用不了。 2、升级后&#xff0c;发现没有装wsl&#xff0c;导致启动不了&#xff0c;但wsl又由于国内的关系安装不了&#xff0c;怎么办呢&#xff0c; 1、引言 最近在想有没有什么可以开发在Linux下运行…

公众号留言功能恢复了,你的开通了吗?

了解公众号的人都知道&#xff0c;腾讯在2018年3月宣布暂停新注册公众号的留言功能&#xff0c;这之后注册的公众号都不具备留言功能。 这成了很多号主运营人的一块心病&#xff0c;也包括我。 没有留言&#xff0c;就好似一个人玩单机游戏&#xff0c;无法与读者互动&#xff…

一文总结python的异常数据处理示例

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享&#xff0c;包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…

vue 记录一个echarts页面 单色环形饼图 多色环形饼图 柱状图加折线图 饼状图 双柱状图 雷达图 多色堆叠柱状图

“设备使用”模块没有做 因为项目不需要 仅自己记录使用 可供参考 那么上代码 <template><!--app-container--><div class"home-wrap"><div class"wrap" v-if"schoolId"><!--第一块--><div class"statis…

PS学习-抠图-蒙版-冰块酒杯等透明物体

选中图&#xff0c;ctrlA 全选 ctrlC复制 创建一个蒙版图层 选中蒙版Alt 点击进入 ctrlv 复制 ctrli 反转 原图层 ctrldelete填充为白色 添加一个背景&#xff0c;这个方法通用 首选创建一个 拖到最底部 给它填充颜色 这个可能是我图片的原因。视频是这样做的

第 5 章 TF坐标变换(自学二刷笔记)

重要参考&#xff1a; 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 5.1.6 TF坐标变换实操 需求描述&#xff1a; 程序启动之初&#xff1a;产生两只乌龟&#xff0c;中间的乌龟…