Skip to content

Commit 90ed4fd

Browse files
add a solution for 450
1 parent 9154689 commit 90ed4fd

File tree

2 files changed

+118
-13
lines changed

2 files changed

+118
-13
lines changed

src/main/java/com/fishercoder/solutions/_450.java

+100-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
import com.fishercoder.common.classes.TreeNode;
44

5+
import java.util.ArrayList;
6+
import java.util.List;
7+
58
public class _450 {
69
public static class Solution1 {
7-
810
/**
911
* credit: https://discuss.leetcode.com/topic/65792/recursive-easy-to-understand-java-solution
1012
* Steps:
@@ -45,4 +47,101 @@ private TreeNode getMin(TreeNode node) {
4547
}
4648
}
4749

50+
public static class Solution2 {
51+
/**
52+
* My original, but brute force solution, time complexity: O(n) instead of O(h)
53+
*/
54+
public TreeNode deleteNode(TreeNode root, int key) {
55+
List<Integer> list = new ArrayList<>();
56+
dfs(root, key, list);
57+
return formBst(list, 0, list.size() - 1);
58+
}
59+
60+
private TreeNode formBst(List<Integer> list, int left, int right) {
61+
if (left > right) {
62+
return null;
63+
}
64+
int mid = left + (right - left) / 2;
65+
TreeNode root = new TreeNode(list.get(mid));
66+
root.left = formBst(list, left, mid - 1);
67+
root.right = formBst(list, mid + 1, right);
68+
return root;
69+
}
70+
71+
private List<Integer> dfs(TreeNode root, int key, List<Integer> list) {
72+
if (root == null) {
73+
return list;
74+
}
75+
dfs(root.left, key, list);
76+
if (root.val != key) {
77+
list.add(root.val);
78+
}
79+
dfs(root.right, key, list);
80+
return list;
81+
}
82+
}
83+
84+
public static class Solution3 {
85+
/**
86+
* credit: https://leetcode.com/problems/delete-node-in-a-bst/solution/
87+
*
88+
* Again, using a pen and paper to visualize helps a lot.
89+
* Putting a BST into an inorder traversal array helps a lot to understand:
90+
*
91+
* The successor of a node is always: go the right once, and then go to the left as many times as possible,
92+
* because the successor is the next smallest element that is larger than the current one: so going to the right one time
93+
* makes sure that we are finding the larger one, and then keeping going to the left makes sure that we'll find the smallest one.
94+
*
95+
* The predecessor of a node is always: go the left once, and then go the right as many times as possible,
96+
* because the predecessor is the largest element that is smaller than the current one: so going to the left once makes it smaller than the current node,
97+
* then keeping going to the right makes sure that we are getting the largest element.
98+
*/
99+
public TreeNode deleteNode(TreeNode root, int key) {
100+
if (root == null) {
101+
return null;
102+
}
103+
if (root.val < key) {
104+
//delete from the right subtree
105+
root.right = deleteNode(root.right, key);
106+
} else if (root.val > key) {
107+
//delete from the left subtree
108+
root.left = deleteNode(root.left, key);
109+
} else {
110+
//delete this current node, three cases:
111+
if (root.left == null && root.right == null) {
112+
//case 1: if this is a leaf
113+
root = null;
114+
} else if (root.right != null) {
115+
//case 2: has a right child, regardless whether it has left children or not,
116+
//this is because we want to traverse the tree only once, so we'll want to keep going down the tree
117+
root.val = findSuccessor(root);//we find the value of the successor and assign it to current root.val
118+
root.right = deleteNode(root.right, root.val);//and then we delete this successor's value in the right subtree as it's been moved up
119+
} else if (root.left != null) {
120+
//case 3: this node is not a leaf and no right child, but has a left child
121+
//That means that its successor is somewhere upper in the tree but we don't want to go back.
122+
//Let's use the predecessor here which is somewhere lower in the left subtree.
123+
root.val = findPredecessor(root);
124+
root.left = deleteNode(root.left, root.val);
125+
}
126+
}
127+
return root;
128+
}
129+
130+
private int findPredecessor(TreeNode root) {
131+
root = root.left;
132+
while (root.right != null) {
133+
root = root.right;
134+
}
135+
return root.val;
136+
}
137+
138+
private int findSuccessor(TreeNode root) {
139+
root = root.right;
140+
while (root.left != null) {
141+
root = root.left;
142+
}
143+
return root.val;
144+
}
145+
}
146+
48147
}
+18-12
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,43 @@
11
package com.fishercoder;
22

33
import com.fishercoder.common.classes.TreeNode;
4+
import com.fishercoder.common.utils.TreeUtils;
45
import com.fishercoder.solutions._450;
56
import org.junit.BeforeClass;
67
import org.junit.Test;
78

9+
import java.util.Arrays;
10+
811
import static org.junit.Assert.assertEquals;
912

1013
public class _450Test {
1114
private static _450.Solution1 solution1;
15+
private static _450.Solution2 solution2;
16+
private static _450.Solution3 solution3;
1217
private static TreeNode expected;
1318
private static TreeNode root;
1419

1520
@BeforeClass
1621
public static void setup() {
1722
solution1 = new _450.Solution1();
23+
solution2 = new _450.Solution2();
24+
solution3 = new _450.Solution3();
1825
}
1926

2027
@Test
2128
public void test1() {
22-
root = new TreeNode(5);
23-
root.left = new TreeNode(3);
24-
root.left.left = new TreeNode(2);
25-
root.left.right = new TreeNode(4);
26-
root.right = new TreeNode(6);
27-
root.right.right = new TreeNode(7);
28-
29-
expected = new TreeNode(5);
30-
expected.left = new TreeNode(4);
31-
expected.right = new TreeNode(6);
32-
expected.left.left = new TreeNode(2);
33-
expected.right.right = new TreeNode(7);
29+
root = TreeUtils.constructBinaryTree(Arrays.asList(5, 3, 6, 2, 4, null, 7));
30+
TreeUtils.printBinaryTree(root);
3431

32+
expected = TreeUtils.constructBinaryTree(Arrays.asList(5, 4, 6, 2, null, null, 7));
33+
TreeUtils.printBinaryTree(expected);
3534
assertEquals(expected, solution1.deleteNode(root, 3));
35+
36+
expected = TreeUtils.constructBinaryTree(Arrays.asList(5, 2, 6, null, 4, null, 7));
37+
TreeUtils.printBinaryTree(expected);
38+
assertEquals(expected, solution2.deleteNode(root, 3));
39+
40+
expected = TreeUtils.constructBinaryTree(Arrays.asList(5, 4, 6, 2, null, null, 7));
41+
assertEquals(expected, solution3.deleteNode(root, 3));
3642
}
3743
}

0 commit comments

Comments
 (0)