LeetCode 力扣热题100 分割等和子集

news2025/3/15 23:03:07

题目解析

题目:给定一个正整数数组 nums,判断是否可以将数组分成两个和相等的子集。

等价问题

• 计算 nums 的总和 S

• 如果 S 是奇数,直接返回 false(因为不能均分)

• 目标是找到一个子集,使得子集和等于 S / 2

• 这相当于 0-1 背包问题:是否能从 nums 中选取一些数,使其和为 S / 2

解法:动态规划

1. 状态定义

使用 一维 DP 数组 dp[j]:

• dp[j] = true 表示存在一个子集,使得该子集的和为 j

• dp[j] = false 表示不存在这样的子集

目标:判断 dp[target] 是否为 true,其中 target = S / 2

2. 递推公式

• 遍历数组 nums,对于当前元素 num

倒序遍历 j = target 到 num,更新 dp[j]

• dp[j] = dp[j] || dp[j - num]

如果 dp[j - num] 为 true,说明 j - num 可达,那么 j 也可达

如果 dp[j] 原本为 true,则仍为 true

3. 初始化

• dp[0] = true(空集的和为 0)

代码分析

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int s = accumulate(nums.begin(), nums.end(), 0); // 计算总和
        if (s % 2 != 0) return false; // 总和为奇数,无法均分
        int target = s / 2; // 目标和

        vector<bool> dp(target + 1, false); // DP 数组,表示是否能组成某个和
        dp[0] = true; // 0 直接可达

        for (int num : nums) { // 遍历每个数
            for (int j = target; j >= num; j--) { // 逆序遍历
                dp[j] = dp[j] || dp[j - num];
            }
        }
        return dp[target]; // 看 target 是否可达
    }
};

详细运行步骤

示例 1

输入

nums = {1, 5, 11, 5}

计算总和

• S = 1 + 5 + 11 + 5 = 22

• target = 22 / 2 = 11

• 需要找到一个子集和为 11

DP 过程

初始化:

dp = [true, false, false, false, false, false, false, false, false, false, false, false]

(下标 0 代表和为 0 可达)

遍历 1

dp[1] = dp[1] || dp[1 - 1]  (true)

dp = [true, true, false, false, false, false, false, false, false, false, false, false]

遍历 5

dp[6] = dp[6] || dp[6 - 5] (true)
dp[5] = dp[5] || dp[5 - 5] (true)

dp = [true, true, false, false, false, true, true, false, false, false, false, false]

遍历 11

dp[11] = dp[11] || dp[11 - 11] (true)

dp = [true, true, false, false, false, true, true, false, false, false, false, true]

最终 dp[11] = true,返回 true

案例分析

我们用一个不同的测试案例,详细跟踪 dp 数组的变化。

示例 2

输入

nums = {3, 3, 3, 4, 5}

计算总和

• S = 3 + 3 + 3 + 4 + 5 = 18

• target = 18 / 2 = 9

• 目标是找到一个子集,使得该子集的和为 9

初始化

我们初始化 dp 数组:

dp = [true, false, false, false, false, false, false, false, false, false]

• dp[0] = true,表示和为 0 的子集是可行的(空集)

遍历每个数

遍历 3(第一个)

更新 dp[j],从 target = 9 逆序到 num = 3

dp[3] = dp[3] || dp[3 - 3] = true

dp 变化

dp = [true, false, false, true, false, false, false, false, false, false]

表示可以用 {3} 得到和 3

遍历 3(第二个)

dp[6] = dp[6] || dp[6 - 3] = true
dp[3] = dp[3] || dp[3 - 3] = true (已经是 true)

dp 变化

dp = [true, false, false, true, false, false, true, false, false, false]

表示可以用 {3, 3} 得到和 6

遍历 3(第三个)

dp[9] = dp[9] || dp[9 - 3] = true
dp[6] = dp[6] || dp[6 - 3] = true (已经是 true)
dp[3] = dp[3] || dp[3 - 3] = true (已经是 true)

dp 变化

dp = [true, false, false, true, false, false, true, false, false, true]

表示可以用 {3, 3, 3} 得到和 9 ✅ 目标达成

遍历 4

dp[9] = dp[9] || dp[9 - 4] = true (已经是 true)
dp[7] = dp[7] || dp[7 - 4] = true
dp[4] = dp[4] || dp[4 - 4] = true

dp 变化

dp = [true, false, false, true, true, false, true, true, false, true]

表示可以用 {4} 得到和 4,可以用 {3, 4} 得到 7

遍历 5

dp[9] = dp[9] || dp[9 - 5] = true
dp[8] = dp[8] || dp[8 - 5] = true
dp[5] = dp[5] || dp[5 - 5] = true

dp 变化

dp = [true, false, false, true, true, true, true, true, true, true]

可以用 {5} 得到 5,用 {3, 5} 得到 8

最终结果

✅ dp[9] = true,说明可以找到一个子集使得总和为 9,返回 true

完整执行过程

dp 状态

0

1

2

3

4

5

6

7

8

9

初始

T

F

F

F

F

F

F

F

F

F

处理 3

T

F

F

T

F

F

F

F

F

F

处理 3

T

F

F

T

F

F

T

F

F

F

处理 3

T

F

F

T

F

F

T

F

F

T

处理 4

T

F

F

T

T

F

T

T

F

T

处理 5

T

F

F

T

T

T

T

T

T

T

dp[9] = true,所以可以划分两个子集和相等。

复杂度分析

时间复杂度:O(n × target) 其中 target = S/2

空间复杂度:O(target) 只用了一维 dp

总结

思路

1. 计算 S,如果 S 为奇数直接返回 false

2. 定义 dp[j]:表示能否找到一个子集,使得总和为 j

3. 遍历 nums,使用 逆序 更新 dp,确保不会重复使用数字

4. 最终 dp[target] 是否为 true,决定是否能划分

关键优化点

• 使用 一维 DP 数组(空间优化)

倒序遍历 j,避免同一轮重复使用 nums[i]

时间复杂度

• O(n × sum/2),适用于 sum 适中的情况(sum < 10^5)

空间复杂度

• O(sum/2),降低空间占用

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

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

相关文章

【工具】C#游戏防沉迷小工具

背景介绍 嘿&#xff0c;各位小伙伴&#xff01;今天想跟大家唠唠我为啥要搞这么个防沉迷小工具。 咱都清楚&#xff0c;现在这游戏啊&#xff0c;玩起来那叫一个带劲&#xff0c;但时间一长&#xff0c;不仅眼睛累&#xff0c;心也跟着累。有些游戏&#xff0c;规则定得挺有意…

深圳南柯电子|净水器EMC测试整改:水质安全与电磁兼容性的双赢

在当今注重健康生活的时代&#xff0c;净水器作为家庭用水安全的第一道防线&#xff0c;其性能与安全性备受关注。其中&#xff0c;电磁兼容性&#xff08;EMC&#xff09;测试是净水器产品上市前不可或缺的一环&#xff0c;它直接关系到产品在复杂电磁环境中的稳定运行及不对其…

SpeechCraf论文学习

Abstract 核心问题 挑战 语音风格包含细微的多样化信息&#xff08;如情感、语调、节奏&#xff09;&#xff0c;传统基于标签/模板的标注方法难以充分捕捉&#xff0c;制约了语音-语言多模态模型的性能。 数据瓶颈&#xff1a; 大规模数据收集与高质量标注之间存在矛盾&…

Work【2】:PGP-SAM —— 无需额外提示的自动化 SAM!

文章目录 前言AbstractIntroductionMethodsContextual Feature ModulationProgressive Prototype RefinementPrototype-based Prompt Generator ExperimentDatasetsImplementation DetailsResults and AnalysisAblation Study 总结 前言 和大家分享一下我们发表在 ISBI 2025 上…

数据安全之策:备份文件的重要性与自动化实践

在信息化高速发展的今天&#xff0c;数据已成为企业运营和个人生活中不可或缺的重要资源。无论是企业的财务报表、客户资料&#xff0c;还是个人的家庭照片、学习笔记&#xff0c;数据的丢失或损坏都可能带来无法挽回的损失。因此&#xff0c;备份文件的重要性日益凸显&#xf…

uniapp+Vue3 组件之间的传值方法

一、父子传值&#xff08;props / $emit 、ref / $refs&#xff09; 1、props / $emit 父组件通过 props 向子组件传递数据&#xff0c;子组件通过 $emit 触发事件向父组件传递数据。 父组件&#xff1a; // 父组件中<template><view class"container">…

blender使用初体验(甜甜圈教程)

使用blender 建模了甜甜圈&#xff0c;时间空闲了&#xff0c;但愿能创建点好玩的吸引人的东西

大模型学习笔记------Llama 3模型架构之旋转编码(RoPE)

大模型学习笔记------Llama 3模型架构之旋转编码&#xff08;RoPE&#xff09; 1、位置编码简介1.1 绝对位置编码1.2 相对位置编码 2、旋转编码&#xff08;RoPE&#xff09;2.1 基本概念---旋转矩阵2.2 RoPE计算原理2.2.1 绝对位置编码2.2.2 相对位置编码 3、旋转编码&#xf…

04 1个路由器配置一个子网的dhcp服务

前言 这是最近一个朋友的 ensp 相关的问题, 这里来大致了解一下 ensp, 计算机网络拓扑 相关基础知识 这里一系列文章, 主要是参照了这位博主的 ensp 专栏 这里 我只是做了一个记录, 自己实际操作了一遍, 增强了一些 自己的理解 当然 这里仅仅是一个 简单的示例, 实际场景…

安装open-webui

open-webui是一个开源的大语言模型交互界面 前提&#xff1a;Ollama已安装&#xff0c;并下载了deepseek-r1:1.5b模型 拉取镜像 docker pull ghcr.io/open-webui/open-webui:main 配置docker-compose.yml services:open-webui:image: ghcr.io/open-webui/open-webui:mainv…

HCIA-11.以太网链路聚合与交换机堆叠、集群

链路聚合背景 拓扑组网时为了高可用&#xff0c;需要网络的冗余备份。但增加冗余容易后会出现环路&#xff0c;所以我们部署了STP协议来破除环路。 但是&#xff0c;根据实际业务的需要&#xff0c;为网络不停的增加冗余是现实需要的一部分。 那么&#xff0c;为了让网络冗余…

Amazon RDS ProxySQL 探索(一)

:::info &#x1f4a1; 在日常开发中&#xff0c;开发者们会涉及到数据库的连接&#xff0c;在使用Amazon RDS数据库时&#xff0c;若使用集群模式或者多数据库时&#xff0c;会出现一写多读多个Endpoint&#xff0c;在实际开发中&#xff0c; 开发者们配置数据库连接通常希望走…

200多种算法应用于二维和三维无线传感器网络(WSN)覆盖场景

2.1 二元感知模型 在当前无线传感器网络&#xff08;WSN&#xff09;覆盖场景中&#xff0c;最常见且理想的感知模型是二元感知模型[27]。如图2所示&#xff0c; Q 1 Q_1 Q1​和 Q 2 Q_2 Q2​代表平面区域内的两个随机点。 Q 1 Q_1 Q1​位于传感器的检测区域内&#xff0c;其感…

模拟类似 DeepSeek 的对话

以下是一个完整的 JavaScript 数据流式获取实现方案&#xff0c;模拟类似 DeepSeek 的对话式逐段返回效果。包含前端实现、后端模拟和详细注释&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><titl…

Flutter PopScope对于iOS设置canPop为false无效问题

这个问题应该出现很久了&#xff0c;之前的组件WillPopScope用的好好的&#xff0c;flutter做优化打算“软性”处理禁用返回手势&#xff0c;出了PopScope&#xff0c;这个组件也能处理在安卓设备上的左滑返回事件。但是iOS上面左滑返回手势禁用&#xff0c;一直无效。 当然之…

SpringBoot + ResponseBodyEmitter 实时异步流式推送,优雅!

ChatGPT 的火爆&#xff0c;让流式输出技术迅速走进大众视野。在那段时间里&#xff0c;许多热爱钻研技术的小伙伴纷纷开始学习和实践 SSE 异步处理。 我当时也写过相关文章&#xff0c;今天&#xff0c;咱们换一种更为简便的方式来实现流式输出&#xff0c;那就是 ​​Respon…

网络运维学习笔记(DeepSeek优化版) 016 HCIA-Datacom综合实验01

文章目录 综合实验1实验需求总部特性 分支8分支9 配置一、 基本配置&#xff08;IP二层VLAN链路聚合&#xff09;ACC_SWSW-S1SW-S2SW-Ser1SW-CoreSW8SW9DHCPISPGW 二、 单臂路由GW 三、 vlanifSW8SW9 四、 OSPFSW8SW9GW 五、 DHCPDHCPGW 六、 NAT缺省路由GW 七、 HTTPGW 综合实…

02 windows qt配置ffmpeg开发环境搭建

版本说明 首先我使用ffmpeg版本是4.2.1 QT使用版本5.14.2 我选择是c编译 在02Day.pro⾥⾯添加ffmpeg头⽂件和库⽂件路径 win32 { INCLUDEPATH $$PWD/ffmpeg-4.2.1-win32-dev/include LIBS $$PWD/ffmpeg-4.2.1-win32-dev/lib/avformat.lib \$$PWD/ffmpeg-4.2.1-win32-dev/l…

vue-treeselect 【单选/多选】的时候只选择最后一层(绑定的值只绑定最后一层)

欢迎访问我的个人博客 &#xff5c;snows_ls BLOGhttp://snows-l.site 一、单选 1、问题&#xff1a; vue-treeselect 单选的时候只选择最后一层&#xff08;绑定的值只绑定最后一层&#xff09; 2、方法 1、只需要加上 :disable-branch-nodes"true" 就行&#xff0…

微信小程序实现根据不同的用户角色显示不同的tabbar并且可以完整的切换tabbar

直接上图上代码吧 // login/login.js const app getApp() Page({/*** 页面的初始数据*/data: {},/*** 生命周期函数--监听页面加载*/onLoad(options) {},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函…