Amazon sells books, every book has books which are strongly associated with it. Given ListA and ListB,indicates that ListA [i]
is associated with ListB [i]
which represents the book and associated books. Output the largest set associated with each other(output in any sort). You can assume that there is only one of the largest set.
Example
Example 1:
Input: ListA = ["abc","abc","abc"], ListB = ["bcd","acd","def"]
Output: ["abc","acd","bcd","def"]
Explanation:
abc is associated with bcd, acd, dfe, so the largest set is the set of all books
Example 2:
Input: ListA = ["a","b","d","e","f"], ListB = ["b","c","e","g","g"]
Output: ["d","e","f","g"]
Explanation:
The current set are [a, b, c] and [d, e, g, f], then the largest set is [d, e, g, f]
Notice
- The number of books does not exceed
5000
.
思路:以书为node,建立一个<string,Integer> mapping, 注意size是2*n, 用不同的index代表不同的书,如果hashmap里面有了,就不用加了,是同一本书;union完之后,扫描一遍求出最大的size和最大的index,然后根据index来收集书名;注意去重,因为我是扫描了一遍书名,书名就有重复的,必须去重复;
public class Solution {
/**
* @param ListA: The relation between ListB's books
* @param ListB: The relation between ListA's books
* @return: The answer
*/
private class UnionFind {
private int[] father;
private int[] count;
public UnionFind(int n) {
this.father = new int[n + 1];
this.count = new int[n + 1];
for(int i = 0; i <= n; i++) {
father[i] = i;
count[i] = 1;
}
}
public int find(int x) {
int j = x;
while(father[j] != j) {
j = father[j];
}
// path compression;
while(x != j) {
int fx = father[x];
father[x] = j;
x = fx;
}
return j;
}
public void union(int a, int b) {
int root_a = find(a);
int root_b = find(b);
if(root_a != root_b) {
father[root_a] = root_b;
count[root_b] += count[root_a];
}
}
}
public List<String> maximumAssociationSet(String[] ListA, String[] ListB) {
HashMap<String, Integer> bookmap = new HashMap<>();
int index = 0;
for(int i = 0; i < ListA.length; i++) {
String book_a = ListA[i];
if(!bookmap.containsKey(book_a)) {
bookmap.put(book_a, index++);
}
String book_b = ListB[i];
if(!bookmap.containsKey(book_b)) {
bookmap.put(book_b, index++);
}
}
UnionFind uf = new UnionFind(index);
int maxcount = 0;
int maxroot = -1;
for(int i = 0; i < ListA.length; i++) {
int a = bookmap.get(ListA[i]);
int b = bookmap.get(ListB[i]);
uf.union(a, b);
int root = uf.find(b);
if(uf.count[root] > maxcount) {
maxcount = uf.count[root];
maxroot = root;
}
}
List<String> res = new ArrayList<>();
for(String key: bookmap.keySet()) {
if(uf.find(bookmap.get(key)) == maxroot) {
res.add(key);
}
}
return res;
}
}