Distinct Subsequences - Dynamic Programming - Leetcode 115 - Python

  Рет қаралды 41,448

NeetCode

NeetCode

Күн бұрын

🚀 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/count-su...
0:00 - Read the problem
1:05 - Drawing Explanation
9:00 - Coding Explanation
leetcode 115
This question was identified as an interview question from here: github.com/xizhengszhang/Leet...
#twitter #interview #python
Disclosure: Some of the links above may be affiliate links, from which I may earn a small commission.

Пікірлер: 79
@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 11 ай бұрын
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 11 ай бұрын
damn youre right! went from 7% to 98% lol. good catch
@hetanthakkar5066
@hetanthakkar5066 27 күн бұрын
Apart from this trick, How do you come up with such optimization? any specific pointers would help for further problems
@themagickalmagickman
@themagickalmagickman 26 күн бұрын
@@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 26 күн бұрын
@@themagickalmagickman got it.Thank you for the explanation.
@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 4 ай бұрын
I was searching the comment section for someone who commented on it :D
@barked2786
@barked2786 4 күн бұрын
@@Hiroki-Takahashi me to
@B0JACK
@B0JACK 2 жыл бұрын
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 3 ай бұрын
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 8 ай бұрын
Men you always save me i almost solved 200 problem in leetcode, and now i start solving DP problems, thank you.
@runzsh
@runzsh 10 ай бұрын
I really like the transition modelling visualization, Thanks for such brilliant explanantion!
@aryanyadav3926
@aryanyadav3926 2 жыл бұрын
Wonderful! Will definitely watch your dp series.
@sk_4142
@sk_4142 11 ай бұрын
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.
@pritampawar6478
@pritampawar6478 3 жыл бұрын
such a neat and to a point solution keep it up👍👍👍
@kartikeyrana3736
@kartikeyrana3736 9 ай бұрын
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; } }
@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 Жыл бұрын
big boost in ex. time on leet
@markolainovic
@markolainovic Жыл бұрын
Good one!
@vinayakgupta1
@vinayakgupta1 2 жыл бұрын
Your channel is GOLD !!!!
@sumeetbisen9708
@sumeetbisen9708 2 жыл бұрын
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
@swastikgorai2332
@swastikgorai2332 Жыл бұрын
simple and clear! thanks !!!
@mansimishra7089
@mansimishra7089 2 жыл бұрын
Very Nice Explanation ...Thankyou
@homyakMilashka
@homyakMilashka 8 ай бұрын
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.
@anandjaiswal9870
@anandjaiswal9870 Жыл бұрын
Clean Explanation
@shrimpo6416
@shrimpo6416 2 жыл бұрын
Thank you!
@tomtran6936
@tomtran6936 Жыл бұрын
Love it !
@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
@hoyinli7462
@hoyinli7462 2 жыл бұрын
in the question, there is 1 constraint: 1
@DeGoya
@DeGoya Жыл бұрын
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
@shrimpo6416
@shrimpo6416 2 жыл бұрын
so clear!
@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!
@hoyinli7462
@hoyinli7462 2 жыл бұрын
you made the world super simple again
@thyminegaming6943
@thyminegaming6943 4 ай бұрын
in if case why can't we write if(s[i]==t[j]){ dp[i][j]= rec(i+1,j+1,s,t,dp)+rec(i+2,j+1,s,t,dp); } instead of if(s[i]==t[j]){ dp[i][j]= rec(i+1,j+1,s,t,dp)+rec(i+1,j,s,t,dp); } can any body please explain me??
@hoyinli7462
@hoyinli7462 2 жыл бұрын
and liked this video as always. big THX
@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
@rishabhsinha3713
@rishabhsinha3713 2 жыл бұрын
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 4 ай бұрын
That looks correct, not sure why nobody else said this
@theWrongCode
@theWrongCode 3 жыл бұрын
Perfect
@TheVideogamemaster9
@TheVideogamemaster9 8 ай бұрын
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.
@pranjityadav3620
@pranjityadav3620 2 жыл бұрын
awesome
@danielsun716
@danielsun716 Жыл бұрын
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.
@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.
@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
@conormurphy5794
@conormurphy5794 10 ай бұрын
First hard problem i solved
@nagarjunvinukonda162
@nagarjunvinukonda162 Жыл бұрын
Time limit exceeds, you need to do memoization...
@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.
@heroicrhythms8302
@heroicrhythms8302 Жыл бұрын
Neetcode Nagaraj
@jonaskhanwald566
@jonaskhanwald566 3 жыл бұрын
combination sum ???
@NeetCode
@NeetCode 3 жыл бұрын
Combination Sum IV? I can try to do it soon
@jonaskhanwald566
@jonaskhanwald566 3 жыл бұрын
@@NeetCode Thanks
@supinVerse
@supinVerse 5 ай бұрын
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)
@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 Жыл бұрын
oh shit thanks!
@cooldudeakki3435
@cooldudeakki3435 2 жыл бұрын
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 9 ай бұрын
Probably because you're checking S[I] == S[J] instead of S[I] == 'T'[J].. 2 years late but hey better late than never :)
@DavidDLee
@DavidDLee Жыл бұрын
Why is the complexity M*N? Needs a better explanation.
@juliuskingsley6212
@juliuskingsley6212 8 ай бұрын
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]
@mohamadilhamramadhan6354
@mohamadilhamramadhan6354 11 ай бұрын
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)]
Burst Baloons - Dynamic Programming - Leetcode 312 - Python
21:20
DP 32. Distinct Subsequences | 1D Array Optimisation Technique 🔥
40:15
Stay on your way 🛤️✨
00:34
A4
Рет қаралды 26 МЛН
لااا! هذه البرتقالة مزعجة جدًا #قصير
00:15
One More Arabic
Рет қаралды 13 МЛН
Edit Distance - Dynamic Programming - Leetcode 72 - Python
21:00
Maximal Square - Top Down Memoization - Leetcode 221
19:50
NeetCode
Рет қаралды 63 М.
Longest Palindromic Subsequence - Leetcode 516 - Python
18:04
NeetCodeIO
Рет қаралды 22 М.
5 Useful F-String Tricks In Python
10:02
Indently
Рет қаралды 288 М.
SHA: Secure Hashing Algorithm - Computerphile
10:21
Computerphile
Рет қаралды 1,2 МЛН
The moment we stopped understanding AI [AlexNet]
17:38
Welch Labs
Рет қаралды 853 М.
8 Товаров с Алиэкспресс, о которых ты мог и не знать!
49:47
РасПаковка ДваПаковка
Рет қаралды 178 М.
$1 vs $100,000 Slow Motion Camera!
0:44
Hafu Go
Рет қаралды 29 МЛН
Запрещенный Гаджет для Авто с aliexpress 2
0:50
Тимур Сидельников
Рет қаралды 1 МЛН