721. 账户合并(中等)twiceFor

1,问题描述

721. 账户合并

难度:中等

给定一个列表 accounts,每个元素 accounts[i] 是一个字符串列表,其中第一个元素 accounts[i][0]名称 (name),其余元素是 emails 表示该账户的邮箱地址。

现在,我们想合并这些账户。如果两个账户都有一些共同的邮箱地址,则两个账户必定属于同一个人。请注意,即使两个账户具有相同的名称,它们也可能属于不同的人,因为人们可能具有相同的名称。一个人最初可以拥有任意数量的账户,但其所有账户都具有相同的名称。

合并账户后,按以下格式返回账户:每个账户的第一个元素是名称,其余元素是 按字符 ASCII 顺序排列 的邮箱地址。账户本身可以以 任意顺序 返回。

示例 1:

1
2
3
4
5
6
7
输入:accounts = [["John", "johnsmith@mail.com", "john00@mail.com"], ["John", "johnnybravo@mail.com"], ["John", "johnsmith@mail.com", "john_newyork@mail.com"], ["Mary", "mary@mail.com"]]
输出:[["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ["John", "johnnybravo@mail.com"], ["Mary", "mary@mail.com"]]
解释:
第一个和第三个 John 是同一个人,因为他们有共同的邮箱地址 "johnsmith@mail.com"。
第二个 John 和 Mary 是不同的人,因为他们的邮箱地址没有被其他帐户使用。
可以以任何顺序返回这些列表,例如答案 [['Mary','mary@mail.com'],['John','johnnybravo@mail.com'],
['John','john00@mail.com','john_newyork@mail.com','johnsmith@mail.com']] 也是正确的。

示例 2:

1
2
输入:accounts = [["Gabe","Gabe0@m.co","Gabe3@m.co","Gabe1@m.co"],["Kevin","Kevin3@m.co","Kevin5@m.co","Kevin0@m.co"],["Ethan","Ethan5@m.co","Ethan4@m.co","Ethan0@m.co"],["Hanzo","Hanzo3@m.co","Hanzo1@m.co","Hanzo0@m.co"],["Fern","Fern5@m.co","Fern1@m.co","Fern0@m.co"]]
输出:[["Ethan","Ethan0@m.co","Ethan4@m.co","Ethan5@m.co"],["Gabe","Gabe0@m.co","Gabe1@m.co","Gabe3@m.co"],["Hanzo","Hanzo0@m.co","Hanzo1@m.co","Hanzo3@m.co"],["Kevin","Kevin0@m.co","Kevin3@m.co","Kevin5@m.co"],["Fern","Fern0@m.co","Fern1@m.co","Fern5@m.co"]]

示例3:

1

提示:

  • 1 <= accounts.length <= 1000
  • 2 <= accounts[i].length <= 10
  • 1 <= accounts[i][j].length <= 30
  • accounts[i][0] 由英文字母组成
  • accounts[i][j] (for j > 0) 是有效的邮箱地址

2,初步思考

​ 整理、去重、合并

整理:我直接使用散列表处理(HashMap)

去重:HashSet处理

合并:删除历史

并查集的解决方法,我没来得及弄懂

3,代码处理

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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import java.util.*;

public class _721账户合并 {

// 解法2:并查集解决
public List<List<String>> accountsMerge_gov(List<List<String>> accounts) {
Map<String, Integer> emailToIndex = new HashMap<String, Integer>();
Map<String, String> emailToName = new HashMap<String, String>();
int emailsCount = 0;
for (List<String> account : accounts) {
String name = account.get(0);
int size = account.size();
for (int i = 1; i < size; i++) {
String email = account.get(i);
if (!emailToIndex.containsKey(email)) {
emailToIndex.put(email, emailsCount++);
emailToName.put(email, name);
}
}
}
UnionFind uf = new UnionFind(emailsCount);
for (List<String> account : accounts) {
String firstEmail = account.get(1);
int firstIndex = emailToIndex.get(firstEmail);
int size = account.size();
for (int i = 2; i < size; i++) {
String nextEmail = account.get(i);
int nextIndex = emailToIndex.get(nextEmail);
uf.union(firstIndex, nextIndex);
}
}
Map<Integer, List<String>> indexToEmails = new HashMap<Integer, List<String>>();
for (String email : emailToIndex.keySet()) {
int index = uf.find(emailToIndex.get(email));
List<String> account = indexToEmails.getOrDefault(index, new ArrayList<String>());
account.add(email);
indexToEmails.put(index, account);
}
List<List<String>> merged = new ArrayList<List<String>>();
for (List<String> emails : indexToEmails.values()) {
Collections.sort(emails);
String name = emailToName.get(emails.get(0));
List<String> account = new ArrayList<String>();
account.add(name);
account.addAll(emails);
merged.add(account);
}
return merged;
}


static class UnionFind {
int[] parent;

public UnionFind(int n) {
parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}

public void union(int index1, int index2) {
parent[find(index2)] = find(index1);
}

public int find(int index) {
if (parent[index] != index) {
parent[index] = find(parent[index]);
}
return parent[index];
}
}


// 解法1:利用hashMap缓存email和name的相互映射关系,去重
public List<List<String>> accountsMerge(List<List<String>> accounts) {
Map<String, Set<String>> mapAccount = new HashMap<>();// key:name value:emails
Map<String, String> mapEmail = new HashMap<>();// key:emial value:name

for (int i = 0; i < accounts.size(); i++) {
List<String> strings = accounts.get(i);
Set<String> temp = new HashSet<>();// 缓存之前历史的
Set<String> set = new HashSet<>(strings.subList(1, strings.size()));// 缓存当前的
String name = i + "-" + strings.getFirst();// 新建一个key
for (String email : set) {
if (mapEmail.containsKey(email)) {
String nameBefore = mapEmail.get(email);
if (mapAccount.containsKey(nameBefore)) {
temp.addAll(mapAccount.get(nameBefore));
mapAccount.remove(nameBefore);
}
}
mapEmail.put(email, name);
}

for (String email : temp) {
mapEmail.put(email, name);
}
temp.addAll(set);
mapAccount.put(name, temp);
}
List<List<String>> res = new ArrayList<>();
mapAccount.forEach((key, value) -> {
List<String> list = new ArrayList<>(value);
Collections.sort(list);
list.addFirst(key.split("-")[1]);
res.add(list);
});
return res;
}

public static void main(String[] args) {
_721账户合并 accountMerge = new _721账户合并();
List<List<String>> accounts = new ArrayList<>();
// accounts.add(new ArrayList<>(List.of("Alex", "Alex5@m.co", "Alex4@m.co", "Alex0@m.co")));
// accounts.add(new ArrayList<>(List.of("Ethan", "Ethan3@m.co", "Ethan3@m.co", "Ethan0@m.co")));
// accounts.add(new ArrayList<>(List.of("Kevin", "Kevin4@m.co", "Kevin2@m.co", "Kevin2@m.co")));
// accounts.add(new ArrayList<>(List.of("Gabe", "Gabe0@m.co", "Gabe3@m.co", "Gabe2@m.co")));
// accounts.add(new ArrayList<>(List.of("Gabe", "Gabe3@m.co", "Gabe4@m.co", "Gabe2@m.co")));

// accounts.add(new ArrayList<>(List.of("David", "David0@m.co", "David1@m.co")));
// accounts.add(new ArrayList<>(List.of("David", "David3@m.co", "David4@m.co")));
// accounts.add(new ArrayList<>(List.of("David", "David4@m.co", "David5@m.co")));
// accounts.add(new ArrayList<>(List.of("David", "David2@m.co", "David3@m.co")));
// accounts.add(new ArrayList<>(List.of("David", "David1@m.co", "David2@m.co")));

accounts.add(new ArrayList<>(List.of("Isa", "Isa6@m.co", "Isa0@m.co", "Isa1@m.co", "Isa6@m.co", "Isa1@m.co")));
accounts.add(new ArrayList<>(List.of("David", "David10@m.co", "David12@m.co", "David7@m.co", "David6@m.co", "David1@m.co")));
accounts.add(new ArrayList<>(List.of("Alex", "Alex1@m.co", "Alex7@m.co", "Alex6@m.co", "Alex11@m.co", "Alex2@m.co")));
accounts.add(new ArrayList<>(List.of("Hanzo", "Hanzo11@m.co", "Hanzo2@m.co", "Hanzo5@m.co", "Hanzo5@m.co", "Hanzo3@m.co")));
accounts.add(new ArrayList<>(List.of("Bob", "Bob12@m.co", "Bob1@m.co", "Bob12@m.co", "Bob7@m.co", "Bob5@m.co")));
accounts.add(new ArrayList<>(List.of("Isa", "Isa4@m.co", "Isa1@m.co", "Isa3@m.co", "Isa9@m.co", "Isa2@m.co")));
accounts.add(new ArrayList<>(List.of("Kevin", "Kevin0@m.co", "Kevin7@m.co", "Kevin12@m.co", "Kevin3@m.co", "Kevin5@m.co")));
accounts.add(new ArrayList<>(List.of("David", "David12@m.co", "David6@m.co", "David10@m.co", "David0@m.co", "David8@m.co")));
accounts.add(new ArrayList<>(List.of("Celine", "Celine0@m.co", "Celine8@m.co", "Celine10@m.co", "Celine2@m.co", "Celine12@m.co")));
accounts.add(new ArrayList<>(List.of("Kevin", "Kevin1@m.co", "Kevin8@m.co", "Kevin5@m.co", "Kevin9@m.co", "Kevin0@m.co")));
accounts.add(new ArrayList<>(List.of("Alex", "Alex3@m.co", "Alex8@m.co", "Alex1@m.co", "Alex12@m.co", "Alex12@m.co")));
accounts.add(new ArrayList<>(List.of("Kevin", "Kevin8@m.co", "Kevin12@m.co", "Kevin1@m.co", "Kevin10@m.co", "Kevin9@m.co")));

for (List<String> strings : accountMerge.accountsMerge(accounts)) {
System.out.println(strings);
}
}
}

参考链接:

https://leetcode.cn/problems/accounts-merge/submissions/607624298