09_分割等和子集

· 浏览次数 : 0

小编点评

本题是要判断一个给定数组是否可以分割成两个子集,使得两个子集的元素和相等。这类问题通常可以通过“0/1背包问题”来解决,即给定一组物品,每个物品有一定的重量和价值,我们需要将它们装进背包,使得背包的容量最大化,并且不超过背包的容量。这里的背包是二进制的,只能选择放或者不放某个物品。 具体来说,我们可以维护一个dp数组,其中dp[i]表示只装下前i个物品时,背包容量为i时的最大价值。通过枚举所有可能的背包容量,我们可以找出是否存在一种方式将前i个物品装入背包中,使得背包容量减去这些物品的重量后的剩余容量刚好等于j,这样就能得到dp[j]的值。 这个问题的关键点在于: 1. 确定dp数组的含义和初始化方法。 2. 确定递推公式。 3. 如何遍历背包并剪枝来优化时间复杂度。 4. 理解dp数组的值应该小于等于背包的当前容量。 最终,如果我们能够找到一种方式使得dp[target]等于target,那就意味着可以将数组分割成两个子集,使得它们的元素和相等。

正文

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背包的写法来的。

与09_分割等和子集相似的内容:

09_分割等和子集

416. 分割等和子集 题目难易:中等 给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200 示例 1: 输入: [1, 5, 11, 5] 输出: true 解释: 数组可以分割成 [1,

[转帖]GC日志分析工具——GCViewer案例

原创 石页粑粑 来自zxsk的码农 2020-09-28 06:18 一、GCViewer介绍 业界较为流行分析GC日志的两个工具——GCViewer、GCEasy。GCEasy部分功能还是要收费的,今天笔者给大家介绍一下GCViewer的使用与功能点。 二、GCViewer 使用 2.1 编译 首

[转帖]TiKV 内存调优

TiDB试用 来源:TiDB 浏览 87 扫码 分享 2023-05-09 09:02:19 TiKV 内存参数性能调优 参数说明 TiKV 内存使用情况 TiKV 机器配置推荐 TiKV 内存参数性能调优 本文档用于描述如何根据机器配置情况来调整 TiKV 的参数,使 TiKV 的性能达到最优。你

[转帖]DM 达梦数据库 记录超长 错误解决方法

2022-08-24 09:423551原创DM 达梦 本文链接:https://www.cndba.cn/dave/article/108596 1 问题说明与分析 在达梦数据库中进行数据库Insert时可能会遇到如下错误: java.sql.SQLException: Record length

[转帖]编译器优化那些事儿(6):别名分析概述

https://bbs.huaweicloud.com/forum/thread-0211985213969460007-1-1.html 应用性能调优 发表于 2022-09-14 15:03:17298查看 1.简介 别名分析是编译器理论中的一种技术,用于确定存储位置是否可以以多种方式访问。如果

[转帖]minio性能测试

https://zhangzhuo.ltd/articles/2021/09/08/1631106274550.html 压测参数说明 压测数据量为:2个backet,每个backet为10000对象。每个对象大小512kb 所有minio服务内核以及资源优化都相同 整体读写压测时间为10分,读写比

[转帖][译] 大规模微服务利器:eBPF + Kubernetes(KubeCon, 2020)

http://arthurchiao.art/blog/ebpf-and-k8s-zh/ Published at 2020-09-06 | Last Update 2021-02-21 译者序 本文翻译自 2020 年 Daniel Borkmann 在 KubeCon 的一篇分享: eBPF a

[转帖][译] 大规模微服务利器:eBPF + Kubernetes(KubeCon, 2020)

http://arthurchiao.art/blog/ebpf-and-k8s-zh/ Published at 2020-09-06 | Last Update 2021-02-21 译者序 本文翻译自 2020 年 Daniel Borkmann 在 KubeCon 的一篇分享: eBPF a

k8s 入门到实战--部署应用到 k8s

![k8s 入门到实战 01.png](https://s2.loli.net/2023/09/04/ymUpcXZrxfNsT91.png) # 背景 最近这这段时间更新了一些 k8s 相关的博客和视频,也收到了一些反馈;大概分为这几类: - 公司已经经历过服务化改造了,但还未接触过云原生。 -

C++算法之旅、09 力扣篇 | 常见面试笔试题(上)算法小白专用

算法学习笔记,记录容易忘记的知识点和难题。详解时空复杂度、50道常见面试笔试题,包括数组、单链表、栈、队列、字符串、哈希表、二叉树、递归、迭代、分治类型题目,均带思路与C++题解