【动态规划】Leetcode 416. 分割等和子集【中等】

ops/2024/9/23 18:33:38/

分割等和子集

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

示例 1:

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

解题思路

这是一个典型的动态规划问题,可以使用动态规划来解决

  • 1、计算数组 nums 的总和 sum。
  • 2、如果 sum 为奇数,那么无法将数组分割成两个和相等的子集,直接返回 false。
  • 3、将问题转化为背包问题:尝试从数组中挑选一些数字,使得它们的和等于 sum 的一半。 如果能够找到这样的数字组合,就说明可以将数组分割成两个和相等的子集。
  • 4、定义一个二维数组 dp,其中 dp[i][j] 表示在前 i 个数字中是否存在和为 j 的子集。
  • 5、初始化 dp 数组,当不选取任何数字时,可以得到和为 0 的子集,因此 dp[i][0] = true(0 <= i <= nums.length);当没有数字可选时,除了和为 0 的子集,其他和均不可能存在,因此 dp[0][j] = false(1 <= j <= sum/2)。
  • 6、遍历数组 nums,在每个位置考虑选取或不选取当前数字,更新 dp 数组。
  • 7、返回 dp[nums.length][sum/2],表示是否存在和为 sum/2 的子集。

Java实现

public class PartitionEqualSubsetSum {public boolean canPartition(int[] nums) {int sum = 0;for (int num : nums) {sum += num;}if (sum % 2 != 0) {return false;}int target = sum / 2;boolean[][] dp = new boolean[nums.length + 1][target + 1];for (int i = 0; i <= nums.length; i++) {dp[i][0] = true;}/*** 这段代码是典型的动态规划解法,用于解决一个背包问题。在这里,dp[i][j]* 表示使用数组 nums 的前 i 个数字能否组成和为 j 的情况。** 具体来说,内层的两个循环分别是:* 外层循环遍历数组 nums 的每个数字(从 1 到 nums.length)。* 内层循环遍历目标和 target 的可能取值(从 1 到 target)。** 在每一次迭代中,我们需要考虑两种情况:* 1、如果当前数字 nums[i - 1] 大于当前目标和 j,则无法使用当前数字来达到目标和 j,* 因此 dp[i][j] 应该等于 dp[i - 1][j],即不使用当前数字 nums[i - 1];** 2、如果当前数字 nums[i - 1] 小于等于当前目标和 j,则存在两种选择:* 不使用当前数字 nums[i - 1],即 dp[i][j] = dp[i - 1][j];* 使用当前数字 nums[i - 1],即 dp[i][j] = dp[i - 1][j - nums[i - 1]]。*  如果选择使用当前数字,则需要查看前一个状态 dp[i - 1][j - nums[i - 1]] 是否为 true,*  即在不考虑当前数字时,前一个状态能否达到目标和为 j - nums[i - 1] 的情况。*  如果为 true,则说明使用当前数字后,目标和为 j 的情况可以通过选择当前数字来实现。** 因此,最终 dp[i][j] 的值是以上两种情况的逻辑或(||)结果。这样,* 在外层循环和内层循环的遍历结束后,dp[nums.length][target]* 就表示使用数组 nums 中的所有数字能否组成目标和为 target 的情况。*/for (int i = 1; i <= nums.length; i++) {for (int j = 1; j <= target; j++) {if (nums[i - 1] > j) {dp[i][j] = dp[i - 1][j];} else {dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]];}}}return dp[nums.length][target];}public static void main(String[] args) {PartitionEqualSubsetSum partitionEqualSubsetSum = new PartitionEqualSubsetSum();// Test case 1int[] nums1 = {1, 5, 11, 5};System.out.println(partitionEqualSubsetSum.canPartition(nums1)); // Output: true// Test case 2int[] nums2 = {1, 2, 3, 5};System.out.println(partitionEqualSubsetSum.canPartition(nums2)); // Output: false}
}

时间空间复杂度

  • 时间复杂度:遍历了一次数组nums,并使用了一个二维数组dp,时间复杂度为O(n * sum),其中n为数组nums的长度,sum为数组nums的总和。

  • 空间复杂度:使用了一个二维数组dp,空间复杂度为O(n * sum)。


http://www.ppmy.cn/ops/24935.html

相关文章

Rust Web开发实战:打造高效稳定的服务端应用

Rust Web开发实战&#xff1a;打造高效稳定的服务端应用 本书将带领您从零开始构建Web应用程序&#xff0c;无论是API、微服务还是单体应用&#xff0c;都将一一涵盖。您将学到如何优雅地对外开放API&#xff0c;如何连接数据库以安全存储数据&#xff0c;以及如何对应用程序进…

JavaScript实现在线屏幕录制

本文主要介绍在线屏幕录制 Demo Its sole method is MediaDevices.getDisplayMedia() !移动端暂不支持 环境要求 新版本 Chrome,Edge,Firefox 桌面浏览器 常见问题 1. navigator.mediaDevices为undefined 在不安全的情况下&#xff0c;navigator.mediaDevices是undefine…

二分法(Java实现)

二分法&#xff08;也称为二分查找法或折半查找法&#xff09;是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始&#xff0c;如果中间元素正好是要查找的元素&#xff0c;则搜索过程结束&#xff1b;如果某一特定元素大于或者小于中间元素&#xf…

[iOS]使用CocoaPods发布私有库

1.创建私有 Spec 仓库 首先&#xff0c;需要一个私有的 Git 仓库来存放你的 Podspec 文件&#xff0c;这个仓库用于索引你所有的私有 Pods。 在 GitHub 或其他 Git 服务上创建一个新的私有仓库&#xff0c;例如&#xff0c;名为 PrivatePodSpecs。克隆这个仓库到本地&#xf…

观成科技:蔓灵花组织加密通信研究分析总结

1.概述 蔓灵花&#xff0c;又名"Bitter"&#xff0c;常对南亚周边及孟加拉湾海域的相关国家发起网络攻击&#xff0c;主要针对巴基斯坦和中国两国。其攻击目标主要包括政府部门、核工业、能源、国防、军工、船舶工业、航空工业以及海运等行业&#xff0c;其主要意图…

解决Linux CentOS 7安装了vim编辑器却vim编辑器不起作用、无任何反应

文章目录 前言一、解决vim不起作用&#xff08;卸载重新安装&#xff09;1.重新安装vim2.测试vim是否能正常使用 二、解决vim: error while loading shared libraries: /lib64/libgpm.so.2: file too short报错三、解决vim编辑器不能使用方向键和退格键问题 remove vim-common …

未来已来:PostCSS插件让你提前使用CSS新特性

PostCSS是一个用JavaScript工具和插件生态系统来转换CSS代码的工具。它允许开发者使用现代CSS语法来编写样式&#xff0c;然后自动将它们转换为大多数浏览器能够理解的格式。 PostCSS的主要功能包括&#xff1a; 当然&#xff0c;让我们更详细地了解PostCSS的每个功能点&…

合泰杯(HT32F52352)RTC的应用(计时)--->掉电不丢失VBAT(代码已经实现附带源码)

摘要 在HT32F52352合泰单片机开发中&#xff0c;rtc在网上还是挺少人应用的&#xff0c;找了很久没什么资料&#xff0c;现在我根据手册和官方的代码进行配置理解。 RTC在嵌入式单片机中是一个很重要的应用资源。 记录事件时间戳&#xff1a;RTC可以记录事件发生的精确时间&…