forked from neetcode-gh/leetcode
-
Notifications
You must be signed in to change notification settings - Fork 0
/
0416-partition-equal-subset-sum.go
102 lines (88 loc) · 2.15 KB
/
0416-partition-equal-subset-sum.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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
}
}