416. 分割等和子集
一、题目
给你一个 只包含正整数 的 非空 数组 nums
。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。
二、思路
假定nums[]
数组下标从1
开始,如何确定f[i][j]
的值?
我们一般去考虑最后一步,那么对于当前的数字 nums[i]
,可以选取也可以不选取:
- 1、不选
nums[i]
,那么我们就从前i - 1
个数中选,看是否使得这些数字的和恰好等于j
,即f[i][j] = f[i - 1][j]
。 - 2、选择
nums[i]
,在背包可以装下的情况下,那么相应的背包容量就要减去nums[i]
,f[i][j]
的状态就可以从f[i - 1][j - nums[i]]
转移过来,即f[i][j] = f[i - 1][j - nums[i]]
。
综上,两种情况只要有一个为true
,f[i][j]
就为true
。因此状态转移方程为f[i][j] = f[i - 1][j] | f[i - 1][j - nums[i]]
。
三、代码
class Solution { public boolean canPartition(int[] nums) { int n = nums.length, sum = 0; for(int x : nums) sum += x; if(sum % 2 != 0) return false; int m = sum / 2; boolean[][] f = new boolean[n + 1][m + 1]; f[0][0] = true; for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ if(j >= nums[i - 1]) f[i][j] = f[i - 1][j - nums[i - 1]] || f[i - 1][j]; else f[i][j] = f[i - 1][j]; } } return f[n][m]; } }
四、分析
时间复杂度分析: O(n∗m),n
是nums
数组的大小,m
是数组元素和的一半。
空间复杂度分析:O(n∗m)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了