From 77ccc65cd4366d263fab4b2419684a3bbb857454 Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Sat, 12 Oct 2024 08:43:57 +0530 Subject: [PATCH] batch-2/Neetcode-150/articles --- articles/balanced-binary-tree.md | 616 ++++++++++++++++ articles/binary-tree-right-side-view.md | 398 +++++++++++ articles/count-good-nodes-in-binary-tree.md | 379 ++++++++++ .../level-order-traversal-of-binary-tree.md | 412 +++++++++++ ...t-common-ancestor-in-binary-search-tree.md | 332 +++++++++ articles/same-binary-tree.md | 358 ++++++++++ articles/subtree-of-a-binary-tree.md | 539 ++++++++++++++ articles/valid-binary-search-tree.md | 656 ++++++++++++++++++ 8 files changed, 3690 insertions(+) create mode 100644 articles/balanced-binary-tree.md create mode 100644 articles/binary-tree-right-side-view.md create mode 100644 articles/count-good-nodes-in-binary-tree.md create mode 100644 articles/level-order-traversal-of-binary-tree.md create mode 100644 articles/lowest-common-ancestor-in-binary-search-tree.md create mode 100644 articles/same-binary-tree.md create mode 100644 articles/subtree-of-a-binary-tree.md create mode 100644 articles/valid-binary-search-tree.md diff --git a/articles/balanced-binary-tree.md b/articles/balanced-binary-tree.md new file mode 100644 index 000000000..d54120d9e --- /dev/null +++ b/articles/balanced-binary-tree.md @@ -0,0 +1,616 @@ +## 1. Brute Force + +::tabs-start + +```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 isBalanced(self, root: Optional[TreeNode]) -> bool: + if not root: + return True + + left = self.height(root.left) + right = self.height(root.right) + if abs(left - right) > 1: + return False + return self.isBalanced(root.left) and self.isBalanced(root.right) + + def height(self, root: Optional[TreeNode]) -> int: + if not root: + return 0 + + return 1 + max(self.height(root.left), self.height(root.right)) +``` + +```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 isBalanced(TreeNode root) { + if (root == null) return true; + + int left = height(root.left); + int right = height(root.right); + if (Math.abs(left - right) > 1) return false; + return isBalanced(root.left) && isBalanced(root.right); + } + + public int height(TreeNode root) { + if (root == null) { + return 0; + } + + return 1 + Math.max(height(root.left), height(root.right)); + } +} +``` + +```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 isBalanced(TreeNode* root) { + if (!root) return true; + + int left = height(root->left); + int right = height(root->right); + if (abs(left - right) > 1) return false; + return isBalanced(root->left) && isBalanced(root->right); + } + + int height(TreeNode* root) { + if (root == nullptr) { + return 0; + } + + return 1 + max(height(root->left), height(root->right)); + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {boolean} + */ + isBalanced(root) { + if (root === null) return true; + + let left = this.height(root.left); + let right = this.height(root.right); + if (Math.abs(left - right) > 1) return false; + return this.isBalanced(root.left) && this.isBalanced(root.right); + } + + /** + * @param {TreeNode} root + * @return {number} + */ + height(root) { + if (root === null) { + return 0; + } + + return ( + 1 + Math.max(this.height(root.left), this.height(root.right)) + ); + } +} +``` + +```csharp +/** + * 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 { + public bool IsBalanced(TreeNode root) { + if (root == null) return true; + + int left = Height(root.left); + int right = Height(root.right); + if (Math.Abs(left - right) > 1) return false; + return IsBalanced(root.left) && IsBalanced(root.right); + } + + public int Height(TreeNode root) { + if (root == null) { + return 0; + } + + return 1 + Math.Max(Height(root.left), Height(root.right)); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n)$ + +--- + +## 2. Depth First Search + +::tabs-start + +```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 isBalanced(self, root: Optional[TreeNode]) -> bool: + def dfs(root): + if not root: + return [True, 0] + + left, right = dfs(root.left), dfs(root.right) + balanced = left[0] and right[0] and abs(left[1] - right[1]) <= 1 + return [balanced, 1 + max(left[1], right[1])] + + return dfs(root)[0] +``` + +```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 isBalanced(TreeNode root) { + return dfs(root)[0] == 1; + } + + private int[] dfs(TreeNode root) { + if (root == null) { + return new int[]{1, 0}; + } + + int[] left = dfs(root.left); + int[] right = dfs(root.right); + + boolean balanced = (left[0] == 1 && right[0] == 1) && + (Math.abs(left[1] - right[1]) <= 1); + int height = 1 + Math.max(left[1], right[1]); + + return new int[]{balanced ? 1 : 0, height}; + } +} +``` + +```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 isBalanced(TreeNode* root) { + return dfs(root)[0] == 1; + } + +private: + vector dfs(TreeNode* root) { + if (!root) { + return {1, 0}; + } + + vector left = dfs(root->left); + vector right = dfs(root->right); + + bool balanced = (left[0] == 1 && right[0] == 1) && + (abs(left[1] - right[1]) <= 1); + int height = 1 + max(left[1], right[1]); + + return {balanced ? 1 : 0, height}; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {boolean} + */ + isBalanced(root) { + return this.dfs(root)[0] === 1; + } + + /** + * @param {TreeNode} root + * @return {number[]} + */ + dfs(root) { + if (!root) { + return [1, 0]; + } + + const left = this.dfs(root.left); + const right = this.dfs(root.right); + + const balanced = + left[0] === 1 && + right[0] === 1 && + Math.abs(left[1] - right[1]) <= 1; + const height = 1 + Math.max(left[1], right[1]); + + return [balanced ? 1 : 0, height]; + } +} +``` + +```csharp +/** + * 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 { + + public bool IsBalanced(TreeNode root) { + return Dfs(root)[0] == 1; + } + + private int[] Dfs(TreeNode root) { + if (root == null) { + return new int[]{1, 0}; + } + + int[] left = Dfs(root.left); + int[] right = Dfs(root.right); + + bool balanced = (left[0] == 1 && right[0] == 1) && + (Math.Abs(left[1] - right[1]) <= 1); + int height = 1 + Math.Max(left[1], right[1]); + + return new int[]{balanced ? 1 : 0, height}; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Depth First Search (Stack) + +::tabs-start + +```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 isBalanced(self, root): + stack = [] + node = root + last = None + depths = {} + + while stack or node: + if node: + stack.append(node) + node = node.left + else: + node = stack[-1] + if not node.right or last == node.right: + stack.pop() + left = depths.get(node.left, 0) + right = depths.get(node.right, 0) + + if abs(left - right) > 1: + return False + + depths[node] = 1 + max(left, right) + last = node + node = None + else: + node = node.right + + return True +``` + +```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; + * } + * } + */ + +public class Solution { + public boolean isBalanced(TreeNode root) { + Stack stack = new Stack<>(); + TreeNode node = root, last = null; + Map depths = new HashMap<>(); + + while (!stack.isEmpty() || node != null) { + if (node != null) { + stack.push(node); + node = node.left; + } else { + node = stack.peek(); + if (node.right == null || last == node.right) { + stack.pop(); + int left = depths.getOrDefault(node.left, 0); + int right = depths.getOrDefault(node.right, 0); + if (Math.abs(left - right) > 1) return false; + depths.put(node, 1 + Math.max(left, right)); + last = node; + node = null; + } else { + node = node.right; + } + } + } + return true; + } +} +``` + +```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 isBalanced(TreeNode* root) { + stack stack; + TreeNode* node = root; + TreeNode* last = nullptr; + unordered_map depths; + + while (!stack.empty() || node != nullptr) { + if (node != nullptr) { + stack.push(node); + node = node->left; + } else { + node = stack.top(); + if (node->right == nullptr || last == node->right) { + stack.pop(); + int left = depths[node->left]; + int right = depths[node->right]; + if (abs(left - right) > 1) return false; + depths[node] = 1 + max(left, right); + last = node; + node = nullptr; + } else { + node = node->right; + } + } + } + return true; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {boolean} + */ + isBalanced(root) { + let stack = []; + let node = root, last = null; + let depths = new Map(); + + while (stack.length > 0 || node !== null) { + if (node !== null) { + stack.push(node); + node = node.left; + } else { + node = stack[stack.length - 1]; + if (node.right === null || last === node.right) { + stack.pop(); + let left = depths.get(node.left) || 0; + let right = depths.get(node.right) || 0; + if (Math.abs(left - right) > 1) return false; + depths.set(node, 1 + Math.max(left, right)); + last = node; + node = null; + } else { + node = node.right; + } + } + } + return true; + } +} +``` + +```csharp +/** + * 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 { + public bool IsBalanced(TreeNode root) { + Stack stack = new Stack(); + TreeNode node = root, last = null; + Dictionary depths = new Dictionary(); + + while (stack.Count > 0 || node != null) { + if (node != null) { + stack.Push(node); + node = node.left; + } else { + node = stack.Peek(); + if (node.right == null || last == node.right) { + stack.Pop(); + + int left = (node.left != null && depths.ContainsKey(node.left)) + ? depths[node.left] : 0; + int right = (node.right != null && depths.ContainsKey(node.right)) + ? depths[node.right] : 0; + + if (Math.Abs(left - right) > 1) return false; + + depths[node] = 1 + Math.Max(left, right); + last = node; + node = null; + } else { + node = node.right; + } + } + } + return true; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/binary-tree-right-side-view.md b/articles/binary-tree-right-side-view.md new file mode 100644 index 000000000..406f9295e --- /dev/null +++ b/articles/binary-tree-right-side-view.md @@ -0,0 +1,398 @@ +## 1. Depth First Search + +::tabs-start + +```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 rightSideView(self, root: Optional[TreeNode]) -> List[int]: + res = [] + + def dfs(node, depth): + if not node: + return None + if depth == len(res): + res.append(node.val) + + dfs(node.right, depth + 1) + dfs(node.left, depth + 1) + + dfs(root, 0) + return res +``` + +```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; + * } + * } + */ + +public class Solution { + List res = new ArrayList<>(); + + public List rightSideView(TreeNode root) { + dfs(root, 0); + return res; + } + + private void dfs(TreeNode node, int depth) { + if (node == null) { + return; + } + + if (res.size() == depth) { + res.add(node.val); + } + + dfs(node.right, depth + 1); + dfs(node.left, depth + 1); + } +} +``` + +```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: + vector res; + + vector rightSideView(TreeNode* root) { + dfs(root, 0); + return res; + } + + void dfs(TreeNode* node, int depth) { + if (!node) return; + + if (res.size() == depth) { + res.push_back(node->val); + } + + dfs(node->right, depth + 1); + dfs(node->left, depth + 1); + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {number[]} + */ + rightSideView(root) { + let res = []; + + function dfs(node, depth) { + if (!node) return; + + if (res.length === depth) { + res.push(node.val); + } + + dfs(node.right, depth + 1); + dfs(node.left, depth + 1); + } + + dfs(root, 0); + return res; + } +} +``` + +```csharp +/** + * 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 { + List res = new List(); + + public List RightSideView(TreeNode root) { + dfs(root, 0); + return res; + } + + private void dfs(TreeNode node, int depth) { + if (node == null) { + return; + } + + if (res.Count == depth) { + res.Add(node.val); + } + + dfs(node.right, depth + 1); + dfs(node.left, depth + 1); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Breadth First Search + +::tabs-start + +```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 rightSideView(self, root: Optional[TreeNode]) -> List[int]: + res = [] + q = deque([root]) + + while q: + rightSide = None + qLen = len(q) + + for i in range(qLen): + node = q.popleft() + if node: + rightSide = node + q.append(node.left) + q.append(node.right) + if rightSide: + res.append(rightSide.val) + return res +``` + +```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 List rightSideView(TreeNode root) { + List res = new ArrayList<>(); + Queue q = new LinkedList<>(); + q.offer(root); + + while (!q.isEmpty()) { + TreeNode rightSide = null; + int qLen = q.size(); + + for (int i = 0; i < qLen; i++) { + TreeNode node = q.poll(); + if (node != null) { + rightSide = node; + q.offer(node.left); + q.offer(node.right); + } + } + if (rightSide != null) { + res.add(rightSide.val); + } + } + return res; + } +} +``` + +```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: + vector rightSideView(TreeNode* root) { + vector res; + queue q; + q.push(root); + + while (!q.empty()) { + TreeNode* rightSide = nullptr; + int qLen = q.size(); + + for (int i = 0; i < qLen; i++) { + TreeNode* node = q.front(); + q.pop(); + if (node) { + rightSide = node; + q.push(node->left); + q.push(node->right); + } + } + if (rightSide) { + res.push_back(rightSide->val); + } + } + return res; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {number[]} + */ + rightSideView(root) { + const res = []; + const q = new Queue(); + + q.push(root); + + while (!q.isEmpty()) { + let rightSide = null; + const qLen = q.size(); + + for (let i = 0; i < qLen; i++) { + const node = q.pop(); + if (node) { + rightSide = node; + q.push(node.left); + q.push(node.right); + } + } + if (rightSide) { + res.push(rightSide.val); + } + } + return res; + } +} +``` + +```csharp +/** + * 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 { + public List RightSideView(TreeNode root) { + List res = new List(); + Queue q = new Queue(); + q.Enqueue(root); + + while (q.Count > 0) { + TreeNode rightSide = null; + int qLen = q.Count; + + for (int i = 0; i < qLen; i++) { + TreeNode node = q.Dequeue(); + if (node != null) { + rightSide = node; + q.Enqueue(node.left); + q.Enqueue(node.right); + } + } + if (rightSide != null) { + res.Add(rightSide.val); + } + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/count-good-nodes-in-binary-tree.md b/articles/count-good-nodes-in-binary-tree.md new file mode 100644 index 000000000..9dcd4d053 --- /dev/null +++ b/articles/count-good-nodes-in-binary-tree.md @@ -0,0 +1,379 @@ +## 1. Depth First Search + +::tabs-start + +```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 goodNodes(self, root: TreeNode) -> int: + + def dfs(node, maxVal): + if not node: + return 0 + + res = 1 if node.val >= maxVal else 0 + maxVal = max(maxVal, node.val) + res += dfs(node.left, maxVal) + res += dfs(node.right, maxVal) + return res + + return dfs(root, root.val) +``` + +```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 int goodNodes(TreeNode root) { + return dfs(root, root.val); + } + + private int dfs(TreeNode node, int maxVal) { + if (node == null) { + return 0; + } + + int res = (node.val >= maxVal) ? 1 : 0; + maxVal = Math.max(maxVal, node.val); + res += dfs(node.left, maxVal); + res += dfs(node.right, maxVal); + return res; + } +} +``` + +```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: + int goodNodes(TreeNode* root) { + return dfs(root, root->val); + } + +private: + int dfs(TreeNode* node, int maxVal) { + if (!node) { + return 0; + } + + int res = (node->val >= maxVal) ? 1 : 0; + maxVal = max(maxVal, node->val); + res += dfs(node->left, maxVal); + res += dfs(node->right, maxVal); + return res; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {number} + */ + goodNodes(root) { + return this.dfs(root, root.val); + } + + /** + * @param {TreeNode} node + * @param {number} maxVal + * @return {number} + */ + dfs(node, maxVal) { + if (!node) { + return 0; + } + + let res = node.val >= maxVal ? 1 : 0; + maxVal = Math.max(maxVal, node.val); + res += this.dfs(node.left, maxVal); + res += this.dfs(node.right, maxVal); + return res; + } +} +``` + +```csharp +/** + * 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 { + + public int GoodNodes(TreeNode root) { + return Dfs(root, root.val); + } + + private int Dfs(TreeNode node, int maxVal) { + if (node == null) { + return 0; + } + + int res = (node.val >= maxVal) ? 1 : 0; + maxVal = Math.Max(maxVal, node.val); + res += Dfs(node.left, maxVal); + res += Dfs(node.right, maxVal); + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Breadth First Search + +::tabs-start + +```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 goodNodes(self, root: TreeNode) -> int: + res = 0 + q = deque() + + q.append((root,-float('inf'))) + + while q: + node,maxval = q.popleft() + if node.val >= maxval: + res += 1 + + if node.left: + q.append((node.left,max(maxval,node.val))) + + if node.right: + q.append((node.right,max(maxval,node.val))) + + return res +``` + +```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; + * } + * } + */ + +public class Solution { + public int goodNodes(TreeNode root) { + int res = 0; + Queue> q = new LinkedList<>(); + q.offer(new Pair<>(root, Integer.MIN_VALUE)); + + while (!q.isEmpty()) { + Pair pair = q.poll(); + TreeNode node = pair.getKey(); + int maxval = pair.getValue(); + if (node.val >= maxval) { + res++; + } + if (node.left != null) { + q.offer(new Pair<>(node.left, Math.max(maxval, node.val))); + } + if (node.right != null) { + q.offer(new Pair<>(node.right, Math.max(maxval, node.val))); + } + } + return res; + } +} +``` + +```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: + int goodNodes(TreeNode* root) { + int res = 0; + queue> q; + q.push({root, -INT_MAX}); + + while (!q.empty()) { + auto [node, maxval] = q.front(); + q.pop(); + if (node->val >= maxval) { + res++; + } + if (node->left) { + q.push({node->left, max(maxval, node->val)}); + } + if (node->right) { + q.push({node->right, max(maxval, node->val)}); + } + } + return res; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {number} + */ + goodNodes(root) { + let res = 0; + let q = new Queue(); + q.push([root, -Infinity]); + + while (!q.isEmpty()) { + let [node, maxval] = q.pop(); + if (node.val >= maxval) { + res++; + } + if (node.left) { + q.push([node.left, Math.max(maxval, node.val)]); + } + if (node.right) { + q.push([node.right, Math.max(maxval, node.val)]); + } + } + return res; + } +} +``` + +```csharp +/** + * 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 { + public int GoodNodes(TreeNode root) { + int res = 0; + Queue<(TreeNode, int)> q = new Queue<(TreeNode, int)>(); + q.Enqueue((root, int.MinValue)); + + while (q.Count > 0) { + var (node, maxval) = q.Dequeue(); + if (node.val >= maxval) { + res++; + } + if (node.left != null) { + q.Enqueue((node.left, Math.Max(maxval, node.val))); + } + if (node.right != null) { + q.Enqueue((node.right, Math.Max(maxval, node.val))); + } + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/level-order-traversal-of-binary-tree.md b/articles/level-order-traversal-of-binary-tree.md new file mode 100644 index 000000000..ccb2cb491 --- /dev/null +++ b/articles/level-order-traversal-of-binary-tree.md @@ -0,0 +1,412 @@ +## 1. Depth First Search + +::tabs-start + +```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 levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + res = [] + + def dfs(node, depth): + if not node: + return None + if len(res) == depth: + res.append([]) + + res[depth].append(node.val) + dfs(node.left, depth + 1) + dfs(node.right, depth + 1) + + dfs(root, 0) + return res +``` + +```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; + * } + * } + */ + +public class Solution { + List> res = new ArrayList<>(); + + public List> levelOrder(TreeNode root) { + dfs(root, 0); + return res; + } + + private void dfs(TreeNode node, int depth) { + if (node == null) { + return; + } + + if (res.size() == depth) { + res.add(new ArrayList<>()); + } + + res.get(depth).add(node.val); + dfs(node.left, depth + 1); + dfs(node.right, depth + 1); + } +} +``` + +```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: + vector> res; + + vector> levelOrder(TreeNode* root) { + dfs(root, 0); + return res; + } + + void dfs(TreeNode* node, int depth) { + if (!node) return; + + if (res.size() == depth) { + res.push_back(vector()); + } + + res[depth].push_back(node->val); + dfs(node->left, depth + 1); + dfs(node->right, depth + 1); + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {number[][]} + */ + levelOrder(root) { + let res = []; + + /** + * @param {TreeNode} node + * @param {number} depth + */ + function dfs(node, depth) { + if (!node) return; + + if (res.length === depth) { + res.push([]); + } + + res[depth].push(node.val); + dfs(node.left, depth + 1); + dfs(node.right, depth + 1); + } + + dfs(root, 0); + return res; + } +} +``` + +```csharp +/** + * 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 { + List> res = new List>(); + + public List> LevelOrder(TreeNode root) { + dfs(root, 0); + return res; + } + + private void dfs(TreeNode node, int depth) { + if (node == null) { + return; + } + + if (res.Count == depth) { + res.Add(new List()); + } + + res[depth].Add(node.val); + dfs(node.left, depth + 1); + dfs(node.right, depth + 1); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Breadth First Search + +::tabs-start + +```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 levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + res = [] + + q = collections.deque() + q.append(root) + + while q: + qLen = len(q) + level = [] + for i in range(qLen): + node = q.popleft() + if node: + level.append(node.val) + q.append(node.left) + q.append(node.right) + if level: + res.append(level) + + return res +``` + +```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 List> levelOrder(TreeNode root) { + List> res = new ArrayList<>(); + + Queue q = new LinkedList<>(); + q.add(root); + + while (!q.isEmpty()) { + List level = new ArrayList<>(); + + for (int i = q.size(); i > 0; i--) { + TreeNode node = q.poll(); + if (node != null) { + level.add(node.val); + q.add(node.left); + q.add(node.right); + } + } + if (level.size() > 0) { + res.add(level); + } + } + return res; + } +} +``` + +```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: + vector> levelOrder(TreeNode* root) { + vector> res; + if (!root) return res; + + queue q; + q.push(root); + + while (!q.empty()) { + vector level; + int size = q.size(); + + for (int i = q.size(); i > 0; i--) { + TreeNode* node = q.front(); + q.pop(); + if (node) { + level.push_back(node->val); + q.push(node->left); + q.push(node->right); + } + } + if (!level.empty()) { + res.push_back(level); + } + } + return res; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {number[][]} + */ + levelOrder(root) { + let res = []; + if (!root) return res; + + const q = new Queue(); + q.push(root); + + while (!q.isEmpty()) { + let level = []; + + for (let i = q.size(); i > 0; i--) { + let node = q.pop(); + if (node !== null) { + level.push(node.val); + q.push(node.left); + q.push(node.right); + } + } + if (level.length > 0) { + res.push(level); + } + } + return res; + } +} +``` + +```csharp +/** + * 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 { + public List> LevelOrder(TreeNode root) { + List> res = new List>(); + if (root == null) return res; + + Queue q = new Queue(); + q.Enqueue(root); + + while (q.Count > 0) { + List level = new List(); + + for (int i = q.Count; i > 0; i--) { + TreeNode node = q.Dequeue(); + if (node != null) { + level.Add(node.val); + q.Enqueue(node.left); + q.Enqueue(node.right); + } + } + if (level.Count > 0) { + res.Add(level); + } + } + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/lowest-common-ancestor-in-binary-search-tree.md b/articles/lowest-common-ancestor-in-binary-search-tree.md new file mode 100644 index 000000000..298aba06e --- /dev/null +++ b/articles/lowest-common-ancestor-in-binary-search-tree.md @@ -0,0 +1,332 @@ +## 1. Recursion + +::tabs-start + +```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 lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode: + if not root or not p or not q: + return None + if (max(p.val, q.val) < root.val): + return self.lowestCommonAncestor(root.left, p, q) + elif (min(p.val, q.val) > root.val): + return self.lowestCommonAncestor(root.right, p, q) + else: + return root +``` + +```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; + * } + * } + */ + +public class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null || p == null || q == null) { + return null; + } + if (Math.max(p.val, q.val) < root.val) { + return lowestCommonAncestor(root.left, p, q); + } else if (Math.min(p.val, q.val) > root.val) { + return lowestCommonAncestor(root.right, p, q); + } else { + return root; + } + } +} +``` + +```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: + TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { + if (!root || !p || !q) { + return nullptr; + } + if (max(p->val, q->val) < root->val) { + return lowestCommonAncestor(root->left, p, q); + } else if (min(p->val, q->val) > root->val) { + return lowestCommonAncestor(root->right, p, q); + } else { + return root; + } + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @param {TreeNode} p + * @param {TreeNode} q + * @return {TreeNode} + */ + lowestCommonAncestor(root, p, q) { + if (!root || !p || !q) { + return null; + } + if (Math.max(p.val, q.val) < root.val) { + return this.lowestCommonAncestor(root.left, p, q); + } else if (Math.min(p.val, q.val) > root.val) { + return this.lowestCommonAncestor(root.right, p, q); + } else { + return root; + } + } +} +``` + +```csharp +/** + * 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 { + public TreeNode LowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (root == null || p == null || q == null) { + return null; + } + if (Math.Max(p.val, q.val) < root.val) { + return LowestCommonAncestor(root.left, p, q); + } else if (Math.Min(p.val, q.val) > root.val) { + return LowestCommonAncestor(root.right, p, q); + } else { + return root; + } + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(h)$ +* Space complexity: $O(h)$ + +> Where $h$ is the height of the tree. + +--- + +## 2. Iteration + +::tabs-start + +```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 lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode: + cur = root + + while cur: + if p.val > cur.val and q.val > cur.val: + cur = cur.right + elif p.val < cur.val and q.val < cur.val: + cur = cur.left + else: + return cur +``` + +```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; + * } + * } + */ + +public class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + TreeNode cur = root; + + while (cur != null) { + if (p.val > cur.val && q.val > cur.val) { + cur = cur.right; + } else if (p.val < cur.val && q.val < cur.val) { + cur = cur.left; + } else { + return cur; + } + } + return null; + } +} +``` + +```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: + TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { + TreeNode* cur = root; + + while (cur) { + if (p->val > cur->val && q->val > cur->val) { + cur = cur->right; + } else if (p->val < cur->val && q->val < cur->val) { + cur = cur->left; + } else { + return cur; + } + } + return nullptr; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @param {TreeNode} p + * @param {TreeNode} q + * @return {TreeNode} + */ + lowestCommonAncestor(root, p, q) { + let cur = root; + + while (cur) { + if (p.val > cur.val && q.val > cur.val) { + cur = cur.right; + } else if (p.val < cur.val && q.val < cur.val) { + cur = cur.left; + } else { + return cur; + } + } + return null; + } +} +``` + +```csharp +/** + * 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 { + public TreeNode LowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + TreeNode cur = root; + + while (cur != null) { + if (p.val > cur.val && q.val > cur.val) { + cur = cur.right; + } else if (p.val < cur.val && q.val < cur.val) { + cur = cur.left; + } else { + return cur; + } + } + return null; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(h)$ +* Space complexity: $O(1)$ + +> Where $h$ is the height of the tree. \ No newline at end of file diff --git a/articles/same-binary-tree.md b/articles/same-binary-tree.md new file mode 100644 index 000000000..1414d326d --- /dev/null +++ b/articles/same-binary-tree.md @@ -0,0 +1,358 @@ +## 1. Depth First Search + +::tabs-start + +```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 isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: + if not p and not q: + return True + if p and q and p.val == q.val: + return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right) + else: + return False +``` + +```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 isSameTree(TreeNode p, TreeNode q) { + if (p == null && q == null) { + return true; + } + if (p != null && q != null && p.val == q.val) { + return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); + } else { + return false; + } + } +} +``` + +```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 isSameTree(TreeNode* p, TreeNode* q) { + if (!p && !q) { + return true; + } + if (p && q && p->val == q->val) { + return isSameTree(p->left, q->left) && isSameTree(p->right, q->right); + } else { + return false; + } + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} p + * @param {TreeNode} q + * @return {boolean} + */ + isSameTree(p, q) { + if (!p && !q) { + return true; + } + if (p && q && p.val === q.val) { + return ( + this.isSameTree(p.left, q.left) && + this.isSameTree(p.right, q.right) + ); + } else { + return false; + } + } +} +``` + +```csharp +/** + * 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 { + public bool IsSameTree(TreeNode p, TreeNode q) { + if (p == null && q == null) { + return true; + } + if (p != null && q != null && p.val == q.val) { + return IsSameTree(p.left, q.left) && IsSameTree(p.right, q.right); + } else { + return false; + } + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Breadth First Search + +::tabs-start + +```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 isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: + q1 = deque([p]) + q2 = deque([q]) + + while q1 and q2: + nodeP = q1.popleft() + nodeQ = q2.popleft() + + if nodeP is None and nodeQ is None: + continue + if nodeP is None or nodeQ is None or nodeP.val != nodeQ.val: + return False + + q1.append(nodeP.left) + q1.append(nodeP.right) + q2.append(nodeQ.left) + q2.append(nodeQ.right) + + return True +``` + +```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; + * } + * } + */ + +public class Solution { + public boolean isSameTree(TreeNode p, TreeNode q) { + Queue q1 = new LinkedList<>(); + Queue q2 = new LinkedList<>(); + q1.add(p); + q2.add(q); + + while (!q1.isEmpty() && !q2.isEmpty()) { + TreeNode nodeP = q1.poll(); + TreeNode nodeQ = q2.poll(); + + if (nodeP == null && nodeQ == null) continue; + if (nodeP == null || nodeQ == null || nodeP.val != nodeQ.val) + return false; + + q1.add(nodeP.left); + q1.add(nodeP.right); + q2.add(nodeQ.left); + q2.add(nodeQ.right); + } + + return true; + } +} +``` + +```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 isSameTree(TreeNode* p, TreeNode* q) { + queue q1; + queue q2; + q1.push(p); + q2.push(q); + + while (!q1.empty() && !q2.empty()) { + TreeNode* nodeP = q1.front(); q1.pop(); + TreeNode* nodeQ = q2.front(); q2.pop(); + + if (!nodeP && !nodeQ) continue; + if (!nodeP || !nodeQ || nodeP->val != nodeQ->val) + return false; + + q1.push(nodeP->left); + q1.push(nodeP->right); + q2.push(nodeQ->left); + q2.push(nodeQ->right); + } + + return true; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} p + * @param {TreeNode} q + * @return {boolean} + */ + isSameTree(p, q) { + const q1 = new Queue(); + const q2 = new Queue(); + q1.push(p); + q2.push(q); + + while (!q1.isEmpty() && !q2.isEmpty()) { + let nodeP = q1.pop(); + let nodeQ = q2.pop(); + + if (nodeP === null && nodeQ === null) continue; + if (nodeP === null || nodeQ === null || nodeP.val !== nodeQ.val) + return false; + + q1.push(nodeP.left); + q1.push(nodeP.right); + q2.push(nodeQ.left); + q2.push(nodeQ.right); + } + + return true; + } +} +``` + +```csharp +/** + * 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 { + public bool IsSameTree(TreeNode p, TreeNode q) { + var q1 = new Queue(new[] { p }); + var q2 = new Queue(new[] { q }); + + while (q1.Count > 0 && q2.Count > 0) { + var nodeP = q1.Dequeue(); + var nodeQ = q2.Dequeue(); + + if (nodeP == null && nodeQ == null) continue; + if (nodeP == null || nodeQ == null || nodeP.val != nodeQ.val) + return false; + + q1.Enqueue(nodeP.left); + q1.Enqueue(nodeP.right); + q2.Enqueue(nodeQ.left); + q2.Enqueue(nodeQ.right); + } + + return true; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/subtree-of-a-binary-tree.md b/articles/subtree-of-a-binary-tree.md new file mode 100644 index 000000000..953edf76b --- /dev/null +++ b/articles/subtree-of-a-binary-tree.md @@ -0,0 +1,539 @@ +## 1. Brute Force (DFS) + +::tabs-start + +```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 isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: + if not subRoot: + return True + if not root: + return False + + if self.sameTree(root, subRoot): + return True + return (self.isSubtree(root.left, subRoot) or + self.isSubtree(root.right, subRoot)) + + def sameTree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: + if not root and not subRoot: + return True + if root and subRoot and root.val == subRoot.val: + return (self.sameTree(root.left, subRoot.left) and + self.sameTree(root.right, subRoot.right)) + return False +``` + +```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 isSubtree(TreeNode root, TreeNode subRoot) { + if (subRoot == null) { + return true; + } + if (root == null) { + return false; + } + + if (sameTree(root, subRoot)) { + return true; + } + return isSubtree(root.left, subRoot) || + isSubtree(root.right, subRoot); + } + + public boolean sameTree(TreeNode root, TreeNode subRoot) { + if (root == null && subRoot == null) { + return true; + } + if (root != null && subRoot != null && root.val == subRoot.val) { + return sameTree(root.left, subRoot.left) && + sameTree(root.right, subRoot.right); + } + return false; + } +} +``` + +```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 isSubtree(TreeNode* root, TreeNode* subRoot) { + if (!subRoot) { + return true; + } + if (!root) { + return false; + } + + if (sameTree(root, subRoot)) { + return true; + } + return isSubtree(root->left, subRoot) || + isSubtree(root->right, subRoot); + } + + bool sameTree(TreeNode* root, TreeNode* subRoot) { + if (!root && !subRoot) { + return true; + } + if (root && subRoot && root->val == subRoot->val) { + return sameTree(root->left, subRoot->left) && + sameTree(root->right, subRoot->right); + } + return false; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @param {TreeNode} subRoot + * @return {boolean} + */ + isSubtree(root, subRoot) { + if (!subRoot) { + return true; + } + if (!root) { + return false; + } + + if (this.sameTree(root, subRoot)) { + return true; + } + return ( + this.isSubtree(root.left, subRoot) || + this.isSubtree(root.right, subRoot) + ); + } + + /** + * @param {TreeNode} root + * @param {TreeNode} subRoot + * @return {boolean} + */ + sameTree(root, subRoot) { + if (!root && !subRoot) { + return true; + } + if (root && subRoot && root.val === subRoot.val) { + return ( + this.sameTree(root.left, subRoot.left) && + this.sameTree(root.right, subRoot.right) + ); + } + return false; + } +} +``` + +```csharp +/** + * 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 { + + public bool IsSubtree(TreeNode root, TreeNode subRoot) { + if (subRoot == null) { + return true; + } + if (root == null) { + return false; + } + + if (SameTree(root, subRoot)) { + return true; + } + return IsSubtree(root.left, subRoot) || + IsSubtree(root.right, subRoot); + } + + public bool SameTree(TreeNode root, TreeNode subRoot) { + if (root == null && subRoot == null) { + return true; + } + if (root != null && subRoot != null && root.val == subRoot.val) { + return SameTree(root.left, subRoot.left) && + SameTree(root.right, subRoot.right); + } + return false; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(m * n)$ +* Space complexity: $O(m + n)$ + +> Where $m$ is the number of nodes in $subRoot$ and $n$ is the number of nodes in $root$. + +--- + +## 2. Serialization And Pattern Matching + +::tabs-start + +```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 serialize(self, root: Optional[TreeNode]) -> str: + if root == None: + return "$#" + + return ("$" + str(root.val) + + self.serialize(root.left) + self.serialize(root.right)) + + def z_function(self, s: str) -> list: + z = [0] * len(s) + l, r, n = 0, 0, len(s) + for i in range(1, n): + if i <= r: + z[i] = min(r - i + 1, z[i - l]) + while i + z[i] < n and s[z[i]] == s[i + z[i]]: + z[i] += 1 + if i + z[i] - 1 > r: + l, r = i, i + z[i] - 1 + return z + + def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: + serialized_root = self.serialize(root) + serialized_subRoot = self.serialize(subRoot) + combined = serialized_subRoot + "|" + serialized_root + + z_values = self.z_function(combined) + sub_len = len(serialized_subRoot) + + for i in range(sub_len + 1, len(combined)): + if z_values[i] == sub_len: + return True + return False +``` + +```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; + * } + * } + */ + +public class Solution { + public String serialize(TreeNode root) { + if (root == null) { + return "$#"; + } + return "$" + root.val + serialize(root.left) + serialize(root.right); + } + + public int[] z_function(String s) { + int[] z = new int[s.length()]; + int l = 0, r = 0, n = s.length(); + for (int i = 1; i < n; i++) { + if (i <= r) { + z[i] = Math.min(r - i + 1, z[i - l]); + } + while (i + z[i] < n && s.charAt(z[i]) == s.charAt(i + z[i])) { + z[i]++; + } + if (i + z[i] - 1 > r) { + l = i; + r = i + z[i] - 1; + } + } + return z; + } + + public boolean isSubtree(TreeNode root, TreeNode subRoot) { + String serialized_root = serialize(root); + String serialized_subRoot = serialize(subRoot); + String combined = serialized_subRoot + "|" + serialized_root; + + int[] z_values = z_function(combined); + int sub_len = serialized_subRoot.length(); + + for (int i = sub_len + 1; i < combined.length(); i++) { + if (z_values[i] == sub_len) { + return true; + } + } + return false; + } +} +``` + +```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: + string serialize(TreeNode* root) { + if (root == nullptr) { + return "$#"; + } + return "$" + to_string(root->val) + + serialize(root->left) + serialize(root->right); + } + + vector z_function(string s) { + vector z(s.length()); + int l = 0, r = 0, n = s.length(); + for (int i = 1; i < n; i++) { + if (i <= r) { + z[i] = min(r - i + 1, z[i - l]); + } + while (i + z[i] < n && s[z[i]] == s[i + z[i]]) { + z[i]++; + } + if (i + z[i] - 1 > r) { + l = i; + r = i + z[i] - 1; + } + } + return z; + } + + bool isSubtree(TreeNode* root, TreeNode* subRoot) { + string serialized_root = serialize(root); + string serialized_subRoot = serialize(subRoot); + string combined = serialized_subRoot + "|" + serialized_root; + + vector z_values = z_function(combined); + int sub_len = serialized_subRoot.length(); + + for (int i = sub_len + 1; i < combined.length(); i++) { + if (z_values[i] == sub_len) { + return true; + } + } + return false; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {string} + */ + serialize(root) { + if (root === null) { + return "$#"; + } + return "$" + root.val + + this.serialize(root.left) + this.serialize(root.right); + } + + /** + * @param {string} s + * @return {number[]} + */ + z_function(s) { + const z = new Array(s.length).fill(0); + let l = 0, r = 0, n = s.length; + for (let i = 1; i < n; i++) { + if (i <= r) { + z[i] = Math.min(r - i + 1, z[i - l]); + } + while (i + z[i] < n && s[z[i]] === s[i + z[i]]) { + z[i]++; + } + if (i + z[i] - 1 > r) { + l = i; + r = i + z[i] - 1; + } + } + return z; + } + + /** + * @param {TreeNode} root + * @param {TreeNode} subRoot + * @return {boolean} + */ + isSubtree(root, subRoot) { + const serialized_root = this.serialize(root); + const serialized_subRoot = this.serialize(subRoot); + const combined = serialized_subRoot + "|" + serialized_root; + + const z_values = this.z_function(combined); + const sub_len = serialized_subRoot.length; + + for (let i = sub_len + 1; i < combined.length; i++) { + if (z_values[i] === sub_len) { + return true; + } + } + return false; + } +} +``` + +```csharp +/** + * 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 { + public string Serialize(TreeNode root) { + if (root == null) { + return "$#"; + } + return "$" + root.val + + Serialize(root.left) + Serialize(root.right); + } + + public int[] ZFunction(string s) { + int[] z = new int[s.Length]; + int l = 0, r = 0, n = s.Length; + for (int i = 1; i < n; i++) { + if (i <= r) { + z[i] = Math.Min(r - i + 1, z[i - l]); + } + while (i + z[i] < n && s[z[i]] == s[i + z[i]]) { + z[i]++; + } + if (i + z[i] - 1 > r) { + l = i; + r = i + z[i] - 1; + } + } + return z; + } + + public bool IsSubtree(TreeNode root, TreeNode subRoot) { + string serialized_root = Serialize(root); + string serialized_subRoot = Serialize(subRoot); + string combined = serialized_subRoot + "|" + serialized_root; + + int[] z_values = ZFunction(combined); + int sub_len = serialized_subRoot.Length; + + for (int i = sub_len + 1; i < combined.Length; i++) { + if (z_values[i] == sub_len) { + return true; + } + } + return false; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(m + n)$ +* Space complexity: $O(m + n)$ + +> Where $m$ is the number of nodes in $subRoot$ and $n$ is the number of nodes in $root$. \ No newline at end of file diff --git a/articles/valid-binary-search-tree.md b/articles/valid-binary-search-tree.md new file mode 100644 index 000000000..5ee96b0f3 --- /dev/null +++ b/articles/valid-binary-search-tree.md @@ -0,0 +1,656 @@ +## 1. Brute Force + +::tabs-start + +```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: + left_check = staticmethod(lambda val, limit: val < limit) + right_check = staticmethod(lambda val, limit: val > limit) + + def isValidBST(self, root: Optional[TreeNode]) -> bool: + if not root: + return True + + if (not self.isValid(root.left, root.val, self.left_check) or + not self.isValid(root.right, root.val, self.right_check)): + return False + + return self.isValidBST(root.left) and self.isValidBST(root.right) + + def isValid(self, root: Optional[TreeNode], limit: int, check) -> bool: + if not root: + return True + if not check(root.val, limit): + return False + return (self.isValid(root.left, limit, check) and + self.isValid(root.right, limit, check)) +``` + +```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; + * } + * } + */ + +public class Solution { + static boolean left_check(int val, int limit) { + return val < limit; + } + + static boolean right_check(int val, int limit) { + return val > limit; + } + + public boolean isValidBST(TreeNode root) { + if (root == null) { + return true; + } + + if (!isValid(root.left, root.val, Solution::left_check) || + !isValid(root.right, root.val, Solution::right_check)) { + return false; + } + + return isValidBST(root.left) && isValidBST(root.right); + } + + public boolean isValid(TreeNode root, int limit, CheckFunction check) { + if (root == null) { + return true; + } + if (!check.apply(root.val, limit)) { + return false; + } + return isValid(root.left, limit, check) && + isValid(root.right, limit, check); + } + + interface CheckFunction { + boolean apply(int val, int limit); + } +} +``` + +```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: + static bool left_check(int val, int limit) { + return val < limit; + } + + static bool right_check(int val, int limit) { + return val > limit; + } + + bool isValidBST(TreeNode* root) { + if (!root) { + return true; + } + + if (!isValid(root->left, root->val, left_check) || + !isValid(root->right, root->val, right_check)) { + return false; + } + + return isValidBST(root->left) && isValidBST(root->right); + } + + bool isValid(TreeNode* root, int limit, bool (*check)(int, int)) { + if (!root) { + return true; + } + if (!check(root->val, limit)) { + return false; + } + return isValid(root->left, limit, check) && + isValid(root->right, limit, check); + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {number} val + * @param {number} limit + * @returns {boolean} + */ + left_check(val, limit) { + return val < limit; + } + + /** + * @param {number} val + * @param {number} limit + * @returns {boolean} + */ + right_check(val, limit) { + return val > limit; + } + + /** + * @param {TreeNode} root + * @returns {boolean} + */ + isValidBST(root) { + if (!root) { + return true; + } + + if (!this.isValid(root.left, root.val, this.left_check) || + !this.isValid(root.right, root.val, this.right_check)) { + return false; + } + + return this.isValidBST(root.left) && this.isValidBST(root.right); + } + + /** + * @param {TreeNode} root + * @param {number} limit + * @param {function} check + * @returns {boolean} + */ + isValid(root, limit, check) { + if (!root) { + return true; + } + if (!check.call(this, root.val, limit)) { + return false; + } + return this.isValid(root.left, limit, check) && + this.isValid(root.right, limit, check); + } +} +``` + +```csharp +/** + * 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 { + static bool LeftCheck(int val, int limit) { + return val < limit; + } + + static bool RightCheck(int val, int limit) { + return val > limit; + } + + public bool IsValidBST(TreeNode root) { + if (root == null) { + return true; + } + + if (!IsValid(root.left, root.val, LeftCheck) || + !IsValid(root.right, root.val, RightCheck)) { + return false; + } + + return IsValidBST(root.left) && IsValidBST(root.right); + } + + public bool IsValid(TreeNode root, int limit, Func check) { + if (root == null) { + return true; + } + if (!check(root.val, limit)) { + return false; + } + return IsValid(root.left, limit, check) && + IsValid(root.right, limit, check); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n)$ + +--- + +## 2. Depth First Search + +::tabs-start + +```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 valid(node, left, right): + if not node: + return True + if not (left < node.val < right): + return False + + return valid(node.left, left, node.val) and valid( + node.right, node.val, right + ) + + return valid(root, float("-inf"), float("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; + * } + * } + */ + +public class Solution { + public boolean isValidBST(TreeNode root) { + return valid(root, Long.MIN_VALUE, Long.MAX_VALUE); + } + + public boolean valid(TreeNode node, long left, long right) { + if (node == null) { + return true; + } + if (!(left < node.val && node.val < right)) { + return false; + } + return valid(node.left, left, node.val) && + valid(node.right, node.val, right); + } +} +``` + +```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 valid(root, LONG_MIN, LONG_MAX); + } + + bool valid(TreeNode* node, long left, long right) { + if (!node) { + return true; + } + if (!(left < node->val && node->val < right)) { + return false; + } + return valid(node->left, left, node->val) && + valid(node->right, node->val, right); + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {boolean} + */ + isValidBST(root) { + return this.valid(root, -Infinity, Infinity); + } + + /** + * @param {TreeNode} node + * @param {number} left + * @param {number} right + */ + valid(node, left, right) { + if (node === null) { + return true; + } + if (!(left < node.val && node.val < right)) { + return false; + } + return this.valid(node.left, left, node.val) && + this.valid(node.right, node.val, right); + } +} +``` + +```csharp +/** + * 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 { + public bool IsValidBST(TreeNode root) { + return valid(root, long.MinValue, long.MaxValue); + } + + public bool valid(TreeNode node, long left, long right) { + if (node == null) { + return true; + } + if (!(left < node.val && node.val < right)) { + return false; + } + return valid(node.left, left, node.val) && + valid(node.right, node.val, right); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Breadth First Search + +::tabs-start + +```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: + if not root: + return True + + q = deque([(root, float("-inf"), float("inf"))]) + + while q: + node, left, right = q.popleft() + if not (left < node.val < right): + return False + if node.left: + q.append((node.left, left, node.val)) + if node.right: + q.append((node.right, node.val, right)) + + return True +``` + +```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; + * } + * } + */ + +public class Solution { + public boolean isValidBST(TreeNode root) { + if (root == null) { + return true; + } + + Queue queue = new LinkedList<>(); + queue.offer(new Object[]{root, Long.MIN_VALUE, Long.MAX_VALUE}); + + while (!queue.isEmpty()) { + Object[] current = queue.poll(); + TreeNode node = (TreeNode) current[0]; + long left = (long) current[1]; + long right = (long) current[2]; + + if (!(left < node.val && node.val < right)) { + return false; + } + + if (node.left != null) { + queue.offer(new Object[]{node.left, left, (long) node.val}); + } + if (node.right != null) { + queue.offer(new Object[]{node.right, (long) node.val, right}); + } + } + + return true; + } +} +``` + +```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) { + if (!root) { + return true; + } + + queue> queue; + queue.push(make_tuple(root, LONG_MIN, LONG_MAX)); + + while (!queue.empty()) { + auto [node, left, right] = queue.front(); + queue.pop(); + + if (!(left < node->val && node->val < right)) { + return false; + } + if (node->left) { + queue.push(make_tuple(node->left, left, node->val)); + } + if (node->right) { + queue.push(make_tuple(node->right, node->val, right)); + } + } + + return true; + } +}; +``` + +```javascript +/** + * Definition for a binary tree node. + * class TreeNode { + * constructor(val = 0, left = null, right = null) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ + +class Solution { + /** + * @param {TreeNode} root + * @return {boolean} + */ + isValidBST(root) { + if (root === null) { + return true; + } + + const queue = new Queue([[root, -Infinity, Infinity]]); + + while (queue.size() > 0) { + const [node, left, right] = queue.pop(); + + if (!(left < node.val && node.val < right)) { + return false; + } + if (node.left) { + queue.push([node.left, left, node.val]); + } + if (node.right) { + queue.push([node.right, node.val, right]); + } + } + + return true; + } +} +``` + +```csharp +/** + * 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 { + public bool IsValidBST(TreeNode root) { + if (root == null) { + return true; + } + + Queue<(TreeNode node, long left, long right)> queue = new Queue<(TreeNode, long, long)>(); + queue.Enqueue((root, long.MinValue, long.MaxValue)); + + while (queue.Count > 0) { + var (node, left, right) = queue.Dequeue(); + + if (!(left < node.val && node.val < right)) { + return false; + } + if (node.left != null) { + queue.Enqueue((node.left, left, node.val)); + } + if (node.right != null) { + queue.Enqueue((node.right, node.val, right)); + } + } + + return true; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy