Skip to content

Commit a2e5bed

Browse files
authored
Problems/tree (#22)
* Re-order the traversal topics * Add 94. Binary Tree Inorder Traversal solution * Add 102. Binary Tree Level Order Traversal solution * Add 104. Maximum Depth of Binary Tree solution * Add 226. Invert Binary Tree solution * * Add 101. Symmetric Tree solution * Add 105. Construct Binary Tree from Preorder and Inorder Traversal solution * Add 112. Path Sum solution * Add 236. Lowest Common Ancestor of a Binary Tree solution * Add 236. Lowest Common Ancestor of a Binary Tree solution * Add 543. Diameter of Binary Tree solution * Add 124. Binary Tree Maximum Path Sum solution Add 114. Flatten Binary Tree to Linked List solution Add different solutions to 114. Flatten Binary Tree to Linked List Add 116. Populating Next Right Pointers in Each Node solution Add 199. Binary Tree Right Side View solution Add 100. Same Tree solution * Add 863. All Nodes Distance K in Binary Tree solution * Add 110. Balanced Binary Tree solution * Add 297. Serialize and Deserialize Binary Tree attempt (WA) * Add 110. Balanced Binary Tree solution * Add 297. Serialize and Deserialize Binary Tree solution * Update some solutions and notes for tree * Add 257. Binary Tree Paths solution * Update problem listing and binary search tree note * Add 700. Search in a Binary Search Tree solution * Add 108. Convert Sorted Array to Binary Search Tree solution * Add 450. Delete Node in a BST solution * Update 450. Delete Node in a BST my solution comment * Add 701. Insert into a Binary Search Tree solution * Add 98. Validate Binary Search Tree solution * Update 98. Validate Binary Search Tree iterative inorder traversal solution and update the note * Update some problem solutions and notes * Add 230. Kth Smallest Element in a BST solution * Add 235. Lowest Common Ancestor of a Binary Search Tree solution
1 parent 66ab902 commit a2e5bed

36 files changed

+1604
-164
lines changed

leetcode/100.same-tree.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
## [100. Same Tree](https://leetcode.com/problems/same-tree/)
2+
### Recursive
3+
```kotlin
4+
fun isSameTree(p: TreeNode?, q: TreeNode?): Boolean {
5+
if (p == null && q == null) return true
6+
if (p == null || q == null) return false
7+
return (p.`val` == q.`val`) && isSameTree(p.left, q.left) && isSameTree(p.right, q.right)
8+
}
9+
```
10+
11+
### Traversal
12+
```kotlin
13+
class Solution {
14+
15+
private val pNodes = mutableListOf<Int>()
16+
private val qNodes = mutableListOf<Int>()
17+
18+
fun isSameTree(p: TreeNode?, q: TreeNode?): Boolean {
19+
inOrderTraversal(p, pNodes)
20+
inOrderTraversal(q, qNodes)
21+
22+
if (pNodes.size != qNodes.size) return false
23+
else {
24+
for (i in 0 until pNodes.size) {
25+
if (pNodes[i] != qNodes[i]) return false
26+
}
27+
}
28+
return true
29+
}
30+
31+
private fun inOrderTraversal(node: TreeNode?, results: MutableList<Int>) {
32+
results.add(node?.`val` ?: Int.MAX_VALUE)
33+
if (node?.left != null) inOrderTraversal(node?.left, results) else results.add(Int.MAX_VALUE)
34+
if (node?.right != null) inOrderTraversal(node?.right, results) else results.add(Int.MAX_VALUE)
35+
}
36+
}
37+
```
38+
39+
### Failed Cases
40+
```js
41+
[1, 2]
42+
[1, null, 2]
43+
```
44+
I skip the null node, so two trees are content identical, not structurely. Can't skip the null node.

leetcode/101.symmetric-tree.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
## [101. Symmetric Tree](https://leetcode.com/problems/symmetric-tree/)
2+
### Recursive
3+
```kotlin
4+
fun isSymmetric(root: TreeNode?): Boolean {
5+
if (root == null) return true
6+
return check(root?.left, root?.right)
7+
}
8+
9+
fun check(left: TreeNode?, right: TreeNode?): Boolean {
10+
if (left == null || right == null) return left == right
11+
if (left?.`val` != right?.`val`) return false
12+
return check(left?.left, right?.right) && check(left?.right, right?.left)
13+
}
14+
```
15+
16+
### Iterative
17+
```kotlin
18+
fun isSymmetric(root: TreeNode?): Boolean {
19+
if (root == null) return true
20+
else {
21+
val queue = ArrayDeque<TreeNode>()
22+
if (root?.left != null) queue.add(root?.left)
23+
if (root?.right != null) queue.add(root?.right)
24+
25+
while (!queue.isEmpty()) {
26+
val left = queue.removeFirstOrNull()
27+
val right = queue.removeFirstOrNull()
28+
29+
if (left == null && right == null) continue
30+
if (left == null || right == null || left?.`val` != right?.`val`) return false
31+
32+
// We have to push in the symmetric order
33+
queue.addLast(left!!.left)
34+
queue.addLast(right!!.right)
35+
36+
queue.addLast(left!!.right)
37+
queue.addLast(right!!.left)
38+
}
39+
return true
40+
}
41+
}
42+
```
43+
44+
> Idea is correct, but code won't compile successfully, LeetCode jvm doesn't support `removeFirstOrNull()` function.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
## [102. Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/)
2+
3+
```kotlin
4+
class Solution {
5+
6+
data class MyNode(
7+
val node: TreeNode,
8+
val level: Int
9+
)
10+
11+
private val results = mutableListOf<MutableList<Int>>()
12+
13+
fun levelOrder(root: TreeNode?): List<List<Int>> {
14+
val queue = ArrayDeque<MyNode>()
15+
if (root == null) return emptyList()
16+
queue.addLast(MyNode(root, 0))
17+
while (!queue.isEmpty()) {
18+
val myNode = queue.removeFirst()
19+
if (myNode.node.left != null) queue.addLast(MyNode(myNode.node.left, myNode.level + 1))
20+
if (myNode.node.right != null) queue.addLast(MyNode(myNode.node.right, myNode.level + 1))
21+
22+
if (results.size < myNode.level + 1) {
23+
results.add(mutableListOf<Int>())
24+
}
25+
results[myNode.level].add(myNode.node.`val`)
26+
}
27+
return results
28+
}
29+
}
30+
```
31+
32+
Solution without addition `level` variable:
33+
34+
```kotlin
35+
fun levelOrder(root: TreeNode?): List<List<Int>> {
36+
if (root == null) return emptyList()
37+
val results = mutableListOf<List<Int>>()
38+
val queue = ArrayDeque<TreeNode>()
39+
queue.addLast(root)
40+
while (!queue.isEmpty()) {
41+
val levelNodes = mutableListOf<Int>()
42+
// The items in queue now are at the same level.
43+
// We iterate the all nodes now for same level.
44+
val size = queue.size
45+
for (i in 0 until size) {
46+
val node = queue.removeFirst()
47+
levelNodes.add(node.`val`)
48+
if (node?.left != null) queue.addLast(node.left!!)
49+
if (node?.right != null) queue.addLast(node.right!!)
50+
}
51+
results.add(levelNodes)
52+
}
53+
return results
54+
}
55+
```
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## [104. Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/)
2+
3+
### DFS
4+
```kotlin
5+
fun maxDepth(root: TreeNode?): Int {
6+
if (root == null) return 0
7+
return 1 + max(maxDepth(root?.left), maxDepth(root?.right))
8+
}
9+
10+
private fun max(n1: Int, n2: Int) = if (n1 > n2) n1 else n2
11+
```
12+
13+
* **Time Complexity**: `O(n)`, iterate all nodes.
14+
* **Space Complextiy**: `O(height)`, height might be `lg n` (balanced) or `n` (skewed)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
## [105. Construct Binary Tree from Preorder and Inorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
2+
3+
```js
4+
Preorder = [D L R]
5+
Inorder = [L D R]
6+
```
7+
8+
You locate the `D` at first, then get the range of left subtree from inorder based on the `D` index, the remaining part is right subtree.
9+
10+
```kotlin
11+
fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? {
12+
if (preorder.isEmpty()) return null
13+
14+
val root = TreeNode(preorder.first())
15+
if (preorder.size == 1) return root
16+
17+
val leftInInorder = inorder.sliceArray(0 until inorder.indexOf(preorder.first()))
18+
val leftInPreorder = preorder.sliceArray(1 until leftInInorder.size + 1)
19+
20+
val rightIndexInPreorder = 1 + leftInPreorder.size
21+
val rightInPreorder = preorder.sliceArray(rightIndexInPreorder until preorder.size)
22+
val rightInInOrder = inorder.sliceArray(rightIndexInPreorder until inorder.size)
23+
24+
root.left = buildTree(leftInPreorder, leftInInorder)
25+
root.right = buildTree(rightInPreorder, rightInInOrder)
26+
return root
27+
}
28+
```
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## [108. Convert Sorted Array to Binary Search Tree](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/)
2+
3+
```kotlin
4+
fun sortedArrayToBST(nums: IntArray): TreeNode? {
5+
if (nums.isEmpty()) return null
6+
val middle = nums.size / 2
7+
val root = TreeNode(nums[middle])
8+
if (middle > 0) {
9+
root.left = sortedArrayToBST(nums.sliceArray(0 until middle))
10+
root.right = sortedArrayToBST(nums.sliceArray(middle + 1 until nums.size))
11+
}
12+
return root
13+
}
14+
```
15+
16+
* **Time Complexity**: `O(n)`, iterate all elements.
17+
* **Space Complexity**: `O(lg n)`, stack depth = tree height.

leetcode/110.balanced-binary-tree.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
## [110. Balanced Binary Tree](https://leetcode.com/problems/balanced-binary-tree/)
2+
3+
### Top-Down Recursion
4+
```kotlin
5+
fun isBalanced(root: TreeNode?): Boolean {
6+
if (root == null) return true
7+
val leftHeight = height(root?.left)
8+
var rightHeight = height(root?.right)
9+
val diff = leftHeight - rightHeight
10+
return diff * diff <= 1 && isBalanced(root?.left) && isBalanced(root?.right)
11+
}
12+
13+
private fun height(node: TreeNode?): Int {
14+
return if (node == null) 0
15+
else {
16+
1 + max(height(node?.left), height(node?.right))
17+
}
18+
}
19+
20+
private fun max(n1: Int, n2: Int) = if (n1 > n2) n1 else n2
21+
```
22+
23+
* **Time Complexity**: Calculate the height = `O(lg n)`, and we have to calculate every node `n`, the average case (every node has children) is `O(n lg n)`, but the worst case is `O(n^2)` when the tree is skewed because the height becomes `O(n)`.
24+
25+
### Bottom-Up Solution (Optimal)
26+
* We traverse all nodes in postorder, and determine if it's balanced of its child nodes, then check the current node.
27+
* If it's not balanced from its child node, then it's not balanced as well for the current node.
28+
29+
![](../media/110.balanced-binary-tree.png)
30+
> Source: [Solution](https://leetcode.cn/problems/balanced-binary-tree/solution/ping-heng-er-cha-shu-by-leetcode-solution/), please take a very close look at it explanation.
31+
```kotlin
32+
fun isBalanced(root: TreeNode?): Boolean {
33+
return height(root) != -1
34+
}
35+
36+
private fun height(node: TreeNode?): Int {
37+
if (node == null) return 0
38+
39+
val leftHeight = height(node?.left)
40+
val rightHeight = height(node?.right)
41+
42+
val diff = if (leftHeight > rightHeight) leftHeight - rightHeight else rightHeight - leftHeight
43+
44+
if (leftHeight == -1 || rightHeight == -1 || diff > 1) {
45+
return -1
46+
} else {
47+
return (if (leftHeight > rightHeight) leftHeight else rightHeight) + 1
48+
}
49+
}
50+
```
51+
* **Time Complexity**: It becomes `O(n)` since we calculate the height only once for every node.
52+
53+
### My Solution (Accepted)
54+
```kotlin
55+
fun isBalanced(root: TreeNode?): Boolean {
56+
return checkBalanced(root?.left, root?.right)
57+
}
58+
59+
private fun checkBalanced(n1: TreeNode?, n2: TreeNode?): Boolean {
60+
if (n1 == null && n2 == null) return true
61+
val diff = (height(n1) - height(n2))
62+
return (diff * diff <= 1) && checkBalanced(n1?.left, n1?.right) && checkBalanced(n2?.left, n2?.right)
63+
}
64+
65+
private fun height(node: TreeNode?): Int {
66+
return if (node == null) 0
67+
else {
68+
1 + max(height(node?.left), height(node?.right))
69+
}
70+
}
71+
72+
private fun max(n1: Int, n2: Int) = if (n1 > n2) n1 else n2
73+
```
74+
75+
### Special Cases
76+
It's not balanced.
77+
```js
78+
1
79+
/ \
80+
2 3
81+
/ \
82+
4 5
83+
/ \
84+
5 7
85+
```

leetcode/112.path-sum.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## [112. Path Sum](https://leetcode.com/problems/path-sum/)
2+
3+
```kotlin
4+
fun hasPathSum(root: TreeNode?, targetSum: Int): Boolean {
5+
if (root == null) return false
6+
else if (root.left == null && root.right == null) return targetSum == root.`val`
7+
else {
8+
return hasPathSum(root.left, targetSum - root.`val`) || hasPathSum(root.right, targetSum - root.`val`)
9+
}
10+
}
11+
```

0 commit comments

Comments
 (0)