1. 程式人生 > 實用技巧 >leetcode刷題筆記九十九題 恢復二叉搜尋樹

leetcode刷題筆記九十九題 恢復二叉搜尋樹

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) 空間複雜度的解法很容易實現。
你能想出一個只使用常數空間的解決方案嗎?

/**
處理本題主要採用三種方法,遞迴,非遞迴,莫里斯排序
由於本題中提到了二叉搜尋樹及兩個結點的數值出現顛倒,很容易聯想到之前對二叉搜尋樹中常見的中序遍歷,結點有序。在遍歷過程中,易發現兩組prev值大於cur值現象,前一組的prev 和 後一組的cur即為需要調換的位置。
*/
//遞迴方法
/**
 * Definition for a binary tree node.
 * class TreeNode(_value: Int = 0, _left: TreeNode = null, _right: TreeNode = null) {
 *   var value: Int = _value
 *   var left: TreeNode = _left
 *   var right: TreeNode = _right
 * }
 */
object Solution {
    def recoverTree(root: TreeNode): Unit = {
        var x: TreeNode = null
        var y: TreeNode = null
        var prev: TreeNode = null
        def helper(root: TreeNode): Unit = {
            if (root == null) return
            //遞迴左子樹
            helper(root.left)
            //出現prev.value > root.value這種情況
            if (prev  != null && prev.value > root.value){
                y = root
                //如果x沒更新,即第一組情況需要優先更新x
                //第二組將重新更新y
                if (x == null) x = prev
                else return
            }
            prev = root
            //遞迴右子樹
            helper(root.right)
        }
        helper(root)
        val temp = x.value
        x.value = y.value
        y.value = temp
    }
}

//非遞迴使用stack進行迭代
/**
 * Definition for a binary tree node.
 * class TreeNode(_value: Int = 0, _left: TreeNode = null, _right: TreeNode = null) {
 *   var value: Int = _value
 *   var left: TreeNode = _left
 *   var right: TreeNode = _right
 * }
 */
import scala.collection.mutable.Stack
object Solution {
    def recoverTree(root: TreeNode): Unit = {
        var x: TreeNode = null
        var y: TreeNode = null
        var prev: TreeNode = null
        var start = root
        val stack = new Stack[TreeNode]()
		//棧不為空且當前結點不為空,依次放入左子樹結點
        while (stack.size > 0 || start != null){
            while (start != null){
                stack.push(start)
                start = start.left
            }
            //到達最左側,彈出
            start = stack.pop
            //如果出現顛倒情況處理
            if (prev != null && prev.value > start.value){
                y = start
                if (x == null)  x = prev
            }
            //嘗試遍歷退出結點的右子樹
            prev = start 
            start = start.right
        }

        val temp = x.value
        x.value = y.value
        y.value = temp
    }
}

//莫里斯遍歷
//莫里斯遍歷之前在中序遍歷時已經看到,這裡主要針對幾類情況進行處理
//1.是否有左子樹
//2.沒有左子樹右節點與根節點連結,加鏈;否則,斷鏈
/**
 * Definition for a binary tree node.
 * class TreeNode(_value: Int = 0, _left: TreeNode = null, _right: TreeNode = null) {
 *   var value: Int = _value
 *   var left: TreeNode = _left
 *   var right: TreeNode = _right
 * }
 */
object Solution {
    def recoverTree(root: TreeNode): Unit = {
        var x: TreeNode = null
        var y: TreeNode = null
        var prev: TreeNode = null
        var predecessor: TreeNode = null
        var start = root
        
        while (start != null){
            if (start.left != null){
                predecessor = start.left
                while (predecessor.right != null && predecessor.right != start) predecessor = predecessor.right
                if (predecessor.right == null){
                    predecessor.right = start
                    start = start.left
                }
                else{
                    if (prev != null && prev.value > start.value){
                        y = start
                        if(x == null) x = prev
                    }
                    prev = start
                    predecessor.right = null
                    start = start.right
                }
            }
            else{
                if (prev != null && prev.value > start.value){
                    y = start
                    if(x == null) x = prev
                }
                prev = start
                start = start.right
            }
        }
        
        val temp = x.value
        x.value = y.value
        y.value = temp
    }
}