最优解:Morris 算法
Morris 算法介绍及代码: https://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/
Use Morris in-order traverse, keep the two wrong nodes and switch their values after the traverse.
Time complexity: O(n)
Space complexity: O(1), the benefit of Morris algorithm
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def recoverTree(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
x = y = pred = None
while root:
if not root.left:
if pred and root.val < pred.val:
y = root
if not x:
x = pred
pred = root
root = root.right
else:
predecessor = root.left
while predecessor.right and predecessor.right != root:
predecessor = predecessor.right
if not predecessor.right:
predecessor.right = root
root = root.left
else:
if pred and root.val < pred.val:
y = root
if not x:
x = pred
pred = root
predecessor.right = None
root = root.right
x.val, y.val = y.val, x.val
方法2: By in order traverse list
Time complexity: O(n)
Space complexity: O(n)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def recoverTree(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
in_order = []
self.dfs(root, in_order)
node1, node2 = None, None
print(in_order)
for i in range(len(in_order) - 1):
if in_order[i].val > in_order[i + 1].val:
node1 = in_order[i]
break
for i in range(len(in_order) - 1, 0, -1):
if in_order[i].val < in_order[i - 1].val:
node2 = in_order[i]
break
tmp = node1.val
node1.val = node2.val
node2.val = tmp
def dfs(self, root, in_order):
if root is None:
return
self.dfs(root.left, in_order)
in_order.append(root)
self.dfs(root.right, in_order)
方法3: keep wrong nodes during recursion
time complexity: O(n)
space complexity: O(n) stack space
** dfs时先左边,最后右边,中间是对当前情况的处理和判断。注意判断当前node的合法性的位置,在prev赋值为当前node之前
class Solution:
def recoverTree(self, root: TreeNode) -> None:
"""
Do not return anything, modify root in-place instead.
"""
self.prev = None
self.count = 0
self.dfs(root)
tmp = self.node1.val
self.node1.val = self.node2.val
self.node2.val = tmp
def dfs(self, root):
if root is None:
return
self.dfs(root.left)
if self.prev and root.val < self.prev.val:
if self.count == 0:
self.node1 = self.prev
self.node2 = root
self.count += 1
elif self.count == 1:
self.node2 = root
self.count += 1
return
self.prev = root
self.dfs(root.right)