Buttercola: Zenefits: Validate Graph Binary Tree
Determine if a directed graph is a binary tree. If yes, print out the tree in string format.
Input: (A,B) (A,C) (B,G) (C,H) (E,F) (B,D) (C,E)
Output: (A(B(D)(G))(C(E(F))(H))))
ie.. (parent(child)(child))
If not, print out the error code Error code Type of error
E1 More than 2 children
E2 Duplicate edges -- (A,B) (A,B)
E3 Cycle present
E4 Mulitple roots
E5 Another other error
http://yuanhsh.iteye.com/blog/2207890
Determine if a directed graph is a binary tree. If yes, print out the tree in string format.
Input: (A,B) (A,C) (B,G) (C,H) (E,F) (B,D) (C,E)
Output: (A(B(D)(G))(C(E(F))(H))))
ie.. (parent(child)(child))
If not, print out the error code Error code Type of error
E1 More than 2 children
E2 Duplicate edges -- (A,B) (A,B)
E3 Cycle present
E4 Mulitple roots
E5 Another other error
public String graphValidBinaryTree(char[][] edges) { if (edges == null || edges.length == 0) { return "E5"; } // Check inDegree for each node Map<Character, Integer> inDegree = new HashMap<>(); for (char[] edge : edges) { if (inDegree.containsKey(edge[1])) { int degree = inDegree.get(edge[1]); inDegree.put(edge[1], degree + 1); } else { inDegree.put(edge[1], 1); } if (!inDegree.containsKey(edge[0])) { inDegree.put(edge[0], 0); } } // For a valid binary tree, there is one and only one node with inDegree 0, and all the other nodes // has inDegree 1 char root = '\0'; int count = 0; for (char vertexId : inDegree.keySet()) { if (inDegree.get(vertexId) == 0) { root = vertexId; count++; } if (count > 1) { return "E4"; } if (inDegree.get(vertexId) > 1) { return "E4"; } } // No root if (count == 0) { return "E3"; } // Step 2: transform the edge list to adjList Map<Character, Set<Character>> adjList = new HashMap<>(); for (char[] edge : edges) { if (adjList.containsKey(edge[0])) { Set<Character> neighbors = adjList.get(edge[0]); // Duplicate edges if (neighbors.contains(edge[1])) { return "E2"; } else { neighbors.add(edge[1]); } // More than 2 children if (neighbors.size() > 2) { return "E1"; } } else { Set<Character> neighbors = new HashSet<>(); neighbors.add(edge[1]); adjList.put(edge[0], neighbors); } } // Step 3: do a topological sort, if not exist, return E3, cycle presents // Note: Couldn't use a boolean[] visited, because vertexId is char // Have to use a set Set<Character> visited = new HashSet<>(); boolean ans = toplogicalSort(root, visited, adjList); if (!ans) { return "E3"; } // Step 4: there must be valid binary tree exists, output the results. String result = treeToString(root, adjList); return result; } private boolean toplogicalSort(char vertex, Set<Character> visited, Map<Character, Set<Character>> adjList) { if (visited.contains(vertex)) { return false; } visited.add(vertex); Set<Character> neighbors = adjList.get(vertex); if (neighbors != null) { for (char neighbor : neighbors) { if (!toplogicalSort(neighbor, visited, adjList)) { return false; } } } visited.remove(vertex); return true; } private String treeToString(char root, Map<Character, Set<Character>> adjList) { Set<Character> neighbors = adjList.get(root); if (neighbors == null || neighbors.size() == 0) { return "(" + root + ")"; } StringBuffer result = new StringBuffer(); result.append("(" + root); for (char neighbor : neighbors) { result.append(treeToString(neighbor, adjList)); } result.append(")"); return result.toString(); } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int numEdges = sc.nextInt(); char[][] edges = new char[numEdges][2]; for (int i = 0; i < numEdges; i++) { String edge = sc.next(); edges[i][0] = edge.charAt(1); edges[i][1] = edge.charAt(3); } Solution solution = new Solution(); String result = solution.graphValidBinaryTree(edges); System.out.println(result); sc.close(); }- public class GraphEdgeTree {
- public static class Edge {
- char from, to;
- public Edge(String exp) {
- String[] nodes = exp.replaceAll("[\\(\\)\\s]", "").split(",");
- from = nodes[0].charAt(0);
- to = nodes[1].charAt(0);
- }
- }
- private Map<Character, Character> map = new HashMap<>();
- private Map<Character, Set<Character>> childMap = new HashMap<>();
- private List<Edge> edges = new ArrayList<>();
- public GraphEdgeTree(String exp) {
- String[] arr = exp.split("\\s");
- for(String str:arr) {
- Edge edge = new Edge(str);
- edges.add(edge);
- map.put(edge.from, edge.from);
- map.put(edge.to, edge.to);
- Set<Character> children = childMap.get(edge.from);
- if(children == null) {
- children = new HashSet<Character>();
- }
- children.add(edge.to);
- childMap.put(edge.from, children);
- }
- }
- public Character find(char x) {
- Character parent = map.get(x);
- if(parent == null || parent == x) {
- return parent;
- }
- return find(parent);
- }
- public void union(char x, char y) {
- Character xp = find(x);
- Character yp = find(y);
- map.put(xp, yp);
- }
- public boolean isEdgeExisted(Edge edge) {
- Character p = map.get(edge.to);
- return p != null && p == edge.from;
- }
- public String buildTree() {
- for(Character key:childMap.keySet()) {
- Set<Character> set = childMap.get(key);
- if(set != null && set.size()>2) {
- return "E1";
- }
- }
- for(Edge edge:edges) {
- if(isEdgeExisted(edge)) {
- return "E2";
- }
- char xp = find(edge.from);
- char yp = find(edge.to);
- if(xp == yp) {
- return "E3";
- }
- union(edge.to, edge.from);
- }
- if(rootNum() > 1) {
- return "E4";
- }
- return null;
- }
- private int rootNum() {
- int cnt = 0;
- for(char key:map.keySet()) {
- if(find(key) == key) {
- cnt++;
- }
- }
- return cnt;
- }
- public String treeString(char root) {
- Set<Character> children = childMap.get(root);
- if(children == null || children.size() == 0) {
- return "("+root+")";
- }
- StringBuilder result = new StringBuilder("("+root);
- for(char child:children) {
- result.append(",").append(treeString(child));
- }
- result.append(")");
- return result.toString();
- }
- public char getRoot() {
- return find(edges.get(0).from);
- }
- public static void main(String[] args) {
- String input = "(A,B) (A,C) (B,G) (C,H) (E,F) (B,D) (C,E)";
- GraphEdgeTree gt = new GraphEdgeTree(input);
- String error = gt.buildTree();
- if(error != null) {
- System.out.println(error);
- } else {
- String result = gt.treeString(gt.getRoot());
- System.out.println(result);
- }
- }
- }
- class TreeNode{
- char value;
- TreeNode left;
- TreeNode right;
- TreeNode(char inp){
- this.value = inp;
- }
- }
- public String sExp(char[][] pair){. visit 1point3acres.com for more.
- // build an adj matrix row is the parent node, col is the child node
- int len = pair.length;
- if (len == 0) return "";
- int[][] adjMat = new int[26][26];
- int[] inNode = new int[26]; // count the incoming edges of each node
- int[] children = new int[26]; // count the number of children of each node
- Map<Character, TreeNode> nodes = new HashMap();
- TreeNode parent, child;
- UnionFind myUnion = new UnionFind(26);
- // build binary tree based on pair
- for (int i = 0; i < len; i++){. more info on 1point3acres.com
- int row = pair[i][0] - 'A';
- int col = pair[i][1] - 'A';. from: 1point3acres.com/bbs
- if (children[row] == 2 && adjMat[row][col] != 1){
- // more than 2 children but not the same edge. 1point 3acres 璁哄潧
- return "E1";
- }else if (adjMat[row][col] == 1){
- // duplicated edges
- return "E2";
- } else if (myUnion.connected(row, col)){. 涓€浜�-涓夊垎-鍦帮紝鐙鍙戝竷
- // if new link connect two that are already in same union there is loop
- return "E3";
- }
- adjMat[row][col] = 1;
- children[row]++;
- inNode[col]++;
- myUnion.connect(row, col);
- connectNodes(pair, nodes, i);
- }
- // check multiple roots. 鍥磋鎴戜滑@1point 3 acres
- int rNum = 0;
- TreeNode root = null;
- for (char x : nodes.keySet()){
- if (inNode[x - 'A'] == 0){
- rNum++;
- if (rNum > 1) return "E4";
- root = nodes.get(x);
- }
- }
- if (root == null) return "E5";
- // convert it to s-expression
- return toSExpression(root);
- }
- // convert it to s-expression. 1point3acres.com/bbs
- String toSExpression(TreeNode root){.鐣欏璁哄潧-涓€浜�-涓夊垎鍦�
- if (root == null) return "";
- return "(" + root.value + toSExpression(root.left) + toSExpression(root.right) + ")";
- }
- // connect parent and child node
- private void connectNodes(char[][] pair, Map<Character, TreeNode> nodes,
- int i) {.1point3acres缃�
- TreeNode parent;
- TreeNode child;
- if (nodes.containsKey(pair[i][0])) parent = nodes.get(pair[i][0]);
- else{.1point3acres缃�
- parent = new TreeNode(pair[i][0]);
- nodes.put(pair[i][0], parent);
- }
- if (nodes.containsKey(pair[i][1])) child = nodes.get(pair[i][1]);. 1point 3acres 璁哄潧
- else{
- child = new TreeNode(pair[i][1]);
- nodes.put(pair[i][1], child);
- }
- if (parent.left == null) parent.left = child;
- else {
- if (parent.left.value < pair[i][1]){
- parent.right = child;
- } else {
- parent.right = parent.left;. 1point 3acres 璁哄潧
- parent.left = child;
- }
- }
- }