Distinct Subsequences - Dynamic Programming - Leetcode 115 - Python

  Рет қаралды 49,516

NeetCode

NeetCode

Күн бұрын

Пікірлер: 85
@NeetCode
@NeetCode 3 жыл бұрын
💡 DP PLAYLIST: kzbin.info/www/bejne/bWTVZH6Nnqqpr80
@dollyvishwakarma2
@dollyvishwakarma2 2 жыл бұрын
Hey @NeetCode, where all do you prefer using a hasmap to a 2D array?
@nikhil6842
@nikhil6842 2 жыл бұрын
Watching this at 1 am. I’m more addicted to you playlist than Netflix.
@ARTEMvorkhlik
@ARTEMvorkhlik Жыл бұрын
I'm looking forward, one day Netflix will buy the Neetcode's DP playlist and film it.
@AmeyaGharpure
@AmeyaGharpure Жыл бұрын
There's just something so peaceful about these videos
@themagickalmagickman
@themagickalmagickman Жыл бұрын
A really easy optimization that can be added is to check if there are enough characters left in s to create t, this can be done as easily as: if len(s) - i < len(t) - j: return 0. Improves runtime significantly
@amogh3275
@amogh3275 Жыл бұрын
damn youre right! went from 7% to 98% lol. good catch
@hetanthakkar5066
@hetanthakkar5066 6 ай бұрын
Apart from this trick, How do you come up with such optimization? any specific pointers would help for further problems
@themagickalmagickman
@themagickalmagickman 6 ай бұрын
@@hetanthakkar5066 I think it just comes down to understanding the code and seeing if there are any obvious deficiencies. When I noticed this optimization, I probably was looking for ways to know when we were done
@hetanthakkar5066
@hetanthakkar5066 6 ай бұрын
@@themagickalmagickman got it.Thank you for the explanation.
@icvetz
@icvetz 5 ай бұрын
Just did this problem and also though of this optimization, it increased my runtime from 32ms to 10ms. Glad to see someone else did the same! :)
@bernardpark3196
@bernardpark3196 3 жыл бұрын
Hey NeetCode, I think there’s a typo on line 14/16 where we’re moving the i pointer forward but not the j pointer - it should be dfs(i + 1, j) instead correct? And thanks again for another great video!
@NeetCode
@NeetCode 3 жыл бұрын
Oh crap... Good catch! You're right, it should be "+ 1" not "+ i", thanks for letting me know!
@Hiroki-Takahashi
@Hiroki-Takahashi 9 ай бұрын
I was searching the comment section for someone who commented on it :D
@barked2786
@barked2786 5 ай бұрын
@@Hiroki-Takahashi me to
@ermiaazarkhalili5586
@ermiaazarkhalili5586 Ай бұрын
@@Hiroki-Takahashi me too!
@abilkaiyrdoszhanov7645
@abilkaiyrdoszhanov7645 Ай бұрын
I think this comment is worth pinning:)
@B0JACK
@B0JACK 3 жыл бұрын
Great video, was able to write this after watching! class Solution: def numDistinct(self, s: str, t: str) -> int: @cache def dp( i, j ) -> int: if j == len( t ): return 1 if i == len( s ): return 0 res = dp( i+1, j ) if s[i] == t[j]: res += dp( i+1, j+1 ) return res return dp( 0, 0 )
@JLJConglomeration
@JLJConglomeration 8 ай бұрын
i can't believe i solved a hard on my own in like 10 minutes, but its all thanks to your 1-D and 2-D DP guides, the patterns start to emerge and this suddenly becomes simple
@yassineacherkouk
@yassineacherkouk Жыл бұрын
Men you always save me i almost solved 200 problem in leetcode, and now i start solving DP problems, thank you.
@sadekjn
@sadekjn Жыл бұрын
slight optimization: Instead of returning 0 if i == len(s), we can return 0 earlier by checking if len(s) - i < len(t) - j, which means that the rest of s is too small for the rest of t.
@phaninag7438
@phaninag7438 2 жыл бұрын
We can add a optimization as first line in the dfs function if (len(t)-j) > (len(s)-i): return 0 As there is no valid matching when length of t to be matched is greater than the characters left in string s
@karanthacker5554
@karanthacker5554 2 жыл бұрын
big boost in ex. time on leet
@markolainovic
@markolainovic 2 жыл бұрын
Good one!
@kartikeyrana3736
@kartikeyrana3736 Жыл бұрын
i dont usually comment on videos but EXCELLENT video, short, crisp and to the point ! here's the java version class Solution { int[][] cache; public int numDistinct(String s, String t) { if(s.length() == 0) return 0; else if(t.length() == 0) return 1; cache = new int[s.length()+1][t.length()+1]; for(int[] arr : cache) Arrays.fill(arr, -1); return dfs(s, t, 0, 0); } public int dfs(String s, String t, int x, int y){ if(y == t.length()) return 1; else if(x == s.length()) return 0; else if(cache[x][y] != -1) return cache[x][y]; int ans = 0; if(s.charAt(x) == t.charAt(y)) ans += dfs(s,t,x+1,y+1) + dfs(s,t,x+1,y); else ans += dfs(s,t,x+1,y); return cache[x][y] = ans; } }
@runzsh
@runzsh Жыл бұрын
I really like the transition modelling visualization, Thanks for such brilliant explanantion!
@hoyinli7462
@hoyinli7462 3 жыл бұрын
in the question, there is 1 constraint: 1
@rishabhsinha3713
@rishabhsinha3713 3 жыл бұрын
Hey, Thanks for the explanation but I think in the solution it will be `if s[i] == t[j]: cache[(i,j)] = dfs(i+1,j+1) + dfs(i+1,j) else: cache[(i,j)] = dfs(i+1,j)`
@hwang1607
@hwang1607 9 ай бұрын
That looks correct, not sure why nobody else said this
@aryanyadav3926
@aryanyadav3926 2 жыл бұрын
Wonderful! Will definitely watch your dp series.
@for_whom_the_bell_tolls
@for_whom_the_bell_tolls 15 күн бұрын
Maaan, your explanation is brilliant as always
@vinayakgupta1
@vinayakgupta1 2 жыл бұрын
Your channel is GOLD !!!!
@pritampawar6478
@pritampawar6478 3 жыл бұрын
such a neat and to a point solution keep it up👍👍👍
@sumeetbisen9708
@sumeetbisen9708 3 жыл бұрын
It's so simple, really appreciate your work, I wrote a solution for this one but having some trouble with memoization, need some advice: count = 0 def check(sub, i, length): nonlocal count if i>=n: return if length>m: return if sub!=t[:length]: return if sub==t: count+=1 return for j in range(i+1,n): temp = sub sub+=s[j] check(sub, j, length+1) sub = temp for i in range(n): check(s[i], i, 1) return count n and m are lengths of s and t respectively
@pramodhjajala8021
@pramodhjajala8021 Жыл бұрын
Hey Navdeep(@Neetcode), just a small suggestion , May be for the sake of future viewers ,you could fix the typo(i + i) in line 14, may be any kind of overlay on video should do i guess
@kuangyimeng8850
@kuangyimeng8850 2 жыл бұрын
Hi, I am confused with the difference between ' dynamic programming ' and ' dfs + cache"
@SachinKumar-cd1sg
@SachinKumar-cd1sg Жыл бұрын
DFS means recursive solution DFS+memorization==recursion+memoization
@danielsun716
@danielsun716 2 жыл бұрын
1D, DP solution def numDistinct(self, s: str, t: str) -> int: dp = [1] * (len(s) + 1) for j in range(len(t)- 1, -1, -1): nextDP = [0] * (len(s) + 1) for i in range(len(s) - 1, -1, -1): if s[i] == t[j]: nextDP[i] = nextDP[i + 1] + dp[i + 1] else: nextDP[i] = nextDP[i + 1] dp = nextDP return dp[0] And it is pretty efficient.
@hoyinli7462
@hoyinli7462 3 жыл бұрын
you made the world super simple again
@aradog3213
@aradog3213 3 жыл бұрын
HI! what age did you start programming and how long did it take you to be able to solve most of these questions? im 14 i started 2 months ago and im able to solve most of leetcode's problems but i kinda struggle with dynamic problems thanks!
@ZQutui
@ZQutui 3 жыл бұрын
It's a perfect age, the sooner the better. I would say that your struggling will be solved with practice. Just don't give up and you will succeed in programming
@aradog3213
@aradog3213 3 жыл бұрын
@@ZQutui thanks I sure will!
@DeGoya
@DeGoya 2 жыл бұрын
I've got this solution but I thought it's only a backtrack approach. I assumed there must be another dp solution where we use some kind of table like, for instance, in longest subsequence
@mansimishra7089
@mansimishra7089 3 жыл бұрын
Very Nice Explanation ...Thankyou
@TheVideogamemaster9
@TheVideogamemaster9 Жыл бұрын
Interestingly, when implementing this in JavaScript with a Map, I only get to question 53/65 before the time limit exceeds, even when I use the optimizations listed in the comments.
@swastikgorai2332
@swastikgorai2332 Жыл бұрын
simple and clear! thanks !!!
@anandjaiswal9870
@anandjaiswal9870 2 жыл бұрын
Clean Explanation
@homyakMilashka
@homyakMilashka Жыл бұрын
How do I know when to use like a table dp approach and when to use this recursive with memoization. I really am confused. The recursive is so much easier but it almost always TLEs on leetcode even with memoization.
@MAK_007
@MAK_007 2 ай бұрын
every single DP problem can be solved using both recursive (top down approach) and tabulation (bottom up approach). its just that some problems are easy to write in recursive form and some are easy to write in tabulation form. but the confusion will stop only when you actually understand why tabulation form works in every single problem. patterns in tabulation form differs more than recursive form hence recursive is easy. but you can learn few patterns in tabulation form thoroughly (best way is debug each step in tabulation form then you will understand easily ) then you can understand most of the problems
@supinVerse
@supinVerse 10 ай бұрын
class Solution: def numDistinct(self, s: str, t: str) -> int: cache = {} def dfs(i,j): if j==len(t): return 1 if i==len(s): return 0 # if i==len(s) or j==len(t): # return int(j==len(t)) if (i,j) in cache: return cache[(i,j)] if s[i]==t[j]: cache[(i,j)] = dfs(i+1,j+1)+dfs(i+1,j) else: cache[(i,j)] = dfs(i+1,j) return cache[(i,j)] return dfs(0,0)
@bchen1403
@bchen1403 2 жыл бұрын
Can someone explain why we must first examine if j reaches string t's end?
@yasharthgupta9002
@yasharthgupta9002 2 жыл бұрын
To take care of the situation when both the i and j ended together since j ended this possible sequence needs to be counted but if you return for the i first it will be 0 hence the formed string will not be counted so we need to check before if j ended and return 1 as required.
@hoyinli7462
@hoyinli7462 3 жыл бұрын
and liked this video as always. big THX
@kevinburke3941
@kevinburke3941 4 ай бұрын
This solution leads to Time Limit Exceeded on Leetcode.
@anshumansinha5874
@anshumansinha5874 Жыл бұрын
This isn’t dp, right? It’s memoisation (i.e DFS + Hash map)
@ryanaugustine5940
@ryanaugustine5940 Жыл бұрын
DP is an approach to solve recursive problems wherein the overlapping sub-problems are only executed once. So yes when we use memoisation, this is DP.
@chaitanyasaibeesabathuni928
@chaitanyasaibeesabathuni928 2 жыл бұрын
There is a huge change when we don't write the base cases in order ; incase we interchange the base case orders we get wrong output!!!!!!!
@oxyht
@oxyht 2 жыл бұрын
oh shit thanks!
@shrimpo6416
@shrimpo6416 2 жыл бұрын
Thank you!
@nagarjunvinukonda162
@nagarjunvinukonda162 Жыл бұрын
Time limit exceeds, you need to do memoization...
@conormurphy5794
@conormurphy5794 Жыл бұрын
First hard problem i solved
@heroicrhythms8302
@heroicrhythms8302 Жыл бұрын
Neetcode Nagaraj
@tomtran6936
@tomtran6936 2 жыл бұрын
Love it !
@shrimpo6416
@shrimpo6416 2 жыл бұрын
so clear!
@juliuskingsley6212
@juliuskingsley6212 Жыл бұрын
there is a true DP approach using just O(N) space that beats 85% on LeetCode. class Solution: def numDistinct(self, s: str, t: str) -> int: prevDP = [0] * (len(t) + 1) prevDP[-1] = 1 for i in range(len(s) - 1, -1, -1): currDP = [0] * (len(t) + 1) currDP[-1] = 1 for j in range(len(t) - 1, -1, -1): if s[i] == t[j]: currDP[j] = prevDP[j] + prevDP[j + 1] else: currDP[j] = prevDP[j] prevDP = currDP return prevDP[0]
@cooldudeakki3435
@cooldudeakki3435 3 жыл бұрын
Hey NeetCode, I tested this solution for some of the inputs and it didn't output the right answer. Eg: 1. Let s="babgbag" t= "bag"; The output of the program is 2 while the expected output is 5. 2. Let s="rabbbit" t="rabbit"; The output of the program is 1 while the expected output is 3. Kindly look into it.
@pradipakshar
@pradipakshar Жыл бұрын
Probably because you're checking S[I] == S[J] instead of S[I] == 'T'[J].. 2 years late but hey better late than never :)
@chaithanyachallapalli8608
@chaithanyachallapalli8608 Жыл бұрын
hi can anyone explain this if (s[i] == t[j]) { dp[{i, j}] = dfs(s, t, i + 1, j + 1) + dfs(s, t, i + 1, j); } else { dp[{i, j}] = dfs(s, t, i + 1, j); } insted of this can I do int ans=0; for(int z = i;z
@jonaskhanwald566
@jonaskhanwald566 3 жыл бұрын
combination sum ???
@NeetCode
@NeetCode 3 жыл бұрын
Combination Sum IV? I can try to do it soon
@jonaskhanwald566
@jonaskhanwald566 3 жыл бұрын
@@NeetCode Thanks
@kushagrakasliwal3930
@kushagrakasliwal3930 3 ай бұрын
Excellenrtrrtttttt😮
@theWrongCode
@theWrongCode 3 жыл бұрын
Perfect
@DavidDLee
@DavidDLee Жыл бұрын
Why is the complexity M*N? Needs a better explanation.
@pranjityadav3620
@pranjityadav3620 3 жыл бұрын
awesome
@mohamadilhamramadhan6354
@mohamadilhamramadhan6354 Жыл бұрын
It could be even O(s) space. Runtime beats 90% and memory beats 90%: dp = [1] * (len(s) + 1) for i in range(len(t)): newRow = [0] for j in range(len(s)): if t[i] == s[j]: newRow.append( newRow[j] + dp[j] ) else: newRow.append( newRow[j]) dp = newRow return dp[len(s)]
How to treat Acne💉
00:31
ISSEI / いっせい
Рет қаралды 108 МЛН
DP 32. Distinct Subsequences | 1D Array Optimisation Technique 🔥
40:15
Burst Baloons - Dynamic Programming - Leetcode 312 - Python
21:20
How I Approach a New Leetcode Problem (live problem solving)
25:31
Uncrossed Lines - Leetcode 1035 - Python
29:14
NeetCodeIO
Рет қаралды 10 М.
Longest Increasing Path in a Matrix - Leetcode 329
17:45
NeetCode
Рет қаралды 67 М.
Making an Algorithm Faster
30:08
NeetCodeIO
Рет қаралды 194 М.
Coin Change - Dynamic Programming Bottom Up - Leetcode 322
19:23
Climbing Stairs - Dynamic Programming - Leetcode 70 - Python
18:08
Longest Palindromic Subsequence - Leetcode 516 - Python
18:04
NeetCodeIO
Рет қаралды 29 М.