28. Validate Binary Search Tree
読了目安 約2分
Tree / LC 98 (Medium) — BST の検証。値の範囲を上から伝える再帰。
この章の目次
問題
LeetCode 98. Validate Binary Search Tree(Medium / カテゴリ: Tree)
二分木の根 root が与えられるので、正しい二分探索木(BST)かを判定します。
条件は、各ノードについて「左の部分木のすべての値 < ノードの値 < 右の部分木のすべての値」です。
等しい値は許されません。
このページのテストでは、ノードの値として Int.min や Int.max も現れます。
考え方
ヒント 1
「左の子 < 親 < 右の子」を各ノードで確かめるだけでは足りません。
[5, 1, 4, nil, nil, 3, 6] のように、右の部分木の奥に親より小さい値が隠れている反例があります。
ヒント 2
各ノードが取り得る値の範囲(下限, 上限)を根から伝えます。 左に降りるときは上限をそのノードの値に、右に降りるときは下限をそのノードの値に狭めます。 別解として、中間順走査の列が真に昇順(等しい値なし)かを確かめる方法もあります。
Swift 実装のポイント
- 下限・上限を
Int.min/Int.maxの番兵で初期化すると、ノードの値がちょうどInt.min/Int.maxのときに誤判定します。範囲はInt?で持ち、nilを「制限なし」と扱うのが安全です。 - 比較は「下限 < 値 < 上限」の狭義の不等号です。等しい値は BST に許されません。
if let low = low, node.val <= low { return false }の形で、オプショナルの下限を自然に検査できます。
模範解答
class Solution {
func isValidBST(_ root: TreeNode?) -> Bool {
func valid(_ node: TreeNode?, _ low: Int?, _ high: Int?) -> Bool {
guard let node = node else { return true }
if let low = low, node.val <= low { return false }
if let high = high, node.val >= high { return false }
return valid(node.left, low, node.val) && valid(node.right, node.val, high)
}
return valid(root, nil, nil)
}
}計算量: O(N)。各ノードを 1 回ずつ検査します。