Maximum Width Ramp - Leetcode 962 - Python

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

Key Takeaways

The video discusses the Maximum Width Ramp problem on LeetCode, presenting a solution using a sliding window algorithm and a two-pointer approach, and providing an optimized implementation in Python.

Full Transcript

hey everyone welcome back and let's write some more neat code today so today I'll solve the problem maximum with ramp and before I even get into this problem I want to quickly say something imagine that this is like the normal distribution of people watching these videos from what I know about half of you guys only care about knowing what the solution is and then I would say the next like 40% actually want to know why the solution works and lastly we have the 10% the top 10% who actually care about the intuition to be able to come up with Solutions like this in the future and so of course I'm going to be covering like these two but I'm really going to try to focus on that last 10% mostly because I enjoy it and I hope you guys find it helpful so let's get into it suppose we're given an array like this we want to find the maximum subarray pretty much and I'll kind of describe what I mean by that but we want to find the maximum that satisfies two particular condition one is that these two pointers I and J have to be different and this pointer has to be less than the other one and second the value at that pointer that is less than the other pointer has to be less than or equal to the value at the other pointer so those are the only two conditions now when I said subray that's not entirely correct like if this is that subarray we actually just want to return the end minus the beginning so in this case that would be three which is the index here - 1 so we'd get 2 which technically is not the length but it's the length minus one so I think it's fine to think of it in those terms so of course to this solution there is a Brute Force solution you just go with nested Loops so starting here we want to find the longest subray we can create starting here so we have that I pointer there J pointer over here and just keep going compare the values this doesn't obviously form a valid subarray so go here it does like the values are less than or equal so we're good so we found one that's of length two so J minus I in this case is two we'll keep going and we'll find that now there aren't any other values greater than or equal to six so very important observation to make even though this is the Brute Force solution we're looking only for values greater than or equal to 6 if only there was a way we could early determine that there are no more values greater than or equal to six if only that was the case we might be able to optimize this solution but we can't so now we go to the next position and do the same thing so I here keep looking for values that are greater than or equal to zero this one is this one is this one is and this one is as well so the longest that we could create I think in this case is four and at this point like our Brute Force solution is going to keep running it's going to try the same thing from here here here and here but can't you kind of tell that I mean the longest we could create from here was this and the longest we can create from here is that we went up until the end of the array so there's never going to be a subarray from anywhere in here that's going to end up being longer than that so if you're a seasoned leak coder you probably have heard of the sliding window algorithm this Brute Force Solution by the way was an N squ solution and it's a pretty simple one so for a medium problem we should probably expect that we want to do better and the sliding window algorithm the way we're going to kind of do it like I don't know if this is technically the sliding window because like we don't actually care about the window itself we care more about like the end values I prefer to think of it in terms of sliding window Some people prefer to call this the two-pointer approach I mean technically sliding window is a two-pointer algorithm but anyways by the way I'm probably going to gloss over some of the basics so in case like you want to learn more about like these fundamental algorithms sliding window TW pointer prefix sums you might find some of the courses on N code iio helpful now the sliding window algorithm is one that generally runs in linear time it's a two-pointer algorithm this intuition is making me think that perhaps we can apply the sliding window here so it doesn't cost us much to see if like that's valid maybe it'll take 30 seconds just to see if there's a very naive sliding window solution to this so let's try that we have our pointers here and here with the sliding window we generally want to increase the window as much as we possibly can like shift that right pointer as much as we possibly can now if we can't shift the right pointer any further then we shrink the window we take the left pointer and then shift it and it can sometimes be in the same position as the right pointer but the left pointer will never pass the right pointer so I'll just start drawing these as left and right now we're here this is our window but this window is not valid so what should we do because the value zero is less than the value here well the naive sliding window would say well take the left pointer and shift it until that's not the case so then now we're here and this this is fine like for this example it actually will work because now we're going to take our right pointer and shift it by one where here we're going to try this window it's valid we're going to try this window it's valid this is valid and this is valid so it works for this example but it's not always going to be the case and this example we can change it very simply I'm just going to take this five and turn it into a six by drawing over it very badly but now this is a six and now our previous naive sliding window it won't work we just broke it with this simple example cuz now this solution will find this as the longest window but that's not the correct solution the correct solution is actually this and so we made a mistake a bad judgment call when we were back here when you take the left pointer and shift it to the right you're basically saying that we cannot create a window bigger than this that starts at this left pointer the sliding window basically does that that it computes the longest window you can create starting from here here here eventually and when you can't create one from here then we shift the pointer to the right and sometimes we don't shift it at all if we're trying to look for like the maximum subarray which in this case that's exactly what we're doing but specifically when we take this left pointer we're saying that there is not a value to the right of this that is greater than or equal to that but that's clearly not the case here so how would we even determine that how would we know that there actually is a value to the right of six that is greater than or equal to 6 I mean we could scan through every value to the right of it but that's just the Brute Force N squared solution so instead how about we do something called preprocessing the way to eliminate a left candidate is to know what is the max value to the right of that and if the max value to the right of that the max is less than this value then we can safely eliminate this value so that's what I'm going to do I'm going to create a new array down here so I have this new array down here it's called Max right it's going to be the same length as the array up above we're going to fill it in by just for every value Computing the maximum value to the right of it and if we do that obviously going left to right it's going to be n^2 so how about we try doing it right to left and then we just maintain what the max value is that we've seen so far so the max value to the right of this we're actually going to include that value itself so when we do like the two-pointer approach and we want to know like what's the max value to the right of this we're actually going to be using the right pointer so it's fine that we include the value itself because from here we're going to say what's the max value in this whole portion if it's less than six well then this is not a valid subarray so that's why we would shift the left pointer but anyway so this is six we'll put a six here this is one what's the max we've seen so far it's six so we'll put a six over here same thing over here over here we finally see an eight a different number that's bigger than six so we will say eight is the max we've seen so far and it's also going to be the max here and here so with these values I'm going to show you how the solution is going to work for now I think it's fine if you just memorize this and just kind of focus on what the solution is then understand why it works and once you know that then try to focus on how you could come up with it yourself in the future so now starting here with our two pointers our window is this we don't care about this window itself we just want to know does there exist a window whether it's this one or maybe further to the right where this can be the starting point because we're trying to be greedy we're trying to find the maximum window so of course we'd start right at the beginning ideally we can create this window and in this example we can so we're going to see what's the max value at this right pointer it's eight that tells us that in here somewhere in here there is an eight so this is a valid subarray so we can take right minus left that's going to be one and that's going to be the max we've seen so far I'm going to call that the result and now we're going to take the right poter and shift it we're going to do the same thing take the value that's at this index it's eight that tells us that there is an eight somewhere in here so thus there does exist at least a window of this length either it's this window itself or maybe there's a bigger window so it's safe to say that the result is at least going to be two and then we'll take the right pointer here do the same thing even though this value is less than six we know that the max value to the right of here possibly including that value is a six and thus we can say that this window is valid because either it is valid or there is a larger window that's valid so now we'll update the result to three and just keep going we're going to get here same thing we're going to get here same thing so we would get a total of five in this example now let's change the example let's change it back to what it was I'm just going to draw over this just to make it quick let's assume that that's a five so now let's populate this let's put a five here and the max we've seen so far here is five here is five and then I think this will be eight and these will be eight as well well so quickly going through this example we'll get the left pointer here right pointer here we want to know if this window is valid and we don't do that by checking this value we look at the max value here so there's an eight here so that tells us either this is valid or there is another value somewhere over here where we can create a valid window so we'll set the result to one right now we'll shift this pointer over here we're at eight still valid so now we'll increment the result to two now the right pointer will be shifted over here I'm going to clean this up a little bit right pointer is over over here we take a look at the max value in this portion of the array it's five five is less than the left value so now we shift our left pointer we take the left pointer and we shift it over here right pointer is still here and now we kind of do the same check we compare this value with the max right at this pointer which is five this five tells us that there is a five somewhere over here so 0 and five 5 is greater than zero so this is valid and from here we just take this right pointer and then shift it here and then eventually shift it whoops over here where we would get this window so that's the intuition behind this algorithm I know it's not easy to come up with it's not even easy to understand but I hope this does make it at least a little bit easier you can see why this solution would be a linear time algorithm again the key points are with the sliding window when you shift that left pointer you want to eliminate that completely and the only way to do that is to know what's the max value to the right of it and due to this array are going to need extra space as well typically with sliding window you actually don't need extra space so this is a very interesting variation of that so the first thing I'm going to do is that pre-processing I talked about I'm going to create an array called Max right initially I'm going to fill it with all zeros because we know that the smallest value in our input is actually zero so this is perfectly fine and I'm going to multiply it by the length of the input array because in Python that will create an array of the same size filled with all zeros then I want to start start iterating through the input in Reverse I'm going to do that like this for n in reversed nums I believe that just creates an iterator over nums and then we'll go in reverse order so I don't think that actually creates extra space but maybe I'm wrong and what we want to do is the max value at the last position let's call that index I we want to set it to the max of the current value n and whatever the previous Max was which would be Max right of I + one now there's a few things wrong here there's a few issues one we don't have like the ey pointer so that's an easy fix let's set I equal to whoops some all caps I equal length of nums minus one so we're starting at the last index but if we're starting at the last index I +1 is going to be out of bounds in that case there's multiple ways we could deal with this I'm going to deal with it just by having a variable which I'm going to call the previous Max and initially I'll set it to zero and then here we'll replace that with previous Max and then down here we'll update the previous Max every single time to the value that we just populated here and don't forget to update that pointer I so let's decrement it by one each time this is just doing that pre-processing building Max right array now for the two-pointer or sliding window solution we're going to initially set the result to zero we're going to return the result and we're going to try to maximize it so I'm going to have one pointer left it's going to be zero I'm going to have the pointer right which is going to go through the length of the input every time we want to update the result by maximizing it and we're going to assume our current window is valid we're going to add the validation here but just assume that eventually we validated the window and so this is the current length of the window right minus left and we want to try to maximize it so set it to the result of the max of these two okay so now to actually validate the window how do we know if the window is invalid well while the number at index left is greater than the maximum number to the right of it so max right at pointer R while this is the case if they were equal that's actually fine then it's valid but if this is strictly greater than the max value to the right of it well that window is no good we can safely eliminate the left pointer from the solution set so left will be incremented by one so this is the entire solution it doesn't look very complicated but it's definitely harder than it looks I'll run it and you can see that it works I promise you that it is more efficient than leak code indicates right now I believe this is the optimal solution in terms of time and space if you found this helpful or if you're a beginner looking to learn more and improve your problem solving skills definitely check out n cod. whether you just want to use the free resources or you want to buy the courses I genuinely think you'll find it useful

Original Description

🚀 https://neetcode.io/ - A better way to prepare for Coding Interviews 🧑‍💼 LinkedIn: https://www.linkedin.com/in/navdeep-singh-3aaa14161/ 🐦 Twitter: https://twitter.com/neetcode1 ⭐ BLIND-75 PLAYLIST: https://www.youtube.com/watch?v=KLlXCFG5TnA&list=PLot-Xpze53ldVwtstag2TL4HQhAnC8ATf Problem Link: https://leetcode.com/problems/maximum-width-ramp/description/ 0:00 - Read the problem 0:30 - Drawing Explanation 11:36 - Coding Explanation leetcode 962 #neetcode #leetcode #python
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from NeetCodeIO · NeetCodeIO · 0 of 60

← Previous Next →
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
17 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

This video teaches how to solve the Maximum Width Ramp problem on LeetCode using a sliding window algorithm and a two-pointer approach, and provides an optimized implementation in Python. The solution involves preprocessing the array, using a max right array, and validating the window to maximize its length.

Key Takeaways
  1. Implement Brute Force solution with nested loops
  2. Apply sliding window algorithm for optimization
  3. Use two-pointer approach for finding maximum subarray
  4. Preprocess the array to find max value to the right for each element
  5. Create an array called Max right and fill it with zeros
  6. Iterate through the input array in reverse order to populate the max right array
  7. Update the max right array by taking the max of the current value and the previous max value
  8. Maximize window length by moving left pointer
  9. Validate window by checking max number to the right
  10. Increment left pointer when window is invalid
💡 The key insight is to use a sliding window algorithm with a max right array to efficiently validate the window and maximize its length, resulting in an optimized solution with optimal time and space complexity.

Related AI Lessons

Bloom Filters, Explained Properly
Learn how Bloom filters work and their benefits, including tiny memory and blazing speed, in exchange for potential false positives.
Dev.to · Daksh Gargas
Prefix Sums: The Preprocessing Trick That Makes Range Queries Instant
Learn how prefix sums enable instant range queries in arrays, boosting performance in various applications
Medium · Programming
I Thought I Was Ready for the Interview — Then One Simple Math Question Destroyed Me
A simple math question can destroy a developer's interview, highlighting the importance of being prepared for unexpected questions
Medium · Programming
Week 2(Day 10): LeetCode Two Pointers(slow & fast): Remove Duplicates from Sorted Array (Brute…
Learn to remove duplicates from a sorted array using the two pointers technique, improving from brute force to optimized solutions
Medium · Python

Chapters (3)

Read the problem
0:30 Drawing Explanation
11:36 Coding Explanation
Up next
Stump Grinder Carbide Wheel Grinds Hardwood To Chips
Innoforge Studio
Watch →