-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathminimum_deletions_to_make_character_frequencies_unique.go
74 lines (64 loc) · 1.58 KB
/
minimum_deletions_to_make_character_frequencies_unique.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
package main
type DSU struct {
par []int
}
func NewDSU(n int) *DSU {
par := make([]int, n+1)
for i := 0; i <= n; i++ {
par[i] = i
}
return &DSU{par}
}
func (d *DSU) findPar(x int) int {
if x == d.par[x] {
return x
}
d.par[x] = d.findPar(d.par[x])
return d.par[x]
}
func (d *DSU) merge(u, v int) {
d.par[v] = u
}
func minDeletions(s string) int {
// Using DSU
// Think of this problem as a Job Sequencing Problem
// First, store the frequency of all characters
a := make([]int, 26)
n := len(s)
for i := 0; i < n; i++ {
a[int(s[i]-'a')]++
}
// Find the maximum among all the frequencies
maxi := 0
for _, it := range a {
if it > maxi {
maxi = it
}
}
// Make DSU of size - maximum
d := NewDSU(maxi)
cnt := 0 // cnt stores the answer
for i := 0; i < 26; i++ {
// Find the nearest available free slot for
// this frequency (corresponding to its frequency)
available := d.findPar(a[i])
// If an available free slot is greater
// than 0, then a free slot is available
if available > 0 {
// This slot is taken by this job 'i'
// so we need to update the greatest(nearest)
// free slot. Note that, in merge, we
// make the first parameter as the parent of
// the second parameter. So future queries
// for availableSlot will return the maximum(nearest)
// available slot in the set of
// "availableSlot - 1"
d.merge(d.findPar(available-1), available)
}
// We assign the nearest (greatest) frequency now
// (frequency-assign slot) will be the number of
// removed characters (answer)
cnt += (a[i] - available)
}
return cnt
}