【力扣】416. 分割等和子集 <动态规划、回溯>

这篇具有很好参考价值的文章主要介绍了【力扣】416. 分割等和子集 <动态规划、回溯>。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【力扣】416. 分割等和子集

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

示例 1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5] 和 [11] 。

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

提示:
1 <= nums.length <= 200
1 <= nums[i] <= 100

题解

动态规划

01背包问题:有 N 件物品和一个最多能背重量为 W 的背包。第 i 件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

  • 背包的体积为sum / 2
  • 背包要放入的商品(集合里的元素)重量为元素的数值,价值也为元素的数值
  • 背包如果正好装满,说明找到了总和为 sum / 2 的子集
  • 背包中每一个元素是不可重复放入

回溯五步:

  • 确定dp数组以及下标的含义
    01背包中,dp[j] 表示: 容量为 j 的背包,所背的物品价值最大可以为 dp[j]
    本题中每一个元素的数值既是重量,也是价值。
    dp[j] 表示背包总容量(所能装的总重量)是 j,放进物品后,背的最大重量为 dp[j]
    如果背包容量为 target, dp[target] 就是装满背包之后的重量,所以 当 dp[target] == target 的时候,背包就装满了。
  • 确定递推公式
    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]);
  • dp数组如何初始化
    dp[j] 的定义来看,首先dp[0]一定是0,如果题目给的价值都是正整数那么非0下标都初始化为0就可以了,如果题目给的价值有负数,那么非0下标就要初始化为负无穷。
  • 确定遍历顺序
    如果使用一维 dp数组,物品遍历的 for 循环放在外层,遍历背包的for循环放在内层,且内层 for 循环倒序遍历。
  • 举例推导dp数组
    dp[j] == j 说明,集合中的子集总和正好可以凑成总和 j
    【力扣】416. 分割等和子集 <动态规划、回溯>,力扣及OJ,# 动态规划,leetcode,动态规划,算法
class B {
    public boolean canPartition(int[] nums) {
        if(nums == null || nums.length == 0) {
            return false;
        }
        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 < nums.length; 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;
    }
}

回溯(会超时)

取与不取文章来源地址https://www.toymoban.com/news/detail-692026.html

class B {
    public static void main(String[] args) {
        B b = new B();
        int[] nums = {1,5,11,5};//true
//        int[] nums = {1,2,3,5};//false
        System.out.println(b.canPartition(nums));
    }

    // 回溯
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public boolean canPartition(int[] nums) {
        int target = 0;
        for (int i = 0; i < nums.length; i++) {
            target += nums[i];
        }
        if (target % 2 != 0) {
            return false;
        }

        target = target / 2;
        //Arrays.sort(nums);
        trace(nums, 0, target, 0);

        if (res.size() > 0) {
            // System.out.println(res);
            return true;
        } else {
            return false;
        }
    }

    public void trace(int[] nums, int start, int target, int sum) {
        if (sum == target) {
            res.add(new ArrayList<>(path));
            return;
        }
        if (sum > target) {
            return;
        }
        for (int i = start; i < nums.length; i++) {
            path.add(nums[i]);
            sum += nums[i];
            trace(nums, i + 1, target, sum);
            sum -= nums[i];
            path.remove(path.size() - 1);
        }
    }
}

到了这里,关于【力扣】416. 分割等和子集 <动态规划、回溯>的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【十七】【动态规划】DP41 【模板】01背包、416. 分割等和子集、494. 目标和,三道题目深度解析

    动态规划就像是解决问题的一种策略,它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题,并将每个小问题的解保存起来。这样,当我们需要解决原始问题的时候,我们就可以直接利用已经计算好的小问题的解,而不需要重

    2024年02月03日
    浏览(45)
  • Day42|动态规划part04: 01背包问题,你该了解这些!、滚动数组、416. 分割等和子集

    其他背包,面试几乎不会问,都是竞赛级别的了,leetcode上连多重背包的题目都没有,所以题库也告诉我们,01背包和完全背包就够用了。 而完全背包又是也是01背包稍作变化而来,即:完全背包的物品数量是无限的。 01 背包问题描述 有n件物品和一个最多能背重量为w 的背包

    2024年04月25日
    浏览(38)
  • 代码随想录 Day35 动态规划04 01背包问题和完全背包问题 LeetCode T416 分割等和子集

    说到背包问题大家都会想到使用动规的方式来求解,那么为什么用动规呢, dp数组代表什么呢 ? 初始化是什么 , 遍历方式又是什么 ,这篇文章笔者将详细讲解背包问题的经典例题0-1背包问题和完全背包问题的解题方式,希望能帮助到大家 有人一提到背包问题就只会使用动态规划来

    2024年02月06日
    浏览(76)
  • 第九章 动态规划part04(● 01背包问题,你该了解这些! ● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集 )

    ● 01背包问题,你该了解这些! ● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集 https://programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-1.html 视频讲解:https://www.bilibili.com/video/BV1cg411g7Y6 1.确定dp数组以及下标的含义 i是物品,j是背包容量

    2024年01月16日
    浏览(52)
  • 力扣算法刷题Day42|动态规划:01背包问题 分割等和子集

    力扣题目:01背包问题(二维数组) 刷题时长:参考题解 解题方法:动态规划 + 二维dp数组 复杂度分析 时间 空间 问题总结 理解递推公式困难 本题收获 动规思路:两层for循环,第一层i遍历物品,第二层j枚举背包容量以内所有值 确定dp数组及下标的含义:dp[i][j] 表示从下标

    2024年02月13日
    浏览(62)
  • 动态规划(分割等和子集)

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

    2024年02月02日
    浏览(42)
  • Leetcode 416 分割等和子集

    题意理解 :         给你一个  只包含正整数  的  非空  数组  nums  。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。         即将数组的元素分成两组,每组数值=sum(nums)/2         若能分成这样的两组,则返回true,否则返回false      

    2024年02月01日
    浏览(44)
  • 【LeetCode】416.分割等和子集

    给你一个  只包含正整数  的  非空  数组  nums  。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 示例 1: 示例 2: 提示: 1 = nums.length = 200 1 = nums[i] = 100 实际上是求能否从背包里选取元素,使这些元素之和等于数组所有元素之和的一半。dp

    2024年02月11日
    浏览(36)
  • LeetCode416. 分割等和子集

    一、题目 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 示例 1: 示例 2: 提示: 1 = nums.length = 200 1 = nums[i] = 100 二、题解 方法一:0-1背包二维数组 步骤1:理解题目以及01 背包问题 在 01 背包问题中,

    2024年02月10日
    浏览(46)
  • 【算法与数据结构】416、LeetCode分割等和子集

    所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。    思路分析 :本题可以抽象成一个01背包的问题,关于01背包可以看【算法与数据结构】算法与数据结构知识点。 本题只需要求出数组的累积和,然后和的一半就可以视为背包的最大重量,目标

    2024年01月19日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包