1. 程式人生 > >Leetcode 99:恢復二叉搜尋樹(超詳細的解法!!!)

Leetcode 99:恢復二叉搜尋樹(超詳細的解法!!!)

二叉搜尋樹中的兩個節點被錯誤地交換。

請在不改變其結構的情況下,恢復這棵樹。

示例 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

很明顯,此時不是遞增陣列,我們只需要將31換一下位置即可。對於例二來說,輸入樹的中序遍歷是

1 3 2 4

此時也不是遞增陣列,我們只需要將23換一下位置即可。現在的問題是我們怎麼知道要交換哪兩個數呢?我們可以對輸入的樹進行中序遍歷,遍歷的過程中判斷之前訪問的節點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

如有問題,希望大家指出!!!