ποΈ Problems
Partition Equal Subset Sum - LeetCode
Given a non-empty array nums containing only positive integers,
find if the array can be partitioned into two subsets such
that the sum of elements in both subsets is equal.
Input: nums = [1,5,11,5]
Output: true
Explanation: The array can be partitioned as [1, 5, 5] and [11].
Constraints:
1 <= nums.length <= 200
1 <= nums[i] <= 100
π π€ First attempt
The first algorithm that I came up with is the backtrack algorithm. But the input size is upto 200
. The backtrack algorithm won't work.
var canPartition = function (nums) {
const total = nums.reduce((a, b) => a + b, 0);
if (total % 2 === 1) return false;
const target = total / 2;
const N = nums.length;
const dp = (remain, cur, index) => {
if (remain === 0) {
if (cur.length < N) return true;
return false;
}
if (remain < 0) return false;
let local = false;
for (let i = index; i < N; i += 1) {
cur.push(nums[i]);
local = local || dp(remain - nums[i], cur, i + 1);
cur.pop();
}
return local;
};
return dp(target, [], 0);
};
λ°λ‘ TLE λ°μν©λλ€. μ¬κΈ°μ memo
λΆμΌ μλ μκ² μ§λ§ knapsackμ μ΄μ©ν dynamic programming λ°©λ² νμ΄λ κ°λ₯νλ€κ³ ν©λλ€.
β¨ Idea
nums[]
ν©μ λ°μ΄ λλλ‘ νλ subset μ΄ μλκ° ?nums[]
μ€μμ μ νν΄μ νμΌ λ¬΄κ² (μ£Όμ΄μ§ μ΄ν© λ¬΄κ² /2)λ₯Ό λ§λ€ μ μλκ° ?
- 01 Knapsack
- νμΌ λ¬΄κ² : μ£Όμ΄μ§ λ¬΄κ² / 2
- κ° λ¬Όκ±΄ λ¬΄κ² :
nums[]
dp[n][w]
: 물건[1,...,n]
μ΄μ©ν΄μ λ¬΄κ² w λ₯Ό κ½ μ±μΈ μ μλκ° ?
π Intuition
basecase
무κ²κ° 0μ΄λΌλ©΄ μλ¬΄λ° μ νμ νμ§ μμλ λͺ©ν λ¬μ±ν¨.
for (let n = 0; n <= N; n += 1) {
dp[n][0] = true;
}
πΈοΈπ‘ μν μ μ΄ λ°©μ μ
νμ¬ μ νμ κ²°μ ν΄μΌνλ nums[n-1]
νλλ§μΌλ‘ limit λ¬΄κ² w
λ³΄λ€ ν¬λ€λ©΄ μ ν κ²°μ μ ν μ μμΌλ―λ‘ λ°λ‘ μ΄μ κ²°κ³Όμ λμΌν¨.
if (nums[n - 1] > w) {
dp[n][w] = dp[n - 1][w];
}
nums[c-1]
μ νμ νλ κ²½μ°μλ
- μ ννμ§ μκ³ μ΄μ μ μ΄λ―Έ μ±κ³΅ν κ²½μ°
dp[n-1][w]
nums[n-1]
μ λ£μ κ²½μ°,nums[n-1]
μ λ£μμΌλ―λ‘ μ΄ λ¬΄κ²λ₯Ό λΊΈ μ΄μ κ²°κ³Όμ λ°λΌμ κ²°κ³Όκ° κ²°μ λ¨.dp[n-1][w - nums[n-1]]
} else {
dp[n][w] = dp[n-1][w] || dp[n-1][w - nums[n-1]];
}
π₯β¬οΈπΈοΈ My Solution
/**
* @param {number[]} nums
* @return {boolean}
*/
var canPartition = function (nums) {
const total = nums.reduce((a, b) => a + b, 0);
if (total % 2 === 1) return false;
const W = total / 2;
const N = nums.length;
const dp = Array(N + 1)
.fill(null)
.map((_) => Array(W + 1).fill(false));
for (let n = 0; n <= N; n += 1) {
dp[n][0] = true;
}
for (let n = 1; n <= N; n += 1) {
for (let w = 1; w <= W; w += 1) {
if (nums[n - 1] > w) {
dp[n][w] = dp[n - 1][w];
} else {
dp[n][w] = dp[n - 1][w] || dp[n - 1][w - nums[n - 1]];
}
}
}
return dp[N][W];
};