/**
* This problem was asked by Facebook.
Given a multiset of integers, return whether it can be partitioned into two subsets whose sums are the same.
For example, given the multiset {15, 5, 20, 10, 35, 15, 10}, it would return true,
since we can split it up into {15, 5, 10, 15, 10} and {20, 35}, which both add up to 55.
Given the multiset {15, 5, 20, 10, 35}, it would return false,
since we can't split it up into two subsets that add up to the same sum.
* */
class Problem_647 {
/*
* solution: DP, Top-Down, Memorization;
* Time complexity:O(m*n), m is the total different number we have, n is the size of multiset,
* Space complexity:O(n)
* */
fun canPartitioned(multiset: IntArray): Boolean {
val total = multiset.sum()
val map = HashMap<String, Boolean>()
return dfs(0,0, total, multiset, map)
}
private fun dfs(index: Int, sum: Int, total: Int, multiset: IntArray, map: HashMap<String, Boolean>): Boolean {
//set the key for map to save sub problem result
val key = "$index-$sum"
if (map.containsKey(key)) {
map.get(key)!!
}
//the sum of current part
if (sum * 2 == total) {
return true
}
if (sum > total / 2 || index > multiset.size) {
return false
}
//check this two situation: choose or not choose the number
val result = dfs(index + 1, sum, total, multiset, map) ||
dfs(index + 1, sum + multiset[index], total, multiset, map)
map.put(key, result)
return result
}
}