K sum subset
This problem was asked by Google.
Given a list of integers S and a target number k, write a function that returns a subset of S that adds up to k. If such a subset cannot be made, then return null.
Integers can appear more than once in the list. You may assume all numbers in the list are positive.
For example, given S = [12, 1, 61, 5, 9, 2]
and k = 24, return [12, 9, 2, 1]
since it sums up to 24.
My Solution(Python):
# Recursive solution (Inefficient)
def kSumSubsetPresent(S: list, k: int) -> bool:
if k==0:
return True
if len(S)==0 and k != 0:
return False
if S[-1]>k:
return kSumSubsetPresent(S[:-1], k)
return kSumSubsetPresent(S[:-1], k) or kSumSubsetPresent(S[:-1], k-S[-1])
def findkSumSubset(S: list, k: int, A = []) -> list:
if k==0 and len(S)==0:
return A
if k!=0 and len(S)==0:
return "No subset adds to desired target"
if kSumSubsetPresent(S[:-1], k-S[-1]):
A.append(S[-1])
k=k-S[-1]
S.pop()
return findkSumSubset(S, k, A)
else:
return findkSumSubset(S[:-1], k, A)
S = [12, 1, 61, 5, 9, 2]
k = 24
print(findkSumSubset(S, k, A=[]))
S = [12, 1, 61, 5, 9, 20]
k = 24
print(findkSumSubset(S, k, A=[]))
# DP Solution (Efficient)
def findkSumSubset(S: list, k: int) -> list:
"""
DP Solution - First create a 2-D matrix A of N rows and k+1 columns
A[i][j] = True if sum of j is possible with the first i+1 elements
and False otherwise.
Then backtrack.
"""
S = sorted(S)
N=len(S)
A = [[None for _ in range(k+1)] for _ in range(len(S))]
for j in range(k+1):
A[0][j] = S[0]==j
for i in range(len(S)):
A[i][0] = True
for i in range(1, N):
for j in range(1, k+1):
if j<S[i]:
A[i][j] = A[i-1][j]
else:
A[i][j] = A[i-1][j] or A[i-1][j-S[i]]
# for line in A:
# print(line)
if not A[-1][-1]:
return "No subset adds to desired target"
ans = []
i=N-1
j=k
while j!=0:
while i>=0 and A[i][j]:
i-=1
i+=1
ans.append(S[i])
j-=S[i]
return ans
S = [12, 1, 61, 5, 9, 2]
k = 24
print(findkSumSubset(S, k))
S = [12, 1, 61, 5, 9, 20]
k = 24
print(findkSumSubset(S, k))