I am 45 mins in, but I had to stop to drop this comment. This is hands down one of the best tutorials I've ever seen. Alvin is a true teacher. I am blown away by his style. I have taken paid courses on this topic, but this is the first time I am understanding what this is about. I can't wait to finish this tutorial. I am going to go for all your courses.
a note: go donate on their website, it's tax free (As they are non profit), they get the full amount and you pay no taxes. TH-cam charges taxes to both the channel and the donator.
I've been coding since 1998 and have watched countless tutorials on countless topics. This guy is definitely one of the best teachers I've ever come across.
Simply THE best dynamic programming course on youtube, wonderfully explained. The course made understanding the difficult concepts a breeze. Loved the progression of problems, even the harder ones felt easy after understanding the basic strategy and the recipe. Thank you freeCodeCamp and Alvin.
@@LogansDarling while I'd argue there are probably better, more direct ways to support a creator, what makes it so weird to you? People have been spending cumulative billions of dollars over the past years just for having their message read on stream or purely for support. It's basically a pay-what-you-want scheme. If you really feel like shaming other people's spending, I suggest you may start with people buying shiny rocks to put on rings with otherwise zero value and ethically questionable production.
@@TomasLKarlik while I'd argue that shaming someone for how they choose to support someone is lame, financially or otherwise, what makes you think that's what I was doing? People have been being confused by the billions of new features YT has put on their platform over the past years just because they're not used to it. It's basically a guess-what-this-symbol-means scheme. If you really feel like assuming the motives of peoples' questions, I suggest you may start with people sarcastically belittling people to cancel anyone who doesn't follow their exact position with otherwise zero value and ethically questionable means. jokes aside i understand how that could be misconstrued as an insult but i was genuinely wanting to kno cuz it could have been like idk - Spending money on a specific comment. - Spending money on a channel. - Spending money on YT. - Spending money outside of the platform and the YTer giving them the badge. - No money even being spent and me just thinking something is a currency symbol. - It could be _anything_ considering how stupid I am, so I have no clue. although if u kno that its for a specific comment then ig u answered me so thx (I do think that it's stupid, but that's more on YT's part than the commenter's part. Seems like a stupid feature to add on the platform, but that hasn't stopped YT before so oh well. ¯\_(ツ)_/¯)
It took me a week to finish this tutorial. This tutorial is just pure gold. I always found it hard to understand time complexity for recursive solutions. But this video explains it perfectly. This is probably the best tutorial on dynamic programming. I can't believe you're giving such quality content for free...
I'm here after watching graph algo. I am a data engineer and I always struggled to understand the space and time complexity, this animation is all I ever wanted. This is by far the best video I watched on dynamic programming. Moreover, Alvin has that charm to keep me captivated for long hours without loosing focus. Keep up the great work man!
After getting frustrated from these dynamics programing, after hunting to know the real concepts in books, articles, online paid courses, TH-cam videos, finally got this here and that too free. I can't believe this. He teaches like crazy. Thanks a lot.👍
Phenomenal teacher, I’ve got an hour left and even though I’ve fumbled my way through similar problems I feel I understand everything much better. This is now my go to recommended video for recursion and dynamic coding
This is the slickest way I've ever seen not only Dynamic Programming, but also recursion presented. His slides/animations are just perfect for guiding every single step your brain needs to go through along the way, and he handles all kinds of gotchas and keeps you from getting stuck. I'm already going from "holy cow how am I going to even approach these problems" to "ok this is starting to get intuitive with this workflow" just an hour in. Literally better than any professor's teaching style than I remember from my college CS program. The effort put into this video is insane! I have a feeling this video just covers some of the basics-intermediate problem types, but I bet this will be a great stepping stone to tackling the harder DP problems.
Brilliant video! The entire community of learners owes you a coffee for teaching us this excellent approach to solving the infamous dynamic programming problems. Other videos and books do not go into this well-defined mindset and step-by-step strategy that you need to develop, in order to understand and ultimately solve these problems from a *pragmatic* approach (which is what ultimately aces technical interviews). Keep up the great work, Alvin!
Damn this guy was the instructor for app academy. His explanations actually put me on the track to understanding this crazy world of code. So glad he's back on the scene!!!
my man Alvin! I'm a Senior Developer but it was always a grind to brush up DSA topics when I'm in the job hunt. Your videos helped me quantify it a lot. I just watch your DSA videos in 1.5x half a day before an interview and that is all I need. Very well put both for beginners and for folks like me who need a quick run-through. This is the kind of stuff internet is made for. Appreciate the great work. keep it up!
@@khz2172 I don't think he's that good, the course only teaches the basics and some simple problems. If you want to become good at DP I think you should practice with some DP problems (from codeforces, for example)
Wow. Dynamic programming looked so daunting on the outside. In a matter of 2 days, you changed my mindset about it for good :) Now it seems easy and doable. Many thanks!
This is hands down the best crash course on dynamic programming. After struggling for so many hours on dp, I actually feel that I understand the logic and process for tackling dp problems now. Thank you for this amazing video!
Really found a great starting point to learn dp and found a thinking process to approach the problem with recursion without optimization and then use memorization or go for tabulation
It's amazing to realize that grid traveler problem sounds like a completely different problem to fibonacci, but it's solved with the same pattern. Just wow.
You will find in theory of computation that the problems are divided into sets of similar problems ie we can reduce any problem to any other problem to solve and if we can solve just one problem in that set in an more efficient time complexity then we can solve other problems in that set the same way
I am writing this review by just viewing the content for 30 mins. I loved it. I was bit reluctant to start as Dynamic Programming is very difficult and yet very important at the same time. This has given me a boost of confidence as i was able to code the same concept in Java. Thank you so much. And Happy Coding everyone. No matter how difficult it seems, we would go through it Together. :)
After finishing this video in 2 full days, I am able to come up with an approach now, and write solutions. No matter how much efforts I made to learn dp, I was no where close to coming up with a neat approach. With these concepts and some more practice on the DP problems, I can sure be good as a hell pro problem solver in a month.
You are a coding instructing master. There are millions of people who code, but only a few coding instructing masters. Great stuff. You deserved every one of those subs and likes.
Man, Alvin, I watched your Graph Algorithms course first and I absolutely loved it! I saw people there, recommending this legendary course and I just knew I had to come here! Every single second watching this video was completely worth it! There is no way I can praise your explanation enough Alvin! There just is not! After this going through this video, I went from literally have no clue whatsoever about what dynamic programming even means, to completely falling in love with this subject. I would surely indulge myself into this subject, and I believe that this video right here is simply the best entry point for any developer out there who is willing to learn this subject. Thanks Alvin. I am really very grateful!!
Definitely, one of the best courses to start with DP. Just started with the tabulation approach and, decided to attempt it after watching the initial explanation. But decided to follow a different approach as below: def fibDPTabulation(position): if position
Yeah, I wondered that too, why he's doing forward tabulation instead of backward one. But for the later problems with strings, it really makes much more sense to think forward, so he just wanted to establish consistent practice.
I'm not one to watch any 5 hour video but this one really hooked me to go all the way. Explaining hard things in a simple and engaging way is hard and you delivered it perfectly.
YOu should be given an award as the best tutor on Dynamic Programming concepts in the history!!! You approach is so detailed and step-by-step. You found the best formula on how to teach these complex things. Thank you very much for your job!!!
This course just proves that when you go through each minute detail of a problem in a calm and precise manner, while also hinting at the obvious even, a student is much more likely to pick up on the subject. Judging by all the other comments, slower people like myself are starting to get the concept. 🤣 Fantastic coure, thank you very much for uploading this piece.
I don't think it's about slow or quick, it's just that schools don't teach us how to think. They just cram crap down our throats and expect use to puke up rainbows.
The author did not include in the compute complexity the access of the memoized data. For the fibonacci, the algorithm can be optimized to o(1) instead of o(n).
Assalamualaikum brothers and sis, I am seeking Software Engineers, whom can code in Tensor flow and RNN Time series. I am paying.. I am based in USA.. Please check out lighttheory.page/ or email us at info@LightTheory.tech SALAM
@John Leal i was looking for this in the comments memoized base case after this optimization would look like if (m, n) in memo: return memo[(m, n)] elif (n, m) in memo: return memo[(n, m)]
Was wondering that too, I tried it out... Passing a grid of 500,500, I measured the time it took for it to run... 230ms without and 125ms with the sorting.
This is an amazing and helpful tutorial! For GridTraveler program, we can solve it analytically. Assume a grid with size m*n , then to go from the top left to the bottom right, the total number of step moving right has to be (n-1), and the total number of step moving bottom has to be (m-1), the overall total number of step has to be n-1+m-1 = m+n-2. Any particular path is an arrangement of steps of these two types of directions. Therefore, it is equivalent to say that if we have total m-1+n-2=m+n-2, then count the number of ways we can pick m-1. So the analytical solution is (m+n-2)!/[(m-1)!(n-1)!] , where ! means factorial
one of the worst things about learning new DSA concepts is the jump in logic/thinking thats made where it doesn't make sense until you've done a million examples because people don't really explain their thought process and the intuition behind it much. this has none of those issues. this is probably the best DSA video i think i ever seen. amazing work, thank you. 🎉
After graduating with a CS degree and working for 2 years, I can finally explain to someone what DP is! Phenomenal and unbelievable course. Can't thank you enough for this high-quality content.
Thanks for the great content. In gridTraveler problem, base condition could be that if either of rows or columns is 1 , we can return 1 So, if(m == 1 || n == 1) return 1; And i think we could just check m and n interchangeably : if ((m + "-" + n) in memory) return memory[m + "-" + n]; if ((n + "-" + m) in memory) return memory[n + "-" + m]; As number of ways to travel a grid for (2,3) will be same as number of ways in case of (3,2)
We are mathematician see these problem in very different way. 1. We can reuse an array of value already calculated, 2. We can linearize a two dimensional array to one dimensional array. 3. It’s good couse.
Assalamualaikum brothers and sis, I am seeking Software Engineers, whom can code in Tensor flow and RNN Time series. I am paying.. I am based in USA.. Please check out lighttheory.page/ or email us at info@LightTheory.tech SALAM
Hands down. I am not a very good student of programming however, the way this person teaches is impeccable. I am solving questions side by side and I am getting all the answers right within the first go. Thank you so much for your efforts and you should really teach me everything because I am UNSTOPPABLEEE.
@@ScorpionKing-z8n it's not a scam but they are definitely over priced. I think of college as my source for what I need to know, and the internet (mainly youtube) as my source of knowing those things. Without college/universities, it's hard to know what you need to know. It would take a lot of asking questions and bothering people who didn't sign up to be questioned... lol
I usually can't symphatize with ppl who say this, but yeah, DP is probably the biggest thing the internet has been able to taught me better than a price-near-the-seven-hundred-thousand-colombian-pesos uni course.
This is the best dynamic programming content I've ever seen. What I found particularly helpful is being able to understand and view recursive problems as a tree. Because of course trees are recursive data structures. When you have a tree from the outset, as long as you understand general principles of DFS and BFS, a lot of solutions become obvious. What this guy does is show a way to make the implicit, explicit. It's that step that is usually the most difficult because sometimes you're just given a number and asked to solve the problem. Once you understand that problem with that starting value represents a tree of decisions, it allows you to visualize it in such a way that the solution becomes evident. Great job.
I've never seen anyone before who was able to better and more clearly explain dynamic programming. The way you're leading us there step by step and also how the material is presented is outstanding. I'm very impressed Good Sir :-) Thank you very, very much 🙇
That's extremely clear! Had fun and learnt. Thanks Alvin! Btw, the exceeddings (3:20:45) of array at line 5 and 6 are okay for js, but may trouble other language practicing.
Great video! I think some problems can be further optimized and I am sharing my notes below [spoiler alert]: 1. Fib numbers 1. Obviously, can have constant space complexity. 2. Grid traveller 1. I think there is a O(min(m, n)) space complexity solution. you can keep track of only the “outer” part of the grid. 3. CanSum 1. For CanSum and HowSum, space and time complexity can be optimized by a factor of m, by storing the only last number that got added to the final target. In the end, we can obtain the final results by traversing the table once. 4. HowSum 5. BestSum -> Leetcode39 (similar to allConstruct but using numbers instead of strings)
00:00 Intro to dynamic programming 3:22 Understanding the need for Dynamic programming 10:48 Understanding time complexity and space complexity 22:27 Back to the need for dynamic programming with an example 23:31 Dynamic programming - how it reduces the time complexity 25:56 Implementation of dynamic programming using memoization 38:38 More problem
This the best and most informative explanation of DP I've seen in 25 years! Great job and I hopefully some day you'll be compensated well for your outstanding teaching ability.
This is a great short course with a great teacher!! 😉😉😉😙 The classes I attended about dynamic programming in my university are not even comparable to this. This is much more understandable, well presented and makes you want to keep learning the topic.
47:00 last node to the right should be 2,0... still a base case, so no difference overall, but it's best to clarify to prevent people of confusion and frustration...
In the example of canConstruct 2:24:00 you can use the method `startsWith` since you're just interested in knowing if the target starts with the word, so you don't need to traverse the entire string finding the index! Amazing course btw I really appreciated!
Repent to Jesus Christ “We demolish arguments and every pretension that sets itself up against the knowledge of God, and we take captive every thought to make it obedient to Christ.” 2 Corinthians 10:5 NIV
For the howSum and bestSum problems, the additional product of m in the complexity can be avoided by mutating the array instead of creating a new one and copying it over. Just use combination.push(num) and it will be O(1) since appending an element at the end of an array is O(1). So time complexity can be O(m*n) and O(m) which is even better. Other than that, great video.
Hey, could you explain why the time complexity of canSum with a memo is O(m*n)? I can understand the brute force way is O(n^m) but I'm confused with the improved one.
@@liangyu3771 Think about how many different ways there are to call canSum. With an amount of m, canSum could be called recursively with any number from 1 to m, so there are m different ways. Similarly, for each node from 1 to m, there are n edges to branch from. In total, there exists at most m * n nodes to traverse through. The difference between n^m and m * n is due to the memo object saving us from doing repeated work.
This is my first comment on youtube but i can't thank you enough for this course it literally saved my life and my algorithms and data structures exam. My professor was completely useless, he just copy-pasted notes from a mit course by Erkik Demaine (while obviously not having the same teaching nor programming skills lol ) and arranged our exam as a coding interview (two problems in 1 hour and a half). University gave us little to no experience in programming (we just had two programming courses in computer engineering) and after graduations i felt like my skills were very weak and coding was my biggest fear. This course gave me confidence and made me realize once and for all that coding is 80% thinking and 20% writing actual code. Now i can't say i'm a pro but i feel a lot better and i passed the exam with 30/30 so a complete success! Unfortunately i'm still studying so i don't have a job, but i will donate once i have a stable income! For everyone worrying about failure, trust yourself, you're smart enough, i know you can do it! Just don't panic and break the problem into simple fool-proof steps. I promise it gets easier and even fun, don't give up!
This is one of the best videos on both recursion and dynamic programming I've ever seen. Thank you for making this available and sharing this knowledge with the programming community.
Thanks for this tutorial: with your lectures I improved an algorithm that calculates any of level the Pascal's triangle, it was really satisfying to see the big improvement with a very few lines of code
Before I thought I would never be able to solve problems using dynamic programming , but now I have a lot more confidence. Thank you for this amazing video😁
Bro is using 2 tricks called memorization and tabulation all over the video but there are more tricks to cover those problems such as 1. Optimization Using Space Reduction 2. Recursive With State Compression 3. Greedy Algorithms and more, but it was impressive on how bro using visualize to cover those problems for a nearly newbie to fully understand. Great work out there man. 💬
Learning to code by myself, this course brought me so much. I didn't know anything about dynamic programming, not much about time and space complexity. Now I wouldn't say that i master it of course, but with those great explanations and examples I happened to cruise through all these exercises with ease. I am genuinely shocked to see how easy it is for me now, as those problems just seemed impossible before and their solutions looked like witchcraft. Thank you so much, this is a wonderful course !
It is always a treat to find content perfectly paired to one's journey in programming. For me, this content is exactly what I need. Thank you Alvin and thank you FCC for distributing! Unbelievable that this is free.
Really good video, so well explained. Unless I am missing something I think there is a small mistake in the time and space complexity of howSum: There is no need to store the positive result (an array in this case) in the memo object, since as soon as we find one good result, we stop the exploration and just return all the way up, so no other recursive call will be made, and the memo object will never be checked again. Only storing false/null is useful. By that logic, even if you do store the array in memo, at most there will be a single array of length m in memo, so the space complexity would be O(m*2) so O(m) and not O(m*m). In the same way, we are going to create a new array at most m times (a single path will ever return an array, never multiples, so 1 time per node in the path), so time complexity of copying the arrays would be O(m) again, for a total time complexity of O(n*m+m) instead of O(n*m^2). So basically, you are assuming that in the worst-case scenario (say a numbers array filled with 1) every single path will return an array, while in reality it's always at most 1 path, since we stop all exploration as soon as we have one match. Am I missing something?
- I agree with you regarding the first part "There is no need to store the positive result (an array in this case) in the memo object" - Regarding the second part of analyzing the space and time complexity (even if you do store the array in memo, at most there will be a single array of length m in memo) , take care that we are copying the whole array at each call (i.e. each element of the memo will be an array). Each element is an array that represents the **whole path** from that **current** targetSum to the leaf (i.e. it would be sth like memo = { [3], [3,2], [3,2,2]}). memo will contain multiple arrays of lengths ( one , two, three, ...... m)
I agree with you. I also noticed it. The copying of array occurs at most m times. I checked this by incrementing a global variable for every recursive call that copies an array. That means the total time complexity for brute force would be O(n^m + m^2) and for the memoized O(n*m + m^2)
Thanks for the fabulous course 👏🙏One modification that I think the video needs is that for the grid travel algo with memoization, the space complexity is O(m*n) and not O(m+n) [1:04:15]. The stack of course uses O(m+n) space but the 'memo' object grows to store m * n key/val pairs. So the overall space complexity would be O(m*n).
Apart from the knowledge served, I also want to appreciate the work done to choose colours for slides. It works so perfect for both day and night mode.
40:00 In fact, combinatorics saves a lot of trouble. nCr (n choose k) requires one line of code. Let 'm' be the height and 'n' the width. Then, we notice that if we treat each move as an arrow - in a 3x3 grid there'll be only 2 columns allowing for 'arrow right' and only 2 rows allowing for 'arrow down' - so we now have a number of strings (sequences like 'right' 'right' 'down' down' or 'down' right' down' 'right') of 'right' and 'down' which is (m - 1) + (n - 1) = (3 - 1) + (3 -1) = 4. So we have 4! = 24 permutations (as usual we don't want to double count so we do the next step). Now these 24 permutations will just swap these arrows around purposelessly, i.e. (without loss of generality) a combination of 'right' and 'right' would yield 2 in this case (when, in fact, there is just one. It's like counting AB and BA except the letters are AA, so it counts AA and AA as if they were two distinct combinations). How do we not double count? Well, there are only 'down' and 'right' - so simply by dividing our (m + n - 2)! by (m - 1)! (permutations of 'down') * (n - 1)! (permutations of 'right') that is, all redundant permutations of 'down' (2 rows) and all redundant permutations of 'right' (2 columns) are addressed. So the answer is (3 + 3 - 2)! -------------------------- = 4! / 2! * 2! = 24 / 2 * 2 = 6 (m - 1)! * (n - 1)!
I had the same idea, but as @Taniea said, you still end up computing all possible pairs. You don't even save the lookup time, as the lookup occurs before the 'if' condition.
20:57 No you cannot simplify O(2^(n/2)) to O(2^n) as 2^(n/2) cannot be expressed as a * 2^n + b * 2^(n-1) + ... + c form. 1:04:08 No, the cache size can become n * m / 2 in the worst case. So, the space complexity should also be O(n * m)
It is not a simplification. I guess what he meant was big O in the academic sense, i.e. the upper bound function. Since 2^(n/2) == sqrt(2)^n, so you can say that it is always less than 2^n.
What I can't grasp is how he got O(n^m * m) in the unoptimized howSum. Upon each recursive call you do at most one copy of m elements, and you do it m times, so the final O is O(n^m + m^2).
Since I finally got a Data Structure & Algorithm course that can keep me learning repeatedly for hours, I can safely say this is one of the best startup programming series on Data S. & A. Also, this comes with a full recommendation on my part to anyone interested in Software Programming. Thank you, sir!
Almost an hour in and I'm shouting "Where have you been all my life???" Just had a lightbulb moment which other tutorials have failed to do for me. Well done!
Hey! you'd mentioned that 2,1 or 1,2 basically return the same value previously but in the code these values are being separately calculated... at 1:01:50 by using, const key1 = m+","+n; const key2 = n+","+m; we can check for both key1 or key2 in memo and return the associated value. (also, great video! loved the visualizations!)
No. I don't want to be a software engineer at Google. Please leave me alone algoexpert I just wanna learn dynamic programming.
resistance is futile, you will be absorbed, prepare for the interview
@@donsurlylyte haha...me neither. I should apply just for grins, to see what it's like.
Literally every video I click!!
Yeah, man. Whats with the grin .. Little too happy..
in fact, this is the most annoying ad ever! This plump woman with a nasty voice will come to me in my nightmares.
I am 45 mins in, but I had to stop to drop this comment. This is hands down one of the best tutorials I've ever seen.
Alvin is a true teacher. I am blown away by his style. I have taken paid courses on this topic, but this is the first time I am understanding what this is about. I can't wait to finish this tutorial.
I am going to go for all your courses.
bro what's your current status i mean are you working ?
This is definitely the best course on Dynamic Programming I have ever done. Notice, not the _best free_ course, the _best_ course, period.
a note: go donate on their website, it's tax free (As they are non profit), they get the full amount and you pay no taxes. TH-cam charges taxes to both the channel and the donator.
bro what's your current status i mean are you working ?
I've been coding since 1998 and have watched countless tutorials on countless topics. This guy is definitely one of the best teachers I've ever come across.
The first thing I'm gonna do when I get a job is to donate to FCC. I've learned so much from their content on TH-cam and tutorials on their website.
What a good guy!🎉
People like you make me believe in humanity
Good luck! 👍
Ikr! I'm going to do the same. It's only fair.
FCC rocks
Simply THE best dynamic programming course on youtube, wonderfully explained.
The course made understanding the difficult concepts a breeze.
Loved the progression of problems, even the harder ones felt easy after understanding the basic strategy and the recipe.
Thank you freeCodeCamp and Alvin.
did u spend money making this comment
@@LogansDarling while I'd argue there are probably better, more direct ways to support a creator, what makes it so weird to you? People have been spending cumulative billions of dollars over the past years just for having their message read on stream or purely for support. It's basically a pay-what-you-want scheme.
If you really feel like shaming other people's spending, I suggest you may start with people buying shiny rocks to put on rings with otherwise zero value and ethically questionable production.
@@TomasLKarlik while I'd argue that shaming someone for how they choose to support someone is lame, financially or otherwise, what makes you think that's what I was doing? People have been being confused by the billions of new features YT has put on their platform over the past years just because they're not used to it. It's basically a guess-what-this-symbol-means scheme.
If you really feel like assuming the motives of peoples' questions, I suggest you may start with people sarcastically belittling people to cancel anyone who doesn't follow their exact position with otherwise zero value and ethically questionable means.
jokes aside i understand how that could be misconstrued as an insult but i was genuinely wanting to kno cuz it could have been like idk
- Spending money on a specific comment.
- Spending money on a channel.
- Spending money on YT.
- Spending money outside of the platform and the YTer giving them the badge.
- No money even being spent and me just thinking something is a currency symbol.
- It could be _anything_ considering how stupid I am, so I have no clue.
although if u kno that its for a specific comment then ig u answered me so thx
(I do think that it's stupid, but that's more on YT's part than the commenter's part. Seems like a stupid feature to add on the platform, but that hasn't stopped YT before so oh well. ¯\_(ツ)_/¯)
@@TomasLKarlik could you shed more light on the more direct ways to support a creator ?
first time seeing a GOLDEN -COMMON- comment on youtube
(sorry... I played too much hearthstone recently...)
It took me a week to finish this tutorial.
This tutorial is just pure gold.
I always found it hard to understand time complexity for recursive solutions. But this video explains it perfectly.
This is probably the best tutorial on dynamic programming. I can't believe you're giving such quality content for free...
Agree
I guess you already know how to reverse a binary tree...
Key is a tree
Agreed.
Same .. I took more than a week
I'm here after watching graph algo. I am a data engineer and I always struggled to understand the space and time complexity, this animation is all I ever wanted. This is by far the best video I watched on dynamic programming. Moreover, Alvin has that charm to keep me captivated for long hours without loosing focus. Keep up the great work man!
i think it would've been better if you supported his main channel
@@billcosta can someone please suggest the main channel of the tutor....
His teaching style looks best to me.
Thanks
www.youtube.com/@AlvintheProgrammer@@ankitjaiswal272
Give this to Alvin
After getting frustrated from these dynamics programing, after hunting to know the real concepts in books, articles, online paid courses, TH-cam videos, finally got this here and that too free. I can't believe this. He teaches like crazy. Thanks a lot.👍
Alvin is amazing. He currently works for google right now
That's because he is crazy
He's crazy - 01:04:10 - OBVIOUS MISTAKE - he forgot to calculate space occupided by THE CACHE. Space is O(n * m), not O(n + m) OMG OMG OMG
This guy has the most relaxing voice of any lecturer I've heard.
So true!
ARE YOU HIGH????????? ON COKE PROBABLY. CAUSE A CRACKED SQUIRREL WOUDL SOUND CALMER.
Phenomenal teacher, I’ve got an hour left and even though I’ve fumbled my way through similar problems I feel I understand everything much better. This is now my go to recommended video for recursion and dynamic coding
does he teach backtracking in the video ? Haven't started watching it.
@@shivamdhir640 not specifically but discussed in some questions
This video is hands down the best explanation of DP. The guy did a fantastic job of making tabulation a breeze to understand.
You'll never, and I repeat, you will never find someone on this entire planet who explains things clearly like this guy.. OMG!
This is the slickest way I've ever seen not only Dynamic Programming, but also recursion presented. His slides/animations are just perfect for guiding every single step your brain needs to go through along the way, and he handles all kinds of gotchas and keeps you from getting stuck. I'm already going from "holy cow how am I going to even approach these problems" to "ok this is starting to get intuitive with this workflow" just an hour in. Literally better than any professor's teaching style than I remember from my college CS program. The effort put into this video is insane!
I have a feeling this video just covers some of the basics-intermediate problem types, but I bet this will be a great stepping stone to tackling the harder DP problems.
This is the first standing ovation I've given to a TH-cam video.
still can't believe how good this course is, like legitimately taught me more on algorithms, recursion, and dp than anything I've ever seen
You mean so?
The visualization and break down of these concepts are so well done. Kudos!
Brilliant video! The entire community of learners owes you a coffee for teaching us this excellent approach to solving the infamous dynamic programming problems. Other videos and books do not go into this well-defined mindset and step-by-step strategy that you need to develop, in order to understand and ultimately solve these problems from a *pragmatic* approach (which is what ultimately aces technical interviews). Keep up the great work, Alvin!
Damn this guy was the instructor for app academy. His explanations actually put me on the track to understanding this crazy world of code. So glad he's back on the scene!!!
we meet again! thanks for watching -Alvin
@@CoderbyteDevelopers ooooo you just got a new sub.
Hey join this guys
www.scaler.com/event/coding-interviews-dynamic-programming?rcy=1&rce=f6cd5eeb1984
@B Q is there a video link for his data structures and programming videos?
@@CoderbyteDevelopers completely off-topic question if you don't mind: What microphone are you using?
Thank you for FREELY supplying QUALITY material.... this DESERVES a recompense. I am COMPELLED to reward you.
I can't believe you made this with over 2,000 slides. You're a hero.
What did he use to create those slides ?
Yeah, that coordination is spot-on.
my man Alvin! I'm a Senior Developer but it was always a grind to brush up DSA topics when I'm in the job hunt. Your videos helped me quantify it a lot. I just watch your DSA videos in 1.5x half a day before an interview and that is all I need. Very well put both for beginners and for folks like me who need a quick run-through. This is the kind of stuff internet is made for. Appreciate the great work. keep it up!
Did you get it
I finished it and I feel like my head is burning from excitement and curiosity for practicing. It was amazing.
Thank you so much for this course
Dynamic programming truly is crystal meth
how good are you in DP now?
which pograming language are you uisng for coding?
If you are using java can i ask you some questions?
@@khz2172 I don't think he's that good, the course only teaches the basics and some simple problems. If you want to become good at DP I think you should practice with some DP problems (from codeforces, for example)
all 5 hours?
Best content on TH-cam on Dynamic Programming! Many thanks!
Wow. Dynamic programming looked so daunting on the outside. In a matter of 2 days, you changed my mindset about it for good :)
Now it seems easy and doable. Many thanks!
I love the way he teaches and his love for coding can be seen in his face, whenever he smiles after hitting the code. Thanks man
This is hands down the best crash course on dynamic programming. After struggling for so many hours on dp, I actually feel that I understand the logic and process for tackling dp problems now. Thank you for this amazing video!
Really found a great starting point to learn dp and found a thinking process to approach the problem with recursion without optimization and then use memorization or go for tabulation
Had I searched for "dynamic programming" two days earlier, this video wouldn't even have been uploaded to youtube. The timing couldn't be better!
It's amazing to realize that grid traveler problem sounds like a completely different problem to fibonacci, but it's solved with the same pattern. Just wow.
@black c yeah, C(m + n, n).
which pograming language are you uisng for coding?
If you are using java can i ask you some questions?
You will find in theory of computation that the problems are divided into sets of similar problems ie we can reduce any problem to any other problem to solve and if we can solve just one problem in that set in an more efficient time complexity then we can solve other problems in that set the same way
I am writing this review by just viewing the content for 30 mins. I loved it. I was bit reluctant to start as Dynamic Programming is very difficult and yet very important at the same time. This has given me a boost of confidence as i was able to code the same concept in Java. Thank you so much. And Happy Coding everyone.
No matter how difficult it seems, we would go through it Together. :)
The moment I saw that tabulation approach for `canSum`, my eyes sparkles!
This is one of the most clear and succinct explanations on the memoization and tabulation techniques for dynamic programming!
which pograming language are you uisng for coding?
If you are using java can i ask you some questions?
After finishing this video in 2 full days, I am able to come up with an approach now, and write solutions. No matter how much efforts I made to learn dp, I was no where close to coming up with a neat approach. With these concepts and some more practice on the DP problems, I can sure be good as a hell pro problem solver in a month.
You are a coding instructing master. There are millions of people who code, but only a few coding instructing masters. Great stuff. You deserved every one of those subs and likes.
Thanks you so much. This is the best Dynamic Programming course. Thank you for putting lot of efforts for explaining with diagrams.
Man, Alvin, I watched your Graph Algorithms course first and I absolutely loved it! I saw people there, recommending this legendary course and I just knew I had to come here! Every single second watching this video was completely worth it!
There is no way I can praise your explanation enough Alvin! There just is not!
After this going through this video, I went from literally have no clue whatsoever about what dynamic programming even means, to completely falling in love with this subject. I would surely indulge myself into this subject, and I believe that this video right here is simply the best entry point for any developer out there who is willing to learn this subject.
Thanks Alvin. I am really very grateful!!
Link
@@ytg6663 th-cam.com/video/tWVWeAqZ0WU/w-d-xo.html
Definitely, one of the best courses to start with DP. Just started with the tabulation approach and, decided to attempt it after watching the initial explanation. But decided to follow a different approach as below:
def fibDPTabulation(position):
if position
Yeah, I wondered that too, why he's doing forward tabulation instead of backward one. But for the later problems with strings, it really makes much more sense to think forward, so he just wanted to establish consistent practice.
I'm not one to watch any 5 hour video but this one really hooked me to go all the way.
Explaining hard things in a simple and engaging way is hard and you delivered it perfectly.
YOu should be given an award as the best tutor on Dynamic Programming concepts in the history!!! You approach is so detailed and step-by-step. You found the best formula on how to teach these complex things. Thank you very much for your job!!!
This course just proves that when you go through each minute detail of a problem in a calm and precise manner, while also hinting at the obvious even, a student is much more likely to pick up on the subject. Judging by all the other comments, slower people like myself are starting to get the concept. 🤣
Fantastic coure, thank you very much for uploading this piece.
I don't think it's about slow or quick, it's just that schools don't teach us how to think. They just cram crap down our throats and expect use to puke up rainbows.
The author did not include in the compute complexity the access of the memoized data. For the fibonacci, the algorithm can be optimized to o(1) instead of o(n).
o(1) for storage.
No book can explain DP this well and believe me I have tried!
Assalamualaikum brothers and sis, I am seeking Software Engineers, whom can code in Tensor flow and RNN Time series. I am paying.. I am based in USA.. Please check out lighttheory.page/ or email us at info@LightTheory.tech SALAM
1:04:12 The number of paths of [2,3] is the same as [3,2], so the function can be optimized a little more by sorting the keys: if m
you're right, so that solution give O((m+n)/2)
@John Leal i was looking for this in the comments
memoized base case after this optimization would look like
if (m, n) in memo:
return memo[(m, n)]
elif (n, m) in memo:
return memo[(n, m)]
Finally i found the comment i was looking for thanks.
Exactly. He even mentions this while describing the solution, but didn't implement it.
Was wondering that too, I tried it out... Passing a grid of 500,500, I measured the time it took for it to run... 230ms without and 125ms with the sorting.
Excellent material, thanks!
Hey, I agree too.
Looking for a learning on work experience.
This is an amazing and helpful tutorial!
For GridTraveler program, we can solve it analytically. Assume a grid with size m*n , then to go from the top left to the bottom right, the total number of step moving right has to be (n-1), and the total number of step moving bottom has to be (m-1), the overall total number of step has to be n-1+m-1 = m+n-2.
Any particular path is an arrangement of steps of these two types of directions. Therefore, it is equivalent to say that if we have total m-1+n-2=m+n-2, then count the number of ways we can pick m-1. So the analytical solution is (m+n-2)!/[(m-1)!(n-1)!] , where ! means factorial
This is THE BEST algorithm course I have ever seen on youtube. Wish there are more videos like this!
Great so far. If the first half hour is an indicator of the rest, I already learnt more in that half hour than in the past 10 years... Great job
one of the worst things about learning new DSA concepts is the jump in logic/thinking thats made where it doesn't make sense until you've done a million examples because people don't really explain their thought process and the intuition behind it much.
this has none of those issues. this is probably the best DSA video i think i ever seen. amazing work, thank you. 🎉
After graduating with a CS degree and working for 2 years, I can finally explain to someone what DP is!
Phenomenal and unbelievable course. Can't thank you enough for this high-quality content.
R u doing job ?
Thanks for the great content.
In gridTraveler problem, base condition could be that if either of rows or columns is 1 , we can return 1
So, if(m == 1 || n == 1) return 1;
And i think we could just check m and n interchangeably :
if ((m + "-" + n) in memory) return memory[m + "-" + n];
if ((n + "-" + m) in memory) return memory[n + "-" + m];
As number of ways to travel a grid for (2,3) will be same as number of ways in case of (3,2)
This is probably THE best DP tutorial on the web! Kudos to FCC, Coderbyte, and Alvin.
We are mathematician see these problem in very different way. 1. We can reuse an array of value already calculated,
2. We can linearize a two dimensional array to one dimensional array.
3. It’s good couse.
The good teacher explains. The superior teacher demonstrates. The great teacher inspires. You are a great teacher Sir! Thank you!
Quality content from Quality Teachers,that too for free!!❤️❤️
Hey join this guys
www.scaler.com/event/coding-interviews-dynamic-programming?rcy=1&rce=f6cd5eeb1984
Someone tell this to WhiteHatJr ppl
@@neerajkale I can't still fathom that scam is still running
Assalamualaikum brothers and sis, I am seeking Software Engineers, whom can code in Tensor flow and RNN Time series. I am paying.. I am based in USA.. Please check out lighttheory.page/ or email us at info@LightTheory.tech SALAM
Did you say free?? Because I count 16 ADs they placed in the video
Definitely one of the best instructors I've ever known. Thank you sir
Hands down. I am not a very good student of programming however, the way this person teaches is impeccable. I am solving questions side by side and I am getting all the answers right within the first go. Thank you so much for your efforts and you should really teach me everything because I am UNSTOPPABLEEE.
Simply incredible. Keep it up, you're making an invaluable impact on those who need a little extra help :)
This man literally taught me more dynamic programming than paid university courses
Kis language ka hai, c ya c++ ,ya java
This is the problem with America lol
@@milkmeapollo9048 entire world dude , I aint american but my country has the same problem , universities are the biggest scams ever.
@@ScorpionKing-z8n it's not a scam but they are definitely over priced. I think of college as my source for what I need to know, and the internet (mainly youtube) as my source of knowing those things. Without college/universities, it's hard to know what you need to know. It would take a lot of asking questions and bothering people who didn't sign up to be questioned... lol
I usually can't symphatize with ppl who say this, but yeah, DP is probably the biggest thing the internet has been able to taught me better than a price-near-the-seven-hundred-thousand-colombian-pesos uni course.
This is the best dynamic programming content I've ever seen. What I found particularly helpful is being able to understand and view recursive problems as a tree. Because of course trees are recursive data structures. When you have a tree from the outset, as long as you understand general principles of DFS and BFS, a lot of solutions become obvious. What this guy does is show a way to make the implicit, explicit. It's that step that is usually the most difficult because sometimes you're just given a number and asked to solve the problem. Once you understand that problem with that starting value represents a tree of decisions, it allows you to visualize it in such a way that the solution becomes evident. Great job.
Perfectly made and superb problems choice!
Thank you so much
I've never seen anyone before who was able to better and more clearly explain dynamic programming. The way you're leading us there step by step and also how the material is presented is outstanding. I'm very impressed Good Sir :-) Thank you very, very much 🙇
That's extremely clear! Had fun and learnt. Thanks Alvin!
Btw, the exceeddings (3:20:45) of array at line 5 and 6 are okay for js, but may trouble other language practicing.
do you know what programming language he is using?
@@jertdw3646 Isn’t it NodeJS?
@@jertdw3646 It's JS ran through through the Node interpreter
This is one of the best explanation for Dynamic programming on entire TH-cam. I have never seen such an clean and Fantastic explanation. Thanks alot
Great video! I think some problems can be further optimized and I am sharing my notes below [spoiler alert]:
1. Fib numbers
1. Obviously, can have constant space complexity.
2. Grid traveller
1. I think there is a O(min(m, n)) space complexity solution. you can keep track of only the “outer” part of the grid.
3. CanSum
1. For CanSum and HowSum, space and time complexity can be optimized by a factor of m, by storing the only last number that got added to the final target. In the end, we can obtain the final results by traversing the table once.
4. HowSum
5. BestSum -> Leetcode39 (similar to allConstruct but using numbers instead of strings)
00:00 Intro to dynamic programming
3:22 Understanding the need for Dynamic programming
10:48 Understanding time complexity and space complexity
22:27 Back to the need for dynamic programming with an example
23:31 Dynamic programming - how it reduces the time complexity
25:56 Implementation of dynamic programming using memoization
38:38 More problem
This the best and most informative explanation of DP I've seen in 25 years! Great job and I hopefully some day you'll be compensated well for your outstanding teaching ability.
This is a great short course with a great teacher!! 😉😉😉😙 The classes I attended about dynamic programming in my university are not even comparable to this. This is much more understandable, well presented and makes you want to keep learning the topic.
Thanks a lot for this amazing content. Im just contributing the money I can.. this course is a gem .
47:00 last node to the right should be 2,0... still a base case, so no difference overall, but it's best to clarify to prevent people of confusion and frustration...
This guy is going to be invited to my wedding.
Make sure you have a prenuptial aggrement bro.
Same
and this will be his 5 hour-long toast speech :D
Invite me too, i wanna meet him 😂😂
Better still, marry him !
Many thanks for the high-quality course!!! Definitely learned more than $5! Hope you can create more in the future!
This simplicity is what I am looking for .This is right tutorial I can ever ask for !!!! Awesome collection of problems .
In the example of canConstruct 2:24:00 you can use the method `startsWith` since you're just interested in knowing if the target starts with the word, so you don't need to traverse the entire string finding the index! Amazing course btw I really appreciated!
Repent to Jesus Christ “We demolish arguments and every pretension that sets itself up against the knowledge of God, and we take captive every thought to make it obedient to Christ.”
2 Corinthians 10:5 NIV
@@repentandbelieveinJesusChrist3 Annoying-ass bot.
Also, I was thinking, can't you also use a trie to pre-compute data within the word bank, so you can efficiently access it during the recursion?
For the howSum and bestSum problems, the additional product of m in the complexity can be avoided by mutating the array instead of creating a new one and copying it over. Just use combination.push(num) and it will be O(1) since appending an element at the end of an array is O(1). So time complexity can be O(m*n) and O(m) which is even better. Other than that, great video.
Hey, could you explain why the time complexity of canSum with a memo is O(m*n)? I can understand the brute force way is O(n^m) but I'm confused with the improved one.
@@liangyu3771 Think about how many different ways there are to call canSum. With an amount of m, canSum could be called recursively with any number from 1 to m, so there are m different ways. Similarly, for each node from 1 to m, there are n edges to branch from. In total, there exists at most m * n nodes to traverse through. The difference between n^m and m * n is due to the memo object saving us from doing repeated work.
@@ericx3woo THANK YOU SO MUCH Your comment helped me not only to understand this problem but justify one current solution for my University.
The best Dynamic Programing course I've had so far, thanks a lot for the best teacher.
which pograming language are you uisng for coding?
If you are using java can i ask you some questions?
This is my first comment on youtube but i can't thank you enough for this course it literally saved my life and my algorithms and data structures exam.
My professor was completely useless, he just copy-pasted notes from a mit course by Erkik Demaine (while obviously not having the same teaching nor programming skills lol ) and arranged our exam as a coding interview (two problems in 1 hour and a half). University gave us little to no experience in programming (we just had two programming courses in computer engineering) and after graduations i felt like my skills were very weak and coding was my biggest fear. This course gave me confidence and made me realize once and for all that coding is 80% thinking and 20% writing actual code. Now i can't say i'm a pro but i feel a lot better and i passed the exam with 30/30 so a complete success! Unfortunately i'm still studying so i don't have a job, but i will donate once i have a stable income! For everyone worrying about failure, trust yourself, you're smart enough, i know you can do it! Just don't panic and break the problem into simple fool-proof steps. I promise it gets easier and even fun, don't give up!
This is one of the best videos on both recursion and dynamic programming I've ever seen. Thank you for making this available and sharing this knowledge with the programming community.
Thanks for this tutorial: with your lectures I improved an algorithm that calculates any of level the Pascal's triangle, it was really satisfying to see the big improvement with a very few lines of code
Before I thought I would never be able to solve problems using dynamic programming , but now I have a lot more confidence. Thank you for this amazing video😁
Hey join this for more stuffs
www.scaler.com/event/coding-interviews-dynamic-programming?rcy=1&rce=f6cd5eeb1984
Bro is using 2 tricks called memorization and tabulation all over the video but there are more tricks to cover those problems such as
1. Optimization Using Space Reduction
2. Recursive With State Compression
3. Greedy Algorithms
and more, but it was impressive on how bro using visualize to cover those problems for a nearly newbie to fully understand.
Great work out there man. 💬
Learning to code by myself, this course brought me so much.
I didn't know anything about dynamic programming, not much about time and space complexity.
Now I wouldn't say that i master it of course, but with those great explanations and examples I happened to cruise through all these exercises with ease.
I am genuinely shocked to see how easy it is for me now, as those problems just seemed impossible before and their solutions looked like witchcraft.
Thank you so much, this is a wonderful course !
OMG I LOVE THIS GUY! This is the absolute god of dynamic programming. The CS-version of 3B1B.
It is always a treat to find content perfectly paired to one's journey in programming. For me, this content is exactly what I need. Thank you Alvin and thank you FCC for distributing! Unbelievable that this is free.
Thanks for this wonderful video!
Really good video, so well explained. Unless I am missing something I think there is a small mistake in the time and space complexity of howSum:
There is no need to store the positive result (an array in this case) in the memo object, since as soon as we find one good result, we stop the exploration and just return all the way up, so no other recursive call will be made, and the memo object will never be checked again. Only storing false/null is useful.
By that logic, even if you do store the array in memo, at most there will be a single array of length m in memo, so the space complexity would be O(m*2) so O(m) and not O(m*m).
In the same way, we are going to create a new array at most m times (a single path will ever return an array, never multiples, so 1 time per node in the path), so time complexity of copying the arrays would be O(m) again, for a total time complexity of O(n*m+m) instead of O(n*m^2).
So basically, you are assuming that in the worst-case scenario (say a numbers array filled with 1) every single path will return an array, while in reality it's always at most 1 path, since we stop all exploration as soon as we have one match.
Am I missing something?
- I agree with you regarding the first part "There is no need to store the positive result (an array in this case) in the memo object"
- Regarding the second part of analyzing the space and time complexity (even if you do store the array in memo, at most there will be a single array of length m in memo) , take care that we are copying the whole array at each call (i.e. each element of the memo will be an array). Each element is an array that represents the **whole path** from that **current** targetSum to the leaf (i.e. it would be sth like memo = { [3], [3,2], [3,2,2]}). memo will contain multiple arrays of lengths ( one , two, three, ...... m)
I agree with you. I also noticed it. The copying of array occurs at most m times. I checked this by incrementing a global variable for every recursive call that copies an array. That means the total time complexity for brute force would be O(n^m + m^2) and for the memoized O(n*m + m^2)
Thanks for the fabulous course 👏🙏One modification that I think the video needs is that for the grid travel algo with memoization, the space complexity is O(m*n) and not O(m+n) [1:04:15]. The stack of course uses O(m+n) space but the 'memo' object grows to store m * n key/val pairs. So the overall space complexity would be O(m*n).
for the tabulated canSum, although changing the outer loop bound to i
Apart from the knowledge served, I also want to appreciate the work done to choose colours for slides. It works so perfect for both day and night mode.
Computer Science students would appreciated this very much. Thanks for intelligible explanations !
40:00 In fact, combinatorics saves a lot of trouble. nCr (n choose k) requires one line of code.
Let 'm' be the height and 'n' the width.
Then, we notice that if we treat each move as an arrow - in a 3x3 grid there'll be only 2 columns allowing for 'arrow right' and only 2 rows allowing for 'arrow down' - so we now have a number of strings (sequences like 'right' 'right' 'down' down' or 'down' right' down' 'right') of 'right' and 'down' which is (m - 1) + (n - 1) = (3 - 1) + (3 -1) = 4.
So we have 4! = 24 permutations (as usual we don't want to double count so we do the next step).
Now these 24 permutations will just swap these arrows around purposelessly, i.e. (without loss of generality) a combination of 'right' and 'right' would yield 2 in this case (when, in fact, there is just one. It's like counting AB and BA except the letters are AA, so it counts AA and AA as if they were two distinct combinations).
How do we not double count?
Well, there are only 'down' and 'right' - so simply by dividing our (m + n - 2)! by (m - 1)! (permutations of 'down') * (n - 1)! (permutations of 'right')
that is, all redundant permutations of 'down' (2 rows) and all redundant permutations of 'right' (2 columns) are addressed.
So the answer is
(3 + 3 - 2)!
-------------------------- = 4! / 2! * 2! = 24 / 2 * 2 = 6
(m - 1)! * (n - 1)!
Very simple, indeed. Only slugs would not understand.
/s
@@Spaaace indeed
Thanks, well explained to make it easy to understand.
In the GridTraveler I would have used (1,x) and (y,1) as base cases, as there's only one way to go down a straight line.
yeah more optimization
Same here
Anyways every unique pair is getting calculated only once.
I had the same idea, but as @Taniea said, you still end up computing all possible pairs.
You don't even save the lookup time, as the lookup occurs before the 'if' condition.
I actually felt bad when this course ended. Felt as if a part of my life's story just rested.
😅😄
What a nice line there👍👍
which pograming language are you uisng for coding?
If you are using java can i ask you some questions?
20:57 No you cannot simplify O(2^(n/2)) to O(2^n) as 2^(n/2) cannot be expressed as a * 2^n + b * 2^(n-1) + ... + c form.
1:04:08 No, the cache size can become n * m / 2 in the worst case. So, the space complexity should also be O(n * m)
Thanks for pointing this out. I was about to comment on the O(n * m) space complexity.
but wouldn't 2^(n/2) simplify to sqr(2)*2^n?
after checking closely what I said is in fact not true lol
It is not a simplification. I guess what he meant was big O in the academic sense, i.e. the upper bound function. Since 2^(n/2) == sqrt(2)^n, so you can say that it is always less than 2^n.
What I can't grasp is how he got O(n^m * m) in the unoptimized howSum. Upon each recursive call you do at most one copy of m elements, and you do it m times, so the final O is O(n^m + m^2).
Mind blowing explanation. I don't think you will ever find a better tutorial than this. Super, thanks for this classic
Since I finally got a Data Structure & Algorithm course that can keep me learning repeatedly for hours, I can safely say this is one of the best startup programming series on Data S. & A. Also, this comes with a full recommendation on my part to anyone interested in Software Programming.
Thank you, sir!
Time to time, I exit full screen mode and am trying to like this video, and see that I've already liked it :D
Almost an hour in and I'm shouting "Where have you been all my life???" Just had a lightbulb moment which other tutorials have failed to do for me. Well done!
Hey! you'd mentioned that 2,1 or 1,2 basically return the same value previously but in the code these values are being separately calculated...
at 1:01:50 by using, const key1 = m+","+n; const key2 = n+","+m;
we can check for both key1 or key2 in memo and return the associated value.
(also, great video! loved the visualizations!)
I can't believe we're getting this sort of quality content for FREE