Matchsticks to Square - Leetcode 473 - Python

  Рет қаралды 27,720

NeetCode

NeetCode

Күн бұрын

Пікірлер: 72
@MonsterhunterFTWWTF
@MonsterhunterFTWWTF 2 жыл бұрын
I managed to pass my Google SWE intern interviews thanks to your videos Neetcode! I talked through all my solutions and applied a lot of the thinking patterns from your videos. Finally after 200+ LC and 5 months of interviewing I’m done.
@NeetCode
@NeetCode 2 жыл бұрын
That's awesome!!! Good luck at Google!
@hp1612
@hp1612 2 жыл бұрын
Over the last 2 months, I've been following the way you walk through the problems and apply that to my daily practice. Last week I got an offer from Amazon. Thank you so much man. Keep it up. You're changing people's lives.
@vinayak186f3
@vinayak186f3 2 жыл бұрын
congrats 🎊🎊🎊
@hp1612
@hp1612 2 жыл бұрын
@@vinayak186f3 thanks
@NeetCode
@NeetCode 2 жыл бұрын
Congrats on the Amazon offer and good luck in your future! Happy I could help :)
@fsteve6443
@fsteve6443 2 жыл бұрын
amazon offer in just 2 months?
@hp1612
@hp1612 2 жыл бұрын
FBA Steven yessir
@zactamzhermin1434
@zactamzhermin1434 2 жыл бұрын
For those of y'all getting TLE, I'll just paste what I wrote to another guy on how to fix it. TLDR, you need to memoize. Hi met the same problem as it's today's daily. It's not enough to backtrack blindly. For me it TLE all the time with naive backtracking, even after optimizing by sorting first. So to avoid TLE, you need to memoize the sides array, kind of like the state (memoizing the index i is useless because it does not prevent any recalculation so using python's caching decorator shortcut @cache wouldn't help). Finally of course, you have to transform the sides array into a tuple before memoizing because arrays are immutable and hence not hashable into a set or dict. ``` # add extra base case in the backtracking function if tuple(sides) in memo: return memo[tuple(sides)] ... # outside of the sides backtracking for loop memo[tuple(sides)] = False # we only need to memoize the False case because if it's ever True, we've finished the problem return memo[tuple(sides)] ```
@aishwaryaranghar3385
@aishwaryaranghar3385 2 жыл бұрын
waaao!!!!! thankyouuuuuu
@LiuGang
@LiuGang Жыл бұрын
Thank for your valuable comments, it is extremely helpful. BTW, using frozenset or tuple(sorted(sides))) instead of tuple(sides) can even further speed-up.
@Ragdoll333-q5l
@Ragdoll333-q5l 2 жыл бұрын
Thanks for your amazing video! I made some optimization: I added a if statement at the end of for loop which means we do not need to loop through all four sides as a starting side. If it does not work from one side at the very beginning, just return False. for j in range(4): if cur[j] + matchsticks[i]
@techpowercoders8009
@techpowercoders8009 2 жыл бұрын
@Qiaoqiao your optimization works !!!
@ruiqimao1078
@ruiqimao1078 2 жыл бұрын
Similar to leetcode: 698. Partition to K Equal Sum Subsets
@sidazhong2019
@sidazhong2019 Жыл бұрын
Not similar, exactly the same.
@Deschuttes
@Deschuttes 2 жыл бұрын
I've a question. By about the 2:00 mark you've already figured out the "has to be divisible by 4" piece. However, initially figuring out what the problem is even for a brute-force solution isn't always clear, especially if trying to apply a dozen previously seen paradigms to the question. Any tips there on what to do for the very start? It's obvious when you explain it but not as obvious in the heat of the battle.
@TheElementFive
@TheElementFive 2 жыл бұрын
The dual screen format would be especially helpful for recursive problems such as this!
@fa11en1ce
@fa11en1ce 2 жыл бұрын
The matches are on fire! What a reckless leetcode problem.
@kagekami-gaming
@kagekami-gaming 2 жыл бұрын
By 4:24 i knew what i have to write. Thanks a lot.
@jasdn93bsad992
@jasdn93bsad992 9 ай бұрын
The backtracking function should return `sides[0] == sides[1] && sides[1] == sides[2] && sides[2] == sides[3];` instead of true. This would prevent false positives.
@qichengma9336
@qichengma9336 2 жыл бұрын
i use the same approach and the it's totally depends on luck if leetcode would accept it. 4 trials, only one not reaching time limit. Would you care to try to submit it now and possibly upload some optimize suggestion to the code pls?
@zactamzhermin1434
@zactamzhermin1434 2 жыл бұрын
Hi met the same problem as it's today's daily. It's not enough to backtrack blindly. For me it TLE all the time with naive backtracking, even after optimizing by sorting first. So to avoid TLE, you need to memoize the sides array, kind of like the state (memoizing the index i is useless because it does not prevent any recalculation so using python's caching decorator shortcut @cache wouldn't help). Finally of course, you have to transform it into a tuple before memoizing because arrays are immutable and hence not hashable into a set or dict. ``` if tuple(sides) in memo: return memo[tuple(sides)] ... # outside of the sides backtracking for loop memo[tuple(sides)] = False # we only need to memoize the False case because if it's ever True, we've finished the problem return memo[tuple(sides)] ```
@nihaljoshi2408
@nihaljoshi2408 2 жыл бұрын
class Solution: def makesquare(self, matchsticks: List[int]) -> bool: side_length = sum(matchsticks) // 4 square = [0] * 4 if sum(matchsticks) / 4 != side_length: return False matchsticks.sort(reverse = True) def backtrack(i): if i == len(matchsticks): return True used = set() for j in range(4): if square[j] + matchsticks[i]
@vipinamar8323
@vipinamar8323 4 ай бұрын
Great explanation as always this is really a Hard problem so the difficulty is inaccurate and btw there is a more generalized version of it leetcode no.698
@abhishekpawar8458
@abhishekpawar8458 2 жыл бұрын
This problem is a variation of k subset sum problem. Here k is 4 class Solution { public: bool canForm(vector &vec, int target, int sum, int ind, int k){ if(k == 4){ return true; } if(sum > target){ return false; } if(sum == target){ return canForm(vec,target,0,0,k+1); } for(int i = ind; i < vec.size(); i++){ if(vec[i] < 0){ continue; } sum += vec[i]; vec[i] = -1*vec[i]; if(canForm(vec, target, sum, i+1, k)){ return true; } vec[i] = -1*vec[i]; sum -= vec[i]; } return false; } bool makesquare(vector& matchsticks) { int perimeter = 0; for(int i = 0; i < matchsticks.size(); i++){ perimeter += matchsticks[i]; } if(perimeter%4 != 0){ return false; } int side = perimeter/4; sort(matchsticks.begin(), matchsticks.end(), greater()); return canForm(matchsticks,side,0,0,0); } };
@raghuvamsi4879
@raghuvamsi4879 Жыл бұрын
Honestly, I just came to your video to see a bit more optimized solution, like using DP 😭! If you have time pls explain that approach, Thank you.
@huaminwang4748
@huaminwang4748 2 жыл бұрын
Is this the same problem as 698 with k = 4?
@vivekshaw2095
@vivekshaw2095 2 жыл бұрын
if you are getting TLE , add if not sides[j]: break after s[j]-=matchsticks[i]
@ningzedai9052
@ningzedai9052 2 жыл бұрын
This line of optimization is so brilliant !!!
@orellavie6233
@orellavie6233 Жыл бұрын
How is that helpful?
@vivekshaw2095
@vivekshaw2095 Жыл бұрын
@@orellavie6233 you will not get tle after this
@orellavie6233
@orellavie6233 Жыл бұрын
@@vivekshaw2095 sorry, I am not sure I got ya Any chance for example?
@pratiksingh9953
@pratiksingh9953 Жыл бұрын
@@orellavie6233 it's an optimization, doesn't changes the TC. Example, length_per_side = 2, and we have already put matchsticks equaling size 2 at, say, top portion, in that case there is no need to make further recursive calls trying to put more matchstick on the top portion.
@prempeacefulchannel
@prempeacefulchannel 2 жыл бұрын
Good explanation of the approach!
@DhruvOberoi
@DhruvOberoi Жыл бұрын
Added memoization to prevent repeated work. Trick here is to store the index and the _sorted_ sides array as the key. We sort as two different states such as [4, 2, 4, 3] at index i would ultimately do the same work as [2, 3, 4, 4] at that index given we iterate through all 4 values in the sides array. This significantly improves runtime if an interviewer potentially asks for further optimisation beyond sorting the matchsticks array in descending order: def get_hashstring(i): return f"{i}_{'_'.join([str(side) for side in sorted(sides)])}" def backtrack(i): if i == len(matchsticks): return True if get_hashstring(i) in memo: return memo[get_hashstring(i)] for j in range(4): if matchsticks[i] + sides[j] > target: continue sides[j] += matchsticks[i] if backtrack(i + 1): memo[get_hashstring(i)] = True return True sides[j] -= matchsticks[i] memo[get_hashstring(i)] = False return Fals
@anjaliyadav9360
@anjaliyadav9360 2 жыл бұрын
Nice Explaination
@shantanukumar4081
@shantanukumar4081 2 жыл бұрын
Great Explanation !!!
@chasehelton2581
@chasehelton2581 2 жыл бұрын
Hey @Neetcode, can you tell me what software you use to draw your solutions?
@NeetCode
@NeetCode 2 жыл бұрын
I use Paint3D
@Sulerhy
@Sulerhy 5 ай бұрын
This problem is too difficult to imagine
@usungyang4934
@usungyang4934 2 жыл бұрын
special case of 698 Partition to K Equal Sum Subsets.
@melarryify
@melarryify 2 жыл бұрын
Didnt understand solution completely, one line 10, you only match "i == len(matchsticks),", Shoudnt you also make sure that its a square, for eg: sides[0] == sides[1] && sides[1] == sides[2] && sides[2] == sides[3] ?
@TheRealEz1ck
@TheRealEz1ck 2 жыл бұрын
@pranav what if the array is [1,2,2,3]? It will still be 8 and divisible by 4, coming out as an integer, but it won't work right?
@MIHIRHUNDIWALA
@MIHIRHUNDIWALA 2 жыл бұрын
@@TheRealEz1ck Yes you will get length of side of square = integer 2, but look at the for loop closely, before another call we check if the matchstick fits the sidelength of square, and matchstick with length 3 wont fit in any of the sides, so ultimately we will come out of the for loop and return false
@serhattural3168
@serhattural3168 2 жыл бұрын
I couldnt figure out how this works without checking lenght of sides at the base case of dfs.
@VarunMittal-viralmutant
@VarunMittal-viralmutant 2 жыл бұрын
The weird thing is that without the .sort(reverse=True), this runs into TLE on LeetCode :( If O(4^N) is anyways the complexity, then O(N log N) should not make any difference, correct ?
@danielginovker1984
@danielginovker1984 2 жыл бұрын
It's luck of the draw. NC's solution gets TLE sometimes too
@nihaljoshi2408
@nihaljoshi2408 2 жыл бұрын
class Solution: def makesquare(self, matchsticks: List[int]) -> bool: side_length = sum(matchsticks) // 4 square = [0] * 4 if sum(matchsticks) / 4 != side_length: return False matchsticks.sort(reverse = True) def backtrack(i): if i == len(matchsticks): return True used = set() for j in range(4): if square[j] + matchsticks[i]
@melissac4872
@melissac4872 2 жыл бұрын
@@nihaljoshi2408 I dont quite get this - for example, when we have [1,1,2,2,2], after the first two 1s square[0]+num[0]+num[1]=2, used set: 2 . And now, the next number num[2] is 2, square[1]+num[2] = 2, we can't have the 2 in the set anymore since it's already existed in the set??
@nihaljoshi2408
@nihaljoshi2408 2 жыл бұрын
@@melissac4872 that won't happen right? Because we backtrack first, and then add it to the set.
@anonymoussloth6687
@anonymoussloth6687 2 жыл бұрын
Is there a dp solution for this?
@haydencordeiro
@haydencordeiro 2 жыл бұрын
I initially thought it was a variation of subset sum
@hrvmhv4391
@hrvmhv4391 2 жыл бұрын
@@haydencordeiro You can definitely use the technique provided by @neetcode in this solution kzbin.info/www/bejne/o3POZXxmjZlppas
@haydencordeiro
@haydencordeiro 2 жыл бұрын
@@hrvmhv4391 hey thanks man . I appreciate it
@qahoushh
@qahoushh 2 жыл бұрын
I've tried this code Time Limit Exceeded
@nihaljoshi2408
@nihaljoshi2408 2 жыл бұрын
class Solution: def makesquare(self, matchsticks: List[int]) -> bool: side_length = sum(matchsticks) // 4 square = [0] * 4 if sum(matchsticks) / 4 != side_length: return False matchsticks.sort(reverse = True) def backtrack(i): if i == len(matchsticks): return True used = set() for j in range(4): if square[j] + matchsticks[i]
@eslammaher5946
@eslammaher5946 2 жыл бұрын
Make sure the array is sorted desc
@vinayakgupta1
@vinayakgupta1 2 жыл бұрын
Partition to k equal sum where k is 4.
@danielsun716
@danielsun716 2 жыл бұрын
This is totally a simplified leetcode 698-partition to K equal sum subsets. For this problem, k == 4. Needcode implement that by the O(k^n) algorithm. But there still be another one which has been posted in 698's video. And the time complexity is O(k * 2^n). In this algorithm, the main thing is for each side of the square, can we include the matchstick or not. Therefore, there are 2 decisions. Also, we cannot use each matchstick twice. So we have to create an array to memorize the state. def makesquare(self, matchsticks: List[int]) -> bool: # if sideSum cannot be integer, it won't be created to a square if sum(matchsticks) % 4: return False # target is each side sum target = sum(matchsticks) / 4 matchsticks.sort(reverse = True) used = [False] * len(matchsticks) def backtrack(i, k, sideSum): # base case: if we finish each side, then it works. if k == 4: return True # if one sideSum = target, then do the next side. if sideSum == target: return backtrack(0, k + 1, 0) for j in range(i, len(matchsticks)): ''' since we have sorted, so if the previous matchstick is skipped, then the next one also should be skipped. But we need to conform it is not out of bound and not be used. ''' if j > 0 and not used[j - 1] and matchsticks[j] == matchsticks[j - 1]: continue if used[j] or sideSum + matchsticks[j] > target: continue used[j] = True if backtrack(j + 1, k, sideSum + matchsticks[j]): return True used[j] = False return False return backtrack(0, 0, 0) And it is pretty efficient of 72 ms implementing time. Hope this would be helpful, if you never watched needcode's 698 solution.
@minaFbeshay
@minaFbeshay 2 жыл бұрын
Why don't we start solving this problem by trying to fill the four sides, side by side? If any side failed to be fulfilled, then we are done. This will reduce the time complexity to O(2^n+2): as we have to traverse the matchsticks array 4 times and in each iteration, we check if the current stick fits in the current subset or not. Edit: My proposed solution is not correct. Assuming 1 set is correct and final and should only consider the other 3 sets is in correct, as 1 set could be filled correctly with more than one way.
@sathyanarayanankulasekaran5928
@sathyanarayanankulasekaran5928 2 жыл бұрын
this is exactly partition to k equal sum
@kwaminaessuahmensah8920
@kwaminaessuahmensah8920 2 жыл бұрын
Mans a god.
@jayeshnagarkar7131
@jayeshnagarkar7131 Жыл бұрын
previously my java solution was getting passed through all test cases but now its showing time exceeding . please someone suggest me how to improve. class Solution { public boolean dfs(int i, int left, int top, int right, int bottom, int target, int[] sticks){ if(i == sticks.length && left == target && top == target && right == target && bottom == target){ return true; } if(i == sticks.length) return false; boolean res = false; for(int j = 0; j < 4; j++){ if(j == 0){ left = left + sticks[i]; res = res || dfs(i+1, left, top, right, bottom, target, sticks); left = left - sticks[i]; } else if(j == 1){ top = top + sticks[i]; res = res || dfs(i+1, left, top, right, bottom, target, sticks); top = top - sticks[i]; } else if(j == 2){ right = right + sticks[i]; res = res || dfs(i+1, left, top, right, bottom, target, sticks); right = right - sticks[i]; } else{ bottom = bottom + sticks[i]; res = res || dfs(i+1, left, top, right, bottom, target, sticks); bottom = bottom - sticks[i]; } if(res) return res; } return res; } public boolean makesquare(int[] matchsticks) { Arrays.sort(matchsticks); int sum = Arrays.stream(matchsticks).sum(); if(sum % 4 != 0) return false; int target = sum / 4; return dfs(0,0,0,0,0,target,matchsticks); } }
@Sulerhy
@Sulerhy 5 ай бұрын
never ask some question like this. No one has 2 hours free to read your solution. Learn how to ask a good question!
@jayeshnagarkar7131
@jayeshnagarkar7131 5 ай бұрын
@@Sulerhy thanks that was helpful
@vinayak186f3
@vinayak186f3 2 жыл бұрын
14:50 Can someone plz explain why we need to skip , if the if condition is false , I did the opposite way , return false if sides[j]+ matchstick[i] > sidelength and got incorrect output at 170th TC
@chiraagpala3243
@chiraagpala3243 2 жыл бұрын
you still need to try out the other sides
@CS_n00b
@CS_n00b 9 ай бұрын
i never know when to do backtracking
@aishwaryaranghar3385
@aishwaryaranghar3385 2 жыл бұрын
informative vid!
@hoyinli7462
@hoyinli7462 2 жыл бұрын
this ans seems to be TLE now
@nihaljoshi2408
@nihaljoshi2408 2 жыл бұрын
class Solution: def makesquare(self, matchsticks: List[int]) -> bool: side_length = sum(matchsticks) // 4 square = [0] * 4 if sum(matchsticks) / 4 != side_length: return False matchsticks.sort(reverse = True) def backtrack(i): if i == len(matchsticks): return True used = set() for j in range(4): if square[j] + matchsticks[i]
@anuragtiwari3032
@anuragtiwari3032 2 жыл бұрын
first comment!!!!
Reconstruct Itinerary - Leetcode 332 - Python
17:38
NeetCode
Рет қаралды 71 М.
473. Matchsticks to Square - Day 12/31 Leetcode July Challenge
26:10
Programming Live with Larry
Рет қаралды 758
规则,在门里生存,出来~死亡
00:33
落魄的王子
Рет қаралды 32 МЛН
Стойкость Фёдора поразила всех!
00:58
МИНУС БАЛЛ
Рет қаралды 7 МЛН
How I would learn Leetcode if I could start over
18:03
NeetCodeIO
Рет қаралды 601 М.
Assign Cookies - Leetcode 455 - Python
9:06
NeetCodeIO
Рет қаралды 18 М.
Flatten Nested List Iterator - Leetcode 341 - Python
10:14
NeetCodeIO
Рет қаралды 10 М.
How to Solve ANY LeetCode Problem (Step-by-Step)
12:37
Codebagel
Рет қаралды 259 М.
Count Ways to Build Good Strings - Leetcode 2466 - Python
14:09
Top 5 Coding Interview MISTAKES (from a Google Engineer)
8:03
5 Useful F-String Tricks In Python
10:02
Indently
Рет қаралды 315 М.
Longest String Chain - Leetcode 1048 - Python
15:34
NeetCodeIO
Рет қаралды 9 М.
Word Break - Dynamic Programming - Leetcode 139 - Python
15:35
规则,在门里生存,出来~死亡
00:33
落魄的王子
Рет қаралды 32 МЛН