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
| func accountsMerge(accounts [][]string) [][]string { n := len(accounts) unionFind := newUnionFind(n) mailGroup := make(map[string]int) for i, account := range accounts { for _, mail := range account[1:] { if groupIndex, ok := mailGroup[mail]; ok { unionFind.Union(groupIndex, i) } else { mailGroup[mail] = i } } } groupMail := make(map[int]map[string]bool) visit := make([]bool, n) for i, account := range accounts { if visit[i] { continue } visit[i] = true root := unionFind.Find(i) if len(groupMail[root]) == 0 { groupMail[root] = make(map[string]bool) } for _, mail := range account[1:] { groupMail[root][mail] = true } } ans := make([][]string, 0, len(groupMail)) for i, mails := range groupMail { elements := make([]string, 0, len(mails)+1) elements = append(elements, accounts[i][0]) for mail := range mails { elements = append(elements, mail) } sort.Strings(elements[1:]) ans = append(ans, elements) } return ans }
type UnionFind struct { parent []int }
func newUnionFind(n int) *UnionFind { parent := make([]int, n) for i := 0; i < n; i++ { parent[i] = i } return &UnionFind{ parent, } }
func (unionFind *UnionFind) Find(i int) int { if unionFind.parent[i] != i { unionFind.parent[i] = unionFind.Find(unionFind.parent[i]) } return unionFind.parent[i] }
func (unionFind *UnionFind) Union(i, j int) bool { rootI := unionFind.Find(i) rootJ := unionFind.Find(j) if rootI == rootJ { return false } unionFind.parent[rootI] = rootJ return true }
|