二叉搜索树中的两个节点被错误地交换。
请在不改变其结构的情况下,恢复这棵树。
示例 1:
输入: [1,3,null,null,2]
1
/
3
\
2
输出: [3,1,null,null,2]
3
/
1
\
2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
示例 2:
输入: [3,1,4,null,null,2]
3
/ \
1 4
/
2
输出: [2,1,4,null,null,3]
2
/ \
1 4
/
3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
进阶:
使用 O(n) 空间复杂度的解法很容易实现。
你能想出一个只使用常数空间的解决方案吗?
解题思路
这个问题非常简单。我们知道二分搜索树的中序遍历是一个单调递增的数组。对于例一来说,输入树的中序遍历是
3 2 1
1
很明显,此时不是递增数组,我们只需要将3和1换一下位置即可。对于例二来说,输入树的中序遍历是
1 3 2 4
1
此时也不是递增数组,我们只需要将2和3换一下位置即可。现在的问题是我们怎么知道要交换哪两个数呢?我们可以对输入的树进行中序遍历,遍历的过程中判断之前访问的节点pre.val是不是大于当前访问的节点cur.val,如果是的话,我们就要记录pre,此时pre就是要交换的第一个元素。然后我们继续遍历,直到再也没有出现pre.val > cur.val的情况了,此时我们最后一次出现的cur就是我们要交换的第二个元素(参考第一个例子)。关于遍历操作,可以参看如下这几篇
Leetcode 144:二叉树的前序遍历(最优雅的解法!!!)
Leetcode 94:二叉树的中序遍历(最优雅的解法!!!)
Leetcode 145:二叉树的后序遍历(最详细的解法!!!
class Solution:
def recoverTree(self, root):
"""
:type root: TreeNode
:rtype: void Do not return anything, modify root in-place instead.
"""
self.pre = None
self.m1, self.m2 = None, None
self.inorderTraversal(root)
self.m1.val, self.m2.val = self.m2.val, self.m1.val
def inorderTraversal(self, root):
if root:
self.inorderTraversal(root.left)
if self.pre != None and self.pre.val > root.val:
if self.m1 == None:
self.m1 = self.pre
self.m2 = root
self.pre = root
self.inorderTraversal(root.right)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
同时我们也可以轻松的写出迭代版本。
class Solution:
def recoverTree(self, root):
"""
:type root: TreeNode
:rtype: void Do not return anything, modify root in-place instead.
"""
cur, pre = root, None
first, second = None, None
stack = []
while cur or stack:
if cur:
stack.append(cur)
cur = cur.left
else:
node = stack.pop()
if pre and pre.val >= node.val:
if not first:
first = pre
second = node
pre = node
cur = node.right
first.val, second.val = second.val, first.val
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!
---------------------
作者:coordinate_blog
来源:CSDN
原文:https://blog.csdn.net/qq_17550379/article/details/85157903
版权声明:本文为博主原创文章,转载请附上博文链接!