Longest Increasing Subsequence - Dynamic Programming - Leetcode 300

Поделиться
HTML-код
  • Опубликовано: 30 июл 2024
  • 🚀 neetcode.io/ - A better way to prepare for Coding Interviews
    🐦 Twitter: / neetcode1
    🥷 Discord: / discord
    🐮 Support the channel: / neetcode
    💡 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/longest-...
    0:00 - Read the problem
    1:45 - Brute Force Solution
    2:58 - DFS Solution
    10:55 - Dynamic Programming Solution
    15:35 - Coding Solution
    leetcode 300
    This question was identified as a Google interview question from here: github.com/xizhengszhang/Leet...
    #LIS #subsequence #python
    Disclosure: Some of the links above may be affiliate links, from which I may earn a small commission.
  • НаукаНаука

Комментарии • 305

  • @NeetCode
    @NeetCode  3 года назад +25

    🚀 neetcode.io/ - A better way to prepare for Coding Interviews

  • @Herald50
    @Herald50 2 года назад +960

    Will never forget my first day on the job where a customer requested a feature to find the longest increasing sub-sequence. A totally valid way to test someones competency as a developer

    • @btKaranDhar
      @btKaranDhar 2 года назад +125

      Your sarcasam is depressive and hence ironic

    • @kotb2000
      @kotb2000 2 года назад +142

      It is important to understand the idea of subsequences, use memory efficiently and understand complexities of exponentially increasing subroutines.
      A good Programmer is not the one who solves it the first time seeing it.
      A good Programmer is the one who understands all the dimensions of the problem and Learn as much as he can about underlying intuitions.
      and remember
      when Tony Hoare first made Quick Sort He didn't say I am not going to face a situation where I sort a customer's Needs.
      His attitude as any computer scientist when making a helpful research or an idea was If I am able to think How to sort and even invent a sorting algorithm then I am going to be able to satisfy my Customer needs who were Future Generations that used Quick sort in every Customer related Situation .
      Good bye.

    • @francisconovoa6493
      @francisconovoa6493 2 года назад +5

      @@kotb2000 gg

    • @zweitekonto9654
      @zweitekonto9654 2 года назад +74

      Which interviewer hurt you bro

    • @VibeBlind
      @VibeBlind 2 года назад +52

      @@zweitekonto9654 All of them

  • @lugiadark21
    @lugiadark21 3 года назад +282

    Please keep that tone and speed of voice. It really helps to "understand" the solution. All of us are here to "understand" the solution not just for a solution. You will do great my dude.

    • @shubhamsinghrawat6928
      @shubhamsinghrawat6928 2 года назад +1

      This how you except a google engineer

    • @AnupBhatt
      @AnupBhatt 5 месяцев назад

      You can change the playback speed on RUclips to make it go faster or slower. In case you find a problem that some other youtuber has solved, that Neetcode hasnt solved yet, use that feature.

  • @dj1984x
    @dj1984x 11 месяцев назад +34

    "I really doubt your interviewer is going to expect you to get this without a hint; if they do I'd just walk out of the room"
    Probably worked great up until the layoffs 😥

    • @MaxFung
      @MaxFung 4 месяца назад

      yep, now it feels like every other interview problem has been next level. still some easies out there though :(

  • @srinadhp
    @srinadhp 2 года назад +94

    You sir. Are the savior. Your made it so simple - some times you make me guilty why I could not think of it. Keep them coming!

  • @director8656
    @director8656 3 года назад +56

    Thanks, great explanation as usual, who needs cracking the coding interview when this exists!

  • @anushkachakraborty8635
    @anushkachakraborty8635 2 года назад +10

    That was so simple and an epic explanation of how you can start thinking about approaching this problem.
    Being a beginner at dp, your videos help me understand how to start approaching a problem :)
    Thankyou!

  • @DanhWasHere
    @DanhWasHere 3 года назад +4

    This explanation went down so smooth -your voice was very easy to follow and your diagrams weren't sloppy and not complex to understand -this might be the cleanest solution I have seen for this problem for beginners to study!

  • @quocnguyeninh32
    @quocnguyeninh32 2 года назад +7

    Your explanation is so great. The tone, voice, and the way you say are so clear. Thank you so much

  • @jagrutitiwari2551
    @jagrutitiwari2551 Год назад +52

    Thank you for letting us know when we should walk out of the room. And what difficulty to expect in the interview :)

  • @TheDeepsz
    @TheDeepsz 3 года назад +2

    Thanks for such a great explanation, I searched for it so many places, but I didn't find anything more than the formula. This video should have more likes.

  • @jerrybao1934
    @jerrybao1934 Год назад +2

    Thank you for the clear explanation! For those wondering why going backwards in dynamic programming, you can actually solve this in forward dynamic programming, start from the beginning, too.

  • @thatguy14713
    @thatguy14713 2 года назад +7

    Easily the best channel for leetcode solutions. So easy to understand and code is always clean and concise. Hats off to you, Neetcode!

  • @pujasonawane
    @pujasonawane 3 года назад +5

    I got it crystal clear now. You explained it very well. Thanks a lot.

  • @medievalogic
    @medievalogic 3 года назад +9

    excellent! This taught be how to choose subarrays recursively, and then the problem is trivial. Thanks a bunch.

  • @BadriBlitz
    @BadriBlitz 3 года назад +4

    Superb Explanation.Anyone having doubt in leetcode can refer this channel.Excellent video bro.I was struggling for this problem you made it clear.Thank you.

  • @dominikilja
    @dominikilja 2 года назад +3

    This was a great explanation! I struggled with this, but I'm happy to learn some new techniques!

  • @redomify
    @redomify 3 года назад +11

    thank you omgosh this really is the best explanation one can find for this question on youtube

  • @huseyinbarin1653
    @huseyinbarin1653 2 года назад +2

    DP always surprises me. What a good approach. Thank you

  • @handuongdinh9290
    @handuongdinh9290 2 года назад +1

    The video made it very easy to understand. Thank you for making this video. Keep up the work. I’m looking forward to view yours next videos.

  • @ece-a036nischintasharma5
    @ece-a036nischintasharma5 Год назад

    Was unable to wrap my head around this one. Your explanation was so nice!!

  • @sathyanarayanankulasekaran5928
    @sathyanarayanankulasekaran5928 2 года назад +4

    this is brilliant, I wonder who can think of this solution for the first time during the interview

  • @priyanshupareta9328
    @priyanshupareta9328 3 года назад +1

    Best explanation out there!! Thank you for your efforts.

  • @alex-gz7ud
    @alex-gz7ud 3 года назад +12

    Clear explanation! I believe you are the rising star in solving leetcode problem.

    • @NeetCode
      @NeetCode  3 года назад

      haha, thanks I appreciate the kind words

  • @HC-xh6mh
    @HC-xh6mh 3 года назад +2

    The best explanation video I have watched so far!

  • @Cld136
    @Cld136 3 года назад +1

    Thank you very easy to understand and follow. I had problem understanding the solution on leetcode :)

  • @kineticsquared
    @kineticsquared 6 месяцев назад

    Wow, what a great explanation! Thank you for the detailed step-by-step example.

  • @shuvo0201
    @shuvo0201 3 года назад +1

    Awesome! Very clear and thorough explanation 🙂

  • @d5lw2g
    @d5lw2g 2 года назад

    this is amazing, thank you for your hard work

  • @irinagrechikhina9538
    @irinagrechikhina9538 3 года назад +4

    Great explanation, as usual, thank you! :)

  • @sachin_yt
    @sachin_yt 2 года назад +2

    One of the best solutions ever. thank you.

  • @gargichaurasia4103
    @gargichaurasia4103 3 года назад +1

    You are great.. you explained it very well. Thank you so much!

  • @The6thProgrammer
    @The6thProgrammer 8 месяцев назад +5

    Not sure why, but this one felt much easier than the prior 3-4 problems in the Neetcode Dynamic Programming learning path. Got it on my first try, and solved it exactly the way Neet did. Just goes to show the value of the Neetcode Roadmap, and how the patterns start to solidify in your mind over time.

  • @christendombaffler
    @christendombaffler 9 месяцев назад +7

    Yeah, I agree that being expected to find the O(nlogn) solution is walkout tier. I came damn close to figuring it out: use an ordered set to keep track of the elements you've inserted so far so that you can easily find the greatest value that's smaller than or equal to your current one. From here, assuming nums[i] is not your maximum thus far, there are two ways, and figuring out either of them is easily upper Hard level: either you actually delete the value you've found (the fact that this works because it means you can just return the size of your set at the end is incredibly unintuitive), or you mess with the way you store everything in the set so that you can still retrieve the index of the value corresponding to your found value (which is awful to implement).

    • @SunsetofMana
      @SunsetofMana 2 месяца назад

      Why would deleting the value you found work? If you have input array [2,3,1,5,6] you cannot delete the value found at 5 when you see the 1, because then you cannot use it for the actual longest subsequence of 2,3,5,6
      Tbh the approach of using a heap to store the subsequence length cache is quite reasonable imo… it’s annoying to implement but quite straightforward as an obvious improvement. If you know how to solve heap problems, which are based on the premise that a heap is a priority queue, why not just apply that here when you are searching for the largest element?

  • @JayPatel12928
    @JayPatel12928 2 года назад

    Man this is the best video so far on this problem ✊🏻

  • @Sandeepkumar-uv3rp
    @Sandeepkumar-uv3rp 3 года назад +1

    Really very helpful, explained in a crystal clear manner👌👌

  • @akhtarzaman2189
    @akhtarzaman2189 2 года назад +3

    "I'd just walk outta the room" you solve your own problem Mr interviewer LOL

  • @amitupadhyay6511
    @amitupadhyay6511 2 года назад +3

    I came for that nlogn solution. But again, thanks for the tremendous help as usual

  • @annabellesun4719
    @annabellesun4719 2 года назад

    another day watching neetcode to help me with leetcode. Thank you!

  • @rajatsrivastava555
    @rajatsrivastava555 Год назад +2

    Thanks for the explanation @neetcode , code in java :
    class Solution {
    public int lengthOfLIS(int[] nums) {
    int dp[] = new int[nums.length];
    Arrays.fill(dp, 1);
    for (int i = nums.length - 1; i >= 0; i--) {
    for (int j = i-1; j >=0; j--) {
    if (nums[i] > nums[j]) {
    dp[j] = Math.max(dp[j], 1 + dp[i]);
    }
    }
    }
    int maxLIS = 0;
    for (int i = 0; i < nums.length; i++) {
    maxLIS = Math.max(maxLIS, dp[i]);
    }

    return maxLIS;
    }
    }

  • @diksha8347
    @diksha8347 Год назад

    This explaination is so so good. Thank you.

  • @RajasekharReddi
    @RajasekharReddi 4 месяца назад

    Excellent oration of the logic and the ending is at another level.

  • @goshikvia
    @goshikvia 2 года назад +4

    Optimal Approach O(nlogn)
    bisect_left is a python function which gives the lower bound of the element in O(logn) time.
    bisect_left(array, element, start, end)
    class Solution:
    def lengthOfLIS(self, arr: List[int]) -> int:
    subs = [arr[0]]
    for i in range(1,len(arr)):
    if arr[i] > subs[-1]: subs.append(arr[i])
    else:
    subs[bisect_left(subs, arr[i], 0, len(subs))] = arr[i]
    return len(subs)

    • @davidespinosa1910
      @davidespinosa1910 2 года назад +1

      So if arr = [1,3,4,2], then subs = [1,2,4] ?
      That's not a subsequence.
      And yet it works.
      The mystery deepens... :-)

    • @paulancajima
      @paulancajima 2 года назад

      @@davidespinosa1910 Yeah, the problem asks for the longest increasing subsequence. So, this will still give you the correct length just not the subsequence itself

  • @roxanamoghbel9147
    @roxanamoghbel9147 2 года назад +2

    you're dynamic programming videos are all so well explained and helpful

  • @paul90317
    @paul90317 Год назад +1

    even if it's not the best solution, it's the best tutorial for LIS I've ever seen

  • @alfamatter12
    @alfamatter12 Год назад

    That sarcasm at the end made me laugh like hell😂😂😂! I'm also walking out from this problem

  • @bennypham4337
    @bennypham4337 3 года назад +4

    Really helped me out to understand this question!

    • @NeetCode
      @NeetCode  3 года назад +1

      Thanks, I'm glad it was helpful!

  • @vivekjoshi9073
    @vivekjoshi9073 2 года назад

    Thank you sir best explanation able to do in other programming language easily and concept is clear

  • @nepa8678
    @nepa8678 2 года назад

    You are awesome. Please keep it coming.

  • @realoctavian
    @realoctavian 11 месяцев назад

    finally a good explanation and solution for this, thanks!

  • @username-zs6dv
    @username-zs6dv 10 месяцев назад +1

    noticing the subproblem 'is there an increasing subsequence with length m' is O(n), and m is between 1 and n, we can use binary search and get overall complexity O(nlogn). But it is way neater with DP

  • @juliahuanlingtong6757
    @juliahuanlingtong6757 3 года назад +8

    Great demostration starting from brute force, work way up to memoization and then leads naturally to dp!!! So Nice and easy it becomes with your approach!
    1 question though: Why work from end backwords? How did you get the instinct?Could you please share your thougghts?

    • @NeetCode
      @NeetCode  3 года назад +3

      I'm used to working from the end backwards because it's similar to the recursive approach. But it's possible and maybe more intuitive to start at the beginning. Whatever makes sense for you is the best approach I think.

    • @eltonlobo8697
      @eltonlobo8697 2 года назад

      Example: [1,4,2,3], While computing longest common subsequence starting from index 0, the number at index 2, will be used. While computing longest common subsequence starting from index 1, the number at index 2 will be used. What i mean by "Will be used" is i am asking a question: What is the longest common subsequence starting from index 2. So if we had started computing longest common subsquence from backwards, then when we compute longest common subsquence for index 0 and 1, we already have the answer for longest common subsequence starting from index 2 stored.

  • @MerlynJohnson
    @MerlynJohnson 3 года назад +1

    whether it should be if nums[i] < nums[j] or if nums[j] < nums[i]

  • @amardeepbhowmick3614
    @amardeepbhowmick3614 3 года назад +1

    This is GOLD!

  • @thetechies2259
    @thetechies2259 Год назад +1

    last statement : 'walk out of the room' really made me laugh😂😂.. that's the attitude

  • @souryadeepmukherjee7702
    @souryadeepmukherjee7702 Год назад

    Thanks for the solution and simple and easy to understand explanation. However I wanted to ask why you initialized the outer loop like that because the first iteration of the inner loop won't happen because we initialize i as 4 right?

  • @robyc9545
    @robyc9545 2 года назад +4

    It is interesting that you calculated DP from right to left. I think it also works if you do from left to right.

  • @mohit8299
    @mohit8299 Год назад

    very nicely explained bro
    thanks a lot

  • @srikanthvimjam9753
    @srikanthvimjam9753 3 года назад +1

    Really nice explanation. Your video saved me lot of time.

  • @mikemartin6748
    @mikemartin6748 3 года назад +7

    Why do you not cover the best solution: dynamic programming with binary search? That's the one I'm looking for because you need it to solve later problems like the Russian Doll Envelopes.

  • @mrProgrammingGeek
    @mrProgrammingGeek 2 года назад

    beautiful explanation!

  • @RishinderRana
    @RishinderRana 5 месяцев назад +1

    Agreeing with everything except the walking out part :)

  • @anandkrishnan72
    @anandkrishnan72 Год назад +2

    "I really doubt your interviewer is gonna expect you to get the O(n logn) solution without a hint. If they do, I would personally just walk out of the room." XDDDDD

    • @noorbasha8725
      @noorbasha8725 9 месяцев назад

      This happen with me yesterday, he didnt given any hint, result is i failed the interview

  • @mycityofsky
    @mycityofsky 2 года назад

    Thanks, an excellent explanation!

  • @danielmdubois
    @danielmdubois Год назад

    Great video, much appreciated. However, I didn't understand the logical jump at @10:40 that suggested we were "starting at 3". I would have preferred to see a solution that proceeded front-to-back, because it seemed to me that is what you were doing in the recursive solution.

  • @kumargauravsingh2094
    @kumargauravsingh2094 2 года назад

    Elegant , great explanation .The video made it very easy to understand. 💭 Why I am not think like this ?. Thank you

  • @harishsn4866
    @harishsn4866 2 года назад +3

    since we have already assigned LIS with value 1 for the length of nums, in the first for loop, we can start from len(nums) - 2 instead of len(nums) -1.

  • @shan504
    @shan504 2 года назад +1

    can someone explain the time complexity of the dfs solution? i thought if you memoize it it would help a good amount. without the memoization it would be approximately n^n since you choose from the remaining elements.

  • @keviniori
    @keviniori 2 года назад

    really good tutorial!

  • @user-xo8td6sn5z
    @user-xo8td6sn5z 3 года назад

    Best explaination!

  • @nightmarauder2909
    @nightmarauder2909 2 года назад

    lol you kept typing LIST
    great explanation, thanks!

  • @killerthoughts6150
    @killerthoughts6150 3 года назад +7

    it would be great to see the n log n approach

  • @dcc5244
    @dcc5244 5 месяцев назад

    博主讲的真好!

  • @dhanrajbhosale9313
    @dhanrajbhosale9313 Год назад

    End was epic 😄.. "I'll probably walk out of interview"🙃

  • @ildar5184
    @ildar5184 7 месяцев назад

    No need to complicate it further by doing reverse looping, from 0 to n works just fine with the same function of max(lis[i], 1+lis[j]) for i=0 to n, j=0 to i if nums[j]

  • @ayush3032
    @ayush3032 2 года назад +1

    Please cover follow-ups also. BTW great explanation.

  • @theysay6696
    @theysay6696 2 года назад +1

    "I would personally just walk out the room" LOL

  • @prempeacefulchannel
    @prempeacefulchannel 2 года назад +2

    It’s looks easier after your explanation 👏🏻

    • @NeetCode
      @NeetCode  2 года назад +1

      Glad it was helpful!

  • @santoshkadam8431
    @santoshkadam8431 11 месяцев назад

    Wow great explanation!

  • @asdfasyakitori8514
    @asdfasyakitori8514 9 месяцев назад

    Man 8 lines of code is all it takes, grate solution

  • @vietnguyenquoc4948
    @vietnguyenquoc4948 4 месяца назад

    IDK why but your voice in this video sounds really calming

  • @dhg40
    @dhg40 2 года назад

    Best explain ever!

  • @numberonep5404
    @numberonep5404 2 года назад +2

    Great explanation as usual!! A repost(?) of the O(nlong(n)) solution, not that hard and really comes in handy for other problems :)
    class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
    indices = [None for _ in range(len(nums)+1)] # Mapping of size to the last indice of the subsequence
    size = 0
    def binary(elem, l, r): # a binary search is possible since the sizes are sorted by definition, even if the values in nums are not
    while l

  • @rubenomarpachecosantos7130
    @rubenomarpachecosantos7130 2 года назад +1

    "I would personally just walk out the room" haha

  • @asdfasyakitori8514
    @asdfasyakitori8514 9 месяцев назад

    Great video

  • @gauravthehero
    @gauravthehero Год назад

    Thanks for making such wonderful videos. I had a doubt regarding going in reverse order. I was able to get to the solution going 'in order' with the thought, at each position what is the LIS that can be formed till that point.. What am I missing here. Thanks again!

    • @NeetCode
      @NeetCode  Год назад

      I think the way you did it is probably better, I go in reverse order because it's similar to the drawing explanation.

  • @yahwehagape
    @yahwehagape 3 года назад +6

    Great explanation. Curious about nlogn solution now.

  • @gritcrit4385
    @gritcrit4385 2 месяца назад

    DFS: O(2^n)
    DP: O(n^2)
    Binary search: O(n logn)

  • @srushtinarnaware4919
    @srushtinarnaware4919 Год назад

    Thank You so much

  • @begula_chan
    @begula_chan 4 месяца назад

    Thanks man!

  • @bubbletea8793
    @bubbletea8793 2 года назад

    thanks man pt. 2

  • @chaitrabhat8199
    @chaitrabhat8199 8 месяцев назад

    Neat Explanation

  • @winterheat
    @winterheat Год назад +1

    11:34 I think using the name LIS[ ] is not a good choice, as you may think the final solution is LIS[0] this way. The strict definition of this lookup table, let's call it lookup[ ] is this: IF YOU TAKE THAT NUMBER nums[i] into the sequence, then what is the longest you can get. So lookup[i] IS IF YOU MUST INCLUDE nums[i] into that sequence. If you write LIS[i], it sounds like it is the max NO MATTER you include nums[i] or not, which is not the case. So that's why in the code that follows, the final result is not LIS[0], but max(LIS)

  • @th3tagang
    @th3tagang 3 года назад +1

    great explanation!

  • @ajithkumarspartan
    @ajithkumarspartan 2 месяца назад

    When i feel its so hard to learn DSA problem and crack FAANG like companies my mind tells me "neetcode" and after seeing the video explanation i become calm and motivated to proceed further.

  • @NhanSleeptight
    @NhanSleeptight 2 года назад +10

    do you mind sharing the code for the DFS solution? I just want to practice implementing these ideas.

    • @DavidDLee
      @DavidDLee Год назад

      def lengthOfLIS2(self, nums: List[int]) -> int:
      L = len(nums)
      cache = {L: 0}

      def dfs(i):
      if i in cache:
      return cache[i]
      n = nums[i]
      result = 1
      for j in range(i + 1, L):
      if n < nums[j]:
      result = max(dfs(j) + 1, result)
      cache[i] = result
      return result

      return dfs(0)

  • @adipandhare4061
    @adipandhare4061 Год назад

    What if the sequence is: A = [1, 4, 2, 8, 5, 7, 3]. If we start from the back end, it's very focused on the last element. Almost like it's a greedy algorithm and would not reach the optimum result. So how would this algorithm work in this scenario?

  • @mirrorinfinite5392
    @mirrorinfinite5392 2 года назад

    Anyone know the space complexity for his final solution? Ive seen people on lc discussions say it is O(n^2) but isnt it just O(n) for the extra LIS array?

  • @xeon789
    @xeon789 Год назад

    thank u so much

  • @testbot6899
    @testbot6899 2 года назад

    O(nlogn) solution
    class Solution:
    def lis(self, A):
    res = [A[0]]
    n = len(A)

    for num in A[1:]:
    if num>res[-1]:
    res.append(num)
    else:
    res[bisect_left(res,num)] = num

    return len(res)