算法 - 二叉树07(Swift版本)

63 阅读2分钟

题目1: 235. 二叉搜索树的最近公共祖先

讲解  
leetcode

思路: 粗看了下题解,本题想到最后的答案,需要建立在如何巧妙利用二叉搜索树的特性上。 从上而下,遍历遇到当前节点的val 在 [p, q] 区间内,则这个节点即为 目标节点。

对于这个推论,我最直观想到可能得bad case 如下,既我从上往下找到pq的祖先节点,但他不是最近的。
结果呢,图画出来,就发现这种case也不存在。 比如这个node1,满足祖先节点,但不是最近的,那他一定不在[p, q]区间内。

image.png

自己写的版本 不够高效,缺少的利用二叉搜索树的有序 调整递归方向的操作。

class Solution {
    func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? {
        guard let root, let p, let q else { return nil } 
        if (p.val >= root.val && q.val <= root.val) || (q.val >= root.val && p.val <= root.val) {
            return root
        }
        if let node = lowestCommonAncestor(root.left, p, q) {
            return node
        }
        if let node = lowestCommonAncestor(root.right, p, q) {
            return node
        }
        return nil
    }
}

// 看完题解后 优化
class Solution {
    func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? {
        guard let root, let p, let q else { return nil }
        if root.val > q.val, root.val > p.val, 
           let node = lowestCommonAncestor(root.left, p, q) {
            return node
        }
        if root.val < q.val, root.val < p.val, 
           let node = lowestCommonAncestor(root.right, p, q) {
            return node
        }
        return root
    }

}

题目2: 701.二叉搜索树中的插入操作

讲解     
leetcode

思路有点固化,没有想到。

class Solution {
    func insertIntoBST(_ root: TreeNode?, _ val: Int) -> TreeNode? {
        guard let root else { return TreeNode(val) }
        if val > root.val { root.right = insertIntoBST(root.right, val) }
        if val < root.val { root.left = insertIntoBST(root.left, val) }
        return root
    }
}


// 迭代法
class Solution {
    func insertIntoBST(_ root: TreeNode?, _ val: Int) -> TreeNode? {
        guard let root else { return TreeNode(val) }
        var cur: TreeNode? = root
        var parent: TreeNode?
        while let node = cur {
            parent = node
            if node.val > val { cur = node.left }
            if node.val < val { cur = node.right }
        }
        if let parent {
            if  parent.val > val {
                parent.left = TreeNode(val)
            } else {
                parent.right = TreeNode(val)
            }
        }
        return root
    }
}

题目3:450.删除二叉搜索树中的节点

讲解
leetcode


// 递归法
class Solution {
    func deleteNode(_ root: TreeNode?, _ key: Int) -> TreeNode? {
        guard let root else { return nil }
        if root.val == key {
            if let left = root.left, let right = root.right { 
                var cur = right
                while cur.left != nil { cur = cur.left ?? TreeNode() }
                cur.left = left
                return right
            }
            else if root.right == nil { return root.left }
            else if root.left == nil { return root.right }
            else { return nil }
        }
        
        if key < root.val { root.left = deleteNode(root.left, key) }
        if key > root.val { root.right = deleteNode(root.right, key) }
        return root
    }
}


class Solution {
    func deleteNode(_ root: TreeNode?, _ key: Int) -> TreeNode? {
        guard let root else { return nil }
        var cur: TreeNode? = root
        var pre: TreeNode?
        while cur != nil {
            guard let node = cur else { break }
            if key == node.val { break }
            pre = node
            if key > node.val { cur = node.right }
            if key < node.val { cur = node.left }
        }
        guard let pre else { return removeOneNode(root) }
        if let left = pre.left, left.val == cur?.val ?? 0 {
            pre.left = removeOneNode(cur)
        }
        if let right = pre.right, right.val == cur?.val ?? 0 {
            pre.right = removeOneNode(cur)
        }
        return root
    }

    func removeOneNode(_ root: TreeNode?) -> TreeNode? {
        guard let root else { return nil }
        if root.left == nil { return root.right }
        if root.right == nil { return root.left }
        if let left = root.left, let right = root.right {
            var cur = right
            while cur.left != nil {
                cur = cur.left ?? TreeNode()
            }
            cur.left = left
            return right
        }
        return nil
    }
}