|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +# 2458. Height of Binary Tree After Subtree Removal Queries |
| 4 | +# https://leetcode.com/problems/height-of-binary-tree-after-subtree-removal-queries |
| 5 | +# Hard |
| 6 | + |
| 7 | +=begin |
| 8 | +You are given the root of a binary tree with n nodes. Each node is assigned a unique value from 1 to n. You are also given an array queries of size m. |
| 9 | +You have to perform m independent queries on the tree where in the ith query you do the following: |
| 10 | +* Remove the subtree rooted at the node with the value queries[i] from the tree. It is guaranteed that queries[i] will not be equal to the value of the root. |
| 11 | +Return an array answer of size m where answer[i] is the height of the tree after performing the ith query. |
| 12 | +
|
| 13 | +Note: |
| 14 | +* The queries are independent, so the tree returns to its initial state after each query. |
| 15 | +* The height of a tree is the number of edges in the longest simple path from the root to some node in the tree. |
| 16 | +
|
| 17 | +Example 1: |
| 18 | +Input: root = [1,3,4,2,null,6,5,null,null,null,null,null,7], queries = [4] |
| 19 | +Output: [2] |
| 20 | +Explanation: The diagram above shows the tree after removing the subtree rooted at node with value 4. |
| 21 | +The height of the tree is 2 (The path 1 -> 3 -> 2). |
| 22 | +
|
| 23 | +Example 2: |
| 24 | +Input: root = [5,8,9,2,1,3,7,4,6], queries = [3,2,4,8] |
| 25 | +Output: [3,2,3,2] |
| 26 | +Explanation: We have the following queries: |
| 27 | +- Removing the subtree rooted at node with value 3. The height of the tree becomes 3 (The path 5 -> 8 -> 2 -> 4). |
| 28 | +- Removing the subtree rooted at node with value 2. The height of the tree becomes 2 (The path 5 -> 8 -> 1). |
| 29 | +- Removing the subtree rooted at node with value 4. The height of the tree becomes 3 (The path 5 -> 8 -> 2 -> 6). |
| 30 | +- Removing the subtree rooted at node with value 8. The height of the tree becomes 2 (The path 5 -> 9 -> 3). |
| 31 | +
|
| 32 | +Constraints: |
| 33 | +* The number of nodes in the tree is n. |
| 34 | +* 2 <= n <= 105 |
| 35 | +* 1 <= Node.val <= n |
| 36 | +* All the values in the tree are unique. |
| 37 | +* m == queries.length |
| 38 | +* 1 <= m <= min(n, 104) |
| 39 | +* 1 <= queries[i] <= n |
| 40 | +* queries[i] != root.val |
| 41 | +=end |
| 42 | + |
| 43 | +# Definition for a binary tree node. |
| 44 | +# class TreeNode |
| 45 | +# attr_accessor :val, :left, :right |
| 46 | +# def initialize(val = 0, left = nil, right = nil) |
| 47 | +# @val = val |
| 48 | +# @left = left |
| 49 | +# @right = right |
| 50 | +# end |
| 51 | +# end |
| 52 | +# @param {TreeNode} root |
| 53 | +# @param {Integer[]} queries |
| 54 | +# @return {Integer[]} |
| 55 | +def tree_queries(root, queries) |
| 56 | + @heights = Array.new(50000, 0) |
| 57 | + @len = 0 |
| 58 | + @d = Array.new(100001, 0) |
| 59 | + @l = Array.new(100001, 0) |
| 60 | + @r = Array.new(100001, 0) |
| 61 | + |
| 62 | + search(root, 0) |
| 63 | + |
| 64 | + n = @len |
| 65 | + maxl = Array.new(n, 0) |
| 66 | + maxr = Array.new(n, 0) |
| 67 | + |
| 68 | + (1...n).each do |i| |
| 69 | + maxl[i] = [maxl[i - 1], @heights[i - 1]].max |
| 70 | + maxr[n - i - 1] = [maxr[n - i], @heights[n - i]].max |
| 71 | + end |
| 72 | + |
| 73 | + ret = [] |
| 74 | + queries.each do |query| |
| 75 | + maxxl = maxl[@l[query]] |
| 76 | + maxxr = maxr[@r[query]] |
| 77 | + ret.push([maxxl, maxxr, @d[query] - 1].max) |
| 78 | + end |
| 79 | + |
| 80 | + ret |
| 81 | +end |
| 82 | + |
| 83 | +def search(p, h) |
| 84 | + @d[p.val] = h |
| 85 | + |
| 86 | + if !p.left && !p.right |
| 87 | + @heights[@len] = h |
| 88 | + @l[p.val] = @r[p.val] = @len |
| 89 | + @len += 1 |
| 90 | + return |
| 91 | + end |
| 92 | + |
| 93 | + @l[p.val] = @len |
| 94 | + |
| 95 | + search(p.left, h + 1) if p.left |
| 96 | + search(p.right, h + 1) if p.right |
| 97 | + |
| 98 | + @r[p.val] = @len - 1 |
| 99 | +end |
| 100 | + |
| 101 | +# **************** # |
| 102 | +# TEST # |
| 103 | +# **************** # |
| 104 | + |
| 105 | +require "test/unit" |
| 106 | +class TreeNode |
| 107 | + attr_accessor :val, :left, :right |
| 108 | + def initialize(val = 0, left = nil, right = nil) |
| 109 | + @val = val |
| 110 | + @left = left |
| 111 | + @right = right |
| 112 | + end |
| 113 | +end |
| 114 | + |
| 115 | +class Test_tree_queries < Test::Unit::TestCase |
| 116 | + def setup |
| 117 | + # Example 1 tree setup |
| 118 | + @root1 = TreeNode.new(1) |
| 119 | + @root1.left = TreeNode.new(3) |
| 120 | + @root1.right = TreeNode.new(4) |
| 121 | + @root1.left.left = TreeNode.new(2) |
| 122 | + @root1.right.left = TreeNode.new(6) |
| 123 | + @root1.right.right = TreeNode.new(5) |
| 124 | + @root1.right.right.right = TreeNode.new(7) |
| 125 | + |
| 126 | + # Example 2 tree setup |
| 127 | + @root2 = TreeNode.new(5) |
| 128 | + @root2.left = TreeNode.new(8) |
| 129 | + @root2.right = TreeNode.new(9) |
| 130 | + @root2.left.left = TreeNode.new(2) |
| 131 | + @root2.left.right = TreeNode.new(1) |
| 132 | + @root2.right.left = TreeNode.new(3) |
| 133 | + @root2.right.right = TreeNode.new(7) |
| 134 | + @root2.left.left.left = TreeNode.new(4) |
| 135 | + @root2.left.left.right = TreeNode.new(6) |
| 136 | + end |
| 137 | + |
| 138 | + def test_example_1 |
| 139 | + queries = [4] |
| 140 | + expected = [2] |
| 141 | + assert_equal expected, tree_queries(@root1, queries) |
| 142 | + end |
| 143 | + |
| 144 | + def test_example_2 |
| 145 | + queries = [3, 2, 4, 8] |
| 146 | + expected = [3, 2, 3, 2] |
| 147 | + assert_equal expected, tree_queries(@root2, queries) |
| 148 | + end |
| 149 | +end |
0 commit comments