leetcode 98. 验证二叉搜索树

145 阅读2分钟

题目链接

题目已经描述清楚了二叉搜索树的特征,只要根据特征去验证即可。
有两种思路

  • 中序遍历,验证当前节点值大于遍历过程的前一个节点值
  • 验证当前子树被限定在一个最小值和一个最大值之间

以下是具体解法。以下代码都已提交通过。

解法一

中序遍历,递归实现。

func isValidBST(root *TreeNode) bool {
    var prev *TreeNode
    var isValid func(*TreeNode) bool
    // 递归调用isValid
    isValid = func(root *TreeNode) bool {
        // 终止条件
        if root == nil {
            return true
        }
        if !isValid(root.Left) {
            return false
        }
        // 处理当前子树根节点
        if prev != nil {
            // 与前一个节点值做比较
            if prev.Val >= root.Val {
                return false
            }
        }
        prev = root
        return isValid(root.Right)
    }
    return isValid(root)
}

解法二

中序遍历,迭代法。

func isValidBST(root *TreeNode) bool {
    if root == nil {
        return true
    }
    var (
        sk Stack
        prev *TreeNode
        curr = root
    )
    for {
        if curr != nil {
            sk.Push(curr)
            curr = curr.Left
        } else if !sk.IsEmpty() {
            node := sk.Peek()
            sk.Pop()
            // 当前节点和前一个节点做比较
            if prev != nil {
                if prev.Val >= node.Val {
                    return false
                }
            }
            prev = node
            curr = node.Right
        } else {
            break
        }
    }
    return true
}

// 栈
type Stack struct {
    data []*TreeNode
}

func (o *Stack) Len() int {
    return len(o.data)
}

func (o *Stack) IsEmpty() bool {
    return len(o.data) == 0
}

func (o *Stack) Push(node *TreeNode) {
    o.data = append(o.data, node)
}

func (o *Stack) Peek() *TreeNode {
    if o.IsEmpty() {
        panic("Stack is empty")
    }
    return o.data[len(o.data)-1]
}

func (o *Stack) Pop() {
    if o.IsEmpty() {
        panic("Stack is empty")
    }
    o.data = o.data[:len(o.data)-1]
}

解法三

先序遍历,递归。
思路就是二叉搜索树的特征,左子树上所有节点的值均小于它的根节点的值,右子树上所有节点的值均大于它的根节点的值。

func isValidBST(root *TreeNode) bool {
    return isValid(root, nil, nil)
}

// 递归调用isValid
func isValid(root, min, max *TreeNode) bool {
    // 递归终止条件
    if root == nil {
        return true
    }
    // 验证当前节点大于最小值
    if min != nil {
        if root.Val <= min.Val {
            return false
        }
    }
    // 验证当前节点小于最大值
    if max != nil {
        if root.Val >= max.Val {
            return false
        }
    }
    // 左子树上所有节点的值均小于它的根节点的值。
    // 右子树上所有节点的值均大于它的根节点的值。
    if !isValid(root.Left, min, root) ||
       !isValid(root.Right, root, max) {
        return false
    }
    return true
}

解法四

中序遍历,递归。思路同解法三。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isValidBST(root *TreeNode) bool {
    return isValid(root, nil, nil)
}

func isValid(root, min, max *TreeNode) bool {
    if root == nil {
        return true
    }
    if !isValid(root.Left, min, root) {
        return false
    }
    if min != nil {
        if root.Val <= min.Val {
            return false
        }
    }
    if max != nil {
        if root.Val >= max.Val {
            return false
        }
    }
    return isValid(root.Right, root, max)
}

解法五

后序遍历,递归。思路同解法三。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isValidBST(root *TreeNode) bool {
    return isValid(root, nil, nil)
}

func isValid(root, min, max *TreeNode) bool {
    if root == nil {
        return true
    }
    if !isValid(root.Left, min, root) ||
       !isValid(root.Right, root, max) {
        return false
    }
    if min != nil {
        if root.Val <= min.Val {
            return false
        }
    }
    if max != nil {
        if root.Val >= max.Val {
            return false
        }
    }
    return true
}