DEV Community

Prashant Mishra
Prashant Mishra

Posted on

Remove Methods from project

Problem

TC: O(n*m) where n is the no. of nodes and m is the max no. of nodes/methods present in a component (directly and indirectly initialized by k (given) with no external invocation) that needs to be removed

class Solution {
    public List<Integer> remainingMethods(int n, int k, int[][] invocations) {
        List<Integer> result = new ArrayList<>();

        //Prepare two adjacency lists, 1 for finding all the methods invoked by k,
        // another for DFS traversal of the nodes
        List<List<Integer>> adj = new ArrayList<>();
        List<List<Integer>> adj2 = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            adj.add(new ArrayList<>());
            adj2.add(new ArrayList<>());
        }

        for (int i = 0; i < invocations.length; i++) {
            //Keep the adjacency directional only for finding all methods invoked by k
            // that will be considered as a component that needs to be removed in present in
            // the graph
            adj2.get(invocations[i][0]).add(invocations[i][1]);

            //For DFS traversal make the edges bi-directional in adjacency
            //This will help us to tackle the edge case
            /*
             * e.g n =3, k =0, [[2,0]] there is an edge from 2 to 0,
             * now, DFS will help us find all the components in the above graph
             * since k = 0, and 0 and other nodes that it invokes can only be removed if
             * they are not invoked externally by any other nodes but in the example
             * node 0 is involved by 2.
             * 
             * If we do DFS (with directed adjacency) on the graph we will get 3 components
             * 0,1,2 ( which should not be the case as there are only 2 components i.e (1),
             * (2,0))
             * This is happening because we choose directed adjacency and from 0 there
             * is no direct edge to any other node, So DFS traversal will assume it to be a
             * component ( which is wrong)
             * Hence while creating components we will make the adjacency list
             * bi-directional that way components created will be
             * (0,2) and (1)
             * and Since we will be using directed adjacency for finding all the
             * methods/nodes invoked by k. It will create a component of nodes (directly or
             * indirectly invoked by k only ) i.e 0 only
             */
            adj.get(invocations[i][0]).add(invocations[i][1]);
            adj.get(invocations[i][1]).add(invocations[i][0]);
        }
        // keep track of nodes that need to be removed if a component has only these
        // nodes
        int dc[] = new int[n];
        List<Integer> dcn = new ArrayList<>(); // dcn component that needs to be removed
        prepareDcDfs(k, dc, adj2, dcn);

        int visited[] = new int[n];
        for (int i = 0; i < n; i++) {
            if (visited[i] == 0 && dc[i] == 0) { // only traverse the nodes that are not visited and are not part of
                                                 // dcn, that needs to be removed to save time
                List<Integer> l = new ArrayList<>();// keep track of nodes in each component
                dfs(i, visited, adj, l);
                if (l.size() != dcn.size()) { // if the component l, is not equal to dcn, this is not the
                                              // component we want to remove
                    result.addAll(l);
                } else {// if found a component l, having the same size as dcn, check individual nodes
                        // to make sure that l has all the nodes present in dcn that needs to be removed
                    for (int node : l) {
                        if (!dcn.contains(node)) {// if not the same component then l should not be removed and shoud be
                                                  // part of final node list i.e result
                            result.addAll(l);
                            break;
                        }
                    }
                }
            }
        }
        return result;
    }

    // DFS to find nodes invoked by k directly or indirectly (using directed
    // adjacency)
    public void prepareDcDfs(int node, int dc[], List<List<Integer>> adj, List<Integer> dcn) {
        dc[node] = 1;
        dcn.add(node);
        for (int adjNode : adj.get(node)) {
            if (dc[adjNode] == 0)
                prepareDcDfs(adjNode, dc, adj, dcn);
        }
    }

    // dfs to find all components in the given graph using bi-directional adjacency
    public void dfs(int node, int visited[], List<List<Integer>> adj, List<Integer> list) {
        visited[node] = 1;
        list.add(node);
        for (int adjNode : adj.get(node)) {
            if (visited[adjNode] == 0) {
                dfs(adjNode, visited, adj, list);
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)