首页 > 其他分享 >416. 分割等和子集(leetcode)

416. 分割等和子集(leetcode)

时间:2024-09-01 20:27:11浏览次数:8  
标签:target nums int sum 个数 416 子集 leetcode

https://leetcode.cn/problems/partition-equal-subset-sum/description/

01背包问题,需要考虑到如何把这个问题转化成01背包问题
转换成01背包问题后,如何定义f[i]状态来表示

这里有两种方式:1.按照传统01背包表示,即前i个物品中选,体积小于等于j的最大价值,这里体积和价值是等价的
2.按照标准定义来:f[i][j]表示能否选出 在 前i个数中,和正好为j 的序列,这里仍以第i个数选或者不选来划分子集
可得f[i][j] = f[i-1][j-nums[i]] || f[i-1][j]  ,即若选第i个数,则需要知道 f[i-1][j-nums[i]] 能否凑出, 若不选, 则需要知道 f[i-1][j],能否凑出,这两个子集有一个可以即可

class Solution {
    public boolean canPartition(int[] nums) {
        // f[i][j] 表示前i个物品中选,体积小于等于j的所有选法的集合,表示的属性是最大价值
        // f[i][j] = max(f[i-1][j],f[i-1][j-v[i]]+w[i])
        // 计算出f[i][j]后,根据f的定义可以知,选取出target的最大价值是:f[nums.length-1][target],判断这个最大价值是否是target
        // 即可判断这个数组能否选出来两个和为target的子数组
        int sum=0;
        int[][] f = new int[210][20010];
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if (sum % 2 == 1) return false;
        int target = sum / 2;
        for(int i=1;i<nums.length;i++)
            for(int j=0;j<=target;j++)
            {
                f[i][j]=f[i-1][j];
                if(j>=nums[i])
                    f[i][j] = Math.max(f[i-1][j],f[i-1][j-nums[i]]+nums[i]);
            }
        return f[nums.length-1][target] == target;
    }
}

 

class Solution {
    public boolean canPartition(int[] nums) {
        // 求两个子集元素和相等,则可以求出这个和是sum(nums)/2
        // 剩余就是求在nums中选择若干数使得和正好为目标值
        // f[i][j]表示在前i个数中选择,和正好等于j的选法,f[i][j]表示的意思是
        // 前i个数中选择,和为j是否能够凑齐
        // 以第i个数选或者不选 来划分子集
        // f[0][0]=true
        // f[i][j] = f[i-1][j-nums[i]] || f[i-1][j]
        int target=0;
        for(int i=0;i<nums.length;i++)target+=nums[i];
        if(target%2==1)return false; // 不可能划分的情况
        target/=2;
        boolean[][] f = new boolean[nums.length+1][200*100+1];
        f[0][0]=true;
        for(int i=0;i<nums.length-1;i++)
            for(int j=0;j<=target;j++)
                if(j>=nums[i])f[i+1][j] = f[i][j-nums[i]] || f[i][j];
                else f[i+1][j]=f[i][j];

                
        return f[nums.length-1][target];
    }
}

 

标签:target,nums,int,sum,个数,416,子集,leetcode
From: https://www.cnblogs.com/lxl-233/p/18391661

相关文章

  • Leetcode3234. 统计 1 显著的字符串的数量
    EverydayaLeetcode题目来源:3234.统计1显著的字符串的数量解法1:枚举左端点注意到,如果子串中的0非常多,多到0的个数的平方比1的个数都要大,那么这样的子串必然不是1显著子串。设cnt0为子串中的0的个数,cnt1为子串中的1的个数,那么必须满足:cnt0*cnt0<=......
  • 【Leetcode_Hot100】哈希
    哈希1.两数之和49.字母异位词分组128.最长连续序列1.两数之和方法一:HashMap在元素放入数组之前就进行判断,保证了不会取出同一个元素的情况,,例如[3,3],如果先将数组中的所有元素放入hashMap,再判断是否存在,则返回结果为[1,1],不符合题意。classSolution{publicint[......
  • 数据结构:(LeetCode572)另一棵子树
    给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。示例1:......
  • LeetCode - 6 Z 字形变换
    题目来源6.Z字形变换-力扣(LeetCode) 题目描述将一个给定字符串s根据给定的行数numRows,以从上往下、从左到右进行Z字形排列。比如输入字符串为"PAYPALISHIRING"行数为3时,排列如下:P A H NAPLSIIGY I R之后,你的输出需要从左往右逐......
  • 343. 整数拆分(leetcode)
    https://leetcode.cn/problems/integer-break/dp,思路较为巧妙,需要考虑一个数至少能拆成两份这个点,且需要考虑到拆的这个数的值域是多少(1,i-1)且选择拆一次还是拆多次classSolution{public:intintegerBreak(intn){//f[i]表示拆分i成若干个整数的最大乘......
  • 63. 不同路径 II(leetcode)
    简单dphttps://leetcode.cn/problems/unique-paths-ii/description/传统做法:classSolution{public:intuniquePathsWithObstacles(vector<vector<int>>&obstacleGrid){intf[110]={0};//优化一维f[1]=1;intm=obstacleGrid......
  • 数据结构:(LeetCode965)单值二叉树
     一:定义如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回 true;否则返回false。示例1:输入:[1,1,1,1,1,null,1]输出:true示例2:输入:[2,2,2,5,2]输出:false 提示:给定树的节点数范围是 [1,100]。每个节点的值都是......
  • 数据结构:(LeetCode 965)相同的树
    给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。示例1:输入:p=[1,2,3],q=[1,2,3]输出:true示例2:输入:p=[1,2],q=[1,null,2]输出:false示例3:输入:p=[1,2,1]......
  • leetcode刷题day4|链表部分(24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点、
    前言:链表练习的第二天,对链表的理解加深了24.两两交换链表中的节点这个题一开始的思路是用cur和next两个指针来做,但是绕来绕去绕迷糊了,最后超时了。把错误的代码放在下面警醒大家:主要问题出现在这两行代码,next.next发生了更改。next.next=next.next.next;next.next.nex......
  • leetcode刷题day3|链表部分( 203.移除链表元素、707.设计链表、206.反转链表)
    前言:链表部分之前刷过一些题,掌握的还可以,希望可以顺利把这部分题刷完。203.移除链表元素思路:自己创建一个头节点,使新的头节点指向旧的头节点。错误尝试:一开始考虑的比较复杂,设置了指针pre,能够想到直接比较cur.next.val和val的值会使代码更加简洁,但也要注意想清楚如果删除......