diff --git a/articles/binary-tree-from-preorder-and-inorder-traversal.md b/articles/binary-tree-from-preorder-and-inorder-traversal.md new file mode 100644 index 000000000..5886b2cdd --- /dev/null +++ b/articles/binary-tree-from-preorder-and-inorder-traversal.md @@ -0,0 +1,565 @@ +## 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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + if not preorder or not inorder: + return None + + root = TreeNode(preorder[0]) + mid = inorder.index(preorder[0]) + root.left = self.buildTree(preorder[1 : mid + 1], inorder[:mid]) + root.right = self.buildTree(preorder[mid + 1 :], inorder[mid + 1 :]) + 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; + * } + * } + */ + +class Solution { + public TreeNode buildTree(int[] preorder, int[] inorder) { + if (preorder.length == 0 || inorder.length == 0) { + return null; + } + + TreeNode root = new TreeNode(preorder[0]); + int mid = -1; + for (int i = 0; i < inorder.length; i++) { + if (inorder[i] == preorder[0]) { + mid = i; + break; + } + } + + int[] leftPreorder = Arrays.copyOfRange(preorder, 1, mid + 1); + int[] leftInorder = Arrays.copyOfRange(inorder, 0, mid); + root.left = buildTree(leftPreorder, leftInorder); + + int[] rightPreorder = Arrays.copyOfRange(preorder, mid + 1, preorder.length); + int[] rightInorder = Arrays.copyOfRange(inorder, mid + 1, inorder.length); + root.right = buildTree(rightPreorder, rightInorder); + + 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* buildTree(vector& preorder, vector& inorder) { + if (preorder.empty() || inorder.empty()) { + return nullptr; + } + + TreeNode* root = new TreeNode(preorder[0]); + auto mid = find(inorder.begin(), inorder.end(), preorder[0]) - inorder.begin(); + vector leftPre(preorder.begin() + 1, preorder.begin() + mid + 1); + vector rightPre(preorder.begin() + mid + 1, preorder.end()); + vector leftIn(inorder.begin(), inorder.begin() + mid); + vector rightIn(inorder.begin() + mid + 1, inorder.end()); + root->left = buildTree(leftPre, leftIn); + root->right = buildTree(rightPre, rightIn); + 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 {number[]} preorder + * @param {number[]} inorder + * @return {TreeNode} + */ + buildTree(preorder, inorder) { + if (!preorder.length || !inorder.length) { + return null; + } + + let root = new TreeNode(preorder[0]); + let mid = inorder.indexOf(preorder[0]); + root.left = this.buildTree( + preorder.slice(1, mid + 1), + inorder.slice(0, mid), + ); + root.right = this.buildTree( + preorder.slice(mid + 1), + inorder.slice(mid + 1), + ); + 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 BuildTree(int[] preorder, int[] inorder) { + if (preorder.Length == 0 || inorder.Length == 0) { + return null; + } + + TreeNode root = new TreeNode(preorder[0]); + int mid = Array.IndexOf(inorder, preorder[0]); + root.left = BuildTree(preorder.Skip(1).Take(mid).ToArray(), inorder.Take(mid).ToArray()); + root.right = BuildTree(preorder.Skip(mid + 1).ToArray(), inorder.Skip(mid + 1).ToArray()); + return root; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n ^ 2)$ + +--- + +## 2. Hash Map + +::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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + indices = {val: idx for idx, val in enumerate(inorder)} + + self.pre_idx = 0 + def dfs(l, r): + if l > r: + return None + + root_val = preorder[self.pre_idx] + self.pre_idx += 1 + root = TreeNode(root_val) + mid = indices[root_val] + root.left = dfs(l, mid - 1) + root.right = dfs(mid + 1, r) + return root + + return dfs(0, len(inorder) - 1) +``` + +```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 { + int pre_idx = 0; + HashMap indices = new HashMap<>(); + + public TreeNode buildTree(int[] preorder, int[] inorder) { + for (int i = 0; i < inorder.length; i++) { + indices.put(inorder[i], i); + } + return dfs(preorder, 0, inorder.length - 1); + } + + private TreeNode dfs(int[] preorder, int l, int r) { + if (l > r) return null; + int root_val = preorder[pre_idx++]; + TreeNode root = new TreeNode(root_val); + int mid = indices.get(root_val); + root.left = dfs(preorder, l, mid - 1); + root.right = dfs(preorder, mid + 1, r); + 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 { + int pre_idx = 0; + unordered_map indices; + + TreeNode* dfs(vector& preorder, int l, int r) { + if (l > r) return nullptr; + int root_val = preorder[pre_idx++]; + TreeNode* root = new TreeNode(root_val); + int mid = indices[root_val]; + root->left = dfs(preorder, l, mid - 1); + root->right = dfs(preorder, mid + 1, r); + return root; + } + +public: + TreeNode* buildTree(vector& preorder, vector& inorder) { + for (int i = 0; i < inorder.size(); ++i) { + indices[inorder[i]] = i; + } + return dfs(preorder, 0, inorder.size() - 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 {number[]} preorder + * @param {number[]} inorder + * @return {TreeNode} + */ + buildTree(preorder, inorder) { + let pre_idx = 0; + let indices = new Map(); + + inorder.forEach((val, i) => indices.set(val, i)); + + function dfs(l, r) { + if (l > r) return null; + let root_val = preorder[pre_idx++]; + let root = new TreeNode(root_val); + let mid = indices.get(root_val); + root.left = dfs(l, mid - 1); + root.right = dfs(mid + 1, r); + return root; + } + + return dfs(0, inorder.length - 1); + } +} +``` + +```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 { + int pre_idx = 0; + Dictionary indices = new Dictionary(); + + public TreeNode BuildTree(int[] preorder, int[] inorder) { + for (int i = 0; i < inorder.Length; i++) { + indices[inorder[i]] = i; + } + return Dfs(preorder, 0, inorder.Length - 1); + } + + private TreeNode Dfs(int[] preorder, int l, int r) { + if (l > r) return null; + int root_val = preorder[pre_idx++]; + TreeNode root = new TreeNode(root_val); + int mid = indices[root_val]; + root.left = Dfs(preorder, l, mid - 1); + root.right = Dfs(preorder, mid + 1, r); + return root; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Depth First Search (Optimal) + +::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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + preIdx = inIdx = 0 + def dfs(limit): + nonlocal preIdx, inIdx + if preIdx >= len(preorder): + return None + if inorder[inIdx] == limit: + inIdx += 1 + return None + + root = TreeNode(preorder[preIdx]) + preIdx += 1 + root.left = dfs(root.val) + root.right = dfs(limit) + return root + return dfs(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 { + int preIdx = 0; + int inIdx = 0; + + public TreeNode buildTree(int[] preorder, int[] inorder) { + return dfs(preorder, inorder, Integer.MAX_VALUE); + } + + private TreeNode dfs(int[] preorder, int[] inorder, int limit) { + if (preIdx >= preorder.length) return null; + if (inorder[inIdx] == limit) { + inIdx++; + return null; + } + + TreeNode root = new TreeNode(preorder[preIdx++]); + root.left = dfs(preorder, inorder, root.val); + root.right = dfs(preorder, inorder, limit); + 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 { + int preIdx = 0; + int inIdx = 0; + + TreeNode* dfs(vector& preorder, vector& inorder, int limit) { + if (preIdx >= preorder.size()) return nullptr; + if (inorder[inIdx] == limit) { + inIdx++; + return nullptr; + } + + TreeNode* root = new TreeNode(preorder[preIdx++]); + root->left = dfs(preorder, inorder, root->val); + root->right = dfs(preorder, inorder, limit); + return root; + } + +public: + TreeNode* buildTree(vector& preorder, vector& inorder) { + return dfs(preorder, inorder, INT_MAX); + } +}; +``` + +```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[]} preorder + * @param {number[]} inorder + * @return {TreeNode} + */ + buildTree(preorder, inorder) { + let preIdx = 0, inIdx = 0; + + function dfs(limit) { + if (preIdx >= preorder.length) return null; + if (inorder[inIdx] === limit) { + inIdx++; + return null; + } + + let root = new TreeNode(preorder[preIdx++]); + root.left = dfs(root.val); + root.right = dfs(limit); + return root; + } + + return dfs(Infinity); + } +} +``` + +```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 { + int preIdx = 0; + int inIdx = 0; + + public TreeNode BuildTree(int[] preorder, int[] inorder) { + return Dfs(preorder, inorder, int.MaxValue); + } + + private TreeNode Dfs(int[] preorder, int[] inorder, int limit) { + if (preIdx >= preorder.Length) return null; + if (inorder[inIdx] == limit) { + inIdx++; + return null; + } + + TreeNode root = new TreeNode(preorder[preIdx++]); + root.left = Dfs(preorder, inorder, root.val); + root.right = Dfs(preorder, inorder, limit); + return root; + } +} +``` + +::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-maximum-path-sum.md b/articles/binary-tree-maximum-path-sum.md new file mode 100644 index 000000000..20bce94b0 --- /dev/null +++ b/articles/binary-tree-maximum-path-sum.md @@ -0,0 +1,408 @@ +## 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 maxPathSum(self, root: Optional[TreeNode]) -> int: + res = -float('inf') + def dfs(root): + nonlocal res + if not root: + return + left = self.getMax(root.left) + right = self.getMax(root.right) + res =max(res, root.val + left + right) + dfs(root.left) + dfs(root.right) + dfs(root) + return res + + def getMax(self, root: Optional[TreeNode]) -> int: + if not root: + return 0 + + left = self.getMax(root.left) + right = self.getMax(root.right) + path = root.val + max(left, right) + return max(0, path) +``` + +```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 { + int res = Integer.MIN_VALUE; + + public int maxPathSum(TreeNode root) { + dfs(root); + return res; + } + + private int getMax(TreeNode root) { + if (root == null) return 0; + int left = getMax(root.left); + int right = getMax(root.right); + int path = root.val + Math.max(left, right); + return Math.max(0, path); + } + + private void dfs(TreeNode root) { + if (root == null) return; + int left = getMax(root.left); + int right = getMax(root.right); + res = Math.max(res, root.val + left + right); + dfs(root.left); + dfs(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 { + int res = INT_MIN; + + int getMax(TreeNode* root) { + if (!root) return 0; + int left = getMax(root->left); + int right = getMax(root->right); + int path = root->val + std::max(left, right); + return std::max(0, path); + } + + void dfs(TreeNode* root) { + if (!root) return; + int left = getMax(root->left); + int right = getMax(root->right); + res = std::max(res, root->val + left + right); + dfs(root->left); + dfs(root->right); + } + +public: + int maxPathSum(TreeNode* root) { + dfs(root); + 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} + */ + maxPathSum(root) { + let res = -Infinity; + + function getMax(root) { + if (!root) return 0; + let left = getMax(root.left); + let right = getMax(root.right); + let path = root.val + Math.max(left, right); + return Math.max(0, path); + } + + function dfs(root) { + if (!root) return; + let left = getMax(root.left); + let right = getMax(root.right); + res = Math.max(res, root.val + left + right); + dfs(root.left); + dfs(root.right); + } + + dfs(root); + 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 { + int res = int.MinValue; + + public int MaxPathSum(TreeNode root) { + dfs(root); + return res; + } + + private int GetMax(TreeNode root) { + if (root == null) return 0; + int left = GetMax(root.left); + int right = GetMax(root.right); + int path = root.val + Math.Max(left, right); + return Math.Max(0, path); + } + + private void dfs(TreeNode root) { + if (root == null) return; + int left = GetMax(root.left); + int right = GetMax(root.right); + res = Math.Max(res, root.val + left + right); + dfs(root.left); + dfs(root.right); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n)$ + +--- + +## 2. Depth First Search (Optimal) + +::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 maxPathSum(self, root: Optional[TreeNode]) -> int: + res = [root.val] + + def dfs(root): + if not root: + return 0 + + leftMax = dfs(root.left) + rightMax = dfs(root.right) + leftMax = max(leftMax, 0) + rightMax = max(rightMax, 0) + + res[0] = max(res[0], root.val + leftMax + rightMax) + return root.val + max(leftMax, rightMax) + + dfs(root) + return res[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; + * } + * } + */ + +public class Solution { + + public int maxPathSum(TreeNode root) { + int[] res = new int[]{root.val}; + dfs(root, res); + return res[0]; + } + + private int dfs(TreeNode root, int[] res) { + if (root == null) { + return 0; + } + + int leftMax = Math.max(dfs(root.left, res), 0); + int rightMax = Math.max(dfs(root.right, res), 0); + + res[0] = Math.max(res[0], root.val + leftMax + rightMax); + return root.val + Math.max(leftMax, rightMax); + } +} +``` + +```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 maxPathSum(TreeNode* root) { + int res = root->val; + dfs(root, res); + return res; + } + +private: + int dfs(TreeNode* root, int& res) { + if (!root) { + return 0; + } + + int leftMax = max(dfs(root->left, res), 0); + int rightMax = max(dfs(root->right, res), 0); + + res = max(res, root->val + leftMax + rightMax); + return root->val + max(leftMax, rightMax); + } +}; +``` + +```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} + */ + maxPathSum(root) { + const res = [root.val]; + this.dfs(root, res); + return res[0]; + } + + /** + * @param {TreeNode} root + * @param {number[]} res + * @return {number} + */ + dfs(root, res) { + if (root === null) { + return 0; + } + + const leftMax = Math.max(this.dfs(root.left, res), 0); + const rightMax = Math.max(this.dfs(root.right, res), 0); + + res[0] = Math.max(res[0], root.val + leftMax + rightMax); + return root.val + Math.max(leftMax, rightMax); + } +} +``` + +```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 MaxPathSum(TreeNode root) { + int res = root.val; + Dfs(root, ref res); + return res; + } + + private int Dfs(TreeNode root, ref int res) { + if (root == null) { + return 0; + } + + int leftMax = Math.Max(Dfs(root.left, ref res), 0); + int rightMax = Math.Max(Dfs(root.right, ref res), 0); + + res = Math.Max(res, root.val + leftMax + rightMax); + return root.val + Math.Max(leftMax, rightMax); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/kth-largest-integer-in-a-stream.md b/articles/kth-largest-integer-in-a-stream.md new file mode 100644 index 000000000..eda4c1da1 --- /dev/null +++ b/articles/kth-largest-integer-in-a-stream.md @@ -0,0 +1,253 @@ +## 1. Sorting + +::tabs-start + +```python +class KthLargest: + + def __init__(self, k: int, nums: List[int]): + self.k = k + self.arr = nums + + def add(self, val: int) -> int: + self.arr.append(val) + self.arr.sort() + return self.arr[len(self.arr) - self.k] +``` + +```java +class KthLargest { + List arr; + int K; + public KthLargest(int k, int[] nums) { + K = k; + arr = new ArrayList(); + for (int i = 0; i < nums.length; i++) { + arr.add(nums[i]); + } + } + + public int add(int val) { + arr.add(val); + Collections.sort(arr); + return arr.get(arr.size() - K); + } +} +``` + +```cpp +class KthLargest { +public: + vector arr; + int k; + KthLargest(int k, vector& nums) { + this->arr = nums; + this->k = k; + } + + int add(int val) { + arr.push_back(val); + sort(arr.begin(), arr.end()); + return arr[arr.size() - k]; + } +}; +``` + +```javascript +class KthLargest { + /** + * @param {number} k + * @param {number[]} nums + */ + constructor(k, nums) { + this.arr = nums; + this.k = k; + } + + /** + * @param {number} val + * @return {number} + */ + add(val) { + this.arr.push(val); + this.arr.sort((a, b) => a - b); + return this.arr[this.arr.length - this.k]; + } +} +``` + +```csharp +public class KthLargest { + private List arr; + private int K; + + public KthLargest(int k, int[] nums) { + arr = new List(nums); + K = k; + } + + public int Add(int val) { + arr.Add(val); + arr.Sort(); + return arr[arr.Count - K]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(m * n\log n)$ +* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. + +> Where $m$ is the number of calls made to $add()$ and $n$ is the current size of the array. + +--- + +## 2. Heap + +::tabs-start + +```python +class KthLargest: + + def __init__(self, k: int, nums: List[int]): + self.minHeap, self.k = nums, k + heapq.heapify(self.minHeap) + while len(self.minHeap) > k: + heapq.heappop(self.minHeap) + + def add(self, val: int) -> int: + heapq.heappush(self.minHeap, val) + if len(self.minHeap) > self.k: + heapq.heappop(self.minHeap) + return self.minHeap[0] +``` + +```java +class KthLargest { + + private PriorityQueue minHeap; + private int k; + + public KthLargest(int k, int[] nums) { + this.k = k; + this.minHeap = new PriorityQueue<>(); + for (int num : nums) { + minHeap.offer(num); + if (minHeap.size() > k) { + minHeap.poll(); + } + } + } + + public int add(int val) { + minHeap.offer(val); + if (minHeap.size() > k) { + minHeap.poll(); + } + return minHeap.peek(); + } +} +``` + +```cpp +class KthLargest { +private: + priority_queue, greater> minHeap; + int k; + +public: + KthLargest(int k, vector& nums) { + this->k = k; + for (int num : nums) { + minHeap.push(num); + if (minHeap.size() > k) { + minHeap.pop(); + } + } + } + + int add(int val) { + minHeap.push(val); + if (minHeap.size() > k) { + minHeap.pop(); + } + return minHeap.top(); + } +}; +``` + +```javascript +/** + * const { MinPriorityQueue } = require('@datastructures-js/priority-queue'); + */ + +class KthLargest { + /** + * @param {number} k + * @param {number[]} nums + */ + constructor(k, nums) { + this.minHeap = new MinPriorityQueue(); + this.k = k; + + for (const num of nums) { + this.minHeap.enqueue(num); + } + + while (this.minHeap.size() > k) { + this.minHeap.dequeue(); + } + } + + /** + * @param {number} val + * @return {number} + */ + add(val) { + this.minHeap.enqueue(val); + if (this.minHeap.size() > this.k) { + this.minHeap.dequeue(); + } + return this.minHeap.front(); + } +} +``` + +```csharp +public class KthLargest { + + private PriorityQueue minHeap; + private int k; + + public KthLargest(int k, int[] nums) { + this.k = k; + this.minHeap = new PriorityQueue(); + foreach (int num in nums) { + minHeap.Enqueue(num, num); + if (minHeap.Count > k) { + minHeap.Dequeue(); + } + } + } + + public int Add(int val) { + minHeap.Enqueue(val, val); + if (minHeap.Count > k) { + minHeap.Dequeue(); + } + return minHeap.Peek(); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(m * \log k)$ +* Space complexity: $O(k)$ + +> Where $m$ is the number of calls made to $add()$. \ No newline at end of file diff --git a/articles/kth-smallest-integer-in-bst.md b/articles/kth-smallest-integer-in-bst.md new file mode 100644 index 000000000..08ab8e7fc --- /dev/null +++ b/articles/kth-smallest-integer-in-bst.md @@ -0,0 +1,965 @@ +## 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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int: + arr = [] + + def dfs(node): + if not node: + return + + arr.append(node.val) + dfs(node.left) + dfs(node.right) + + dfs(root) + arr.sort() + return arr[k - 1] +``` + +```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 kthSmallest(TreeNode root, int k) { + List arr = new ArrayList<>(); + + dfs(root, arr); + Collections.sort(arr); + return arr.get(k - 1); + } + + private void dfs(TreeNode node, List arr) { + if (node == null) { + return; + } + + arr.add(node.val); + dfs(node.left, arr); + dfs(node.right, arr); + } +} +``` + +```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 kthSmallest(TreeNode* root, int k) { + vector arr; + dfs(root, arr); + sort(arr.begin(), arr.end()); + return arr[k - 1]; + } + + void dfs(TreeNode* node, vector& arr) { + if (!node) return; + arr.push_back(node->val); + dfs(node->left, arr); + dfs(node->right, arr); + } +}; +``` + +```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 {number} k + * @return {number} + */ + kthSmallest(root, k) { + const arr = []; + this.dfs(root, arr); + arr.sort((a, b) => a - b); + return arr[k - 1]; + } + + /** + * @param {TreeNode} node + * @param {number[]} arr + */ + dfs(node, arr) { + if (!node) return; + arr.push(node.val); + this.dfs(node.left, arr); + this.dfs(node.right, arr); + } +} +``` + +```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 KthSmallest(TreeNode root, int k) { + List arr = new List(); + Dfs(root, arr); + arr.Sort(); + return arr[k - 1]; + } + + private void Dfs(TreeNode node, List arr) { + if (node == null) return; + arr.Add(node.val); + Dfs(node.left, arr); + Dfs(node.right, arr); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ + +--- + +## 2. Inorder Traversal + +::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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int: + arr = [] + + def dfs(node): + if not node: + return + + dfs(node.left) + arr.append(node.val) + dfs(node.right) + + dfs(root) + return arr[k - 1] +``` + +```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 kthSmallest(TreeNode root, int k) { + List arr = new ArrayList<>(); + + dfs(root, arr); + return arr.get(k - 1); + } + + private void dfs(TreeNode node, List arr) { + if (node == null) { + return; + } + + dfs(node.left, arr); + arr.add(node.val); + dfs(node.right, arr); + } +} +``` + +```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 kthSmallest(TreeNode* root, int k) { + vector arr; + dfs(root, arr); + return arr[k - 1]; + } + + void dfs(TreeNode* node, vector& arr) { + if (!node) return; + dfs(node->left, arr); + arr.push_back(node->val); + dfs(node->right, arr); + } +}; +``` + +```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 {number} k + * @return {number} + */ + kthSmallest(root, k) { + const arr = []; + this.dfs(root, arr); + return arr[k - 1]; + } + + /** + * @param {TreeNode} node + * @param {number[]} arr + */ + dfs(node, arr) { + if (!node) return; + this.dfs(node.left, arr); + arr.push(node.val); + this.dfs(node.right, arr); + } +} +``` + +```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 KthSmallest(TreeNode root, int k) { + List arr = new List(); + Dfs(root, arr); + return arr[k - 1]; + } + + private void Dfs(TreeNode node, List arr) { + if (node == null) return; + Dfs(node.left, arr); + arr.Add(node.val); + Dfs(node.right, arr); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. Recursive DFS (Optimal) + +::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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int: + cnt = k + res = root.val + + def dfs(node): + nonlocal cnt, res + if not node: + return + + dfs(node.left) + cnt -= 1 + if cnt == 0: + res = node.val + return + dfs(node.right) + + dfs(root) + 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 kthSmallest(TreeNode root, int k) { + int[] tmp = new int[2]; + tmp[0] = k; + dfs(root, tmp); + return tmp[1]; + } + + private void dfs(TreeNode node, int[] tmp) { + if (node == null) { + return; + } + + dfs(node.left, tmp); + tmp[0] -= 1; + if (tmp[0] == 0) { + tmp[1] = node.val; + return; + } + dfs(node.right, tmp); + } +} +``` + +```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 kthSmallest(TreeNode* root, int k) { + vector tmp(2); + tmp[0] = k; + dfs(root, tmp); + return tmp[1]; + } + + void dfs(TreeNode* node, vector& tmp) { + if (!node) return; + dfs(node->left, tmp); + tmp[0]--; + if (tmp[0] == 0) { + tmp[1] = node->val; + return; + } + dfs(node->right, tmp); + } +}; +``` + +```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 {number} k + * @return {number} + */ + kthSmallest(root, k) { + const tmp = new Int32Array(2); + tmp[0] = k; + this.dfs(root, tmp); + return tmp[1]; + } + + /** + * @param {TreeNode} node + * @param {number[]} tmp + */ + dfs(node, tmp) { + if (!node) return; + this.dfs(node.left, tmp); + tmp[0]--; + if (tmp[0] === 0) { + tmp[1] = node.val; + return; + } + this.dfs(node.right, tmp); + } +} +``` + +```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 KthSmallest(TreeNode root, int k) { + int[] tmp = new int[2]; + tmp[0] = k; + Dfs(root, tmp); + return tmp[1]; + } + + private void Dfs(TreeNode node, int[] tmp) { + if (node == null) return; + Dfs(node.left, tmp); + tmp[0]--; + if (tmp[0] == 0) { + tmp[1] = node.val; + return; + } + Dfs(node.right, tmp); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 4. Iterative DFS (Optimal) + +::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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int: + stack = [] + curr = root + + while stack or curr: + while curr: + stack.append(curr) + curr = curr.left + curr = stack.pop() + k -= 1 + if k == 0: + return curr.val + curr = curr.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 int kthSmallest(TreeNode root, int k) { + Stack stack = new Stack<>(); + TreeNode curr = root; + + while (!stack.isEmpty() || curr != null) { + while (curr != null) { + stack.push(curr); + curr = curr.left; + } + curr = stack.pop(); + k--; + if (k == 0) { + return curr.val; + } + curr = curr.right; + } + + return -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: + int kthSmallest(TreeNode* root, int k) { + stack stack; + TreeNode* curr = root; + + while (!stack.empty() || curr != nullptr) { + while (curr != nullptr) { + stack.push(curr); + curr = curr->left; + } + curr = stack.top(); + stack.pop(); + k--; + if (k == 0) { + return curr->val; + } + curr = curr->right; + } + + return -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 + * @param {number} k + * @return {number} + */ + kthSmallest(root, k) { + let stack = []; + let curr = root; + + while (stack.length > 0 || curr !== null) { + while (curr !== null) { + stack.push(curr); + curr = curr.left; + } + curr = stack.pop(); + k--; + if (k === 0) { + return curr.val; + } + curr = curr.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 int KthSmallest(TreeNode root, int k) { + Stack stack = new Stack(); + TreeNode curr = root; + + while (stack.Count > 0 || curr != null) { + while (curr != null) { + stack.Push(curr); + curr = curr.left; + } + curr = stack.Pop(); + k--; + if (k == 0) { + return curr.val; + } + curr = curr.right; + } + + return -1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 5. Morris Traversal + +::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 kthSmallest(self, root: Optional[TreeNode], k: int) -> int: + curr = root + + while curr: + if not curr.left: + k -= 1 + if k == 0: + return curr.val + curr = curr.right + else: + pred = curr.left + while pred.right and pred.right != curr: + pred = pred.right + + if not pred.right: + pred.right = curr + curr = curr.left + else: + pred.right = None + k -= 1 + if k == 0: + return curr.val + curr = curr.right + + return -1 +``` + +```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 kthSmallest(TreeNode root, int k) { + TreeNode curr = root; + + while (curr != null) { + if (curr.left == null) { + k--; + if (k == 0) return curr.val; + curr = curr.right; + } else { + TreeNode pred = curr.left; + while (pred.right != null && pred.right != curr) + pred = pred.right; + + if (pred.right == null) { + pred.right = curr; + curr = curr.left; + } else { + pred.right = null; + k--; + if (k == 0) return curr.val; + curr = curr.right; + } + } + } + return -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: + int kthSmallest(TreeNode* root, int k) { + TreeNode* curr = root; + + while (curr) { + if (!curr->left) { + k--; + if (k == 0) return curr->val; + curr = curr->right; + } else { + TreeNode* pred = curr->left; + while (pred->right && pred->right != curr) + pred = pred->right; + + if (!pred->right) { + pred->right = curr; + curr = curr->left; + } else { + pred->right = nullptr; + k--; + if (k == 0) return curr->val; + curr = curr->right; + } + } + } + return -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 + * @param {number} k + * @return {number} + */ + kthSmallest(root, k) { + let curr = root; + + while (curr) { + if (!curr.left) { + k--; + if (k === 0) return curr.val; + curr = curr.right; + } else { + let pred = curr.left; + while (pred.right && pred.right !== curr) + pred = pred.right; + + if (!pred.right) { + pred.right = curr; + curr = curr.left; + } else { + pred.right = null; + k--; + if (k === 0) return curr.val; + curr = curr.right; + } + } + } + return -1; + } +} +``` + +```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 KthSmallest(TreeNode root, int k) { + TreeNode curr = root; + + while (curr != null) { + if (curr.left == null) { + k--; + if (k == 0) return curr.val; + curr = curr.right; + } else { + TreeNode pred = curr.left; + while (pred.right != null && pred.right != curr) + pred = pred.right; + + if (pred.right == null) { + pred.right = curr; + curr = curr.left; + } else { + pred.right = null; + k--; + if (k == 0) return curr.val; + curr = curr.right; + } + } + } + return -1; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/last-stone-weight.md b/articles/last-stone-weight.md new file mode 100644 index 000000000..e66544028 --- /dev/null +++ b/articles/last-stone-weight.md @@ -0,0 +1,620 @@ +## 1. Sorting + +::tabs-start + +```python +class Solution: + def lastStoneWeight(self, stones: List[int]) -> int: + + while len(stones) > 1: + stones.sort() + cur = stones.pop() - stones.pop() + if cur: + stones.append(cur) + + return stones[0] if stones else 0 +``` + +```java +public class Solution { + public int lastStoneWeight(int[] stones) { + List stoneList = new ArrayList<>(); + for (int stone : stones) { + stoneList.add(stone); + } + + while (stoneList.size() > 1) { + Collections.sort(stoneList); + int cur = stoneList.remove(stoneList.size() - 1) - + stoneList.remove(stoneList.size() - 1); + if (cur != 0) { + stoneList.add(cur); + } + } + + return stoneList.isEmpty() ? 0 : stoneList.get(0); + } +} +``` + +```cpp +class Solution { +public: + int lastStoneWeight(vector& stones) { + while (stones.size() > 1) { + sort(stones.begin(), stones.end()); + int cur = stones.back() - stones[stones.size() - 2]; + stones.pop_back(); + stones.pop_back(); + if (cur != 0) { + stones.push_back(cur); + } + } + return stones.empty() ? 0 : stones[0]; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} stones + * @return {number} + */ + lastStoneWeight(stones) { + while (stones.length > 1) { + stones.sort((a, b) => a - b); + let cur = stones.pop() - stones.pop(); + if (cur) { + stones.push(cur); + } + } + return stones.length ? stones[0] : 0; + } +} +``` + +```csharp +public class Solution { + public int LastStoneWeight(int[] stones) { + List stoneList = new List(stones); + while (stoneList.Count > 1) { + stoneList.Sort(); + int cur = stoneList[stoneList.Count - 1] - stoneList[stoneList.Count - 2]; + stoneList.RemoveAt(stoneList.Count - 1); + stoneList.RemoveAt(stoneList.Count - 1); + if (cur != 0) { + stoneList.Add(cur); + } + } + + return stoneList.Count == 0 ? 0 : stoneList[0]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2 \log n)$ +* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. + +--- + +## 2. Binary Search + +::tabs-start + +```python +class Solution: + def lastStoneWeight(self, stones: List[int]) -> int: + stones.sort() + n = len(stones) + + while n > 1: + cur = stones.pop() - stones.pop() + n -= 2 + if cur > 0: + l, r = 0, n + while l < r: + mid = (l + r) // 2 + if stones[mid] < cur: + l = mid + 1 + else: + r = mid + pos = l + n += 1 + stones.append(0) + for i in range(n - 1, pos, -1): + stones[i] = stones[i - 1] + stones[pos] = cur + + return stones[0] if n > 0 else 0 +``` + +```java +public class Solution { + public int lastStoneWeight(int[] stones) { + Arrays.sort(stones); + int n = stones.length; + + while (n > 1) { + int cur = stones[n - 1] - stones[n - 2]; + n -= 2; + if (cur > 0) { + int l = 0, r = n; + while (l < r) { + int mid = (l + r) / 2; + if (stones[mid] < cur) { + l = mid + 1; + } else { + r = mid; + } + } + int pos = l; + n++; + stones = Arrays.copyOf(stones, n); + for (int i = n - 1; i > pos; i--) { + stones[i] = stones[i - 1]; + } + stones[pos] = cur; + } + } + return n > 0 ? stones[0] : 0; + } +} +``` + +```cpp +class Solution { +public: + int lastStoneWeight(vector& stones) { + sort(stones.begin(), stones.end()); + int n = stones.size(); + + while (n > 1) { + int cur = stones[n - 1] - stones[n - 2]; + n -= 2; + if (cur > 0) { + int l = 0, r = n; + while (l < r) { + int mid = (l + r) / 2; + if (stones[mid] < cur) { + l = mid + 1; + } else { + r = mid; + } + } + int pos = l; + stones.push_back(0); + for (int i = n + 1; i > pos; i--) { + stones[i] = stones[i - 1]; + } + stones[pos] = cur; + n++; + } + } + return n > 0 ? stones[0] : 0; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} stones + * @return {number} + */ + lastStoneWeight(stones) { + stones.sort((a, b) => a - b); + let n = stones.length; + + while (n > 1) { + let cur = stones.pop() - stones.pop(); + n -= 2; + if (cur > 0) { + let l = 0, r = n; + while (l < r) { + let mid = Math.floor((l + r) / 2); + if (stones[mid] < cur) { + l = mid + 1; + } else { + r = mid; + } + } + let pos = l; + n++; + stones.push(0); + for (let i = n - 1; i > pos; i--) { + stones[i] = stones[i - 1]; + } + stones[pos] = cur; + } + } + return n > 0 ? stones[0] : 0; + } +} +``` + +```csharp +public class Solution { + public int LastStoneWeight(int[] stones) { + Array.Sort(stones); + int n = stones.Length; + + while (n > 1) { + int cur = stones[n - 1] - stones[n - 2]; + n -= 2; + if (cur > 0) { + int l = 0, r = n; + while (l < r) { + int mid = (l + r) / 2; + if (stones[mid] < cur) { + l = mid + 1; + } else { + r = mid; + } + } + int pos = l; + Array.Resize(ref stones, n + 1); + for (int i = n; i > pos; i--) { + stones[i] = stones[i - 1]; + } + stones[pos] = cur; + n++; + } + } + return n > 0 ? stones[0] : 0; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ or $O(n)$ depending on the sorting algorithm. + +--- + +## 3. Heap + +::tabs-start + +```python +class Solution: + def lastStoneWeight(self, stones: List[int]) -> int: + stones = [-s for s in stones] + heapq.heapify(stones) + + while len(stones) > 1: + first = heapq.heappop(stones) + second = heapq.heappop(stones) + if second > first: + heapq.heappush(stones, first - second) + + stones.append(0) + return abs(stones[0]) +``` + +```java +class Solution { + public int lastStoneWeight(int[] stones) { + PriorityQueue minHeap = new PriorityQueue<>(); + for (int s : stones) { + minHeap.offer(-s); + } + + while (minHeap.size() > 1) { + int first = minHeap.poll(); + int second = minHeap.poll(); + if (second > first) { + minHeap.offer(first - second); + } + } + + minHeap.offer(0); + return Math.abs(minHeap.peek()); + } +} +``` + +```cpp +class Solution { +public: + int lastStoneWeight(vector& stones) { + priority_queue maxHeap; + for (int s : stones) { + maxHeap.push(s); + } + + while (maxHeap.size() > 1) { + int first = maxHeap.top(); + maxHeap.pop(); + int second = maxHeap.top(); + maxHeap.pop(); + if (second < first) { + maxHeap.push(first - second); + } + } + + maxHeap.push(0); + return maxHeap.top(); + } +}; +``` + +```javascript +/** + * const { MaxPriorityQueue } = require('@datastructures-js/priority-queue'); + */ + +class Solution { + /** + * @param {number[]} stones + * @return {number} + */ + lastStoneWeight(stones) { + const maxPQ = new MaxPriorityQueue(); + + for (const stone of stones) { + maxPQ.enqueue(stone); + } + + while (maxPQ.size() > 1) { + const stone1 = maxPQ.dequeue(); + const stone2 = maxPQ.dequeue(); + + if (stone1 !== stone2) { + maxPQ.enqueue(stone1 - stone2); + } + } + + return maxPQ.size() === 1 ? maxPQ.dequeue() : 0; + } +} +``` + +```csharp +public class Solution { + public int LastStoneWeight(int[] stones) { + PriorityQueue minHeap = new PriorityQueue(); + foreach (int s in stones) { + minHeap.Enqueue(-s, -s); + } + + while (minHeap.Count > 1) { + int first = minHeap.Dequeue(); + int second = minHeap.Dequeue(); + if (second > first) { + minHeap.Enqueue(first - second, first - second); + } + } + + minHeap.Enqueue(0, 0); + return Math.Abs(minHeap.Peek()); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n \log n)$ +* Space complexity: $O(n)$ + +--- + +## 4. Bucket Sort + +::tabs-start + +```python +class Solution: + def lastStoneWeight(self, stones: List[int]) -> int: + + maxStone = max(stones) + bucket = [0] * (maxStone + 1) + for stone in stones: + bucket[stone] += 1 + + first = second = maxStone + while first > 0: + if bucket[first] % 2 == 0: + first -= 1 + continue + + j = min(first - 1, second) + while j > 0 and bucket[j] == 0: + j -= 1 + + if j == 0: + return first + second = j + bucket[first] -= 1 + bucket[second] -= 1 + bucket[first - second] += 1 + first = max(first - second, second) + return first +``` + +```java +public class Solution { + public int lastStoneWeight(int[] stones) { + int maxStone = 0; + for (int stone : stones) { + maxStone = Math.max(maxStone, stone); + } + + int[] bucket = new int[maxStone + 1]; + for (int stone : stones) { + bucket[stone]++; + } + + int first = maxStone, second = maxStone; + while (first > 0) { + if (bucket[first] % 2 == 0) { + first--; + continue; + } + + int j = Math.min(first - 1, second); + while (j > 0 && bucket[j] == 0) { + j--; + } + + if (j == 0) { + return first; + } + + second = j; + bucket[first]--; + bucket[second]--; + bucket[first - second]++; + first = Math.max(first - second, second); + } + + return first; + } +} +``` + +```cpp +class Solution { +public: + int lastStoneWeight(vector& stones) { + int maxStone = 0; + for (int stone : stones) { + maxStone = max(maxStone, stone); + } + + vector bucket(maxStone + 1, 0); + for (int stone : stones) { + bucket[stone]++; + } + + int first = maxStone, second = maxStone; + while (first > 0) { + if (bucket[first] % 2 == 0) { + first--; + continue; + } + + int j = min(first - 1, second); + while (j > 0 && bucket[j] == 0) { + j--; + } + + if (j == 0) { + return first; + } + + second = j; + bucket[first]--; + bucket[second]--; + bucket[first - second]++; + first = max(first - second, second); + } + + return first; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} stones + * @return {number} + */ + lastStoneWeight(stones) { + let maxStone = 0; + for (let stone of stones) { + maxStone = Math.max(maxStone, stone); + } + + let bucket = Array(maxStone + 1).fill(0); + for (let stone of stones) { + bucket[stone]++; + } + + let first = maxStone, second = maxStone; + while (first > 0) { + if (bucket[first] % 2 === 0) { + first--; + continue; + } + + let j = Math.min(first - 1, second); + while (j > 0 && bucket[j] === 0) { + j--; + } + + if (j === 0) { + return first; + } + + second = j; + bucket[first]--; + bucket[second]--; + bucket[first - second]++; + first = Math.max(first - second, second); + } + + return first; + } +} +``` + +```csharp +public class Solution { + public int LastStoneWeight(int[] stones) { + int maxStone = 0; + foreach (int stone in stones) { + maxStone = Math.Max(maxStone, stone); + } + + int[] bucket = new int[maxStone + 1]; + foreach (int stone in stones) { + bucket[stone]++; + } + + int first = maxStone, second = maxStone; + while (first > 0) { + if (bucket[first] % 2 == 0) { + first--; + continue; + } + + int j = Math.Min(first - 1, second); + while (j > 0 && bucket[j] == 0) { + j--; + } + + if (j == 0) { + return first; + } + + second = j; + bucket[first]--; + bucket[second]--; + bucket[first - second]++; + first = Math.Max(first - second, second); + } + + return first; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n + w)$ +* Space complexity: $O(w)$ + +> Where $n$ is the length of the $stones$ array and $w$ is the maximum value in the $stones$ array. \ No newline at end of file diff --git a/articles/serialize-and-deserialize-binary-tree.md b/articles/serialize-and-deserialize-binary-tree.md new file mode 100644 index 000000000..d937df97f --- /dev/null +++ b/articles/serialize-and-deserialize-binary-tree.md @@ -0,0 +1,624 @@ +## 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 Codec: + + # Encodes a tree to a single string. + def serialize(self, root: Optional[TreeNode]) -> str: + res = [] + + def dfs(node): + if not node: + res.append("N") + return + res.append(str(node.val)) + dfs(node.left) + dfs(node.right) + + dfs(root) + return ",".join(res) + + # Decodes your encoded data to tree. + def deserialize(self, data: str) -> Optional[TreeNode]: + vals = data.split(",") + self.i = 0 + + def dfs(): + if vals[self.i] == "N": + self.i += 1 + return None + node = TreeNode(int(vals[self.i])) + self.i += 1 + node.left = dfs() + node.right = dfs() + return node + + return dfs() +``` + +```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 Codec { + + // Encodes a tree to a single string. + public String serialize(TreeNode root) { + List res = new ArrayList<>(); + dfsSerialize(root, res); + return String.join(",", res); + } + + private void dfsSerialize(TreeNode node, List res) { + if (node == null) { + res.add("N"); + return; + } + res.add(String.valueOf(node.val)); + dfsSerialize(node.left, res); + dfsSerialize(node.right, res); + } + + // Decodes your encoded data to tree. + public TreeNode deserialize(String data) { + String[] vals = data.split(","); + int[] i = {0}; + return dfsDeserialize(vals, i); + } + + private TreeNode dfsDeserialize(String[] vals, int[] i) { + if (vals[i[0]].equals("N")) { + i[0]++; + return null; + } + TreeNode node = new TreeNode(Integer.parseInt(vals[i[0]])); + i[0]++; + node.left = dfsDeserialize(vals, i); + node.right = dfsDeserialize(vals, i); + return node; + } +} +``` + +```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 Codec { +public: + // Encodes a tree to a single string. + string serialize(TreeNode* root) { + vector res; + dfsSerialize(root, res); + return join(res, ","); + } + + // Decodes your encoded data to tree. + TreeNode* deserialize(string data) { + vector vals = split(data, ','); + int i = 0; + return dfsDeserialize(vals, i); + } + +private: + void dfsSerialize(TreeNode* node, vector& res) { + if (!node) { + res.push_back("N"); + return; + } + res.push_back(to_string(node->val)); + dfsSerialize(node->left, res); + dfsSerialize(node->right, res); + } + + TreeNode* dfsDeserialize(vector& vals, int& i) { + if (vals[i] == "N") { + i++; + return NULL; + } + TreeNode* node = new TreeNode(stoi(vals[i])); + i++; + node->left = dfsDeserialize(vals, i); + node->right = dfsDeserialize(vals, i); + return node; + } + + vector split(const string &s, char delim) { + vector elems; + stringstream ss(s); + string item; + while (getline(ss, item, delim)) { + elems.push_back(item); + } + return elems; + } + + string join(const vector &v, const string &delim) { + ostringstream s; + for (const auto &i : v) { + if (&i != &v[0]) + s << delim; + s << i; + } + return s.str(); + } +}; +``` + +```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 Codec { + /** + * Encodes a tree to a single string. + * + * @param {TreeNode} root + * @return {string} + */ + serialize(root) { + const res = []; + this.dfsSerialize(root, res); + return res.join(','); + } + + dfsSerialize(node, res) { + if (node === null) { + res.push('N'); + return; + } + res.push(node.val.toString()); + this.dfsSerialize(node.left, res); + this.dfsSerialize(node.right, res); + } + + /** + * Decodes your encoded data to tree. + * + * @param {string} data + * @return {TreeNode} + */ + deserialize(data) { + const vals = data.split(','); + const i = { val: 0 }; + return this.dfsDeserialize(vals, i); + } + + dfsDeserialize(vals, i) { + if (vals[i.val] === 'N') { + i.val++; + return null; + } + const node = new TreeNode(parseInt(vals[i.val])); + i.val++; + node.left = this.dfsDeserialize(vals, i); + node.right = this.dfsDeserialize(vals, i); + return node; + } +} +``` + +```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 Codec { + + // Encodes a tree to a single string. + public string Serialize(TreeNode root) { + List res = new List(); + dfsSerialize(root, res); + return String.Join(",", res); + } + + private void dfsSerialize(TreeNode node, List res) { + if (node == null) { + res.Add("N"); + return; + } + res.Add(node.val.ToString()); + dfsSerialize(node.left, res); + dfsSerialize(node.right, res); + } + + // Decodes your encoded data to tree. + public TreeNode Deserialize(string data) { + string[] vals = data.Split(','); + int i = 0; + return dfsDeserialize(vals, ref i); + } + + private TreeNode dfsDeserialize(string[] vals, ref int i) { + if (vals[i] == "N") { + i++; + return null; + } + TreeNode node = new TreeNode(Int32.Parse(vals[i])); + i++; + node.left = dfsDeserialize(vals, ref i); + node.right = dfsDeserialize(vals, ref i); + return node; + } +} +``` + +::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 Codec: + + # Encodes a tree to a single string. + def serialize(self, root: Optional[TreeNode]) -> str: + if not root: + return "N" + res = [] + queue = deque([root]) + while queue: + node = queue.popleft() + if not node: + res.append("N") + else: + res.append(str(node.val)) + queue.append(node.left) + queue.append(node.right) + return ",".join(res) + + # Decodes your encoded data to tree. + def deserialize(self, data: str) -> Optional[TreeNode]: + vals = data.split(",") + if vals[0] == "N": + return None + root = TreeNode(int(vals[0])) + queue = deque([root]) + index = 1 + while queue: + node = queue.popleft() + if vals[index] != "N": + node.left = TreeNode(int(vals[index])) + queue.append(node.left) + index += 1 + if vals[index] != "N": + node.right = TreeNode(int(vals[index])) + queue.append(node.right) + index += 1 + 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 Codec { + + // Encodes a tree to a single string. + public String serialize(TreeNode root) { + if (root == null) return "N"; + StringBuilder res = new StringBuilder(); + Queue queue = new LinkedList<>(); + queue.add(root); + + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + if (node == null) { + res.append("N,"); + } else { + res.append(node.val).append(","); + queue.add(node.left); + queue.add(node.right); + } + } + return res.toString(); + } + + // Decodes your encoded data to tree. + public TreeNode deserialize(String data) { + String[] vals = data.split(","); + if (vals[0].equals("N")) return null; + TreeNode root = new TreeNode(Integer.parseInt(vals[0])); + Queue queue = new LinkedList<>(); + queue.add(root); + int index = 1; + + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + if (!vals[index].equals("N")) { + node.left = new TreeNode(Integer.parseInt(vals[index])); + queue.add(node.left); + } + index++; + if (!vals[index].equals("N")) { + node.right = new TreeNode(Integer.parseInt(vals[index])); + queue.add(node.right); + } + index++; + } + 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 Codec { +public: + + // Encodes a tree to a single string. + string serialize(TreeNode* root) { + if (!root) return "N"; + string res; + queue queue; + queue.push(root); + + while (!queue.empty()) { + TreeNode* node = queue.front(); + queue.pop(); + if (!node) { + res += "N,"; + } else { + res += to_string(node->val) + ","; + queue.push(node->left); + queue.push(node->right); + } + } + return res; + } + + // Decodes your encoded data to tree. + TreeNode* deserialize(string data) { + stringstream ss(data); + string val; + getline(ss, val, ','); + if (val == "N") return nullptr; + TreeNode* root = new TreeNode(stoi(val)); + queue queue; + queue.push(root); + + while (getline(ss, val, ',')) { + TreeNode* node = queue.front(); + queue.pop(); + if (val != "N") { + node->left = new TreeNode(stoi(val)); + queue.push(node->left); + } + getline(ss, val, ','); + if (val != "N") { + node->right = new TreeNode(stoi(val)); + queue.push(node->right); + } + } + 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 Codec { + /** + * Encodes a tree to a single string. + * + * @param {TreeNode} root + * @return {string} + */ + serialize(root) { + if (!root) return "N"; + const res = []; + const queue = new Queue(); + queue.push(root); + + while (!queue.isEmpty()) { + const node = queue.pop(); + if (!node) { + res.push("N"); + } else { + res.push(node.val); + queue.push(node.left); + queue.push(node.right); + } + } + return res.join(","); + } + + /** + * Decodes your encoded data to tree. + * + * @param {string} data + * @return {TreeNode} + */ + deserialize(data) { + const vals = data.split(","); + if (vals[0] === "N") return null; + const root = new TreeNode(parseInt(vals[0])); + const queue = new Queue([root]); + let index = 1; + + while (!queue.isEmpty()) { + const node = queue.pop(); + if (vals[index] !== "N") { + node.left = new TreeNode(parseInt(vals[index])); + queue.push(node.left); + } + index++; + if (vals[index] !== "N") { + node.right = new TreeNode(parseInt(vals[index])); + queue.push(node.right); + } + index++; + } + 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 Codec { + + // Encodes a tree to a single string. + public string Serialize(TreeNode root) { + if (root == null) return "N"; + var res = new List(); + var queue = new Queue(); + queue.Enqueue(root); + + while (queue.Count > 0) { + var node = queue.Dequeue(); + if (node == null) { + res.Add("N"); + } else { + res.Add(node.val.ToString()); + queue.Enqueue(node.left); + queue.Enqueue(node.right); + } + } + return string.Join(",", res); + } + + // Decodes your encoded data to tree. + public TreeNode Deserialize(string data) { + var vals = data.Split(','); + if (vals[0] == "N") return null; + var root = new TreeNode(int.Parse(vals[0])); + var queue = new Queue(); + queue.Enqueue(root); + int index = 1; + + while (queue.Count > 0) { + var node = queue.Dequeue(); + if (vals[index] != "N") { + node.left = new TreeNode(int.Parse(vals[index])); + queue.Enqueue(node.left); + } + index++; + if (vals[index] != "N") { + node.right = new TreeNode(int.Parse(vals[index])); + queue.Enqueue(node.right); + } + index++; + } + return root; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file