|
| 1 | +--- |
| 2 | +title: 538.Convert the binary search tree to cumulative tree |
| 3 | +date: '2024.01.01 0:00' |
| 4 | +tags: |
| 5 | + - - Python |
| 6 | + - - answer |
| 7 | + - - Binary tree |
| 8 | +abbrlink: 32401b69 |
| 9 | +--- |
| 10 | + |
| 11 | +# topic: |
| 12 | + |
| 13 | +""" |
| 14 | + |
| 15 | +<p>Give two forks<strong> search </strong>Root node,The node value of the tree is different,Please convert it to a cumulative tree(Greater Sum Tree),Make each node <code>node</code> The new value of the original tree is greater than or equal to the original tree <code>node.val</code> The sum of the value。</p> |
| 16 | + |
| 17 | +<p>remind,二叉searchTree满足下列约束条件:</p> |
| 18 | + |
| 19 | +<ul> |
| 20 | + <li>The left tree of the node contains only the key<strong> Less than </strong>Node node node。</li> |
| 21 | + <li>The right tree of the node contains only the key<strong> more than the</strong> Node node node。</li> |
| 22 | + <li>左右子Tree也必须是二叉searchTree。</li> |
| 23 | +</ul> |
| 24 | + |
| 25 | +<p><strong>Notice:</strong>This question 1038: <a href="https://leetcode-cn.com/problems/binary-search-tree-to-greater-sum-tree/">https://leetcode-cn.com/problems/binary-search-tree-to-greater-sum-tree/</a> same</p> |
| 26 | + |
| 27 | +<p> </p> |
| 28 | + |
| 29 | +<p><strong>Exemplary example 1:</strong></p> |
| 30 | + |
| 31 | +<p><strong><img alt="" src="https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2019/05/03/tree.png" style="height: 364px; width: 534px;" /></strong></p> |
| 32 | + |
| 33 | +<pre><strong>enter:</strong>[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8] |
| 34 | +<strong>Output:</strong>[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8] |
| 35 | +</pre> |
| 36 | + |
| 37 | +<p><strong>Exemplary example 2:</strong></p> |
| 38 | + |
| 39 | +<pre><strong>enter:</strong>root = [0,null,1] |
| 40 | +<strong>Output:</strong>[1,null,1] |
| 41 | +</pre> |
| 42 | + |
| 43 | +<p><strong>Exemplary example 3:</strong></p> |
| 44 | + |
| 45 | +<pre><strong>enter:</strong>root = [1,0,2] |
| 46 | +<strong>Output:</strong>[3,3,2] |
| 47 | +</pre> |
| 48 | + |
| 49 | +<p><strong>Exemplary example 4:</strong></p> |
| 50 | + |
| 51 | +<pre><strong>enter:</strong>root = [3,2,4,1] |
| 52 | +<strong>Output:</strong>[7,9,4,10] |
| 53 | +</pre> |
| 54 | + |
| 55 | +<p> </p> |
| 56 | + |
| 57 | +<p><strong>hint:</strong></p> |
| 58 | + |
| 59 | +<ul> |
| 60 | + <li>The number of nodes in the tree is in <code>0</code> and <code>10<sup>4</sup></code><sup> </sup>between。</li> |
| 61 | + <li>The value of each node <code>-10<sup>4</sup></code> and <code>10<sup>4</sup></code> between。</li> |
| 62 | + <li>All the values in the tree <strong>互不same</strong> 。</li> |
| 63 | + <li>给定的Tree为二叉searchTree。</li> |
| 64 | +</ul> |
| 65 | + |
| 66 | +<div><div>Related Topics</div><div><li>Tree</li><li>深度优先search</li><li>二叉searchTree</li><li>Binary tree</li></div></div><br><div><li>👍 904</li><li>👎 0</li></div> |
| 67 | +""" |
| 68 | + |
| 69 | +# Thought: |
| 70 | + |
| 71 | +method one:Travel in the preface |
| 72 | +Thinking and algorithm |
| 73 | + |
| 74 | +本题中要求我们将每个节点的值修改为原来的节点值加上所有more than the它的节点值之and。这样我们只需要Travel in the preface该二叉searchTree,记录过程中的节点值之and,Not continuously update the node value of the nodes you currently traversed,即可得到topic要求的累加Tree。 |
| 75 | + |
| 76 | +Method Two:Morris Traversal |
| 77 | +Thinking and algorithm |
| 78 | + |
| 79 | +There is a clever way to be online,只占用常数空间来实现中序Traversal。This method is caused by J. H. Morris exist 1979 Annual thesis「Traversing Binary Trees Simply and Cheaply」Proposed for the first time,Because it is called Morris Traversal。 |
| 80 | + |
| 81 | +我们以一个简单的Binary tree为例进行说明。假设我们要进行中序Traversal的 Morris Traversal。 |
| 82 | + |
| 83 | +```markdown |
| 84 | + 1 |
| 85 | + / \ |
| 86 | + 2 3 |
| 87 | + / \ |
| 88 | + 4 5 |
| 89 | + |
| 90 | +``` |
| 91 | +1. Initialization The current node is the root node(current = 1)。 |
| 92 | + |
| 93 | +2. When the current node is not empty,Execute the following steps: |
| 94 | + |
| 95 | + 1. The left node of the current node is not empty。We find the front -drive node of the current node,也就是左子Tree中的最右节点。exist这个例子中,The front -drive node is the node5。 |
| 96 | + 2. The right node of the front -drive node is empty,Point your right node to the current node(5 -> 1)。 |
| 97 | + 3. Move the current node to its left child node(current = 2)。 |
| 98 | + ```markdown |
| 99 | + 1 |
| 100 | + \ |
| 101 | + 2 |
| 102 | + / \ |
| 103 | + 4 5 |
| 104 | + ``` |
| 105 | + |
| 106 | + 1. The left node of the current node is not empty。We find the front -drive node of the current node,也就是左子Tree中的最右节点。exist这个例子中,The front -drive node is the node4。 |
| 107 | + 2. The right node of the front -drive node is empty,Point your right node to the current node(4 -> 2)。 |
| 108 | + 3. Move the current node to its left child node(current = 4)。 |
| 109 | + ```markdown |
| 110 | + 1 |
| 111 | + \ |
| 112 | + 2 |
| 113 | + \ |
| 114 | + 4 |
| 115 | + \ |
| 116 | + 5 |
| 117 | + |
| 118 | + ``` |
| 119 | + |
| 120 | + 1. The left node of the current node is empty。Output当前节点的值(4)。 |
| 121 | + |
| 122 | + 2. Move the current node to its right node(current = 5)。 |
| 123 | + |
| 124 | + 3. The left node of the current node is empty。Output当前节点的值(5)。 |
| 125 | + |
| 126 | + 4. Move the current node to its right node(current = 2)。 |
| 127 | + ```markdown |
| 128 | + 1 |
| 129 | + \ |
| 130 | + 2 |
| 131 | + \ |
| 132 | + 4 |
| 133 | + ``` |
| 134 | + 1. The left node of the current node is empty。Output当前节点的值(2)。 |
| 135 | + 2. Move the current node to its right node(current = 1)。 |
| 136 | + ```markdown |
| 137 | + 1 |
| 138 | + \ |
| 139 | + 2 |
| 140 | + ``` |
| 141 | + 1. The left node of the current node is empty。Output当前节点的值(1)。 |
| 142 | + 2. Move the current node to its right node(current = 3)。 |
| 143 | + ```markdown |
| 144 | + 1 |
| 145 | + \ |
| 146 | + 2 |
| 147 | + ``` |
| 148 | + 1. The left node of the current node is empty。Output当前节点的值(3)。 |
| 149 | + 2. Move the current node to its right node(current = null)。 |
| 150 | +3. The current node is empty,Traversal结束。 |
| 151 | +4. |
| 152 | +According to the above steps,通过修改节点between的指针关系,我们完成了对Binary tree的中序Traversal。 |
| 153 | + |
| 154 | + |
| 155 | +# Code: |
| 156 | +```python 中序Traversal |
| 157 | +class Solution: |
| 158 | + def convertBST(self, root: TreeNode) -> TreeNode: |
| 159 | + def dfs(root: TreeNode): |
| 160 | + nonlocal total |
| 161 | + if root: |
| 162 | + dfs(root.right) |
| 163 | + total += root.val |
| 164 | + root.val = total |
| 165 | + dfs(root.left) |
| 166 | + |
| 167 | + total = 0 |
| 168 | + dfs(root) |
| 169 | + return root |
| 170 | +``` |
| 171 | + |
| 172 | +```python MorrisTraversal |
| 173 | +class Solution: |
| 174 | + def convertBST(self, root: TreeNode) -> TreeNode: |
| 175 | + # Get the successor node of the given node(中序Traversal中的下一个节点) |
| 176 | + def getSuccessor(node: TreeNode) -> TreeNode: |
| 177 | + succ = node.right |
| 178 | + while succ.left and succ.left != node: |
| 179 | + succ = succ.left |
| 180 | + return succ |
| 181 | + |
| 182 | + total = 0 # 记录累加的节点值之and |
| 183 | + node = root # The current node initialization is the root node |
| 184 | + |
| 185 | + while node: |
| 186 | + if not node.right: # If the right node of the current node is empty |
| 187 | + total += node.val # Add the value of the current node to the cumulative value |
| 188 | + node.val = total # Update the value of the current node to accumulate value |
| 189 | + node = node.left # Move the current node to its left child node |
| 190 | + else: # If the right node of the current node is not empty |
| 191 | + succ = getSuccessor(node) # Get the successor node of the current node |
| 192 | + if not succ.left: # If the left node of the successor node is empty |
| 193 | + succ.left = node # Point the left -node of the successor node to the current node,Establish a clue |
| 194 | + node = node.right # Move the current node to its right node |
| 195 | + else: # If the left node of the successor node is not empty |
| 196 | + succ.left = None # Set the left node of the successor node to empty,Remove clues |
| 197 | + total += node.val # Add the value of the current node to the cumulative value |
| 198 | + node.val = total # Update the value of the current node to accumulate value |
| 199 | + node = node.left # Move the current node to its left child node |
| 200 | + |
| 201 | + return root # Return to the root node |
| 202 | + |
| 203 | +class Solution: |
| 204 | + def convertBST(self, root: TreeNode) -> TreeNode: |
| 205 | + def convert(node: TreeNode, total: int) -> int: |
| 206 | + if not node: |
| 207 | + return total |
| 208 | + |
| 209 | + # 递归Traversal右子Tree |
| 210 | + total = convert(node.right, total) |
| 211 | + |
| 212 | + # Update the node value to accumulate and add value |
| 213 | + total += node.val |
| 214 | + node.val = total |
| 215 | + |
| 216 | + # 递归Traversal左子Tree |
| 217 | + total = convert(node.left, total) |
| 218 | + |
| 219 | + return total |
| 220 | + |
| 221 | + convert(root, 0) |
| 222 | + return root |
| 223 | +``` |
0 commit comments