From e47ab1c71129a03e674820f57f41ceb1dbd79460 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 23 Apr 2024 09:34:06 +0800 Subject: [PATCH] feat: add solutions to lc/lcci problems * lc No.0098.Validate Binary Search Tree * lcci No.04.05.Legal Binary Search Tree --- lcci/04.05.Legal Binary Search Tree/README.md | 265 +++++++++------- .../README_EN.md | 267 +++++++++------- .../Solution.cpp | 35 +-- .../Solution.cs | 16 +- .../Solution.go | 34 +- .../Solution.java | 33 +- .../Solution.js | 15 +- .../Solution.py | 38 +-- .../Solution.rs | 10 +- .../Solution.ts | 16 +- .../Solution2.go | 13 - .../README.md | 296 ++++++------------ .../README_EN.md | 296 ++++++------------ .../Solution.cpp | 26 +- .../Solution.cs | 18 +- .../Solution.go | 9 +- .../Solution.java | 12 +- .../Solution.js | 9 +- .../Solution.py | 8 +- .../Solution.rs | 40 +++ .../Solution.ts | 20 +- .../Solution2.cpp | 23 -- .../Solution2.go | 22 -- .../Solution2.java | 30 -- .../Solution2.py | 16 - 25 files changed, 665 insertions(+), 902 deletions(-) rename solution/0000-0099/0098.Validate Binary Search Tree/Solution2.cs => lcci/04.05.Legal Binary Search Tree/Solution.cs (65%) rename solution/0000-0099/0098.Validate Binary Search Tree/Solution2.js => lcci/04.05.Legal Binary Search Tree/Solution.js (64%) delete mode 100644 lcci/04.05.Legal Binary Search Tree/Solution2.go create mode 100644 solution/0000-0099/0098.Validate Binary Search Tree/Solution.rs rename lcci/04.05.Legal Binary Search Tree/Solution2.ts => solution/0000-0099/0098.Validate Binary Search Tree/Solution.ts (55%) delete mode 100644 solution/0000-0099/0098.Validate Binary Search Tree/Solution2.cpp delete mode 100644 solution/0000-0099/0098.Validate Binary Search Tree/Solution2.go delete mode 100644 solution/0000-0099/0098.Validate Binary Search Tree/Solution2.java delete mode 100644 solution/0000-0099/0098.Validate Binary Search Tree/Solution2.py diff --git a/lcci/04.05.Legal Binary Search Tree/README.md b/lcci/04.05.Legal Binary Search Tree/README.md index daa93ce0f171a..69df7c795671a 100644 --- a/lcci/04.05.Legal Binary Search Tree/README.md +++ b/lcci/04.05.Legal Binary Search Tree/README.md @@ -9,36 +9,38 @@ ## 解法 -### 方法一 +### 方法一:递归 + +我们可以对二叉树进行递归中序遍历,如果遍历到的结果是严格升序的,那么这棵树就是一个二叉搜索树。 + +因此,我们使用一个变量 $\textit{prev}$ 来保存上一个遍历到的节点,初始时 $\textit{prev} = -\infty$,然后我们递归遍历左子树,如果左子树不是二叉搜索树,直接返回 $\text{False}$,否则判断当前节点的值是否大于 $\textit{prev}$,如果不是,返回 $\text{False}$,否则更新 $\textit{prev}$ 为当前节点的值,然后递归遍历右子树。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。 ```python # Definition for a binary tree node. # class TreeNode: -# def __init__(self, x): -# self.val = x -# self.left = None -# self.right = None - - +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right class Solution: - res, t = True, None + def isValidBST(self, root: Optional[TreeNode]) -> bool: + def dfs(root: Optional[TreeNode]) -> bool: + if root is None: + return True + if not dfs(root.left): + return False + nonlocal prev + if prev >= root.val: + return False + prev = root.val + return dfs(root.right) - def isValidBST(self, root: TreeNode) -> bool: - self.isValid(root) - return self.res - - def isValid(self, root): - if not root: - return - self.isValid(root.left) - if self.t is None or self.t < root.val: - self.t = root.val - else: - self.res = False - return - self.isValid(root.right) + prev = -inf + return dfs(root) ``` ```java @@ -48,29 +50,34 @@ class Solution: * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - private boolean res = true; - private Integer t = null; + private TreeNode prev; + public boolean isValidBST(TreeNode root) { - isValid(root); - return res; + return dfs(root); } - private void isValid(TreeNode root) { + private boolean dfs(TreeNode root) { if (root == null) { - return; + return true; } - isValid(root.left); - if (t == null || t < root.val) { - t = root.val; - } else { - res = false; - return; + if (!dfs(root.left)) { + return false; + } + if (prev != null && prev.val >= root.val) { + return false; } - isValid(root.right); + prev = root; + return dfs(root.right); } } ``` @@ -82,54 +89,59 @@ class Solution { * int val; * TreeNode *left; * TreeNode *right; - * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: bool isValidBST(TreeNode* root) { - TreeNode* pre = nullptr; - TreeNode* cur = root; - stack stk; - while (cur || !stk.empty()) { - if (cur) { - stk.push(cur); - cur = cur->left; - } else { - cur = stk.top(); - stk.pop(); - if (pre && pre->val >= cur->val) { - return false; - } - pre = cur; - cur = cur->right; + TreeNode* prev = nullptr; + function dfs = [&](TreeNode* root) { + if (!root) { + return true; } - } - return true; + if (!dfs(root->left)) { + return false; + } + if (prev && prev->val >= root->val) { + return false; + } + prev = root; + return dfs(root->right); + }; + return dfs(root); } }; ``` ```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ func isValidBST(root *TreeNode) bool { - stack := make([]*TreeNode, 0) - var prev *TreeNode = nil - node := root - for len(stack) > 0 || node != nil { - for node != nil { - stack = append(stack, node) - node = node.Left + var prev *TreeNode + var dfs func(*TreeNode) bool + dfs = func(root *TreeNode) bool { + if root == nil { + return true } - node = stack[len(stack)-1] - stack = stack[:len(stack)-1] - if prev == nil || node.Val > prev.Val { - prev = node - } else { + if !dfs(root.Left) { return false } - node = node.Right + if prev != nil && prev.Val >= root.Val { + return false + } + prev = root + return dfs(root.Right) } - return true + return dfs(root) } ``` @@ -149,17 +161,19 @@ func isValidBST(root *TreeNode) bool { */ function isValidBST(root: TreeNode | null): boolean { - let pre = -Infinity; - const dfs = (root: TreeNode | null) => { - if (root == null) { + let prev: TreeNode | null = null; + const dfs = (root: TreeNode | null): boolean => { + if (!root) { return true; } - const { val, left, right } = root; - if (!dfs(left) || val <= pre) { + if (!dfs(root.left)) { return false; } - pre = val; - return dfs(right); + if (prev && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); }; return dfs(root); } @@ -187,19 +201,19 @@ function isValidBST(root: TreeNode | null): boolean { use std::rc::Rc; use std::cell::RefCell; impl Solution { - fn dfs(root: &Option>>, pre: &mut Option) -> bool { + fn dfs(root: &Option>>, prev: &mut Option) -> bool { if root.is_none() { return true; } let root = root.as_ref().unwrap().borrow(); - if !Self::dfs(&root.left, pre) { + if !Self::dfs(&root.left, prev) { return false; } - if pre.is_some() && pre.unwrap() >= root.val { + if prev.is_some() && prev.unwrap() >= root.val { return false; } - *pre = Some(root.val); - Self::dfs(&root.right, pre) + *prev = Some(root.val); + Self::dfs(&root.right, prev) } pub fn is_valid_bst(root: Option>>) -> bool { @@ -208,59 +222,72 @@ impl Solution { } ``` - - -### 方法二 - - - -```go -func isValidBST(root *TreeNode) bool { - return check(root, math.MinInt64, math.MaxInt64) -} - -func check(node *TreeNode, lower, upper int) bool { - if node == nil { - return true - } - if node.Val <= lower || node.Val >= upper { - return false - } - return check(node.Left, lower, node.Val) && check(node.Right, node.Val, upper) -} +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {boolean} + */ +var isValidBST = function (root) { + let prev = null; + const dfs = root => { + if (!root) { + return true; + } + if (!dfs(root.left)) { + return false; + } + if (prev && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); + }; + return dfs(root); +}; ``` -```ts +```cs /** * Definition for a binary tree node. - * class TreeNode { - * val: number - * left: TreeNode | null - * right: TreeNode | null - * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) + * public class TreeNode { + * public int val; + * public TreeNode left; + * public TreeNode right; + * public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) { + * this.val = val; + * this.left = left; + * this.right = right; * } * } */ +public class Solution { + private TreeNode prev; -function isValidBST(root: TreeNode | null): boolean { - if (root == null) { - return true; + public bool IsValidBST(TreeNode root) { + return dfs(root); } - const { val, left, right } = root; - const dfs = (root: TreeNode | null, min: number, max: number) => { + + private bool dfs(TreeNode root) { if (root == null) { return true; } - const { val, left, right } = root; - if (val <= min || val >= max) { + if (!dfs(root.left)) { return false; } - return dfs(left, min, Math.min(val, max)) && dfs(right, Math.max(val, min), max); - }; - return dfs(left, -Infinity, val) && dfs(right, val, Infinity); + if (prev != null && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); + } } ``` diff --git a/lcci/04.05.Legal Binary Search Tree/README_EN.md b/lcci/04.05.Legal Binary Search Tree/README_EN.md index 668b007c4f421..2d108cdc6e234 100644 --- a/lcci/04.05.Legal Binary Search Tree/README_EN.md +++ b/lcci/04.05.Legal Binary Search Tree/README_EN.md @@ -46,36 +46,38 @@ ## Solutions -### Solution 1 +### Solution 1: Recursion + +We can perform a recursive in-order traversal on the binary tree. If the result of the traversal is strictly ascending, then this tree is a binary search tree. + +Therefore, we use a variable `prev` to save the last node we traversed. Initially, `prev = -∞`. Then we recursively traverse the left subtree. If the left subtree is not a binary search tree, we directly return `False`. Otherwise, we check whether the value of the current node is greater than `prev`. If not, we return `False`. Otherwise, we update `prev` to the value of the current node, and then recursively traverse the right subtree. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes in the binary tree. ```python # Definition for a binary tree node. # class TreeNode: -# def __init__(self, x): -# self.val = x -# self.left = None -# self.right = None - - +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right class Solution: - res, t = True, None - - def isValidBST(self, root: TreeNode) -> bool: - self.isValid(root) - return self.res - - def isValid(self, root): - if not root: - return - self.isValid(root.left) - if self.t is None or self.t < root.val: - self.t = root.val - else: - self.res = False - return - self.isValid(root.right) + def isValidBST(self, root: Optional[TreeNode]) -> bool: + def dfs(root: Optional[TreeNode]) -> bool: + if root is None: + return True + if not dfs(root.left): + return False + nonlocal prev + if prev >= root.val: + return False + prev = root.val + return dfs(root.right) + + prev = -inf + return dfs(root) ``` ```java @@ -85,29 +87,34 @@ class Solution: * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - private boolean res = true; - private Integer t = null; + private TreeNode prev; + public boolean isValidBST(TreeNode root) { - isValid(root); - return res; + return dfs(root); } - private void isValid(TreeNode root) { + private boolean dfs(TreeNode root) { if (root == null) { - return; + return true; } - isValid(root.left); - if (t == null || t < root.val) { - t = root.val; - } else { - res = false; - return; + if (!dfs(root.left)) { + return false; } - isValid(root.right); + if (prev != null && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); } } ``` @@ -119,54 +126,59 @@ class Solution { * int val; * TreeNode *left; * TreeNode *right; - * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: bool isValidBST(TreeNode* root) { - TreeNode* pre = nullptr; - TreeNode* cur = root; - stack stk; - while (cur || !stk.empty()) { - if (cur) { - stk.push(cur); - cur = cur->left; - } else { - cur = stk.top(); - stk.pop(); - if (pre && pre->val >= cur->val) { - return false; - } - pre = cur; - cur = cur->right; + TreeNode* prev = nullptr; + function dfs = [&](TreeNode* root) { + if (!root) { + return true; } - } - return true; + if (!dfs(root->left)) { + return false; + } + if (prev && prev->val >= root->val) { + return false; + } + prev = root; + return dfs(root->right); + }; + return dfs(root); } }; ``` ```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ func isValidBST(root *TreeNode) bool { - stack := make([]*TreeNode, 0) - var prev *TreeNode = nil - node := root - for len(stack) > 0 || node != nil { - for node != nil { - stack = append(stack, node) - node = node.Left + var prev *TreeNode + var dfs func(*TreeNode) bool + dfs = func(root *TreeNode) bool { + if root == nil { + return true + } + if !dfs(root.Left) { + return false } - node = stack[len(stack)-1] - stack = stack[:len(stack)-1] - if prev == nil || node.Val > prev.Val { - prev = node - } else { + if prev != nil && prev.Val >= root.Val { return false } - node = node.Right + prev = root + return dfs(root.Right) } - return true + return dfs(root) } ``` @@ -186,17 +198,19 @@ func isValidBST(root *TreeNode) bool { */ function isValidBST(root: TreeNode | null): boolean { - let pre = -Infinity; - const dfs = (root: TreeNode | null) => { - if (root == null) { + let prev: TreeNode | null = null; + const dfs = (root: TreeNode | null): boolean => { + if (!root) { return true; } - const { val, left, right } = root; - if (!dfs(left) || val <= pre) { + if (!dfs(root.left)) { return false; } - pre = val; - return dfs(right); + if (prev && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); }; return dfs(root); } @@ -224,19 +238,19 @@ function isValidBST(root: TreeNode | null): boolean { use std::rc::Rc; use std::cell::RefCell; impl Solution { - fn dfs(root: &Option>>, pre: &mut Option) -> bool { + fn dfs(root: &Option>>, prev: &mut Option) -> bool { if root.is_none() { return true; } let root = root.as_ref().unwrap().borrow(); - if !Self::dfs(&root.left, pre) { + if !Self::dfs(&root.left, prev) { return false; } - if pre.is_some() && pre.unwrap() >= root.val { + if prev.is_some() && prev.unwrap() >= root.val { return false; } - *pre = Some(root.val); - Self::dfs(&root.right, pre) + *prev = Some(root.val); + Self::dfs(&root.right, prev) } pub fn is_valid_bst(root: Option>>) -> bool { @@ -245,59 +259,72 @@ impl Solution { } ``` - - -### Solution 2 - - - -```go -func isValidBST(root *TreeNode) bool { - return check(root, math.MinInt64, math.MaxInt64) -} - -func check(node *TreeNode, lower, upper int) bool { - if node == nil { - return true - } - if node.Val <= lower || node.Val >= upper { - return false - } - return check(node.Left, lower, node.Val) && check(node.Right, node.Val, upper) -} +```js +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {boolean} + */ +var isValidBST = function (root) { + let prev = null; + const dfs = root => { + if (!root) { + return true; + } + if (!dfs(root.left)) { + return false; + } + if (prev && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); + }; + return dfs(root); +}; ``` -```ts +```cs /** * Definition for a binary tree node. - * class TreeNode { - * val: number - * left: TreeNode | null - * right: TreeNode | null - * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) + * public class TreeNode { + * public int val; + * public TreeNode left; + * public TreeNode right; + * public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) { + * this.val = val; + * this.left = left; + * this.right = right; * } * } */ +public class Solution { + private TreeNode prev; -function isValidBST(root: TreeNode | null): boolean { - if (root == null) { - return true; + public bool IsValidBST(TreeNode root) { + return dfs(root); } - const { val, left, right } = root; - const dfs = (root: TreeNode | null, min: number, max: number) => { + + private bool dfs(TreeNode root) { if (root == null) { return true; } - const { val, left, right } = root; - if (val <= min || val >= max) { + if (!dfs(root.left)) { return false; } - return dfs(left, min, Math.min(val, max)) && dfs(right, Math.max(val, min), max); - }; - return dfs(left, -Infinity, val) && dfs(right, val, Infinity); + if (prev != null && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); + } } ``` diff --git a/lcci/04.05.Legal Binary Search Tree/Solution.cpp b/lcci/04.05.Legal Binary Search Tree/Solution.cpp index 8c63408bf1fa1..b60f74a1481e1 100644 --- a/lcci/04.05.Legal Binary Search Tree/Solution.cpp +++ b/lcci/04.05.Legal Binary Search Tree/Solution.cpp @@ -4,29 +4,28 @@ * int val; * TreeNode *left; * TreeNode *right; - * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: bool isValidBST(TreeNode* root) { - TreeNode* pre = nullptr; - TreeNode* cur = root; - stack stk; - while (cur || !stk.empty()) { - if (cur) { - stk.push(cur); - cur = cur->left; - } else { - cur = stk.top(); - stk.pop(); - if (pre && pre->val >= cur->val) { - return false; - } - pre = cur; - cur = cur->right; + TreeNode* prev = nullptr; + function dfs = [&](TreeNode* root) { + if (!root) { + return true; } - } - return true; + if (!dfs(root->left)) { + return false; + } + if (prev && prev->val >= root->val) { + return false; + } + prev = root; + return dfs(root->right); + }; + return dfs(root); } }; \ No newline at end of file diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.cs b/lcci/04.05.Legal Binary Search Tree/Solution.cs similarity index 65% rename from solution/0000-0099/0098.Validate Binary Search Tree/Solution2.cs rename to lcci/04.05.Legal Binary Search Tree/Solution.cs index 53723ebe79c07..ad06caf50bb85 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.cs +++ b/lcci/04.05.Legal Binary Search Tree/Solution.cs @@ -12,17 +12,23 @@ * } */ public class Solution { + private TreeNode prev; + public bool IsValidBST(TreeNode root) { - return dfs(root, long.MinValue, long.MaxValue); + return dfs(root); } - public bool dfs(TreeNode root, long l, long r) { + private bool dfs(TreeNode root) { if (root == null) { return true; } - if (root.val <= l || root.val >= r) { + if (!dfs(root.left)) { + return false; + } + if (prev != null && prev.val >= root.val) { return false; } - return dfs(root.left, l, root.val) && dfs(root.right, root.val, r); + prev = root; + return dfs(root.right); } -} +} \ No newline at end of file diff --git a/lcci/04.05.Legal Binary Search Tree/Solution.go b/lcci/04.05.Legal Binary Search Tree/Solution.go index aedd74b56e121..b5f88cb158b1b 100644 --- a/lcci/04.05.Legal Binary Search Tree/Solution.go +++ b/lcci/04.05.Legal Binary Search Tree/Solution.go @@ -1,20 +1,26 @@ +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ func isValidBST(root *TreeNode) bool { - stack := make([]*TreeNode, 0) - var prev *TreeNode = nil - node := root - for len(stack) > 0 || node != nil { - for node != nil { - stack = append(stack, node) - node = node.Left + var prev *TreeNode + var dfs func(*TreeNode) bool + dfs = func(root *TreeNode) bool { + if root == nil { + return true } - node = stack[len(stack)-1] - stack = stack[:len(stack)-1] - if prev == nil || node.Val > prev.Val { - prev = node - } else { + if !dfs(root.Left) { return false } - node = node.Right + if prev != nil && prev.Val >= root.Val { + return false + } + prev = root + return dfs(root.Right) } - return true + return dfs(root) } \ No newline at end of file diff --git a/lcci/04.05.Legal Binary Search Tree/Solution.java b/lcci/04.05.Legal Binary Search Tree/Solution.java index a14ed19dc6be2..de081f5cc1769 100644 --- a/lcci/04.05.Legal Binary Search Tree/Solution.java +++ b/lcci/04.05.Legal Binary Search Tree/Solution.java @@ -4,28 +4,33 @@ * int val; * TreeNode left; * TreeNode right; - * TreeNode(int x) { val = x; } + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } * } */ class Solution { - private boolean res = true; - private Integer t = null; + private TreeNode prev; + public boolean isValidBST(TreeNode root) { - isValid(root); - return res; + return dfs(root); } - private void isValid(TreeNode root) { + private boolean dfs(TreeNode root) { if (root == null) { - return; + return true; + } + if (!dfs(root.left)) { + return false; } - isValid(root.left); - if (t == null || t < root.val) { - t = root.val; - } else { - res = false; - return; + if (prev != null && prev.val >= root.val) { + return false; } - isValid(root.right); + prev = root; + return dfs(root.right); } } \ No newline at end of file diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.js b/lcci/04.05.Legal Binary Search Tree/Solution.js similarity index 64% rename from solution/0000-0099/0098.Validate Binary Search Tree/Solution2.js rename to lcci/04.05.Legal Binary Search Tree/Solution.js index 5ba987359a6f0..78074e3ebbb7a 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.js +++ b/lcci/04.05.Legal Binary Search Tree/Solution.js @@ -11,14 +11,19 @@ * @return {boolean} */ var isValidBST = function (root) { - function dfs(root, l, r) { + let prev = null; + const dfs = root => { if (!root) { return true; } - if (root.val <= l || root.val >= r) { + if (!dfs(root.left)) { return false; } - return dfs(root.left, l, root.val) && dfs(root.right, root.val, r); - } - return dfs(root, -Infinity, Infinity); + if (prev && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); + }; + return dfs(root); }; diff --git a/lcci/04.05.Legal Binary Search Tree/Solution.py b/lcci/04.05.Legal Binary Search Tree/Solution.py index 4ce5597d19181..78e9c57057fa9 100644 --- a/lcci/04.05.Legal Binary Search Tree/Solution.py +++ b/lcci/04.05.Legal Binary Search Tree/Solution.py @@ -1,25 +1,21 @@ # Definition for a binary tree node. # class TreeNode: -# def __init__(self, x): -# self.val = x -# self.left = None -# self.right = None - - +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right class Solution: - res, t = True, None - - def isValidBST(self, root: TreeNode) -> bool: - self.isValid(root) - return self.res + def isValidBST(self, root: Optional[TreeNode]) -> bool: + def dfs(root: Optional[TreeNode]) -> bool: + if root is None: + return True + if not dfs(root.left): + return False + nonlocal prev + if prev >= root.val: + return False + prev = root.val + return dfs(root.right) - def isValid(self, root): - if not root: - return - self.isValid(root.left) - if self.t is None or self.t < root.val: - self.t = root.val - else: - self.res = False - return - self.isValid(root.right) + prev = -inf + return dfs(root) diff --git a/lcci/04.05.Legal Binary Search Tree/Solution.rs b/lcci/04.05.Legal Binary Search Tree/Solution.rs index cd97a90085145..e1cdfad146d8b 100644 --- a/lcci/04.05.Legal Binary Search Tree/Solution.rs +++ b/lcci/04.05.Legal Binary Search Tree/Solution.rs @@ -19,19 +19,19 @@ use std::rc::Rc; use std::cell::RefCell; impl Solution { - fn dfs(root: &Option>>, pre: &mut Option) -> bool { + fn dfs(root: &Option>>, prev: &mut Option) -> bool { if root.is_none() { return true; } let root = root.as_ref().unwrap().borrow(); - if !Self::dfs(&root.left, pre) { + if !Self::dfs(&root.left, prev) { return false; } - if pre.is_some() && pre.unwrap() >= root.val { + if prev.is_some() && prev.unwrap() >= root.val { return false; } - *pre = Some(root.val); - Self::dfs(&root.right, pre) + *prev = Some(root.val); + Self::dfs(&root.right, prev) } pub fn is_valid_bst(root: Option>>) -> bool { diff --git a/lcci/04.05.Legal Binary Search Tree/Solution.ts b/lcci/04.05.Legal Binary Search Tree/Solution.ts index 10ed44e58b84c..037c83d3b1872 100644 --- a/lcci/04.05.Legal Binary Search Tree/Solution.ts +++ b/lcci/04.05.Legal Binary Search Tree/Solution.ts @@ -13,17 +13,19 @@ */ function isValidBST(root: TreeNode | null): boolean { - let pre = -Infinity; - const dfs = (root: TreeNode | null) => { - if (root == null) { + let prev: TreeNode | null = null; + const dfs = (root: TreeNode | null): boolean => { + if (!root) { return true; } - const { val, left, right } = root; - if (!dfs(left) || val <= pre) { + if (!dfs(root.left)) { return false; } - pre = val; - return dfs(right); + if (prev && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); }; return dfs(root); } diff --git a/lcci/04.05.Legal Binary Search Tree/Solution2.go b/lcci/04.05.Legal Binary Search Tree/Solution2.go deleted file mode 100644 index 3b33a98772bd4..0000000000000 --- a/lcci/04.05.Legal Binary Search Tree/Solution2.go +++ /dev/null @@ -1,13 +0,0 @@ -func isValidBST(root *TreeNode) bool { - return check(root, math.MinInt64, math.MaxInt64) -} - -func check(node *TreeNode, lower, upper int) bool { - if node == nil { - return true - } - if node.Val <= lower || node.Val >= upper { - return false - } - return check(node.Left, lower, node.Val) && check(node.Right, node.Val, upper) -} \ No newline at end of file diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/README.md b/solution/0000-0099/0098.Validate Binary Search Tree/README.md index 9397e07e013a4..c27baf0b6611f 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/README.md +++ b/solution/0000-0099/0098.Validate Binary Search Tree/README.md @@ -48,11 +48,11 @@ ### 方法一:递归 -中序遍历,若是一个有效的二叉搜索树,那么遍历到的序列应该是单调递增的。所以只要比较判断遍历到的当前数是否大于上一个数即可。 +我们可以对二叉树进行递归中序遍历,如果遍历到的结果是严格升序的,那么这棵树就是一个二叉搜索树。 -或者考虑以 `root` 为根的子树,所有节点的值是否都在合法范围内,递归判断即可。 +因此,我们使用一个变量 $\textit{prev}$ 来保存上一个遍历到的节点,初始时 $\textit{prev} = -\infty$,然后我们递归遍历左子树,如果左子树不是二叉搜索树,直接返回 $\text{False}$,否则判断当前节点的值是否大于 $\textit{prev}$,如果不是,返回 $\text{False}$,否则更新 $\textit{prev}$ 为当前节点的值,然后递归遍历右子树。 -时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是树中节点的数量。 +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点个数。 @@ -65,18 +65,16 @@ # self.right = right class Solution: def isValidBST(self, root: Optional[TreeNode]) -> bool: - def dfs(root): - nonlocal prev + def dfs(root: Optional[TreeNode]) -> bool: if root is None: return True if not dfs(root.left): return False + nonlocal prev if prev >= root.val: return False prev = root.val - if not dfs(root.right): - return False - return True + return dfs(root.right) prev = -inf return dfs(root) @@ -99,10 +97,9 @@ class Solution: * } */ class Solution { - private Integer prev; + private TreeNode prev; public boolean isValidBST(TreeNode root) { - prev = null; return dfs(root); } @@ -113,14 +110,11 @@ class Solution { if (!dfs(root.left)) { return false; } - if (prev != null && prev >= root.val) { - return false; - } - prev = root.val; - if (!dfs(root.right)) { + if (prev != null && prev.val >= root.val) { return false; } - return true; + prev = root; + return dfs(root.right); } } ``` @@ -139,21 +133,23 @@ class Solution { */ class Solution { public: - TreeNode* prev; - bool isValidBST(TreeNode* root) { - prev = nullptr; + TreeNode* prev = nullptr; + function dfs = [&](TreeNode* root) { + if (!root) { + return true; + } + if (!dfs(root->left)) { + return false; + } + if (prev && prev->val >= root->val) { + return false; + } + prev = root; + return dfs(root->right); + }; return dfs(root); } - - bool dfs(TreeNode* root) { - if (!root) return true; - if (!dfs(root->left)) return false; - if (prev && prev->val >= root->val) return false; - prev = root; - if (!dfs(root->right)) return false; - return true; - } }; ``` @@ -168,8 +164,7 @@ public: */ func isValidBST(root *TreeNode) bool { var prev *TreeNode - - var dfs func(root *TreeNode) bool + var dfs func(*TreeNode) bool dfs = func(root *TreeNode) bool { if root == nil { return true @@ -181,33 +176,30 @@ func isValidBST(root *TreeNode) bool { return false } prev = root - if !dfs(root.Right) { - return false - } - return true + return dfs(root.Right) } - return dfs(root) } ``` -```js +```ts /** * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } * } */ -/** - * @param {TreeNode} root - * @return {boolean} - */ -var isValidBST = function (root) { - let prev = null; - let dfs = function (root) { +function isValidBST(root: TreeNode | null): boolean { + let prev: TreeNode | null = null; + const dfs = (root: TreeNode | null): boolean => { if (!root) { return true; } @@ -218,170 +210,55 @@ var isValidBST = function (root) { return false; } prev = root; - if (!dfs(root.right)) { - return false; - } - return true; + return dfs(root.right); }; - return dfs(root); -}; +} ``` -```cs -/** - * Definition for a binary tree node. - * public class TreeNode { - * public int val; - * public TreeNode left; - * public TreeNode right; - * public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ -public class Solution { - private TreeNode prev; - - public bool IsValidBST(TreeNode root) { - prev = null; - return dfs(root); - } - - private bool dfs(TreeNode root) { - if (root == null) - { +```rust +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::rc::Rc; +use std::cell::RefCell; +impl Solution { + fn dfs(root: &Option>>, prev: &mut Option) -> bool { + if root.is_none() { return true; } - if (!dfs(root.left)) - { - return false; - } - if (prev != null && prev.val >= root.val) - { + let root = root.as_ref().unwrap().borrow(); + if !Self::dfs(&root.left, prev) { return false; } - prev = root; - if (!dfs(root.right)) - { + if prev.is_some() && prev.unwrap() >= root.val { return false; } - return true; + *prev = Some(root.val); + Self::dfs(&root.right, prev) } -} -``` - - - -### 方法二 - - - -```python -# Definition for a binary tree node. -# class TreeNode: -# def __init__(self, val=0, left=None, right=None): -# self.val = val -# self.left = left -# self.right = right -class Solution: - def isValidBST(self, root: Optional[TreeNode]) -> bool: - def dfs(root, l, r): - if root is None: - return True - if root.val <= l or root.val >= r: - return False - return dfs(root.left, l, root.val) and dfs(root.right, root.val, r) - return dfs(root, -inf, inf) -``` - -```java -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ -class Solution { - public boolean isValidBST(TreeNode root) { - return dfs(root, Long.MIN_VALUE, Long.MAX_VALUE); - } - - private boolean dfs(TreeNode root, long l, long r) { - if (root == null) { - return true; - } - if (root.val <= l || root.val >= r) { - return false; - } - return dfs(root.left, l, root.val) && dfs(root.right, root.val, r); + pub fn is_valid_bst(root: Option>>) -> bool { + Self::dfs(&root, &mut None) } } ``` -```cpp -/** - * Definition for a binary tree node. - * struct TreeNode { - * int val; - * TreeNode *left; - * TreeNode *right; - * TreeNode() : val(0), left(nullptr), right(nullptr) {} - * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} - * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} - * }; - */ -class Solution { -public: - bool isValidBST(TreeNode* root) { - return dfs(root, LONG_MIN, LONG_MAX); - } - - bool dfs(TreeNode* root, long long l, long long r) { - if (!root) return true; - if (root->val <= l || root->val >= r) return false; - return dfs(root->left, l, root->val) && dfs(root->right, root->val, r); - } -}; -``` - -```go -/** - * Definition for a binary tree node. - * type TreeNode struct { - * Val int - * Left *TreeNode - * Right *TreeNode - * } - */ -func isValidBST(root *TreeNode) bool { - return dfs(root, math.MinInt64, math.MaxInt64) -} - -func dfs(root *TreeNode, l, r int64) bool { - if root == nil { - return true - } - v := int64(root.Val) - if v <= l || v >= r { - return false - } - return dfs(root.Left, l, v) && dfs(root.Right, v, r) -} -``` - ```js /** * Definition for a binary tree node. @@ -396,16 +273,21 @@ func dfs(root *TreeNode, l, r int64) bool { * @return {boolean} */ var isValidBST = function (root) { - function dfs(root, l, r) { + let prev = null; + const dfs = root => { if (!root) { return true; } - if (root.val <= l || root.val >= r) { + if (!dfs(root.left)) { return false; } - return dfs(root.left, l, root.val) && dfs(root.right, root.val, r); - } - return dfs(root, -Infinity, Infinity); + if (prev && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); + }; + return dfs(root); }; ``` @@ -424,18 +306,24 @@ var isValidBST = function (root) { * } */ public class Solution { + private TreeNode prev; + public bool IsValidBST(TreeNode root) { - return dfs(root, long.MinValue, long.MaxValue); + return dfs(root); } - public bool dfs(TreeNode root, long l, long r) { + private bool dfs(TreeNode root) { if (root == null) { return true; } - if (root.val <= l || root.val >= r) { + if (!dfs(root.left)) { + return false; + } + if (prev != null && prev.val >= root.val) { return false; } - return dfs(root.left, l, root.val) && dfs(root.right, root.val, r); + prev = root; + return dfs(root.right); } } ``` diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/README_EN.md b/solution/0000-0099/0098.Validate Binary Search Tree/README_EN.md index 631a7d09321f4..421fab84039e2 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/README_EN.md +++ b/solution/0000-0099/0098.Validate Binary Search Tree/README_EN.md @@ -44,11 +44,11 @@ ### Solution 1: Recursion -In-order traversal. If it is a valid binary search tree, then the sequence traversed should be monotonically increasing. So, we only need to compare and judge whether the current number traversed is greater than the previous number. +We can perform a recursive in-order traversal on the binary tree. If the result of the traversal is strictly ascending, then this tree is a binary search tree. -Alternatively, consider the subtree with `root` as the root, whether all node values are within the valid range, and judge recursively. +Therefore, we use a variable `prev` to save the last node we traversed. Initially, `prev = -∞`. Then we recursively traverse the left subtree. If the left subtree is not a binary search tree, we directly return `False`. Otherwise, we check whether the value of the current node is greater than `prev`. If not, we return `False`. Otherwise, we update `prev` to the value of the current node, and then recursively traverse the right subtree. -The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the number of nodes in the tree. +The time complexity is $O(n)$, and the space complexity is $O(n)$. Where $n$ is the number of nodes in the binary tree. @@ -61,18 +61,16 @@ The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is # self.right = right class Solution: def isValidBST(self, root: Optional[TreeNode]) -> bool: - def dfs(root): - nonlocal prev + def dfs(root: Optional[TreeNode]) -> bool: if root is None: return True if not dfs(root.left): return False + nonlocal prev if prev >= root.val: return False prev = root.val - if not dfs(root.right): - return False - return True + return dfs(root.right) prev = -inf return dfs(root) @@ -95,10 +93,9 @@ class Solution: * } */ class Solution { - private Integer prev; + private TreeNode prev; public boolean isValidBST(TreeNode root) { - prev = null; return dfs(root); } @@ -109,14 +106,11 @@ class Solution { if (!dfs(root.left)) { return false; } - if (prev != null && prev >= root.val) { - return false; - } - prev = root.val; - if (!dfs(root.right)) { + if (prev != null && prev.val >= root.val) { return false; } - return true; + prev = root; + return dfs(root.right); } } ``` @@ -135,21 +129,23 @@ class Solution { */ class Solution { public: - TreeNode* prev; - bool isValidBST(TreeNode* root) { - prev = nullptr; + TreeNode* prev = nullptr; + function dfs = [&](TreeNode* root) { + if (!root) { + return true; + } + if (!dfs(root->left)) { + return false; + } + if (prev && prev->val >= root->val) { + return false; + } + prev = root; + return dfs(root->right); + }; return dfs(root); } - - bool dfs(TreeNode* root) { - if (!root) return true; - if (!dfs(root->left)) return false; - if (prev && prev->val >= root->val) return false; - prev = root; - if (!dfs(root->right)) return false; - return true; - } }; ``` @@ -164,8 +160,7 @@ public: */ func isValidBST(root *TreeNode) bool { var prev *TreeNode - - var dfs func(root *TreeNode) bool + var dfs func(*TreeNode) bool dfs = func(root *TreeNode) bool { if root == nil { return true @@ -177,33 +172,30 @@ func isValidBST(root *TreeNode) bool { return false } prev = root - if !dfs(root.Right) { - return false - } - return true + return dfs(root.Right) } - return dfs(root) } ``` -```js +```ts /** * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } * } */ -/** - * @param {TreeNode} root - * @return {boolean} - */ -var isValidBST = function (root) { - let prev = null; - let dfs = function (root) { +function isValidBST(root: TreeNode | null): boolean { + let prev: TreeNode | null = null; + const dfs = (root: TreeNode | null): boolean => { if (!root) { return true; } @@ -214,170 +206,55 @@ var isValidBST = function (root) { return false; } prev = root; - if (!dfs(root.right)) { - return false; - } - return true; + return dfs(root.right); }; - return dfs(root); -}; +} ``` -```cs -/** - * Definition for a binary tree node. - * public class TreeNode { - * public int val; - * public TreeNode left; - * public TreeNode right; - * public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ -public class Solution { - private TreeNode prev; - - public bool IsValidBST(TreeNode root) { - prev = null; - return dfs(root); - } - - private bool dfs(TreeNode root) { - if (root == null) - { +```rust +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::rc::Rc; +use std::cell::RefCell; +impl Solution { + fn dfs(root: &Option>>, prev: &mut Option) -> bool { + if root.is_none() { return true; } - if (!dfs(root.left)) - { - return false; - } - if (prev != null && prev.val >= root.val) - { + let root = root.as_ref().unwrap().borrow(); + if !Self::dfs(&root.left, prev) { return false; } - prev = root; - if (!dfs(root.right)) - { + if prev.is_some() && prev.unwrap() >= root.val { return false; } - return true; + *prev = Some(root.val); + Self::dfs(&root.right, prev) } -} -``` - - - -### Solution 2 - - - -```python -# Definition for a binary tree node. -# class TreeNode: -# def __init__(self, val=0, left=None, right=None): -# self.val = val -# self.left = left -# self.right = right -class Solution: - def isValidBST(self, root: Optional[TreeNode]) -> bool: - def dfs(root, l, r): - if root is None: - return True - if root.val <= l or root.val >= r: - return False - return dfs(root.left, l, root.val) and dfs(root.right, root.val, r) - return dfs(root, -inf, inf) -``` - -```java -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ -class Solution { - public boolean isValidBST(TreeNode root) { - return dfs(root, Long.MIN_VALUE, Long.MAX_VALUE); - } - - private boolean dfs(TreeNode root, long l, long r) { - if (root == null) { - return true; - } - if (root.val <= l || root.val >= r) { - return false; - } - return dfs(root.left, l, root.val) && dfs(root.right, root.val, r); + pub fn is_valid_bst(root: Option>>) -> bool { + Self::dfs(&root, &mut None) } } ``` -```cpp -/** - * Definition for a binary tree node. - * struct TreeNode { - * int val; - * TreeNode *left; - * TreeNode *right; - * TreeNode() : val(0), left(nullptr), right(nullptr) {} - * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} - * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} - * }; - */ -class Solution { -public: - bool isValidBST(TreeNode* root) { - return dfs(root, LONG_MIN, LONG_MAX); - } - - bool dfs(TreeNode* root, long long l, long long r) { - if (!root) return true; - if (root->val <= l || root->val >= r) return false; - return dfs(root->left, l, root->val) && dfs(root->right, root->val, r); - } -}; -``` - -```go -/** - * Definition for a binary tree node. - * type TreeNode struct { - * Val int - * Left *TreeNode - * Right *TreeNode - * } - */ -func isValidBST(root *TreeNode) bool { - return dfs(root, math.MinInt64, math.MaxInt64) -} - -func dfs(root *TreeNode, l, r int64) bool { - if root == nil { - return true - } - v := int64(root.Val) - if v <= l || v >= r { - return false - } - return dfs(root.Left, l, v) && dfs(root.Right, v, r) -} -``` - ```js /** * Definition for a binary tree node. @@ -392,16 +269,21 @@ func dfs(root *TreeNode, l, r int64) bool { * @return {boolean} */ var isValidBST = function (root) { - function dfs(root, l, r) { + let prev = null; + const dfs = root => { if (!root) { return true; } - if (root.val <= l || root.val >= r) { + if (!dfs(root.left)) { return false; } - return dfs(root.left, l, root.val) && dfs(root.right, root.val, r); - } - return dfs(root, -Infinity, Infinity); + if (prev && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); + }; + return dfs(root); }; ``` @@ -420,18 +302,24 @@ var isValidBST = function (root) { * } */ public class Solution { + private TreeNode prev; + public bool IsValidBST(TreeNode root) { - return dfs(root, long.MinValue, long.MaxValue); + return dfs(root); } - public bool dfs(TreeNode root, long l, long r) { + private bool dfs(TreeNode root) { if (root == null) { return true; } - if (root.val <= l || root.val >= r) { + if (!dfs(root.left)) { + return false; + } + if (prev != null && prev.val >= root.val) { return false; } - return dfs(root.left, l, root.val) && dfs(root.right, root.val, r); + prev = root; + return dfs(root.right); } } ``` diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.cpp b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.cpp index 8adaef6387fed..b60f74a1481e1 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.cpp +++ b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.cpp @@ -11,19 +11,21 @@ */ class Solution { public: - TreeNode* prev; - bool isValidBST(TreeNode* root) { - prev = nullptr; + TreeNode* prev = nullptr; + function dfs = [&](TreeNode* root) { + if (!root) { + return true; + } + if (!dfs(root->left)) { + return false; + } + if (prev && prev->val >= root->val) { + return false; + } + prev = root; + return dfs(root->right); + }; return dfs(root); } - - bool dfs(TreeNode* root) { - if (!root) return true; - if (!dfs(root->left)) return false; - if (prev && prev->val >= root->val) return false; - prev = root; - if (!dfs(root->right)) return false; - return true; - } }; \ No newline at end of file diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.cs b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.cs index 1a45e1b8f2648..ad06caf50bb85 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.cs +++ b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.cs @@ -15,28 +15,20 @@ public class Solution { private TreeNode prev; public bool IsValidBST(TreeNode root) { - prev = null; return dfs(root); } private bool dfs(TreeNode root) { - if (root == null) - { + if (root == null) { return true; } - if (!dfs(root.left)) - { + if (!dfs(root.left)) { return false; } - if (prev != null && prev.val >= root.val) - { + if (prev != null && prev.val >= root.val) { return false; } prev = root; - if (!dfs(root.right)) - { - return false; - } - return true; + return dfs(root.right); } -} +} \ No newline at end of file diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.go b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.go index 2286df709bf4e..b5f88cb158b1b 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.go +++ b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.go @@ -8,8 +8,7 @@ */ func isValidBST(root *TreeNode) bool { var prev *TreeNode - - var dfs func(root *TreeNode) bool + var dfs func(*TreeNode) bool dfs = func(root *TreeNode) bool { if root == nil { return true @@ -21,11 +20,7 @@ func isValidBST(root *TreeNode) bool { return false } prev = root - if !dfs(root.Right) { - return false - } - return true + return dfs(root.Right) } - return dfs(root) } \ No newline at end of file diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.java b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.java index d3e7f125309dc..de081f5cc1769 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.java +++ b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.java @@ -14,10 +14,9 @@ * } */ class Solution { - private Integer prev; + private TreeNode prev; public boolean isValidBST(TreeNode root) { - prev = null; return dfs(root); } @@ -28,13 +27,10 @@ private boolean dfs(TreeNode root) { if (!dfs(root.left)) { return false; } - if (prev != null && prev >= root.val) { + if (prev != null && prev.val >= root.val) { return false; } - prev = root.val; - if (!dfs(root.right)) { - return false; - } - return true; + prev = root; + return dfs(root.right); } } \ No newline at end of file diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.js b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.js index b37f688eb3cc6..78074e3ebbb7a 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.js +++ b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.js @@ -12,8 +12,7 @@ */ var isValidBST = function (root) { let prev = null; - - let dfs = function (root) { + const dfs = root => { if (!root) { return true; } @@ -24,11 +23,7 @@ var isValidBST = function (root) { return false; } prev = root; - if (!dfs(root.right)) { - return false; - } - return true; + return dfs(root.right); }; - return dfs(root); }; diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.py b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.py index a31d683436812..78e9c57057fa9 100644 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.py +++ b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.py @@ -6,18 +6,16 @@ # self.right = right class Solution: def isValidBST(self, root: Optional[TreeNode]) -> bool: - def dfs(root): - nonlocal prev + def dfs(root: Optional[TreeNode]) -> bool: if root is None: return True if not dfs(root.left): return False + nonlocal prev if prev >= root.val: return False prev = root.val - if not dfs(root.right): - return False - return True + return dfs(root.right) prev = -inf return dfs(root) diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution.rs b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.rs new file mode 100644 index 0000000000000..e1cdfad146d8b --- /dev/null +++ b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.rs @@ -0,0 +1,40 @@ +// Definition for a binary tree node. +// #[derive(Debug, PartialEq, Eq)] +// pub struct TreeNode { +// pub val: i32, +// pub left: Option>>, +// pub right: Option>>, +// } +// +// impl TreeNode { +// #[inline] +// pub fn new(val: i32) -> Self { +// TreeNode { +// val, +// left: None, +// right: None +// } +// } +// } +use std::rc::Rc; +use std::cell::RefCell; +impl Solution { + fn dfs(root: &Option>>, prev: &mut Option) -> bool { + if root.is_none() { + return true; + } + let root = root.as_ref().unwrap().borrow(); + if !Self::dfs(&root.left, prev) { + return false; + } + if prev.is_some() && prev.unwrap() >= root.val { + return false; + } + *prev = Some(root.val); + Self::dfs(&root.right, prev) + } + + pub fn is_valid_bst(root: Option>>) -> bool { + Self::dfs(&root, &mut None) + } +} diff --git a/lcci/04.05.Legal Binary Search Tree/Solution2.ts b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.ts similarity index 55% rename from lcci/04.05.Legal Binary Search Tree/Solution2.ts rename to solution/0000-0099/0098.Validate Binary Search Tree/Solution.ts index 2d831aa8d57f4..037c83d3b1872 100644 --- a/lcci/04.05.Legal Binary Search Tree/Solution2.ts +++ b/solution/0000-0099/0098.Validate Binary Search Tree/Solution.ts @@ -13,19 +13,19 @@ */ function isValidBST(root: TreeNode | null): boolean { - if (root == null) { - return true; - } - const { val, left, right } = root; - const dfs = (root: TreeNode | null, min: number, max: number) => { - if (root == null) { + let prev: TreeNode | null = null; + const dfs = (root: TreeNode | null): boolean => { + if (!root) { return true; } - const { val, left, right } = root; - if (val <= min || val >= max) { + if (!dfs(root.left)) { return false; } - return dfs(left, min, Math.min(val, max)) && dfs(right, Math.max(val, min), max); + if (prev && prev.val >= root.val) { + return false; + } + prev = root; + return dfs(root.right); }; - return dfs(left, -Infinity, val) && dfs(right, val, Infinity); + return dfs(root); } diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.cpp b/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.cpp deleted file mode 100644 index f8576b4d71d23..0000000000000 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Definition for a binary tree node. - * struct TreeNode { - * int val; - * TreeNode *left; - * TreeNode *right; - * TreeNode() : val(0), left(nullptr), right(nullptr) {} - * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} - * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} - * }; - */ -class Solution { -public: - bool isValidBST(TreeNode* root) { - return dfs(root, LONG_MIN, LONG_MAX); - } - - bool dfs(TreeNode* root, long long l, long long r) { - if (!root) return true; - if (root->val <= l || root->val >= r) return false; - return dfs(root->left, l, root->val) && dfs(root->right, root->val, r); - } -}; \ No newline at end of file diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.go b/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.go deleted file mode 100644 index a7cc3f17529bb..0000000000000 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.go +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Definition for a binary tree node. - * type TreeNode struct { - * Val int - * Left *TreeNode - * Right *TreeNode - * } - */ -func isValidBST(root *TreeNode) bool { - return dfs(root, math.MinInt64, math.MaxInt64) -} - -func dfs(root *TreeNode, l, r int64) bool { - if root == nil { - return true - } - v := int64(root.Val) - if v <= l || v >= r { - return false - } - return dfs(root.Left, l, v) && dfs(root.Right, v, r) -} \ No newline at end of file diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.java b/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.java deleted file mode 100644 index c4e27728bb0e6..0000000000000 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Definition for a binary tree node. - * public class TreeNode { - * int val; - * TreeNode left; - * TreeNode right; - * TreeNode() {} - * TreeNode(int val) { this.val = val; } - * TreeNode(int val, TreeNode left, TreeNode right) { - * this.val = val; - * this.left = left; - * this.right = right; - * } - * } - */ -class Solution { - public boolean isValidBST(TreeNode root) { - return dfs(root, Long.MIN_VALUE, Long.MAX_VALUE); - } - - private boolean dfs(TreeNode root, long l, long r) { - if (root == null) { - return true; - } - if (root.val <= l || root.val >= r) { - return false; - } - return dfs(root.left, l, root.val) && dfs(root.right, root.val, r); - } -} \ No newline at end of file diff --git a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.py b/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.py deleted file mode 100644 index 057d2f023c018..0000000000000 --- a/solution/0000-0099/0098.Validate Binary Search Tree/Solution2.py +++ /dev/null @@ -1,16 +0,0 @@ -# Definition for a binary tree node. -# class TreeNode: -# def __init__(self, val=0, left=None, right=None): -# self.val = val -# self.left = left -# self.right = right -class Solution: - def isValidBST(self, root: Optional[TreeNode]) -> bool: - def dfs(root, l, r): - if root is None: - return True - if root.val <= l or root.val >= r: - return False - return dfs(root.left, l, root.val) and dfs(root.right, root.val, r) - - return dfs(root, -inf, inf)