Regular Expression Matching - Dynamic Programming Top-Down Memoization - Leetcode 10

Поділитися
Вставка
  • Опубліковано 25 чер 2024
  • 🚀 neetcode.io/ - A better way to prepare for Coding Interviews
    🐦 Twitter: / neetcode1
    🥷 Discord: / discord
    🐮 Support the channel: / neetcode
    Twitter: / neetcode1
    Discord: / discord
    💡 CODING SOLUTIONS: • Coding Interview Solut...
    💡 DYNAMIC PROGRAMMING PLAYLIST: • House Robber - Leetco...
    🌲 TREE PLAYLIST: • Invert Binary Tree - D...
    💡 GRAPH PLAYLIST: • Course Schedule - Grap...
    💡 BACKTRACKING PLAYLIST: • Word Search - Backtrac...
    💡 LINKED LIST PLAYLIST: • Reverse Linked List - ...
    Problem Link: neetcode.io/problems/regular-...
    Code on Github: github.com/neetcode-gh/leetco...
    0:00 - Read the problem
    3:55 - Drawing Solution
    19:00 - Coding Solution
    leetcode 10
    This question was identified as a google interview question from here: github.com/xizhengszhang/Leet...
    #regular #expression #python
    Disclosure: Some of the links above may be affiliate links, from which I may earn a small commission.
  • Наука та технологія

КОМЕНТАРІ • 181

  • @NeetCode
    @NeetCode  3 роки тому +5

    Dynamic Programming Playlist: ua-cam.com/video/73r3KWiEvyk/v-deo.html

  • @sudheerk7989
    @sudheerk7989 2 роки тому +46

    I can't thank enough for this video! Even after spending nearly 3 hours on various videos showing direct DP (bottom-up) solution, and countless posts in Discuss section with no clear explanation, I could not understand how the formulae are derived. But.... this is gem of a video and probably the only video on UA-cam explaining the Top-Down approach.
    In fact, it is better to try Top-Down approach in interviews. Directly trying to attack a problem with DP formula can lead to disasters. If the interviewer is not dumb expecting a specific answer involving DP, he/she/they should be okay with Top-Down+Memoization approach.
    Thanks again! Keep making such amazing videos.

  • @parambole8671
    @parambole8671 3 роки тому +152

    If I crack my FB interviews it's only going to be because of this channel. Keep up the "NEET" work :)

  • @jimwu3856
    @jimwu3856 Рік тому +10

    To be honest, I never would have even guessed that this is a Dynamic Programming problem. Once you started explaining the decision tree, it ALL made sense. Thanks for teaching me something new!

  • @chinmaym92
    @chinmaym92 3 роки тому +5

    I really appreciate how clean your code was and was so easy to understand

  • @dollyvishwakarma2
    @dollyvishwakarma2 2 роки тому +3

    OMG, the question looked so tough, but you made it soo easy !! Another awesome explanation. Great fan of your NEET coding style :)

  • @xinchenyi9878
    @xinchenyi9878 3 роки тому +5

    The clearest explanation I've seen!!! You are awesome :)

  • @michaeldunlap2693
    @michaeldunlap2693 2 роки тому +1

    This is a fabulous and thorough explanation. The decision tree explanation and visual for the asterisk was what did it for me. Thank you!

  • @TheRetrobek
    @TheRetrobek 2 роки тому +20

    If someone didn't get the cache part, try printing out the (i, j) pairs with the following example: text="aaabaaa" and pattern = "a*b*a*".
    If you take a careful look, since we are backtracking, there are cases where we check the same (i, j) pairs. And that's why caching helps.

    • @adityaathota501
      @adityaathota501 2 роки тому +4

      Ty so much, I was stuck trying to figure out where it was saving time

    • @80kg
      @80kg 2 роки тому +2

      thank you for pointing out the test case it's important for understanding why caching is effective at saving time

    • @shalsteven
      @shalsteven 10 місяців тому

      how did you come with that example to identify the sub-problem?

  • @auto8ot644
    @auto8ot644 2 роки тому +7

    Great explanation! I really like how you easily added memoization to the brute force algorithm. Other DP solutions were SO complicated. This explanation was perfect.

    • @abhimanyuambastha2595
      @abhimanyuambastha2595 18 днів тому

      Maybe its just me but I found the drawing explanation very confusing although the code made more sense. Usually I love all of Neetcode’s explanations but the pointer usage threw me off around first. There’s a similar problem Wildcard Matching and I solved it by checking the current j index and not j+1, thats why the j+2 was confusing. But in the end the code is very similar.
      I recommend others to try the Wildcard Matching problem its Leetcode 40 or 41

  • @arpanbanejee5143
    @arpanbanejee5143 2 роки тому +2

    Simply mind-blowing explanation, you made it so simple!! Thanks you! Please keep up the good work!

  • @AbanoubAsaad-YT
    @AbanoubAsaad-YT 2 роки тому

    BEST EXPLANATIONS ARE HERE :)
    Thank you so much for these quality videos!

  • @buttercup5029
    @buttercup5029 2 роки тому

    I was struggling a lot with this question. Your video cleared my doubts. Thanks for sharing!

  • @hakoHiyo271
    @hakoHiyo271 3 роки тому +4

    Great explanation! You explained the algorithm very clearly. I'm not even Python guy, but I still liked your video!

  • @ruizhu5295
    @ruizhu5295 2 роки тому

    I really appreciate your explanation, so clean, so logical!

  • @user-po5dk2xr7d
    @user-po5dk2xr7d Рік тому

    This explanation makes the whole process clean and simple.

  • @vdyb745
    @vdyb745 2 роки тому

    What a brilliant solution and in-depth explanation for this seriously hard problem !!! WOW .... Thank you !!!!

  • @yukselpolatakbyk8468
    @yukselpolatakbyk8468 2 роки тому

    You make this question easy to udnerstand. Thank you for all your amazing solutions!!

  • @kanwarkajla
    @kanwarkajla 2 роки тому +1

    great explanation .....also the vibe of ur videos is relaxing!

  • @santoshr4212
    @santoshr4212 8 місяців тому

    Thanks alot for helping me understand the issue, I was doing the bottom up and solution was failing in leetcode on last 2 test cases. After watching this video I understood we need to do bound check on index "i" - stupid of me missing such a basic thing. Now solution worked

  • @capriworld
    @capriworld 2 роки тому

    Best explanation ever found for this problem.

  • @saadkhan4049
    @saadkhan4049 3 місяці тому

    You made it look so simple. Thank you!

  • @notsadsisyphus6224
    @notsadsisyphus6224 2 роки тому

    i seriously love your video i swear you dont waste time i love it

  • @pranavkashyap8610
    @pranavkashyap8610 Рік тому +1

    The dramatic decrease in time taken to execute after using cache surprised me .
    Thanks for the explanation and code

  • @daved1113
    @daved1113 2 роки тому

    Excellent work. Earned a sub. Keep it up.

  • @sauravchandra10
    @sauravchandra10 10 місяців тому

    You make hard problems very easy. Thanks for explaining.

  • @thinja
    @thinja 2 роки тому

    Wow so much easier to understand than the DP solution! Thanks for showing your mistakes as well

  • @comander47
    @comander47 Рік тому

    this problem took me soo much time to understand, thank you dude

  • @MutuallyBro
    @MutuallyBro Рік тому

    Very good explanation, love the channel!

  • @NAVNEET549
    @NAVNEET549 2 роки тому

    Awesome explanation. Thank you so much

  • @Iamnoone56
    @Iamnoone56 2 роки тому +1

    Thanks Hokage for explaining it really well.Seen a lot of videos where people directly start drawing table.Will memoized soln be enough for an interview or do we have to give a bottom up soln too??

  • @VishalKumar-kr9me
    @VishalKumar-kr9me 11 місяців тому

    How easy you make a hard problem is unbelievable !!!!!! Salute to you

  • @juliramoos
    @juliramoos 3 місяці тому

    Perfect explanation! Thank you. And the code looks good.

  • @krugerbrent4270
    @krugerbrent4270 2 роки тому

    Wow! You made it look like a piece 'o cake. Thanks, I really appreciate it.

  • @Whatthetrash
    @Whatthetrash Рік тому +1

    Thank you so much for this. After weeks (!) of trying to solve this problem on my own, I decided to look it up and lo and behold -- the solution involves a bunch of stuff that I have never heard of. I feel a bit better (and I need to learn about Dynamic Programming now). >_< Thanks again for the elegant, succinct solution.

  • @nagasivakrishna5660
    @nagasivakrishna5660 Рік тому

    man love ur explanation ,great man ,no words love u man

  • @Avuvos
    @Avuvos 2 роки тому

    Great video and explanation thank you!

  • @sachin_yt
    @sachin_yt 2 роки тому

    I loved it man, thanks a lot :)

  • @xinniu3145
    @xinniu3145 2 роки тому

    Thank you! this is owesome!

  • @lootlook5148
    @lootlook5148 2 роки тому +1

    WTF !! Bro
    You made clear in just 20 minutes🤩

  • @eyosiasbitsu4919
    @eyosiasbitsu4919 2 роки тому +2

    I'll have my google interview in October and this channel is really helping me in my preparation. if i pass then i'll be your biggest supporter neet!

    • @orogheneemudainohwo3493
      @orogheneemudainohwo3493 2 роки тому +3

      How do you have an October interview scheduled in May? Full time or internship? Goodluck

    • @nealp9084
      @nealp9084 18 днів тому

      did you pass?

  • @JameS00989
    @JameS00989 Рік тому

    Super awesome explanation NeetCode 🎉Thanku

  • @aldogutierrez8240
    @aldogutierrez8240 Рік тому

    Very good explanation thanks!

  • @dineshkannam8078
    @dineshkannam8078 3 роки тому +1

    You are a legend.

  • @haodantan2014
    @haodantan2014 3 роки тому

    Best explanations! Thank you!

  • @MsSkip60
    @MsSkip60 3 роки тому

    Awesome mate!

  • @taroserigano6546
    @taroserigano6546 Рік тому

    Super thanks for this!

  • @chaoluncai4300
    @chaoluncai4300 Рік тому +1

    2 more observations/ optimized caches: 1. If j+1 is * and both of its dfs() returned false, we actually dont need to re-check the matching condition again since j+1 is a *, means dfs(i+1, j+1) will fo sho return false due to s[i+1] != p[j+1] which is a *. That being said, we can change the last if (match) condition to else if condition~ 2. current cache will only does its job while next state's dfs() returned false (any next state is true indicates a solution is found). By storing only false returned val into cache will reduce memory space Both opts are negligible / pretty insignificant since either of them only saved limited constant time/space

  • @emmatime2016
    @emmatime2016 2 роки тому

    Great video!!!! Thank you!

  • @thisissheraf2633
    @thisissheraf2633 2 роки тому

    Appreciate your explanation thank you

  • @anujdoshi882
    @anujdoshi882 2 роки тому

    Amazing explanation!

  • @siddharthpandey8516
    @siddharthpandey8516 2 роки тому

    This was perfect!

  • @kocot.
    @kocot. 24 дні тому

    Instead of optimizing it with cache, I've got an almost identical result (1300ms->50ms) by simply ensuring you don't process subsequent stars. So if there is a*a*a*, you'd only check it once. Now the cache seems obvious, but that addressed directly the most compute intensive cases :) Funny to see how it's same efficient. Using both would probably improve it even further.

  • @danielsun1993
    @danielsun1993 3 роки тому

    The best explanation!!!

  • @z08840
    @z08840 3 роки тому

    by switching "use" and "don't use" in or return statement you can significantly cut complexity down even without memoization

  • @yongquanrao7398
    @yongquanrao7398 3 роки тому

    Great one. Thanks.

  • @Tyokok
    @Tyokok 3 роки тому

    Thanks for great explain! Do you also have an explain on complexity analysis of this recursive call? Thank you!

  • @purnimadas768
    @purnimadas768 5 місяців тому

    Thank you for the very good video

  • @lingyunsu1589
    @lingyunsu1589 2 роки тому

    Best explanation ever!

  • @rahuljain281
    @rahuljain281 4 місяці тому

    What an explanation sir ji❤. After this, I was able to solve wildcard matching by myself.

  • @pranavsharma7479
    @pranavsharma7479 Рік тому

    thnks bro i was not getting how to solve this , this is same as wildcard matching with a twist

  • @tanayshah275
    @tanayshah275 3 роки тому

    great explanation!

  • @MaxFung
    @MaxFung 2 роки тому

    thank god for this guy i was STUCK

  • @yangyue2791
    @yangyue2791 3 роки тому +1

    Yeah, that problem is so hard. I tried to use loops to compare character by character, and deal with * differently. Though, that way did not work well.

  • @somilsinghai5966
    @somilsinghai5966 2 роки тому

    This question makes me appreciate the hard work of people who have created the full-blown regex.

  • @jonathanandres1657
    @jonathanandres1657 6 місяців тому

    Great explanation! :) @NeetCode what tool do you use to write and draw ?
    Any specific brand, I'm looking for this kind of tools

  • @sunginjung3854
    @sunginjung3854 3 роки тому +1

    Thank you for the great video! Is there any chance you could also solve Minimum Difficulty of a Job Schedule (LC 1335)? I would really appreciate it.

  • @pinkylover911
    @pinkylover911 2 роки тому

    you are talented

  • @sumeetchawla3545
    @sumeetchawla3545 2 роки тому

    Amazing explanation .. Really thankful for your great efforts.. :)

    • @NeetCode
      @NeetCode  2 роки тому

      Glad it was helpful!

  • @emretekmen1602
    @emretekmen1602 6 місяців тому +1

    you need to explain how the cache actually saves time. How does storing the indexes along with a bool value save any time?

  • @iharshgarg
    @iharshgarg 5 місяців тому

    i checked so many videos of this problem.. but there's simply no compedition to you bro. keep the neet work up bro/>

  • @pulakammalathy6968
    @pulakammalathy6968 Рік тому

    Thank you so much

  • @shai1esh
    @shai1esh Рік тому

    if this is the case below then :
    '*' Matches any sequence of characters (including the empty sequence).
    def isMatch(self, s: str, p: str) -> bool:
    # top down memo
    cache = {}
    def dfs(i, j):
    if(i, j) in cache:
    return cache[(i, j)]
    if i >= len(s) and j >= len(p):
    return True
    if j >= len(p):
    return False
    if p[j] == '*':
    # Check if the '*' matches an empty sequence or matches one or more characters
    cache[(i, j)] = dfs(i, j + 1) or (i < len(s) and dfs(i + 1, j))
    return cache[(i, j)]
    match = i < len(s) and (s[i] == p[j] or p[j] == "?")
    if match:
    cache[(i, j)] = dfs(i + 1, j + 1)
    return cache[(i, j)]
    cache[(i, j)] = False
    return False
    return dfs(0, 0)

  • @koppan
    @koppan 3 роки тому

    Thanks a lot :)

  • @shashwatmaru9238
    @shashwatmaru9238 3 роки тому +1

    Hey what would be the Time and Space complexity ? Backtracking with memoization means 2^n?

  • @jacques-dev
    @jacques-dev Рік тому

    For anyone getting confused with the solution to this problem, I found the bottom-up approach to be much more intuitive. Just my experience, I know everyone is different.

  • @zl7460
    @zl7460 Рік тому

    Thank you for the explanation. I thought according to the problem statement, 'c*' cannot be empty, which was very misleading by Leetcode.

  • @tanaysingh5348
    @tanaysingh5348 9 місяців тому

    the question description feels really incomplete without your explanation , thanks a lot

  • @saksham.malhotra
    @saksham.malhotra 2 роки тому +2

    Thanks!

    • @NeetCode
      @NeetCode  2 роки тому +1

      Thank you so much!

  • @samridhshubham8109
    @samridhshubham8109 Місяць тому

    GOAT

  • @krateskim4169
    @krateskim4169 2 роки тому

    thank you

  • @kaartiknagarajan5009
    @kaartiknagarajan5009 Рік тому

    I've recoded your solution and it's brilliant. However, I've been trying to follow the stack trace of the program execution to convince myself when the first if statement would execute "if (i, j) in cache: return cache([i, j])". I know it does because I tried removing it and got a TLE error o Leetcode, but I don't see when it would be needed as we always progress into a deeper DFS and cache. Would appreciate an explanation if you could please! Thank you.

  • @jerryjohnthomas4908
    @jerryjohnthomas4908 2 роки тому

    can some one explain what happens if i==m and j

  • @srini2010srini
    @srini2010srini 2 роки тому

    Thanks

  • @scottchen2094
    @scottchen2094 2 роки тому

    Can someone explain why we dont add cache for line 11 & line 13 the two base cases?

  • @amitavamozumder73
    @amitavamozumder73 3 роки тому

    can i do it just by using a stack? push any pattern and if found star removes all stack top char and pop it and move on. in case of .* we just push it in the stack and move on..

  • @ashkankipati
    @ashkankipati Рік тому

    Could you explain wildcard matching, a similar problem to this one?

  • @yangyue2791
    @yangyue2791 3 роки тому

    Would you like to explain the case like "s=aab p=a*ab"? In case like that, we need to take care how much times * copies its preceding letter.

  • @Demo-yc8fb
    @Demo-yc8fb Рік тому

    what if s reaches the end but p does not? That will not always return a true right? Where did we cover that case?

  • @algorithmo134
    @algorithmo134 3 роки тому

    @NeetCode can you do validate binary tree nodes next? Leetcode 1361

  • @Chirayu19
    @Chirayu19 10 місяців тому

    I think the time complexity would be O(N^2M) and not O(N*M) since we have to iterate through the s in case of "*". Please do correct me if I am wrong. Thanks!

  • @xyhan98
    @xyhan98 Рік тому +1

    Hi NeetCode, not sure if LeetCode has added some new test cases, but seems like both top down and bottom up approaches are experiencing TLE for test case s = "aaaaaaaaaaaaaaaaaaab", p = "a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*". Other than that, thanks for your great explanation!

  • @axay3.0
    @axay3.0 Рік тому

    this is called Codeagasm. Mind blowing.

  • @meto4545
    @meto4545 Рік тому

    I have a question, why the testcase - s="a", p=".*..a*" has to return false?
    I mean we just make ".*.." a 0 character string "" and the rest we make one "a".
    Edit: Nevermind I thought '.' can be a 0 character string since in the question it doesn't say anything about it.

  • @sungiv
    @sungiv 2 роки тому +1

    this algorithm is not working for case s="aa" and p="*". since its checking for j+1 for * its not working..

  • @schwarzchauhan
    @schwarzchauhan 2 роки тому

    recursion & caching 😊

  • @anonofDeath
    @anonofDeath 2 роки тому

    Can someone explain to me how the aab == c*a*b? Isn't it suppose to cover the entire string?

  • @divijjain4674
    @divijjain4674 3 роки тому

    This was the best explanation ever, but I have a doubt. At 18:45 you said its no problem if i is out of bounds and j isn't. But what if for a string S = a, the pattern is P = a*b. In this case, they do not match? Thanks in advance! Really appreciate it.

    • @NeetCode
      @NeetCode  3 роки тому +2

      Yes you're right that those strings don't match, but the function will continue I think and eventually return false in that case.
      For example, in P, there is a remaining b, but the function doesn't yet know if that is a mandatory b, or if it's a b*, because b* means that the b is not mandatory.

    • @divijjain4674
      @divijjain4674 3 роки тому

      @@NeetCode thanks bud got it

  • @ArpitDhamija
    @ArpitDhamija 2 роки тому

    I tried your method.
    Did in C++, both recurssion and memoization but there was no big significant difference in the time. Gap was only 20ms. But there is huge time difference in your code. Hows that possible

  • @user-or7qq1bz1q
    @user-or7qq1bz1q 5 місяців тому

    but I got a doubt how are we looping the string if we ae not using any loop. like it will check all the conditions for 1 time but how is it looping ??? can anyone help?