LeetCode 416.分割等和子集 | 类0-1背包问题 | 解题思路及代码

Given a nonempty array nums, which only contains positive number. Find if the array can be divided into two parts such that the sum of each part is equal.

Input: nums = [1,5,11,5]
Output: true
Explanation: divide into [1,5,5] and [11].

To satisfy two part sum are equal, then each part sum is half of total sum. If the total sum is an odd or the max number in the array is bigger than half of total sum, then it’s can’t satisfy the requirement.

This problem is similar to 0-1 package problem. What differs is that the total sum we chose can’t exceed the capacity of the package in 0-1 package problem, while the chosen number’s sum must equal to half of total sum in this question. Similar to traditional 0-1 package problem, we can use dynamic programming to solve this problem.

We use a two-dimensional array boolean dp[n][half+1] for dynamic programming. Where n is the length of nums and half is the half of total sum. We define dp[i][j]:

  • i ranges from 0 to n-1, which means the subset(0, i) of nums.

  • j ranges from 0 to half, which means if the subset(0, i) can constitute a sum of value j.

dp[i][j] is true if subset(0, i) of nums can constitute a sum of value j. Then dp[n-1][half] means in the whole array nums, if it can constitute a sum of half.

The state transition equation is as follows:

[dp[i][j]=\begin{cases} dp[i-1][j]\ ||\ dp[i-1][j-num[i]]&num[i]\leq j\ dp[i-1][j]&num[i]>j \end{cases}]

dp[i][j] means we are deciding if we count nums[i] to constitute a sum of j for subset(0, i).

The upper case means: nums[i]<=j< code>, if we not choose this number, then our result(can constitute or not) is equal to "if the subset(0, i-1) can constitute a sum of <code>j</code>", that is<code>dp[i-1][j]</code>. If we choose this number, then our result is equal to "if the subset(0, i-1) can constitute a sum of <code>j-num[i]</code>". Either of them is true, then we can constitute a sum of <code>j</code> by subset(0, i) of <code>nums</code>.<br>The lower case means: <code>nums[i]>j</code>, the number is bigger than the number(<code>j</code>) we want to constitute, so we can't choose. Our result is same as <code>dp[i-1][j]</code>.<!--=j<-->

Observe the transition equation, we found that each line of our two-dimensional array dp only related to the previous line(dp[i] is decided by dp[i-1] only). So we can store the dp in only one line:
When we handle the new line i, the 1-dimensional array stores the i-1 line data! For each line, we ranges j from half to 0. The new state transition equation is as follows:

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

Since j ranges from half to 0, dp[j] or dp[j-nums[i] store the date of last line(i-1). After each round of j, we updated a line.

If nums.length<2< code> or <code>sum(nums)</code> is odd or <code>max(nums)>sum(nums)/2</code>, return <code>false</code>.<br>Create a boolean array <code>dp[sum(nums)/2+1]</code>. For <code>i</code> in range from 0 to <code>num.length</code>, for <code>j</code> in range from <code>sum(nums)/2</code> to 0, if <code>dp[j]==true</code> or <code>dp[j-nums[i]==true</code>, the <code>dp[j]=true</code>.<br>Finally, return <code>dp[sum(nums)/2]</code>.<!--2<-->

The detailed code is as follows

public class p416 {
    public static boolean canPartition(int[] nums) {
        int len = nums.length;
        if (len < 2) {
            return false;
        }
        int totalSum = 0, half = 0, maxNum = 0;
        for (int num : nums) {
            totalSum += num;
            maxNum = Math.max(maxNum, num);
        }
        if (totalSum % 2 != 0 || totalSum / 2 < maxNum) {
            return false;
        }
        half = totalSum / 2;
        boolean[] dp = new boolean[half + 1];
        dp[0] = true;
        for (int i = 0; i < len; i++) {
            int num = nums[i];
            for (int j = half; j >= num; j--) {
                dp[j] = dp[j] | dp[j - num];
            }
        }
        return dp[half];
    }
}

Time complexity: The outer loop nums.length, the inner loop sum(nums)/2, so the total time complexity is O(nums.length &#xD7; sum(nums)/2)
Space complexity: After optimization, the space we used are sum(nums)/2, so the total space complexity is O(sum(nums)/2)

Original: https://www.cnblogs.com/liuzhch1/p/16197049.html
Author: liuzhch1
Title: LeetCode 416.分割等和子集 | 类0-1背包问题 | 解题思路及代码

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/606686/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 前端数据提交给后端之HTML表单简单剖析

    写在开篇 什么是表单呢?当前端想要提交数据给后端,怎么搞?那么在前端开发中,表单是常用的手段,比如常见的场景有:登录框、账号注册页、主机信息录入CMDB等等场景都是需要表单。那么在…

    Linux 2023年6月7日
    099
  • .Net MVC实现全局异常捕捉返回通用异常页面的一种方式

    阅文时长 | 0.54分钟字数统计 | 876字符主要内容 | 1、引言&背景 2、部分通用设计代码 3、声明与参考资料『.Net MVC实现全局异常捕捉返回通用异常页面的…

    Linux 2023年6月13日
    0107
  • 编写 Shell 程序,实现自动删除 50 个账号的功能,账号名为stud1 至 stud50 ?

    #!/bin/bash for((i=1;i<51;i++))< code><code>do</code><code> &am…

    Linux 2023年5月28日
    099
  • PyTorch 介绍 | 快速开始

    本节介绍有关机器学习常见任务重的API。请参阅每一节的链接以深入了解。 Working with data PyTorch有两个有关数据工作的原型: torch.utils.dat…

    Linux 2023年6月16日
    092
  • 输入输出函数

    IDLE name=input(‘输入’) print(name) print函数 print(1,2) print(1,2,sep=",") input函数 …

    Linux 2023年6月8日
    090
  • 聊一聊mycat数据库集群系列之双主双重实现

    最近在梳理数据库集群的相关操作,现在花点时间整理一下关于mysql数据库集群的操作总结,恰好你又在看这一块,供一份参考。本次系列终结大概包括以下内容:多数据库安装、mycat部署安…

    Linux 2023年6月14日
    0120
  • Shading-JDBC、ShadingSphere、ShardingProxy 使用详解

    ShadingSphere ​ShardingSphere是一款起源于当当网内部的应用框架,2015年在当当网内部诞生,2016年由主要开发人员张亮带入京东数科,在国内经历了当当网…

    Linux 2023年6月6日
    0146
  • go-切片的追加

    // The append built-in function appends elements to the end of a slice. If // it has suffi…

    Linux 2023年6月13日
    080
  • 在docker中使用主机串口通讯

    在进行软件docker化的过程时,很大的一个阻碍就是软件与各种外围硬件设备的交互,网口通信的设备能够很容易地接入容器,但是串口设备则要复杂一些。本文讨论在windows和linux…

    Linux 2023年6月6日
    0107
  • Python实现经典算法八皇后问题

    递归回溯解八皇后问题 遗传算法解八皇后问题 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问一共有多少种摆法。 分别用递…

    Linux 2023年6月7日
    0131
  • Dockerfile

    Docker可以通过Dockerfile构建镜像。Dockerfile是一个文本文档,它包含用户可以在命令行上调用的所有命令来组装镜像。使用 docker build用户可以创建一…

    Linux 2023年6月13日
    090
  • jdk 安装(图形界面版)

    在这里为大家提供jdk8的Linux版安装包,下载链接: 提前将jdk安装包放入U盘中,插入U盘,VMware会自动识别,选择将U盘接入虚拟机 打开终端 为避免权限不足,开始之前确…

    Linux 2023年6月8日
    0114
  • 剑指offer计划19( 搜索与回溯算法中等)—java

    1.1、题目1 剑指 Offer 64. 求1+2+…+n 1.2、解法 这题看评论区真的绝了,都是人才,各个说话都好听,我看到个还有用异常来结束的就离谱。这题用了&a…

    Linux 2023年6月11日
    095
  • 【证券从业】金融基础知识-第四章 股票03

    注1:后续学习并整理到第八章,全书完结后再合并成一个笔记进行源文件分享 注2:本章内容巨多,大约分为三篇文章记录消化 posted @2022-06-08 01:28 陈景中 阅读…

    Linux 2023年6月13日
    0104
  • Python中import外部模块全局变量修改规则及踩坑

    最近碰到一个import外部文件全局变量修改后未符合预期效果的问题,简要描述如下: 有env.py, test.py, dal.py三个文件,env.py 中定义了DEBUG=Fa…

    Linux 2023年6月6日
    077
  • k8s 常用命令

    查看所有 pod 列表, -n 后跟namespace,查看指定的命名空间 查看 RC 和service 列表,-o wide 查看详细信息 显示 Node 的详细信息 显示 Po…

    Linux 2023年5月27日
    0121
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球