Leetcode 99:恢復二叉搜尋樹(超詳細的解法!!!)
阿新 • • 發佈:2018-12-22
二叉搜尋樹中的兩個節點被錯誤地交換。
請在不改變其結構的情況下,恢復這棵樹。
示例 1:
輸入: [1,3,null,null,2]
1
/
3
\
2
輸出: [3,1,null,null,2]
3
/
1
\
2
示例 2:
輸入: [3,1,4,null,null,2]
3
/ \
1 4
/
2
輸出: [2,1,4,null,null,3]
2
/ \
1 4
/
3
進階:
- 使用 O(n) 空間複雜度的解法很容易實現。
- 你能想出一個只使用常數空間的解決方案嗎?
解題思路
這個問題非常簡單。我們知道二分搜尋樹的中序遍歷是一個單調遞增的陣列。對於例一來說,輸入樹的中序遍歷是
3 2 1
很明顯,此時不是遞增陣列,我們只需要將3
和1
換一下位置即可。對於例二來說,輸入樹的中序遍歷是
1 3 2 4
此時也不是遞增陣列,我們只需要將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)
同時我們也可以輕鬆的寫出迭代版本。
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
我將該問題的其他語言版本新增到了我的GitHub Leetcode
如有問題,希望大家指出!!!