Power Grid Maintenance

Medium
Watch on YouTube ↗

Solution

/*----- Mapping Array and Sorted Set(TreeSet) Approach */
class Solution {
    HashMap<Integer, List<Integer>> graph;
    int[] mapping;
    // mapping array + sorted set
    public int[] processQueries(int c, int[][] connections, int[][] queries) {
        graph = new HashMap<>();
        // graph in adjacency list format
        for (int i = 1; i <= c; i++) {
            graph.put(i, new ArrayList<>());
        }
        // 1 - [2]
        // 2 - [1,3]
        // 3 - [2,4]
        // 4 - [3,5]
        // 5 - [3]

        for (int[] connection : connections) {
            int src = connection[0];
            int dest = connection[1];
            graph.get(src).add(dest);
            graph.get(dest).add(src);
        }

        int curr = 1; // gridvalue / component 
        mapping = new int[c + 1];

        for (int i = 1; i <= c; i++) {
            if (mapping[i] == 0) {
                dfs(i, curr);
                curr++;
            }
        }   
        // [1,1,1,1,1]

        HashMap<Integer, TreeSet<Integer>> onlinegrid = new HashMap<>();
        // 1 --> [1,2,3,4,5]
        for (int i = 1; i <= c; i++) {
            int gridvalue = mapping[i];
            onlinegrid.putIfAbsent(gridvalue, new TreeSet<>());
            onlinegrid.get(gridvalue).add(i);
        }

        List<Integer> ans = new ArrayList<>();

        for (int[] query : queries) {
            int type = query[0];
            int node = query[1];

            int gridvalue = mapping[node];
            TreeSet<Integer> set = onlinegrid.get(gridvalue);

            if (type == 1) {
                if (set.contains(node)) {
                    ans.add(node);
                } else {
                    ans.add(set.isEmpty() ? -1 : set.first());
                }
            } else if (type == 2) {
                set.remove(node);
            }
        }

        return ans.stream().mapToInt(Integer::intValue).toArray();
    }

    void dfs(int node, int gridvalue) {
        if (mapping[node] != 0)
            return;
        mapping[node] = gridvalue;
        for (int nei : graph.get(node)) {
            if (mapping[nei] == 0) {
                dfs(nei, gridvalue);
            }
        }
    }
}

/*----- Union Find and Priority Queue Approach */
class Solution {
    // union find + priority queue
    int[] parent;
    public int find(int x) {
        if (parent[x] != x)
            parent[x] = find(parent[x]); 
        return parent[x];
    }

    public boolean union(int x, int y) {
        int px = find(x), py = find(y);
        if (px == py)
            return false;
        parent[py] = px;
        return true;
    }

    public int[] processQueries(int c, int[][] connections, int[][] queries) {
        parent = new int[c + 1];
        for (int i = 0; i <= c; i++)
            parent[i] = i;

        boolean[] online = new boolean[c + 1];
        Arrays.fill(online, true);

        for (int[] conn : connections)
            union(conn[0], conn[1]);

        Map<Integer, PriorityQueue<Integer>> componentHeap = new HashMap<>();
        for (int station = 1; station <= c; station++) {
            int root = find(station);
            componentHeap.putIfAbsent(root, new PriorityQueue<>());
            componentHeap.get(root).offer(station);
        }

        List<Integer> result = new ArrayList<>();

        for (int[] query : queries) {
            int type = query[0], node = query[1];

            if (type == 2) {
                online[node] = false;
            } else {
                if (online[node]) {
                    result.add(node);
                } else {
                    int root = find(node);
                    PriorityQueue<Integer> heap = componentHeap.get(root);

                    while (heap != null && !heap.isEmpty() && !online[heap.peek()]) {
                        heap.poll(); // lazy deletion
                    }

                    result.add(heap.isEmpty() ? -1 : heap.peek());
                }
            }
        }

        return result.stream().mapToInt(Integer::intValue).toArray();
    }
}