Skip to content

Commit e6c5a99

Browse files
committed
Delete node in BST
1 parent 86bbf38 commit e6c5a99

File tree

2 files changed

+336
-0
lines changed

2 files changed

+336
-0
lines changed

450.delete_node_in_BST/delete.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// 450. Delete node in BST
2+
// Topics: 'Tree', 'Binary Search Tree', 'Binary Tree'
3+
// Level: 'Medium'
4+
5+
// Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST.
6+
7+
// Basically, the deletion can be divided into two stages:
8+
9+
// Search for a node to remove.
10+
// If the node is found, delete the node.
11+
12+
// Example 1:
13+
14+
// Input: root = [5,3,6,2,4,null,7], key = 3
15+
// Output: [5,4,6,2,null,null,7]
16+
// Explanation: Given key to delete is 3. So we find the node with value 3 and delete it.
17+
// One valid answer is [5,4,6,2,null,null,7], shown in the above BST.
18+
// Please notice that another valid answer is [5,2,6,null,4,null,7] and it's also accepted.
19+
20+
// Example 2:
21+
22+
// Input: root = [5,3,6,2,4,null,7], key = 0
23+
// Output: [5,3,6,2,4,null,7]
24+
// Explanation: The tree does not contain a node with value = 0.
25+
26+
// Example 3:
27+
28+
// Input: root = [], key = 0
29+
// Output: []
30+
31+
// Constraints:
32+
33+
// The number of nodes in the tree is in the range [0, 104].
34+
// -105 <= Node.val <= 105
35+
// Each node has a unique value.
36+
// root is a valid binary search tree.
37+
// -105 <= key <= 105
38+
39+
// Follow up: Could you solve it with time complexity O(height of tree)?
40+
41+
package deletenodeinbst
42+
43+
type TreeNode struct {
44+
Val int
45+
Right *TreeNode
46+
Left *TreeNode
47+
}
48+
49+
func deleteNode(root *TreeNode, key int) *TreeNode {
50+
if root == nil {
51+
return root
52+
}
53+
54+
if root.Val > key {
55+
root.Left = deleteNode(root.Left, key)
56+
} else if root.Val < key {
57+
root.Right = deleteNode(root.Right, key)
58+
} else {
59+
if root.Left == nil {
60+
return root.Right
61+
}
62+
if root.Right == nil {
63+
return root.Left
64+
}
65+
root.Val = successor(root.Right, root)
66+
}
67+
68+
return root
69+
70+
}
71+
72+
func successor(node *TreeNode, parent *TreeNode) int {
73+
if node.Left == nil {
74+
val := node.Val
75+
76+
if parent.Right == node {
77+
parent.Right = node.Right
78+
} else {
79+
parent.Left = node.Right
80+
}
81+
return val
82+
}
83+
return successor(node.Left, node)
84+
}
85+
86+
// func deleteNode(root *TreeNode, key int) *TreeNode {
87+
// if root == nil {
88+
// return root
89+
// }
90+
// var parent *TreeNode
91+
// cur := root
92+
// for cur != nil && cur.Val != key {
93+
// parent = cur
94+
// if cur.Val > key {
95+
// cur = cur.Left
96+
// } else {
97+
// cur = cur.Right
98+
// }
99+
// }
100+
// if cur == nil {
101+
// return root
102+
// }
103+
104+
// successor := successor(cur)
105+
// if parent == nil {
106+
// return successor
107+
// }
108+
109+
// if parent.Left == cur {
110+
// parent.Left = successor
111+
// } else {
112+
// parent.Right = successor
113+
// }
114+
115+
// return root
116+
// }
117+
118+
// func successor(root *TreeNode) *TreeNode {
119+
// if root.Right == nil {
120+
// return root.Left
121+
// }
122+
// if root.Left == nil {
123+
// return root.Right
124+
// }
125+
// parent := root
126+
// successor := root.Right
127+
// for successor.Left != nil {
128+
// parent = successor
129+
// successor = successor.Left
130+
// }
131+
// if parent == root {
132+
// successor.Left = root.Left
133+
// return successor
134+
// }
135+
// parent.Left = successor.Right
136+
// successor.Left = root.Left
137+
// successor.Right = root.Right
138+
139+
// return successor
140+
// }
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
package deletenodeinbst
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestDeleteNode(t *testing.T) {
8+
tests := []struct {
9+
name string
10+
root *TreeNode
11+
key int
12+
expected []int // inorder traversal of expected result
13+
}{
14+
{
15+
name: "delete node with two children",
16+
root: buildTree([]interface{}{5, 3, 6, 2, 4, nil, 7}),
17+
key: 3,
18+
expected: []int{2, 4, 5, 6, 7}, // one valid result
19+
},
20+
{
21+
name: "delete node that doesn't exist",
22+
root: buildTree([]interface{}{5, 3, 6, 2, 4, nil, 7}),
23+
key: 0,
24+
expected: []int{2, 3, 4, 5, 6, 7},
25+
},
26+
{
27+
name: "empty tree",
28+
root: nil,
29+
key: 0,
30+
expected: []int{},
31+
},
32+
{
33+
name: "delete root with no children",
34+
root: buildTree([]interface{}{5}),
35+
key: 5,
36+
expected: []int{},
37+
},
38+
{
39+
name: "delete root with only left child",
40+
root: buildTree([]interface{}{5, 3, nil}),
41+
key: 5,
42+
expected: []int{3},
43+
},
44+
{
45+
name: "delete root with only right child",
46+
root: buildTree([]interface{}{5, nil, 6}),
47+
key: 5,
48+
expected: []int{6},
49+
},
50+
{
51+
name: "delete root with two children",
52+
root: buildTree([]interface{}{5, 3, 6, 2, 4, nil, 7}),
53+
key: 5,
54+
expected: []int{2, 3, 4, 6, 7},
55+
},
56+
{
57+
name: "delete leaf node",
58+
root: buildTree([]interface{}{5, 3, 6, 2, 4, nil, 7}),
59+
key: 2,
60+
expected: []int{3, 4, 5, 6, 7},
61+
},
62+
{
63+
name: "delete node with only right child",
64+
root: buildTree([]interface{}{5, 3, 6, nil, 4, nil, 7}),
65+
key: 3,
66+
expected: []int{4, 5, 6, 7},
67+
},
68+
{
69+
name: "delete node with only left child",
70+
root: buildTree([]interface{}{5, 3, 6, 2, nil, nil, 7}),
71+
key: 3,
72+
expected: []int{2, 5, 6, 7},
73+
},
74+
{
75+
name: "single node tree, delete existing",
76+
root: buildTree([]interface{}{1}),
77+
key: 1,
78+
expected: []int{},
79+
},
80+
{
81+
name: "delete from larger tree",
82+
root: buildTree([]interface{}{8, 5, 12, 4, 7, 10, 14, nil, nil, 6, nil, 9, 11}),
83+
key: 5,
84+
expected: []int{4, 6, 7, 8, 9, 10, 11, 12, 14},
85+
},
86+
{
87+
name: "negative values",
88+
root: buildTree([]interface{}{0, -5, 5, -10, -3, 3, 10}),
89+
key: -5,
90+
expected: []int{-10, -3, 0, 3, 5, 10},
91+
},
92+
{
93+
name: "delete rightmost node",
94+
root: buildTree([]interface{}{5, 3, 6, 2, 4, nil, 7}),
95+
key: 7,
96+
expected: []int{2, 3, 4, 5, 6},
97+
},
98+
{
99+
name: "delete leftmost node",
100+
root: buildTree([]interface{}{5, 3, 6, 2, 4, nil, 7}),
101+
key: 2,
102+
expected: []int{3, 4, 5, 6, 7},
103+
},
104+
}
105+
106+
for _, tt := range tests {
107+
t.Run(tt.name, func(t *testing.T) {
108+
result := deleteNode(tt.root, tt.key)
109+
actual := inorderTraversal(result)
110+
111+
if !equalSlices(actual, tt.expected) {
112+
t.Errorf("deleteNode() = %v, expected %v", actual, tt.expected)
113+
}
114+
115+
// Verify BST property is maintained
116+
if result != nil && !isBST(result, nil, nil) {
117+
t.Errorf("Result tree is not a valid BST")
118+
}
119+
})
120+
}
121+
}
122+
123+
// Helper function to build a tree from level-order array
124+
func buildTree(values []interface{}) *TreeNode {
125+
if len(values) == 0 || values[0] == nil {
126+
return nil
127+
}
128+
129+
root := &TreeNode{Val: values[0].(int)}
130+
queue := []*TreeNode{root}
131+
i := 1
132+
133+
for len(queue) > 0 && i < len(values) {
134+
node := queue[0]
135+
queue = queue[1:]
136+
137+
if i < len(values) && values[i] != nil {
138+
node.Left = &TreeNode{Val: values[i].(int)}
139+
queue = append(queue, node.Left)
140+
}
141+
i++
142+
143+
if i < len(values) && values[i] != nil {
144+
node.Right = &TreeNode{Val: values[i].(int)}
145+
queue = append(queue, node.Right)
146+
}
147+
i++
148+
}
149+
150+
return root
151+
}
152+
153+
// Helper function for inorder traversal
154+
func inorderTraversal(root *TreeNode) []int {
155+
result := []int{}
156+
var traverse func(*TreeNode)
157+
traverse = func(node *TreeNode) {
158+
if node == nil {
159+
return
160+
}
161+
traverse(node.Left)
162+
result = append(result, node.Val)
163+
traverse(node.Right)
164+
}
165+
traverse(root)
166+
return result
167+
}
168+
169+
// Helper function to compare slices
170+
func equalSlices(a, b []int) bool {
171+
if len(a) != len(b) {
172+
return false
173+
}
174+
for i := range a {
175+
if a[i] != b[i] {
176+
return false
177+
}
178+
}
179+
return true
180+
}
181+
182+
// Helper function to verify BST property
183+
func isBST(node *TreeNode, min, max *int) bool {
184+
if node == nil {
185+
return true
186+
}
187+
188+
if min != nil && node.Val <= *min {
189+
return false
190+
}
191+
if max != nil && node.Val >= *max {
192+
return false
193+
}
194+
195+
return isBST(node.Left, min, &node.Val) && isBST(node.Right, &node.Val, max)
196+
}

0 commit comments

Comments
 (0)