首页 > 其他分享 >09_分割等和子集

09_分割等和子集

时间:2024-06-05 22:15:19浏览次数:17  
标签:分割 背包 target nums int 09 子集 数组 dp

416. 分割等和子集

题目难易:中等

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

注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200

示例 1:

  • 输入: [1, 5, 11, 5]
  • 输出: true
  • 解释: 数组可以分割成 [1, 5, 5] 和 [11].

示例 2:

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

提示:

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

【思路】

这道题目是要找是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。那么只要找到集合里能够出现 sum / 2 的子集总和,就算是可以分割成两个相同元素和子集了。

动态规划五部曲:

1、确定dp数组及其下标的含义

01背包找那个,dp[j]表示:容量为j的背包,所背的物品价值最大可以为dp[j]。

本题中每一个元素的数组既是重量,也是价值。

套到本题,dp[j]表示背包总容量(所能装的总重量)是j,放进物品后,背的最大重量为dp[j]

那么如果背包容量为target, dp[target]就是装满背包之后的重量,所以当 dp[target] == target 的时候,背包就装满了。

2、确定递推公式

01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

本题,相当于背包里放入数值,那么物品i的重量是nums[i],其价值也是nums[i]。

所以递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);

3、dp数组如何初始化

在01背包,一维dp如何初始化,已经讲过,

从dp[j]的定义来看,首先dp[0]一定是0。

如果题目给的价值都是正整数那么非0下标都初始化为0就可以了,如果题目给的价值有负数,那么非0下标就要初始化为负无穷。

这样才能让dp数组在递推的过程中取得最大的价值,而不是被初始值覆盖了

本题题目中 只包含正整数的非空数组,所以非0下标的元素初始化为0就可以了。

代码如下:

//题中说:每个数组中的元素不会超过100,数组的大小不会超过200
//总和不会大于20000,背包最大只需要其中一般,所以10001大小就可以了
int[] dp = new dp[10001];

4、确定遍历顺序

如果使用一维dp数组,先遍历物品,在遍历背包。

代码如下:

//开始01背包
for (int i = 0; i < nums.size(); i++) {
	for (int j = target; j >= nums[i]; j--) {  //每一个元素一定是不可重复放入,所以从大到小遍历
	dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
	}
}

5、举例推导dp数组

dp[j]的数值一定是小于等于j的。

如果dp[j] == j 说明,集合中的子集总和正好可以凑成总和j,理解这一点很重要。

完整代码如下:

class Solution {
    public boolean canPartition(int[] nums) {
        if(nums == null || nums.length == 0) return false;
        int n = nums.length;
        int sum = 0;
        for(int num : nums) {
            sum += num;
        }
        //总和为奇数,不能平分
        if(sum % 2 != 0) return false;
        int target = sum / 2;
        int[] dp = new int[target + 1];
        for(int i = 0; i < n; i++) {  //先遍历物品
            for(int j = target; j >= nums[i]; j--) {
                //物品 i 的重量是 nums[i],其价值也是 nums[i]
                dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]);
            }
           
            //剪枝一下,每一次完成内部的for-loop,立即检查是否dp[target] == target,优化时间复杂度(26ms -> 20ms)
            if(dp[target] == target)
                return true;
        }
        return dp[target] == target;
    }
}

总结

这道题目就是一道01背包应用类的题目,需要我们拆解题目,然后套入01背包的场景。

01背包相对于本题,主要要理解,题目中物品是nums[i],重量是nums[i],价值也是nums[i],背包体积是sum/2。

看代码的话,就可以发现,基本就是按照01背包的写法来的。

标签:分割,背包,target,nums,int,09,子集,数组,dp
From: https://www.cnblogs.com/codingbao/p/18233994

相关文章

  • 【Python数据预处理系列】精通Pandas:数据清洗中的字符串分割技巧(例子:如何将籍贯列中的
    本文将深入探讨Pandas库在数据清洗中的应用,特别是字符串分割技巧。在数据分析的预处理步骤中,有效地处理和准备原始数据是至关重要的一步。我们将通过具体示例,展示如何使用Pandas中的.str.split()函数来对数据集中的字符串进行分割,进而提取所需信息。本文例子讲解如何将......
  • 力扣刷题--2553. 分割数组中数字的数位【简单】
    题目描述给你一个正整数数组nums,请你返回一个数组answer,你需要将nums中每个整数进行数位分割后,按照nums中出现的相同顺序放入答案数组中。对一个整数进行数位分割,指的是将整数各个数位按原本出现的顺序排列成数组。比方说,整数10921,分割它的各个数位得到[1,0......
  • 音频剪裁大师:使用 Python 和 ffmpeg 分割音频的完整指南
    前言在音频处理中,有时候我们需要对音频文件进行分割,提取其中的部分内容以满足特定需求。而Python提供了许多强大的工具和库来实现这一目标,其中ffmpeg是一个功能强大的工具,它不仅支持音频分割,还能进行音频转码、合并、提取等操作。本文将介绍如何使用Python和ffmpeg来分......
  • TCP_FLAGS_PROCESSING_09: [close-wait| closing | last-ack] FIN -> ignore
    测试目的:验证TCP在CLOSE-WAIT、CLOSING或LAST-ACK状态下,接收到FIN段时是否能够保持当前状态不变。描述:TCP在CLOSE-WAIT、CLOSING或LAST-ACK状态下,当接收到一个FIN段时,不应改变其状态。这是确保TCP连接能够按照正常的关闭序列进行,避免状态的意外变化。测试拓扑:具体步骤......
  • 打卡信奥刷题(52)用Scratch图形化工具信奥P7909 [普及组] [CSP-J 2021] 分糖果
    [CSP-J2021]分糖果题目背景红太阳幼儿园的小朋友们开始分糖果啦!题目描述红太阳幼儿园有nnn个小朋友,你是其中之一。保证......
  • 代码随想录训练营第28天 | 93.复原IP地址、78.子集 、90.子集II
    93.复原IP地址本期本来是很有难度的,不过大家做完分割回文串之后,本题就容易很多了题目链接/文章讲解:https://programmercarl.com/0093.复原IP地址.html视频讲解:https://www.bilibili.com/video/BV1XP4y1U73i/和分割字符串类似,还有判断当前数字是否符合要求functionisValid......
  • [NOIP2009 普及组] 多项式输出
    题目描述一元 ......
  • Luogu P2036 [COCI2008-2009 #2] PERKET
    LuoguP2036[COCI2008-2009#2]PERKET#include<bits/stdc++.h>usingnamespacestd;intn,ans=1e9+5;//ans初始化值大于所有可用食材全部使用产生的总酸度和总苦度ints[15],b[15];voiddfs(inttot,intk,intl){//k为当前酸度,l为当前甜度if(to......
  • 09-进程和计划任务管理
    9.1查看和控制进程9.1.1查看进程1.ps命令pS命令是Linux操作系统中最为常用的进程查看工具,主要用于显示包含当前运行的各进程完整信息的静态快照。通过不同的命令选项,可以有选择性地查看进程信息。命令作用a显示当前终端下的所有进程信息,包括其他用户的进程。u......
  • Python教程-快速入门基础必看课程09-文件处理
    该视频主要讲述了Python中文件的读写操作和pandas库中的subt函数来处理CSV文件。在Python中,文件的读写操作需要使用open函数打开文件,并指定路径和模式。读取文件时,可以使用f.read()方法读取内容,并使用f.close()方法关闭文件。写入文件时,可以使用f.write()方法写入内容,并使用......