Maximum Association Set

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;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值