[Java/Python 3] Union Find w/ brief explanation and analysis.
Perform union find during the traversal of the connections; deduct the number of components when merging any two components;\n2. If there are less than n - 1 co
1. Perform union find during the traversal of the `connections`; deduct the number of components when merging any two components;\n2. If there are less than n - 1 connections, no way to make the network connected; Otherwise need `number of components - 1` operations for the network to be fully connected.\n\n```java\n    private int[] root; // components roots.\n    private int count; // # of components. \n    public int makeConnected(int n, int[][] connections) {\n        count = n; // # of nodes.\n        root = IntStream.range(0, n).toArray(); // Initialization of the roots of the nodes to themselves.\n        for (int[] c : connections) { \n            union(c[0], c[1]); //  if the 2 connected nodes are NOT in the same component yet, merge their components. \n        } \n        return connections.length < n - 1 ? -1 : count - 1;\n    }\n    private int find(int x) {\n        while (x != root[x]) \n            x = root[x];\n        return x;\n    }\n    private void union(int x, int y) {\n        int rx = find(x), ry = find(y);\n        if (rx == ry) \n            return;\n        root[rx] = ry; \n        --count;\n    }\n```\n```python\n    def makeConnected(self, n: int, connections: List[List[int]]) -> int:\n        self.id, self.count = list(range(n)), n\n        \n        def union(x: int, y: int) -> None:\n            \n            def find(x: int) -> int:\n                while x != self.id[x]:\n                    x = self.id[x]\n                return x   \n\n            rx, ry = find(x), find(y)\n            if rx == ry:\n                return\n            self.id[rx] = ry\n            self.count -= 1\n        \n        for c1, c2 in connections:\n            union(c1, c2)\n        return -1 if len(connections) < n - 1 else self.count - 1\n```\n\n----\nWeighted Quick Union w/ Path Compression.\n```java\n    private int[] root, size; // components roots and sizes.\n    private int count; // # of components.\n    public int makeConnected(int n, int[][] connections) {\n        count = n; // # of nodes.\n        root = IntStream.range(0, n).toArray(); // Initialization of the roots of the nodes to themselves.\n        size = IntStream.range(0, n). map(i -> 1).toArray(); // Initialize the size of the component to 1 for each node.\n        for (int[] c : connections) {\n            union(c[0], c[1]); // merge the nodes if they are in same component.\n        }\n        return connections.length < n - 1 ? -1 : count - 1; \n    }\n    private int find(int x) {\n        while (x != root[x]) {\n            root[x] = root[root[x]]; // path compression.\n            x = root[x];\n        }\n        return x;\n    }\n    private void union(int x, int y) {\n        int rx = find(x), ry = find(y);\n        if (rx == ry) return;\n\t\t// merge to larger components.\n        if (size[rx] > size[ry]) { \n            size[rx] += size[ry]; \n            root[ry] = rx; \n        }else {\n            size[ry] += size[rx]; \n            root[rx] = ry;\n        } \n        --count;\n    }\n```\n```python\n    def makeConnected(self, n: int, connections: List[List[int]]) -> int:\n        self.id, self.size, self.count = list(range(n)), [1] * n, n\n        \n        def union(x: int, y: int) -> None:\n            \n            def find(x: int) -> int:\n                while x != self.id[x]:\n                    self.id[x] = self.id[self.id[x]]\n                    x = self.id[x]\n                return x   \n\n            rx, ry = find(x), find(y)\n            if rx == ry:\n                return\n            if self.size[rx] > self.size[ry]:\n                self.size[rx] += self.size[ry]\n                self.id[ry] = rx\n            else:\n                self.size[ry] += self.size[rx]\n                self.id[rx] = ry\n            self.count -= 1\n        \n        for c1, c2 in connections:\n            union(c1, c2)\n        return -1 if len(connections) < n - 1 else self.count - 1\n```\n**Analysis:**\n\nTime: O(n), space: O(n).
[]