seungriyou / algorithm-study

알고리즘 & SQL 문제 풀이 기록
0 stars 0 forks source link

[LC] 416. Partition Equal Subset Sum #71

Open seungriyou opened 4 months ago

seungriyou commented 4 months ago

https://leetcode.com/problems/partition-equal-subset-sum/

Approach

0/1 knapsack 문제이다. 단, knapsack의 capacity 내에서 담을 수 있는 물건의 최대 가치를 구하는 것이 아닌, capacity와 동일한 값의 total sum을 달성할 수 있는지 여부를 구해야 한다.

이때, knapsack의 capacity는 주어진 nums의 총합의 절반이다.

만약 nums의 총합이 홀수라면 절반으로 나누어떨어지지 않으므로 빠르게 False를 리턴하자!


Idea 1: 2D DP


Idea 2: 1D DP (Space Optimized)

2D DP에서 이전 row(dp[i - 1])의 값(dp[i - 1][j] 혹은 dp[i - 1][j - nums[i - 1]])만 필요했으므로, 1D DP로 space-optimize가 가능하다.

단, dp[i - 1][j] 혹은 [j - nums[i - 1]]와 같이 이전 인덱스를 확인해야하므로, 오른쪽 -> 왼쪽 순으로 순회해야 한다.

또한, j를 순회할 때, dp 테이블을 그대로 재사용하기 때문에 현재 보고 있는 물건의 무게 num 이상인 값까지만 순회해도 되므로 time 측면에서도 약간 optimize가 되지 않을까 싶다!

target = total // 2

# dp[j] = nums의 i번째 원소까지 봤을 때, 그 합이 j인 조합이 존재하는지 여부
dp = [False] * (target + 1)
dp[0] = True

for num in nums:                          # -- 값 (배낭에 넣을 물건)
    for j in range(target, num - 1, -1):  # -- 합 (배낭의 임시 용량): 현재 넣으려는 물건 무게의 이상인 값만 보면 된다!
        dp[j] = dp[j] or dp[j - num]

return dp[target]


Idea 3: 다른 풀이 방법

ref: sol1, sol2

bit mask, DFS 등 다양한 방법으로도 풀 수 있는 듯.

이건 나중에 복습할 때 알아보자..


🔍 Knapsack Problem

0/1 knapsack만 조금 풀어봤었는데 다른 유형들도 풀어봐야겠다...

0/1 Knapsack vs. Fractional Knapsack

구분 특징 풀이 방법
0/1 knapsack item을 쪼갤 수 X dynamic programming
fractional knapsack item을 쪼갤 수 O greedy

Bounded vs. Unbounded

구분 특징
bounded item 당 수량이 정해져 있음
unbounded item 당 수량이 무한 개

References


Complexity

seungriyou commented 4 months ago

https://leetcode.com/discuss/study-guide/1200320/Thief-with-a-knapsack-a-series-of-crimes.

0/1 Knapsack 유사 문제도 풀어보자. 2D -> 1D로 optimize 가능하다면 줄이는 연습까지!