Delete Node in a BST - Leetcode 450 - Python

NeetCodeIO · Intermediate ·⚡ Algorithms & Data Structures ·3y ago

Key Takeaways

Solves Leetcode 450 Delete Node in a BST using Python

Full Transcript

hey everyone welcome back and let's write some more neat code today so today let's solve the problem delete node in a binary search tree we're given the root node of a binary search tree and a key value and we want to delete the node with the key value of course and then we want to return the new root of the tree maybe the root changed maybe it didn't that's kind of what they tell you here it's pretty rare for leak code to give you a hint like this but you got to take what you can get and they even give you how to break down this problem you have to search for the node that you want to remove and then remove the node if only it were that easy though this problem can be surprisingly tricky the first time you solve it especially if you don't have like a deep understanding of how binary search tree operations work but we can use the properties of bsts to our advantage let me show you how I'm going to do that we're given the root of the tree we're given a key 3 in this case we want to find it now finding it is not going to be too bad we know we can do that in log n time well that's assuming the tree is balanced it might not be balanced so actually a more correct way to say this we can find this by using the height of the tree that's all we're gonna have to Traverse but after we find it we also have to delete it finding it is easy we just take the root value 5 is 3 greater than five nope is it less than five yes it is less than five so we search to the left and we would recursively just keep doing that until we find the value now hypothetically the key value might not even exist in the tree in that case we don't have to do anything so that's pretty easy but in this case it does so what do we do with the value once we have found it of course we want to delete it you might first think that well you got to get rid of this node and you got this pointer over here so instead of pointing it at three we should point it somewhere else and we have to like move these nodes around that is technically possible but if you even try to code it up this way you're going to quickly find out that it can get pretty complicated because once you get to the three you're still going to need a reference to it parent so that's going to be kind of complicated there's actually an easier way to do this it's a bit clever and that is we can replace the value of 3 with a different valid value we could pick any value in this tree Why not pick the 7 over here let's get rid of this seven maybe just delete this node and then put a 7 over here well there's two problems here one when we put a seven over here does this still look like a binary search tree to you not to me because every value over here should be less than five but that's not the case seven is greater than five so that's the problem we have to preserve the properties of a binary search tree and second well if we put the 7 over here then we still have to delete a different node anyway so how did that happen how can we prevent that or maybe there's something clever that we can do and yes it turns out that there is something clever first of all what value should we replace three with we should probably pick a value in this subtree if there's one available to us the the reason is because we know every value in this subtree is already less than five so we are allowed to replace this value with two or four but we really have to think through a bunch of edge cases for us to choose the most intelligent value let me tell you why first of all what would happen if this three over here actually did not have any children well in that case it would be pretty easy to delete this value because what we're going to do recursively I'm going to tell you that we're going to solve this problem recursively because it's a lot easier to do so what we want to do is recursively delete from this tree and then recursively delete from this tree Once We delete from this tree we want to return the new tree up to the parent and then we want to return this tree just from our outermost function call but what would we return from here once we delete three we would return null of course and this null value that we're returning is what this parent is going to assign to its left child whatever we return from here is what's going to be assigned to the left child of five so basically what I'm getting at here is if 3 has no children we return null what happens if it only has one child though what if three only has a single child two now this child could have some children or it might not have children I'm arguing to you that whether it has children or not doesn't actually matter for us because we know this itself is a binary search tree and if we get rid of three all we have to do is say that five's new child is two which is a binary search tree and every value here is going to be less than five and of course the exact same thing would be true if three did not have a left child but instead had a right child only and maybe it had some children or maybe it didn't it wouldn't matter we would replace it with this new sub tree regardless so to summarize a really elegant way to write this code code would be if 3 does not have a left child return the right child what if the right child doesn't exist that's okay because this is null and that's exactly what we want to return to the parent anyway and if three does not have a right child we return the left child because if it exists we return it great if it doesn't exist we return null which is what we would want to return anyway so that was the first step now let's go on to the second step which is a bit more tricky I think now of course in this example we actually do have two children for three so what we actually have to do is replace the value we have here we can pick a value from the left subtree or the right sub tree this is a pretty simple tree and I can't really add additional values to four because I can't really add a one that would not make this a binary search tree but just pretend like we have some dummy value here that is valid and some dummy value here that is valid as well what we would want to do logically is pick an intelligent value from the right subtree what value could we put here such that it would satisfy this being a binary search tree if we pick four and put four over here it's actually not going to be a binary search tree because this value is supposed to be less than four that's why it's the left child but if we put 4 here then X is over here x is actually less than 4 but it's on the right sub tree that's not what's supposed to happen so when we pick a value from this right subtree which is what I'm going to do you could pick one from the left subtree but I'm going to pick one from the right subtree I'm going to pick the smallest value aka the minimum value from the right subtree every value in the right subtree is greater than 3 but we want to pick the smallest value because if we pick the smallest value then we know that every value here is still going to be greater than the value here now how do we find the smallest value from the right subtree that's the easy part about a binary search tree you just basically go as left as you can you just keep going in the left Direction you keep going left until you can't go left anymore that's the minimum value and then you put that minimum value over here in this case it's going to be four and then what you do is recursively and this is kind of the hard part you probably wouldn't think of by yourself you recursively call delete node on the right subtree over here because remember if we put 4 over here now we have two four values that's not what we wanted so we have to recursively call delete node on the right subtree passing in not three anymore we're not trying to delete three now we're trying to delete four so in that case we will actually end up with a chain of recursive delete node calls first we delete the value three and then we want to delete the value that we replaced three with so then we want to delete four and it's actually possible that four had a right child let's say it had a right child of five even though five is already here let's just ignore that but if it had a right child of five we'd put the four over here because 4 is the minimum we can't go any further to the left but now we want to call delete node on this tree passing in four so then we get to the four now we want to delete this four so we again pick the minimum value from the right subtree which in this case is five we would delete this node and then we would put the five over here and then we would call delete node on this subtree deleting the five and then possibly we would just keep calling that recursively but the smart thing here is that we are pretty much iterating through the height of the tree as best as we can there are portions that we are going to have to visit twice but if we have to visit a portion of it twice the worst case this would be two times H so still the time complexity is the height of the tree now let's code it up that was a long-winded explanation but the code is actually not too bad so generally with recursive problems we want to start with the base case so it if the root is null then we just want to return the root there's nothing for us to delete anyway otherwise we want to find the node that we want to delete so if the key value is greater than root dot val then we want to go to the right which we can do like this so self dot delete node passing in root dot right passing in the exact same key value else if the key value is less than root dot val then we want to call delete node on the left side of the tree so on the left subtree passing in the exact same key value now the last case is that we actually found the node that we want to delete so this is where we actually do the deletion now you might have forgotten but remember there's actually some simple cases root is the node that we want to delete but what if the left child of root is null then in that case we know the new subtree that we want to return to the parent is going to be root dot right we don't have to do anything super fancy and otherwise if the right subtree is null then we return root dot left which actually reminds me when we call delete well first of all over here we should call this delete node and when we actually call these deletions we might be deleting the left child itself so we probably want to take this updated binary tree and assign it to root dot left imagine if this was the base case that executed instead of returning the root that was actually passed into this function now we want to return root dot right so in that case we would want to take the return value of this call and assign it to however it was called whether it was the left child or the right child so let's do that up above as well now for the slightly more complicated part so now we want to find the minimum from the right subtree just like I showed earlier the easiest way I think to do that is just to take the current pointer and assign it to root because we are going to still need the root and then while Kerr dot left we're gonna keep going down the left child the reason I'm doing this is because we want to make sure we stop at a valid note we don't want Cur to stop at null so by the time this is done Cur should be pointing at the minimum node in the right subtree and remember what we want to do with that minimum value is replace the current root value with it so we say root dot val is equal to curve.val and then we want to delete that value because now we have duplicates we want to delete that from the right subtree exactly where we found it so we say delete node on the right subtree using the value not key we're not using key anymore now we're using the root dot val or you could say occur.val because they're the exact same value I'll just do root dot val and then remember the return value of this we should probably assign it to the right subtree still in case it ends up changing now remember regardless of which one of these three executes we want to return the root node either way you might have the first time you wrote this similar to me you might have had you know return statements here and here as well but then you realize you're returning the same value so you can delete the line from here here and just have one outside of all three of these now let's run this to make sure that it works okay really sorry about that I had a couple mistakes here where we're assigning Cur equal to the root that's not what we want to do of course we want to go to the right subfree so we're going to say Cur is equal to root dot right and here when we're iterating through the loop we're not really doing anything hopefully you caught this one as I was writing it but we want Cur to be equal to cur.left as we go down so now let's run the code and as you can see it's pretty efficient if this was helpful please like And subscribe check out neat code.io if you want to see code solutions for languages other than Python and for a bunch of other free resources to help you prepare for coding interviews thanks for watching and hopefully I'll see you pretty soon

Original Description

🚀 https://neetcode.io/ - A better way to prepare for Coding Interviews Solving Leetcode 450 - Delete Node in a BST. 🥷 Discord: https://discord.gg/ddjKRXPqtk 🐦 Twitter: https://twitter.com/neetcode1 🐮 Support the channel: https://www.patreon.com/NEETcode ⭐ BLIND-75 PLAYLIST: https://www.youtube.com/watch?v=KLlXCFG5TnA&list=PLot-Xpze53ldVwtstag2TL4HQhAnC8ATf 💡 DYNAMIC PROGRAMMING PLAYLIST: https://www.youtube.com/watch?v=73r3KWiEvyk&list=PLot-Xpze53lcvx_tjrr_m2lgD2NsRHlNO&index=1 Problem Link: https://neetcode.io/problems/delete-node-in-a-bst 0:00 - Read the problem 0:50 - Drawing Explanation 8:53 - Coding Explanation leetcode 450 #neetcode #leetcode #python
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from NeetCodeIO · NeetCodeIO · 17 of 60

1 Leetcode 149 - Maximum Points on a Line - Python
Leetcode 149 - Maximum Points on a Line - Python
NeetCodeIO
2 Design Linked List - Leetcode 707 - Python
Design Linked List - Leetcode 707 - Python
NeetCodeIO
3 Minimum Time to Collect All Apples in a Tree - Leetcode 1443 - Python
Minimum Time to Collect All Apples in a Tree - Leetcode 1443 - Python
NeetCodeIO
4 Design Browser History - Leetcode 1472 - Python
Design Browser History - Leetcode 1472 - Python
NeetCodeIO
5 Number of Good Paths - Leetcode 2421 - Python
Number of Good Paths - Leetcode 2421 - Python
NeetCodeIO
6 Flip String to Monotone Increasing - Leetcode 926 - Python
Flip String to Monotone Increasing - Leetcode 926 - Python
NeetCodeIO
7 Maximum Sum Circular Subarray - Leetcode 918 - Python
Maximum Sum Circular Subarray - Leetcode 918 - Python
NeetCodeIO
8 Find Closest Node to Given Two Nodes - Leetcode 2359 - Python
Find Closest Node to Given Two Nodes - Leetcode 2359 - Python
NeetCodeIO
9 Concatenated Words - Leetcode 472 - Python
Concatenated Words - Leetcode 472 - Python
NeetCodeIO
10 Data Stream as Disjoint Intervals - Leetcode 352 - Python
Data Stream as Disjoint Intervals - Leetcode 352 - Python
NeetCodeIO
11 LFU Cache - Leetcode 460 - Python
LFU Cache - Leetcode 460 - Python
NeetCodeIO
12 N-th Tribonacci Number - Leetcode 1137
N-th Tribonacci Number - Leetcode 1137
NeetCodeIO
13 Best Team with no Conflicts - Leetcode 1626 - Python
Best Team with no Conflicts - Leetcode 1626 - Python
NeetCodeIO
14 Greatest Common Divisor of Strings - Leetcode 1071 - Python
Greatest Common Divisor of Strings - Leetcode 1071 - Python
NeetCodeIO
15 Shortest Path in a Binary Matrix - Leetcode 1091 - Python
Shortest Path in a Binary Matrix - Leetcode 1091 - Python
NeetCodeIO
16 Insert into a Binary Search Tree - Leetcode 701 - Python
Insert into a Binary Search Tree - Leetcode 701 - Python
NeetCodeIO
Delete Node in a BST - Leetcode 450 - Python
Delete Node in a BST - Leetcode 450 - Python
NeetCodeIO
18 Shuffle the Array (Constant Space) - Leetcode 1470 - Python
Shuffle the Array (Constant Space) - Leetcode 1470 - Python
NeetCodeIO
19 Fruits into Basket - Leetcode 904 - Python
Fruits into Basket - Leetcode 904 - Python
NeetCodeIO
20 Number of Subarrays of size K and Average Greater than or Equal to Threshold - Leetcode 1343 Python
Number of Subarrays of size K and Average Greater than or Equal to Threshold - Leetcode 1343 Python
NeetCodeIO
21 Naming a Company - Leetcode 2306 - Python
Naming a Company - Leetcode 2306 - Python
NeetCodeIO
22 As Far from Land as Possible - Leetcode 1162 - Python
As Far from Land as Possible - Leetcode 1162 - Python
NeetCodeIO
23 Shortest Path with Alternating Colors - Leetcode 1129 - Python
Shortest Path with Alternating Colors - Leetcode 1129 - Python
NeetCodeIO
24 Minimum Fuel Cost to Report to the Capital - Leetcode 2477 - Python
Minimum Fuel Cost to Report to the Capital - Leetcode 2477 - Python
NeetCodeIO
25 Count Odd Numbers in an Interval Range - Leetcode 1523 - Python
Count Odd Numbers in an Interval Range - Leetcode 1523 - Python
NeetCodeIO
26 Contains Duplicate II - Leetcode 219 - Python
Contains Duplicate II - Leetcode 219 - Python
NeetCodeIO
27 Path with Maximum Probability - Leetcode 1514 - Python
Path with Maximum Probability - Leetcode 1514 - Python
NeetCodeIO
28 Add to Array-Form of Integer - Leetcode 989 - Python
Add to Array-Form of Integer - Leetcode 989 - Python
NeetCodeIO
29 Unique Paths II - Leetcode 63 - Python
Unique Paths II - Leetcode 63 - Python
NeetCodeIO
30 Minimum Distance between BST Nodes - Leetcode 783 - Python
Minimum Distance between BST Nodes - Leetcode 783 - Python
NeetCodeIO
31 Design Hashmap - Leetcode 706 - Python
Design Hashmap - Leetcode 706 - Python
NeetCodeIO
32 Range Sum Query Immutable - Leetcode 303 - Python
Range Sum Query Immutable - Leetcode 303 - Python
NeetCodeIO
33 Binary Tree Zigzag Level Order Traversal - Leetcode 103 - Python
Binary Tree Zigzag Level Order Traversal - Leetcode 103 - Python
NeetCodeIO
34 Middle of the Linked List - Leetcode 876 - Python
Middle of the Linked List - Leetcode 876 - Python
NeetCodeIO
35 Course Schedule IV - Leetcode 1462 - Python
Course Schedule IV - Leetcode 1462 - Python
NeetCodeIO
36 Single Element in a Sorted Array - Leetcode 540 - Python
Single Element in a Sorted Array - Leetcode 540 - Python
NeetCodeIO
37 Capacity to Ship Packages - Leetcode 1011 - Python
Capacity to Ship Packages - Leetcode 1011 - Python
NeetCodeIO
38 IPO - Leetcode 502 - Python
IPO - Leetcode 502 - Python
NeetCodeIO
39 Minimize Deviation in Array - Leetcode 1675 - Python
Minimize Deviation in Array - Leetcode 1675 - Python
NeetCodeIO
40 Longest Turbulent Array - Leetcode 978 - Python
Longest Turbulent Array - Leetcode 978 - Python
NeetCodeIO
41 Last Stone Weight II - Leetcode 1049 - Python
Last Stone Weight II - Leetcode 1049 - Python
NeetCodeIO
42 Construct Quad Tree - Leetcode 427 - Python
Construct Quad Tree - Leetcode 427 - Python
NeetCodeIO
43 Find Duplicate Subtrees - Leetcode 652 - Python
Find Duplicate Subtrees - Leetcode 652 - Python
NeetCodeIO
44 Sort an Array - Leetcode 912 - Python
Sort an Array - Leetcode 912 - Python
NeetCodeIO
45 Ones and Zeroes - Leetcode 474 - Python
Ones and Zeroes - Leetcode 474 - Python
NeetCodeIO
46 Remove Duplicates from Sorted Array II - Leetcode 80 - Python
Remove Duplicates from Sorted Array II - Leetcode 80 - Python
NeetCodeIO
47 Maximum Twin Sum of a Linked List - Leetcode 2130 - Python
Maximum Twin Sum of a Linked List - Leetcode 2130 - Python
NeetCodeIO
48 Concatenation of Array - Leetcode 1929 - Python
Concatenation of Array - Leetcode 1929 - Python
NeetCodeIO
49 Symmetric Tree - Leetcode 101 - Python
Symmetric Tree - Leetcode 101 - Python
NeetCodeIO
50 Check Completeness of a Binary Tree - Leetcode 958 - Python
Check Completeness of a Binary Tree - Leetcode 958 - Python
NeetCodeIO
51 Construct Binary Tree from Inorder and Postorder Traversal - Leetcode 106 - Python
Construct Binary Tree from Inorder and Postorder Traversal - Leetcode 106 - Python
NeetCodeIO
52 Find Peak Element - Leetcode 162 - Python
Find Peak Element - Leetcode 162 - Python
NeetCodeIO
53 Accounts Merge - Leetcode 721 - Python
Accounts Merge - Leetcode 721 - Python
NeetCodeIO
54 Binary Tree Preorder Traversal (Iterative) - Leetcode 144 - Python
Binary Tree Preorder Traversal (Iterative) - Leetcode 144 - Python
NeetCodeIO
55 Binary Tree Postorder Traversal (Iterative) - Leetcode 145 - Python
Binary Tree Postorder Traversal (Iterative) - Leetcode 145 - Python
NeetCodeIO
56 Number of Zero-Filled Subarrays - Leetcode 2348 - Python
Number of Zero-Filled Subarrays - Leetcode 2348 - Python
NeetCodeIO
57 Minimum Score of a Path Between Two Cities - Leetcode 2492 - Python
Minimum Score of a Path Between Two Cities - Leetcode 2492 - Python
NeetCodeIO
58 Sqrt(x) - Leetcode 69 - Python
Sqrt(x) - Leetcode 69 - Python
NeetCodeIO
59 Successful Pairs of Spells and Potions - Leetcode 2300 - Python
Successful Pairs of Spells and Potions - Leetcode 2300 - Python
NeetCodeIO
60 Optimal Partition of String - Leetcode 2405 - Python
Optimal Partition of String - Leetcode 2405 - Python
NeetCodeIO

Related Reads

📰
Building a Power Grid Inside Minecraft with BFS Algorithms
Learn to build a power grid inside Minecraft using BFS algorithms and understand its relevance to cloud services
Dev.to · Carlos Cortez 🇵🇪 [AWS Hero]
📰
The Run-Length Encoding Trick: How Simple Strings Get Compressed
Learn how Run-Length Encoding (RLE) compresses simple strings, a fundamental technique in programming and data compression, and apply it to optimize storage and transmission of data
Medium · Programming
📰
75 Days of Leetcode — Day 4: #238 — Product of Array Except Self
Solve the Product of Array Except Self problem on LeetCode to improve coding skills and learn array manipulation techniques
Medium · AI
📰
I implemented the algorithm that broke the sorting barrier. Dijkstra still wins.
Learn how the author implemented an algorithm that broke the sorting barrier and compare its performance with Dijkstra's algorithm
Medium · Programming

Chapters (3)

Read the problem
0:50 Drawing Explanation
8:53 Coding Explanation
Up next
Stump Grinder Carbide Wheel Grinds Hardwood To Chips
Innoforge Studio
Watch →