模板题目:Union Find( 721 Accounts Merge)

Given a list accounts, each element accounts[i] is a list of strings, where the first element accounts[i][0] is a name, and the rest of the elements are emails representing emails of the account.

Now, we would like to merge these accounts. Two accounts definitely belong to the same person if there is some email that is common to both accounts. Note that even if two accounts have the same name, they may belong to different people as people could have the same name. A person can have any number of accounts initially, but all of their accounts definitely have the same name.

After merging the accounts, return the accounts in the following format: the first element of each account is the name, and the rest of the elements are emails in sorted order. The accounts themselves can be returned in any order.

虽然题干特别长 但是易于理解:
简而言之 就是姓名相同的不一定是一个人 但是email address相同的 一定是一个人 就把这两个array给合并起来,就这样返回最后合并的结果。
就相当于把不同的array看作是节点 这里盎格节点是不是属于同一个图 就看里面有没有一样的 一旦有 就属于同一个图。我们要check所有的节点对。这就是典型的union find题目。当然union find有属于自己的独特的implement方法 非常适合模板。

下面是union find 的模板
先union组件图团,然后用到的时候再find.

//首先 对uf进行初始化 每个的parent都设为自己
for (int i = 0; i < uf.length; i++) {
    uf[i] = i;
}
//然后我们把题目给的输入转换成一个一个图(就是union起来)加黑色输入是一个List<List<Integer>>
for (List<Integer> pair : pairs) {
    union(pair.get(0), pair.get(1));
}
//当我们之后想要判断哪些节点属于同一个图 就重新遍历所有的可能节点 利用find()函数找出其root,然后同一个root都聚集在一个List中 这个可以用Hashmap去存,就是说存一个HashMap<Integer, List<Integer>>

//union函数
private void union(int[] uf, int a, int b) { //这两个节点一定是属于同一个图的 
        int aParent = find(a);
        int bParent = find(b);
        if (aParent < bParent) { //往前找root 往前靠 如果a的parent 小一些 就把b的parent重新设为aParent(之前parent[bParent] = bParent)
            uf[bParent] = aParent;
        } else {
            uf[aParent] = bParent;
        }
    }
//find函数
private int find(int[] uf, int x) {
    if (x != uf[x]) {
        uf[x] = find(uf, uf[x]);
    }
    return uf[x];
}
posted @ 2020-12-18 00:50  EvanMeetTheWorld  阅读(33)  评论(0)    收藏  举报