|
| 1 | +package com.fishercoder.solutions.thirdthousand; |
| 2 | + |
| 3 | +import com.fishercoder.common.classes.TreeNode; |
| 4 | + |
| 5 | +import java.util.ArrayList; |
| 6 | +import java.util.HashMap; |
| 7 | +import java.util.List; |
| 8 | +import java.util.Map; |
| 9 | + |
| 10 | +public class _2049 { |
| 11 | + public static class Solution1 { |
| 12 | + /** |
| 13 | + * My completely original solution. |
| 14 | + * Practice makes perfect! |
| 15 | + */ |
| 16 | + public int countHighestScoreNodes(int[] parents) { |
| 17 | + Map<Integer, TreeNode> valToNodeMap = new HashMap<>(); |
| 18 | + TreeNode root = buildBinaryTree(parents, valToNodeMap); |
| 19 | + |
| 20 | + //it'll be handy if we can cache the number of children each node has as we'll do this many times, so we can quickly calculate the score for each node |
| 21 | + //key is the node since each node's value is unique, value if the number of children this node has |
| 22 | + Map<Integer, Long> nodeCountMap = new HashMap<>(); |
| 23 | + //naturally we should use post-order traversal since we need to count the children for each child first, then we can roll up to add one to get the number of children for the root node |
| 24 | + long allNodeCount = postOrder(root, nodeCountMap); |
| 25 | + nodeCountMap.put(root.val, allNodeCount); |
| 26 | + |
| 27 | + //now calculate the score of each node |
| 28 | + List<Long> scoreList = new ArrayList<>(); |
| 29 | + long highestScore = 0; |
| 30 | + for (int i = 0; i < parents.length; i++) { |
| 31 | + long score = computeScore(i, nodeCountMap, valToNodeMap); |
| 32 | + highestScore = Math.max(score, highestScore); |
| 33 | + scoreList.add(score); |
| 34 | + } |
| 35 | + int count = 0; |
| 36 | + for (long score : scoreList) { |
| 37 | + if (score == highestScore) { |
| 38 | + count++; |
| 39 | + } |
| 40 | + } |
| 41 | + return count; |
| 42 | + } |
| 43 | + |
| 44 | + private Long computeScore(int nodeVal, Map<Integer, Long> nodeCountMap, Map<Integer, TreeNode> nodeValueMap) { |
| 45 | + TreeNode node = nodeValueMap.get(nodeVal); |
| 46 | + Long leftSubtree = 1L; |
| 47 | + Long rightSubtree = 1L; |
| 48 | + Long parentSubtree = 1L; |
| 49 | + if (node.left != null) { |
| 50 | + if (nodeCountMap.get(node.left.val) > 0) { |
| 51 | + leftSubtree = nodeCountMap.get(node.left.val); |
| 52 | + } |
| 53 | + } |
| 54 | + if (node.right != null) { |
| 55 | + if (nodeCountMap.get(node.right.val) > 0) { |
| 56 | + rightSubtree = nodeCountMap.get(node.right.val); |
| 57 | + } |
| 58 | + } |
| 59 | + if (nodeVal != 0) { |
| 60 | + long diff = nodeCountMap.get(0) - nodeCountMap.get(nodeVal); |
| 61 | + if (diff > 0) { |
| 62 | + parentSubtree = diff; |
| 63 | + } |
| 64 | + } |
| 65 | + return leftSubtree * rightSubtree * parentSubtree; |
| 66 | + } |
| 67 | + |
| 68 | + private long postOrder(TreeNode root, Map<Integer, Long> map) { |
| 69 | + if (root == null) { |
| 70 | + return 0; |
| 71 | + } |
| 72 | + long leftCount = postOrder(root.left, map); |
| 73 | + long rightCount = postOrder(root.right, map); |
| 74 | + long sum = leftCount + rightCount + 1; |
| 75 | + map.put(root.val, sum); |
| 76 | + return sum; |
| 77 | + } |
| 78 | + |
| 79 | + private TreeNode buildBinaryTree(int[] parents, Map<Integer, TreeNode> map) { |
| 80 | + map.put(0, new TreeNode(0)); |
| 81 | + for (int i = 1; i < parents.length; i++) { |
| 82 | + TreeNode childNode = map.getOrDefault(i, new TreeNode(i)); |
| 83 | + TreeNode parentNode = map.getOrDefault(parents[i], new TreeNode(parents[i])); |
| 84 | + if (parentNode.left == null) { |
| 85 | + parentNode.left = childNode; |
| 86 | + } else { |
| 87 | + parentNode.right = childNode; |
| 88 | + } |
| 89 | + map.put(parents[i], parentNode); |
| 90 | + map.put(i, childNode); |
| 91 | + } |
| 92 | + return map.get(0); |
| 93 | + } |
| 94 | + } |
| 95 | +} |
0 commit comments