Skip to content

Commit

Permalink
Create 0416-partition-equal-subset-sum.go
Browse files Browse the repository at this point in the history
I also added a solution which works in reverse, by remembering the numbers that can not be solved for.
The algorithm runs in 5ms as opposed to 313ms for the implementation in the video. 

I believe that the reverse algorithm has a faster runtime because we never need to duplicate the set of unsolvable numbers.
  • Loading branch information
AP-Repositories authored Jan 5, 2023
1 parent 568d467 commit e369073
Showing 1 changed file with 102 additions and 0 deletions.
102 changes: 102 additions & 0 deletions go/0416-partition-equal-subset-sum.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
func canPartitionTabulation(nums []int) bool {
sum := sum(nums)
if sum % 2 != 0 {
return false
}

dp := make(map[int]bool)
dp[0] = true
target := sum / 2

for i := len(nums) - 1; i >= 0; i-- {
nextDP := make(map[int]bool)
for t, _ := range dp {
if (t + nums[i]) == target {
return true
}
nextDP[t + nums[i]] = true
nextDP[t] = true
}
dp = nextDP
}
return false
}

func sum(nums []int) int {
res := 0
for _, num := range nums {
res += num
}
return res
}



const NUM = 0
const FREQ = 1
type byNum [][]int
func (s byNum) Len() int {return len(s)}
func (s byNum) Swap(i, j int) {s[i], s[j] = s[j], s[i]}
func (s byNum) Less(i, j int) bool {return s[i][NUM] > s[j][NUM]}

func canPartitionMemoization(nums[] int) bool {
count := make(map[int]int)
sum := 0
for _, n := range nums {
count[n] += 1
sum += n
}

if sum % 2 != 0 {
return false
}

numsF := make([][]int, len(count))
idx := 0
for num, freq := range count {
numsF[idx] = []int{num, freq}
idx++
}
sort.Sort(byNum(numsF))
visited := make([]bool, sum/2 + 1)
visited[0] = true
return solveCanPartition(visited, numsF, sum/2)
}

func solveCanPartition(visited []bool, nums [][]int, target int) bool {
if visited[target] {
return target == 0
}
visited[target] = true

for index := predecessor(nums, target); index < len(nums); index++ {
nums[index][FREQ]--
if nums[index][FREQ] >= 0 && solveCanPartition(visited, nums, target - nums[index][NUM]) {
return true
}
nums[index][FREQ]++
}

return false
}

func predecessor(nums [][]int, target int) int {
l := 0
h := len(nums) - 1
for h - l > 1 {
m := (h + l)/2
if nums[m][NUM] > target {
l = m + 1
} else {
h = m
}
}

if nums[l][0] <= target {
return l
} else if nums[h][0] <= target {
return h
} else {
return math.MaxInt32
}
}

0 comments on commit e369073

Please sign in to comment.