From ef355bc386d6354b9f3c81e8b63ac8e52bed7a9f Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 26 Aug 2019 21:01:28 +0800 Subject: [PATCH 001/187] update answer --- problems/find-peak-element.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/problems/find-peak-element.py b/problems/find-peak-element.py index 6d82cd7..8dbd257 100644 --- a/problems/find-peak-element.py +++ b/problems/find-peak-element.py @@ -5,8 +5,9 @@ Else, it means the `p` and `p+1` is at the right side of the mountain, We move the `r` to `p`, since the peak must be at `p` or the left of the `p`. The `l` and `r` will move closer and closer to the peak until they meet together. -The time complexity is O(LogN) +The time complexity is `O(LogN)` """ +#O(LogN) Solution class Solution(object): def findPeakElement(self, nums): l = 0 From b2f6a8fbf384cc52c7f32a602403774abf32a3b3 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 27 Aug 2019 23:11:34 +0800 Subject: [PATCH 002/187] update readme --- README.md | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 6eb42e9..239d814 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ Because I wanted to help others like me. If you like my answer, a star on GitHub means a lot to me. https://github.com/wuduhren/leetcode-python + # Similar Problems I found it make sense to do similar problems together, so that we can recognize the problem faster when we encounter a new one. @@ -139,6 +140,21 @@ I found it make sense to do similar problems together, so that we can recognize This [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO31DBjfeMoA0dlfIA/edit#gid=126913158) is made by **huahua**, I found this on his [youtube](https://www.youtube.com/user/xxfflower/videos). + +# System Design +1. More resource + + +2. Architecture 101 + + +3. How to scale up? There are also lots of tech interview related topic in his channel. + + +4. Narendra talks about many system design. + + + # Other Resources These are the interview resources I personally used and only if it is really helpful I will put it here. @@ -165,19 +181,12 @@ These are the interview resources I personally used and only if it is really hel Basic data structure and algorithm online course taught in Python. This course is design to help you find job and do well in the interview. -## System Design -1. More resource - - -2. Architecture 101 - - -3. How to scale up? There are also lots of tech interview related topic in his channel. - - -4. Narendra talks about many system design. - - ## Interview Question Survey + + +# Interview Knowledge Base Quesion +1. [Session vs Cookie](https://medium.com/@chriswrite/session-vs-cookie-software-engineer-top-asked-question-1-9bdbc0766739) +2. [Token Authentication](https://medium.com/@chriswrite/token-authentication-software-engineer-top-asked-question-2-76dd2ed7c2d5) +Still making From e076cf2e94ec53680a6edb5f62df0bc12ab1f1f2 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 27 Aug 2019 23:12:54 +0800 Subject: [PATCH 003/187] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 239d814..589ca1a 100644 --- a/README.md +++ b/README.md @@ -189,4 +189,4 @@ Basic data structure and algorithm online course taught in Python. This course i # Interview Knowledge Base Quesion 1. [Session vs Cookie](https://medium.com/@chriswrite/session-vs-cookie-software-engineer-top-asked-question-1-9bdbc0766739) 2. [Token Authentication](https://medium.com/@chriswrite/token-authentication-software-engineer-top-asked-question-2-76dd2ed7c2d5) -Still making +... From 737c345a774da9b8dfb52d1928ad7010607d418e Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 31 Aug 2019 11:58:35 +0800 Subject: [PATCH 004/187] surtax.py --- problems/sqrtx.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 problems/sqrtx.py diff --git a/problems/sqrtx.py b/problems/sqrtx.py new file mode 100644 index 0000000..2e57049 --- /dev/null +++ b/problems/sqrtx.py @@ -0,0 +1,27 @@ +""" +The ans must be in between 0 and `x`. +So we set the lower bound `l` to 0. The upper bound `r` to `x`. +The answer will always between `l` and `r`. +For every iteration, if `l`, `m`, `r` are not answer, we adjust the `l` or `r`. +Until we find the answer +""" +class Solution(object): + def mySqrt(self, x): + def isAns(a): + if a**2<=x and (a+1)**2>x: + return True + return False + + l = 0 + r = x + while True: + m = (l+r)/2 + if isAns(l): return l + if isAns(m): return m + if isAns(r): return r + + if m**2 Date: Wed, 4 Sep 2019 22:06:09 +0800 Subject: [PATCH 005/187] no message --- ...kth-smallest-element-in-a-sorted-matrix.py | 14 ++++++ problems/search-a-2d-matrix.py | 49 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 problems/kth-smallest-element-in-a-sorted-matrix.py create mode 100644 problems/search-a-2d-matrix.py diff --git a/problems/kth-smallest-element-in-a-sorted-matrix.py b/problems/kth-smallest-element-in-a-sorted-matrix.py new file mode 100644 index 0000000..2743e98 --- /dev/null +++ b/problems/kth-smallest-element-in-a-sorted-matrix.py @@ -0,0 +1,14 @@ +class Solution(object): + def kthSmallest(self, matrix, k): + memo = [0]*len(matrix) + opt = [] + while len(opt)target: + r = m-1 + else: + l = m+1 + return False + +class Solution(object): + def searchMatrix(self, matrix, target): + def getMatrix(i): + n = i/M + m = i%M + return matrix[n][m] + + if not matrix or len(matrix)==0 or len(matrix[0])==0: return False + + N = len(matrix) + M = len(matrix[0]) + + l = 0 + r = N*M-1 + while l<=r: + p = (l+r)/2 + if getMatrix(l)==target: return True + if getMatrix(p)==target: return True + if getMatrix(r)==target: return True + + if getMatrix(p)>target: + r = p-1 + else: + l = p+1 + return False From 0a53786c68994ca9dc38c976c665180c49332bd0 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 8 Sep 2019 00:08:19 +0800 Subject: [PATCH 006/187] swim-in-rising-water.py --- problems/swim-in-rising-water.py | 112 +++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 problems/swim-in-rising-water.py diff --git a/problems/swim-in-rising-water.py b/problems/swim-in-rising-water.py new file mode 100644 index 0000000..911a41f --- /dev/null +++ b/problems/swim-in-rising-water.py @@ -0,0 +1,112 @@ +""" +Starting from `(0, 0)` we keep on selecting the neighbor with lower elevation until we reach the end. +There are four possible neighbors `(i+1, j), (i-1, j), (i, j+1), (i, j-1)`. +Every time we select neighbor we check if we visited and choose the smallest elevation to go. +""" +#Wrong +class Solution(object): + def swimInWater(self, grid): + def getNext(i, j): + options = [(i+1, j), (i-1, j), (i, j+1), (i, j-1)] + elevation = float('inf') + opt = (None, None) + for i_next, j_next in options: + if i_next<0 or i_next>=N or j_next<0 or j_next>=M: continue + if (i_next, j_next) in visited: continue + if grid[i_next][j_next]=N or j_next<0 or j_next>=N: continue + if (i_next, j_next) in seen: continue + heapq.heappush(pq, (grid[i_next][j_next], i_next, j_next)) + seen.add((i_next, j_next)) + return ans + + +""" +The answer must lie between `l` and `h`. +Where h is the value we sure that it can pass, l is the value it might or might not pass. +So we gradually test the value between `l~h` by binary search. +Until we find the value which is the lowest possible time that can pass. #[0] + +I init the `l` with the `t` of the destination, because we couldn't have been reach the destination without using `t` amount of time. +I init the `h` with the max `t` in the entire grid, since we can swim withim this time no matter what. + +The function `canPassWtihTimeLimit(t)` takes a parameter `t` and use DFS to see if we can swim to the destination in the time limit t. + +The time complexity is O((N^2)*LogN). +Find the max in the grid took O(N^2). +`canPassWtihTimeLimit(t)` took O(N^2), because we might possibly travel the entire grid. +We call `canPassWtihTimeLimit(t)` about O(LogN) of time because we use the binary search concept to navigate the `l` and `r`. +""" +class Solution(object): + def swimInWater(self, grid): + def canPassWtihTimeLimit(t): + stack = [] + seen = set() + + if grid[0][0]<=t: stack.append((0, 0)) + while stack: + i, j = stack.pop() + if i==N-1 and j==N-1: return True + seen.add((i, j)) + for i_next, j_next in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]: + if i_next<0 or i_next>=N or j_next<0 or j_next>=N: continue + if (i_next, j_next) in seen: continue + if grid[i_next][j_next]>t: continue + stack.append((i_next, j_next)) + return False + + N = len(grid) + l = grid[-1][-1] + h = max(map(max, grid)) #get max value in the grid + while True: + m = (l+h)/2 + p = canPassWtihTimeLimit(m) + if p and not canPassWtihTimeLimit(m-1): return m #[0] + if p: + h = m + else: + l = m+1 + return h + + + + + From b6a6e7f05fef8ba08aef3effc6d44a6fd18b5101 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 8 Sep 2019 22:18:08 +0800 Subject: [PATCH 007/187] no message --- problems/dungeon-game.py | 111 ++++++++++++++++++++++++++++++++ problems/koko-eating-bananas.py | 31 +++++++++ 2 files changed, 142 insertions(+) create mode 100644 problems/dungeon-game.py create mode 100644 problems/koko-eating-bananas.py diff --git a/problems/dungeon-game.py b/problems/dungeon-game.py new file mode 100644 index 0000000..f8325e7 --- /dev/null +++ b/problems/dungeon-game.py @@ -0,0 +1,111 @@ +""" +First, we define an 2-D matrix `hp`. +`hp[i][j]` is, when entering (i, j), the minimum health required, so that we can reach the princess. + +So what is the value of `hp[i][j]`? +At `(i, j)`, we always go to next place where its minimum health required is lowest. (Either `(i+1, j)` or `(i, j+1)`). +And if the value is, for example, `-4` at `(i, j)` the requirement will need to add `4` (`- D[i][j]`). +So the minimum requirement at (i, j) will become: +``` +min_required = min(hp[i+1][j], hp[i][j+1]) - D[i][j] +``` +Now if `min_required` is smaller or equal to `0`, it means that we don't need any requirement at all, set it to minimum, `1`. +``` +hp[i][j] = min_required if min_required>1 else 1 +``` + +Now we only need to work it backward so that we can deduct from the value we are sure. +I add extra row and column to the `hp` and set the bottom and the right of the princess to `1`. +so we don't need to look out for boundaries. +``` +hp[N][M-1] = 1 +hp[N-1][M] = 1 +``` + +The time complexity is O(NM). Since we only traverse the 2-D matrix twice. +One is for constructing `hp`. The second is calculate the value in `hp`. +The space complexity is O(NM), too. + +I learn my anser though [here](https://leetcode.com/problems/dungeon-game/discuss/52826/A-very-clean-and-intuitive-solution-(with-explanation)) which has an awesome explaination, too. +""" +class Solution(object): + def calculateMinimumHP(self, D): + N = len(D) + M = len(D[0]) + hp = [[float('inf')]*(M+1) for _ in xrange(N+1)] + hp[N][M-1] = 1 + hp[N-1][M] = 1 + + for i in reversed(xrange(N)): + for j in reversed(xrange(M)): + min_required = min(hp[i+1][j], hp[i][j+1]) - D[i][j] + hp[i][j] = min_required if min_required>1 else 1 + return hp[0][0] + + +#Time Limit Exceed +class Solution(object): + def calculateMinimumHP(self, dungeon): + def canPass(health_init): + stack = [] + + stack.append((0, 0, health_init)) + while stack: + i, j, health = stack.pop() + health_left = health+dungeon[i][j] + if health<0 or health_left<0: continue + if i==N-1 and j==M-1: return True + if i+1 Date: Thu, 12 Sep 2019 23:04:25 +0800 Subject: [PATCH 008/187] no message --- problems/median-of-two-sorted-arrays.py | 143 ++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 problems/median-of-two-sorted-arrays.py diff --git a/problems/median-of-two-sorted-arrays.py b/problems/median-of-two-sorted-arrays.py new file mode 100644 index 0000000..e61ac70 --- /dev/null +++ b/problems/median-of-two-sorted-arrays.py @@ -0,0 +1,143 @@ +""" +On these two sorted arrays (`A` and `B`), we cut both of them into two part, left and right. +`i` is the number of the element on the left of array `A`. +`j` is the number of the element on the left of array `B`. +`M` is the length of `A`. +`N` is the length of `B`. +Imagine if we find the median, and we use the median to seperate all the elements into two sides, left and right. + +First, The number of elements on the left must equal to the right. That is: +`Number of elements on the left of A` + `Number of elements on the left of B` is equal to `Number of elements on the right of A` + `Number of elements on the right of B` +Thus `i + j == (M-i) + (N-j)`, so `j = (M+N)/2 - i` + +Second, all the elements on the left must be smaller than the median. All the elements on the right must be larger than the median. +The max on the left side of `A` must be <= the min on the right side of `B`. +The max on the left side of `B` must be <= the min on the right side of `A`. +Since both array is sorted, so alreay know +the max on the left side of `A` must be <= to the min on the right side of `A`. +the max on the left side of `B` must be <= the min on the right side of `B`. + +For the coding part. +Keep in mind again that **`i` is the number of the element on the left of array `A`.** +And we can use `j = (M+N)/2 - i` to find `j`. +We only need to use binary search to find the right `i` that matches +```python +max_left_A<=min_right_B and max_left_B<=min_right_A +``` +And if `min_right_Blen(B): A, B = B, A #[0] + + M, N = len(A), len(B) + l, h = 0, M + + while l<=h: + i = (h+l)/2 + j = (M+N)/2-i #[1] + + max_left_A = A[i-1] if i>0 else float('-inf') #[2] + max_left_B = B[j-1] if j>0 else float('-inf') + + min_right_A = A[i] if M-i>0 else float('inf') + min_right_B = B[j] if N-j>0 else float('inf') + + if max_left_A<=min_right_B and max_left_B<=min_right_A: + if (M+N)%2==0: + return (max(max_left_A, max_left_B)+min(min_right_A, min_right_B))/2.0 + else: + return min(min_right_A, min_right_B) #[1] + elif min_right_Blen(Y): X, Y = Y, X + M, N = len(X), len(Y) + + after = (M+N-1)/2 + l, h = 0, M + + while l= Y[after-i-1]: + h = i + else: + l = i + 1 + i = l + nextfew = sorted(X[i:i+2] + Y[after-i:after-i+2]) + return (nextfew[0]+nextfew[1-(M+N)%2])/2.0 From fbfdd147040dcae936f50e10005c7556ab69546d Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 15 Sep 2019 16:48:46 +0800 Subject: [PATCH 009/187] no message --- problems/container-with-most-water.py | 33 ++++++++++++++++++++ problems/two-sum-ii-input-array-is-sorted.py | 28 +++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 problems/container-with-most-water.py create mode 100644 problems/two-sum-ii-input-array-is-sorted.py diff --git a/problems/container-with-most-water.py b/problems/container-with-most-water.py new file mode 100644 index 0000000..e5f49f4 --- /dev/null +++ b/problems/container-with-most-water.py @@ -0,0 +1,33 @@ +""" +`l` and `r` are the points on width that form the area. +The height on `l` is `H[l]` and `r` is `H[r]`. +The area that form by `l` and `r` is `(r-l)*min(H[r], H[l])`. + +We are going to calculate the area everytime we move `l` or `r`. +And maintain the `ans`, which is the max of all area. + +Now, we put `l` and `r` at the beginning and at the end of the array. +We calculate the area and update `ans`, move `l` or `r` inward. +How are we going to find a larger area with shorter width that form by `l` and `r`? +The answer is, we move the `l` or `r` with shorter `H[l]` or `H[r]`, so we might get a larger `min(H[r], H[l])`, which leads to possibly larger area. + +By doing this, we now have a new pair of `l` and `r`. +We calculate the area and update `ans`, move `l` or `r` inward. + +... + +We repeat the process until `l` and `r` collapse. +So by repeatedly moving `l` and `r` inward, we can run through all the shorter width that might form area larger than `ans`. +""" +class Solution(object): + def maxArea(self, H): + r, l = len(H)-1, 0 + ans = float('-inf') + + while r>l: + ans = max(ans, (r-l)*min(H[r], H[l])) + if H[r]>H[l]: + l = l+1 + else: + r = r-1 + return ans diff --git a/problems/two-sum-ii-input-array-is-sorted.py b/problems/two-sum-ii-input-array-is-sorted.py new file mode 100644 index 0000000..80b331b --- /dev/null +++ b/problems/two-sum-ii-input-array-is-sorted.py @@ -0,0 +1,28 @@ +class Solution(object): + def twoSum(self, numbers, target): + memo = {} + for i, n in enumerate(numbers): + if target-n in memo: + return [memo[target-n]+1, i+1] + memo[n] = i + +""" +We put `l` and `r` at the beginning and at the end of the array. +Everytime with new pair of `l` and `r`, we check if its sum is target. If true, return the answer. +If the sum is larger than the target, we need to reduce the sum, and the only way to do that is to move `r` leftward, since `l` is already at the leftmost. +If the sum is smaller than the target, we need to increase the sum, and the only way to do that is to move `l` rightward, since `r` is already at the rightmost. + +The time complexity is O(N). +The space complexity is O(1). +""" +class Solution(object): + def twoSum(self, numbers, target): + r, l = len(numbers)-1, 0 + while r>l: + if numbers[r]+numbers[l]==target: + return [l+1, r+1] + elif numbers[r]+numbers[l]>target: + r = r-1 + else: + l = l+1 + return [] From 2180589271adc30a310788af46f67c8c2759be19 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 15 Sep 2019 22:59:02 +0800 Subject: [PATCH 010/187] no message --- problems/squares-of-a-sorted-array.py | 62 ++++++++++++++++++++ problems/two-sum-ii-input-array-is-sorted.py | 21 ++++--- 2 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 problems/squares-of-a-sorted-array.py diff --git a/problems/squares-of-a-sorted-array.py b/problems/squares-of-a-sorted-array.py new file mode 100644 index 0000000..0e4981a --- /dev/null +++ b/problems/squares-of-a-sorted-array.py @@ -0,0 +1,62 @@ +""" +If all the numbers in the array is larger or equal than 0, all the square value will automatically be sorted. + +If there are negatives in the array, we need to seperate the negatives and the others. +To do that, we need to find the index of 0 or index of first positive element. We call the index `m`. +So for the non-negative part, it is sorted already: `numbers[m:]`. +The negative part sorted: `[-1*n for n in reversed(numbers[:m])]` + +And now we apply the merge method in the merge sort. +The method takes two sorted array and turn it into one. +If you are not familiar it take a look at [this](https://leetcode.com/problems/merge-sorted-array/discuss/208832/Python-O(M%2BN)-Solution-Explained). +After we got the sorted array, we compute all the squares and return. + +The time complexity is O(N). +The space complexity is O(N). +""" +class Solution(object): + def sortedSquares(self, numbers): + if not numbers: return numbers + + if numbers[0]>=0: + return [n**2 for n in numbers] + + m = 0 + for i, n in enumerate(numbers): + if n>=0: + m = i + break + + A, B = numbers[m:], [-1*n for n in reversed(numbers[:m])] + return [n**2 for n in self.merge(A, B)] + + def merge(self, A, B): + a = b = 0 + opt = [] + while a Date: Tue, 17 Sep 2019 20:55:44 +0800 Subject: [PATCH 011/187] no message --- README.md | 10 +++- .../letter-combinations-of-a-phone-number.py | 30 ++++++++++ problems/score-of-parentheses.py | 55 +++++++++++++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 problems/letter-combinations-of-a-phone-number.py create mode 100644 problems/score-of-parentheses.py diff --git a/README.md b/README.md index 589ca1a..9b8406b 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,11 @@ These are the interview resources I personally used and only if it is really hel 3. CS DoJo on "How I Got a Job at Google as a Software Engineer". There are also lots of technique on coding interview in his channel. - + + +4. The #1 Daily Habit of Those Who Dominate with Andy Frisella (Also on Spotify or Youtube, just google it.) + + ## Prepare in a Structural Way 1. @@ -182,8 +186,8 @@ Basic data structure and algorithm online course taught in Python. This course i ## Interview Question Survey - - +1. +2. # Interview Knowledge Base Quesion diff --git a/problems/letter-combinations-of-a-phone-number.py b/problems/letter-combinations-of-a-phone-number.py new file mode 100644 index 0000000..a0b5c26 --- /dev/null +++ b/problems/letter-combinations-of-a-phone-number.py @@ -0,0 +1,30 @@ +""" +I put all the posible answer in the `ans`. +For every digit in the input, we got whole new sets of answers, which is generated from the previous input. +""" +class Solution(object): + def letterCombinations(self, digits): + def helper(A, digit): + if not A: return memo[digit] + + opt = [] + for letter in memo[digit]: + for string in A: + opt.append(string+letter) + return opt + + ans = [] + memo = { + '2': ['a', 'b', 'c'], + '3': ['d', 'e', 'f'], + '4': ['g', 'h', 'i'], + '5': ['j', 'k', 'l'], + '6': ['m', 'n', 'o'], + '7': ['p', 'q', 'r', 's'], + '8': ['t', 'u', 'v'], + '9': ['w', 'x', 'y', 'z'] + } + + for digit in digits: + ans = helper(ans, digit) + return ans diff --git a/problems/score-of-parentheses.py b/problems/score-of-parentheses.py new file mode 100644 index 0000000..f808d16 --- /dev/null +++ b/problems/score-of-parentheses.py @@ -0,0 +1,55 @@ +""" +We parse the content in the parentheses and evaluate it. +If the content is empty string then the value is 1. +Otherwise, the value is the value of the content multiply by 2 +And we use the exact the same function to evaluate the value of the content (recursion). +We can know the start and the end of the parentheses (so we can extract the content) by `depth`, which is the level of parentheses. + +Even though this looks efficient the time complexity is high. O(N^depth). +You can think of a case like this +``` +(((((((((( ... content ... )))))))))) +``` +Where in every level you have to go through the whole thing again. + +The Space complexity is O(depth). +Even we only use O(1) in each function, but the recursion takes stack memory of O(depth). +""" +class Solution(object): + def scoreOfParentheses(self, S): + depth = 0 + start = 0 + score = 0 + for i, s in enumerate(S): + if s=='(': depth+=1 + if s==')': depth-=1 + if depth==0: + content = S[start+1:i] + if content == '': + score+=1 + else: + score+=self.scoreOfParentheses(content)*2 + start = i+1 + return score + +""" +If we take a closer look, we will notice that `()` are the only structure that provides value, the outer parentheses just add some multiplier. +So we only need to be concerned with `depth`. +For level we multiply the inner content by 2, so for each `()`, its value is `1 * 2**depth` + +The time complexity is O(N). +The space complexity is O(1). +""" +class Solution(object): + def scoreOfParentheses(self, S): + score = 0 + depth = 0 + + for i, s in enumerate(S): + if s=='(': + depth+=1 + else: + depth-=1 + if S[i-1]=='(': + score+=2**depth + return score From a125ccc0199518c31a7a5b252b80f1e85a43f444 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 20 Sep 2019 13:47:50 +0800 Subject: [PATCH 012/187] no message --- problems/combination-sum.py | 77 +++++++++++++++++++ .../first-unique-character-in-a-string.py | 9 ++- 2 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 problems/combination-sum.py diff --git a/problems/combination-sum.py b/problems/combination-sum.py new file mode 100644 index 0000000..a134e65 --- /dev/null +++ b/problems/combination-sum.py @@ -0,0 +1,77 @@ +""" +the `helper()` check if the `target_remain` is 0. +If true, it means that the sum of `combination` is equal to the `target`. Put the `combination` to the `answer`. +If not, we For-loop each number, put it in the `combination` and try the `combination`. See if the number can make `target_remain` 0. + + +The `start` means the `candidates[start:]` are the candidate we only need to concider. +For example if +``` +candidates = [2,3,6,7], target = 7 +``` +If we pick 3, we are not allow to pick 2 any more, or we will have duplicate combination. +We are only allow to pick the number at the same index or afterwards. + + +So in the For-loop, if the smallest candidate is larger than the `target_remain`, we don't need to check afterwards. +And that is why we need to sort the `candidates` in the first place. + +``` +candidates = [2,3,6,7] +target = 7 + +helper([], 0, 7) + helper([2], 0, 5) + helper([2, 2], 0, 3) + helper([2, 2, 2], 0, 1) + BREAK. When we are about to call helper([2, 2, 2, 2], 0, 1), we found that 2>target_remain. + + helper([2, 2, 3], 1, 0) --> bingo + + helper([2, 3], 1, 2) + BREAK. When we are about to call helper([2, 6], 2, 2), we found that 6>target_remain. + + helper([3], 1, 4) + . + . + . + + helper([6], 2, 1) + . + . + . + + helper([7], 3, 0) --> bingo + +``` +""" +class Solution(object): + def combinationSum(self, candidates, target): + def helper(combination, start, target_remain): + if target_remain==0: + answer.append(combination) + for i in xrange(start, len(candidates)): + n = candidates[i] + if n>target_remain: break + helper(combination+[n], i, target_remain-n) + + candidates.sort() + answer = [] + helper([], 0, target) + return answer + + + +#Old Solution +class Solution(object): + def combinationSum(self, candidates, target): + def helper(candidates, target, combination): + if not candidates: return [] + n = candidates[0] + if n>target: + return [] + elif n==target: + return [combination+[n]] + else: + return helper(candidates, target-n, combination+[n]) + helper(candidates[1:], target, combination) + return helper(sorted(candidates), target, []) diff --git a/problems/first-unique-character-in-a-string.py b/problems/first-unique-character-in-a-string.py index b80c23c..39d72c0 100644 --- a/problems/first-unique-character-in-a-string.py +++ b/problems/first-unique-character-in-a-string.py @@ -1,10 +1,11 @@ -import collections +from collections import Counter class Solution(object): def firstUniqChar(self, string): - counter = collections.Counter() - for char in string: - counter[char]+=1 + # counter = Counter() + # for char in string: + # counter[char]+=1 + counter = Counter(string) for i in xrange(len(string)): char = string[i] From 5348ac3cbb92d9d5a1b24307c85a251dcf2353c6 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 22 Sep 2019 17:01:22 +0800 Subject: [PATCH 013/187] no message --- problems/combination-sum-ii.py | 38 +++++++++++++++++ problems/combination-sum.py | 7 ++-- problems/combinations.py | 73 +++++++++++++++++++++++++++++++++ problems/subsets-ii.py | 53 ++++++++++++++++++++++++ problems/subsets.py | 74 ++++++++++++++++++++++++++++++++++ 5 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 problems/combination-sum-ii.py create mode 100644 problems/combinations.py create mode 100644 problems/subsets-ii.py create mode 100644 problems/subsets.py diff --git a/problems/combination-sum-ii.py b/problems/combination-sum-ii.py new file mode 100644 index 0000000..a307029 --- /dev/null +++ b/problems/combination-sum-ii.py @@ -0,0 +1,38 @@ +""" +If you haven't see the [first problem](https://leetcode.com/problems/combination-sum/) and [explanation](https://leetcode.com/problems/combination-sum/discuss/386093/) already, I suggest you check it out first. + +This Problem is similar to the [first one](https://leetcode.com/problems/combination-sum/). +Except that we can only select each element in the `candidates` once. +In the first problem, we can choose the same element in the `candidates` for many times as we like. +In this problem, we can't. +So we need to +``` +helper(combination+[num], i+1, target_remain-num) +``` +Instead of +``` +helper(combination+[num], i, target_remain-num) +``` + +Another problem is duplicates. For example, +``` +candidates = [10,1,2,7,6,1,5] +target = 8 +``` +We might end up choosing the fist 1 or second 1 and make the same combination `[1, 2, 5]` +So I use a hash set to prevent duplicate. +""" +class Solution(object): + def combinationSum2(self, candidates, target): + def helper(combination, start, target_remain): + if target_remain==0: + answer.add(tuple(combination)) + for i in xrange(start, len(candidates)): + num = candidates[i] + if num>target_remain: break + helper(combination+[num], i+1, target_remain-num) + + answer = set() + candidates.sort() + helper([], 0, target) + return [list(combination) for combination in answer] diff --git a/problems/combination-sum.py b/problems/combination-sum.py index a134e65..0102ca3 100644 --- a/problems/combination-sum.py +++ b/problems/combination-sum.py @@ -42,7 +42,6 @@ . helper([7], 3, 0) --> bingo - ``` """ class Solution(object): @@ -51,9 +50,9 @@ def helper(combination, start, target_remain): if target_remain==0: answer.append(combination) for i in xrange(start, len(candidates)): - n = candidates[i] - if n>target_remain: break - helper(combination+[n], i, target_remain-n) + num = candidates[i] #try out if with num adding into combination can make target_remain 0 + if num>target_remain: break + helper(combination+[num], i, target_remain-num) candidates.sort() answer = [] diff --git a/problems/combinations.py b/problems/combinations.py new file mode 100644 index 0000000..6be147c --- /dev/null +++ b/problems/combinations.py @@ -0,0 +1,73 @@ +class Solution(object): + def combine(self, N, K): + def helper(first, combination): + if len(combination)==K: + answer.append(combination) + else: + for num in xrange(first, N+1): + helper(num+1, combination+[num]) + answer = [] + helper(1, []) + return answer +""" +`helper()` helps append `combination` to the `answer` if there are already K element in the `combination`. + +The parameter `first` means we are only going to use number fisrt~N. +Because we used the smaller number already, or we will have duplicates. + +If there are not enough element in the `combination`, it will run through fisrt~N and append all the element `num` to the `combination`, and set the `first` to num+1. +In other words, if we use 3, we will not use 3 and the number below 3 anymore. + +The call stack will be +``` +N = 4, K = 2. + +helper(1, []) + helper(2, [1]) + helper(3, [1, 2]) + helper(4, [1, 3]) + helper(5, [1, 4]) + + helper(3, [2]) + helper(4, [2, 3]) + helper(5, [2, 4]) + + helper(4, [3]) + helper(5, [3, 4]) + + helper(5, [4]) +``` +""" + +class Solution(object): + def combine(self, N, K): + answer = [] + combination = [] + first = 1 + while True: + if len(combination)==K: + answer.append(combination[:]) + + if len(combination)==K or first>N: + if not combination: return answer + first = combination.pop()+1 #backtrack + else: + combination.append(first) + first+=1 +""" +Iterative solution is not so easy to understand. +I suggest you run a easier example on paper, and you will know how it works. (`N = 4 , K = 2`) +For every iterative, we append the combination to the answer if the length is equal to K already. +Adjust the `first` whenever needed (`len(combination)==K or first>N`), if not, keep on appending. + +The time complexity is O(N!/(N!(N-K)!)), combination N choose K. +The space complexity is O(N!/(N!(N-K)!)), combination N choose K. +""" + + + + + + + + diff --git a/problems/subsets-ii.py b/problems/subsets-ii.py new file mode 100644 index 0000000..026f681 --- /dev/null +++ b/problems/subsets-ii.py @@ -0,0 +1,53 @@ +""" +If we use the solution from the [last question](https://leetcode.com/problems/subsets/), +We will notice that it will have some duplicates. +This is because if you have three 2 (`[2, 2, 2]`). +You might choosing two different sets of 2 and end up looking the same. +For example, you choose the first and the second => `[2, 2]` +You choose the second and the third => `[2, 2]` + +One workaround I did is just using hash-set. +``` +return list(set([tuple(combination) for combination in answer])) +``` +This cause us really high time complexity. +Since turning list to tuple and tuple to list is actually O(N) in theory. + +Time complexity would be `O((2^N) * N)` be cuase for each element in the answer we need to convert it to tuple and back. +""" +class Solution(object): + def subsetsWithDup(self, nums): + nums.sort() + answer = [[]] + for num in nums: + new_subs = [] + for sub in answer: + new_subs.append(sub+[num]) + answer.extend(new_subs) + return list(set([tuple(combination) for combination in answer])) + +""" +I found the best solution and explaination is made by @ZitaoWang's answer and here is his [explaination](https://leetcode.com/problems/subsets-ii/discuss/171626/Python-solution). I copied from it. +For example, `nums = [1,1,2,2,2,4,4,5]`. In this case, `counter = {1:2, 2:3, 4:2, 5:1}`. +We intialize `answer = [[]]` and build the solution iteratively as we loop over the counter. +We first reach `num, count = 1, 2`. The power set of [1,1] is `[[], [1], [1,1]]`. +Then we reach `num, count = 2, 3`. +The power set of [1,1,2,2,2] is obtained by appending either zero, one, two or three 2's to all elements in `answer`. +After which we get answer = [[], [1], [1,1], [2], [1,2], [1,1,2],[2,2], [1,2,2], [1,1,2,2],[2,2,2], [1,2,2,2], [1,1,2,2,2]]. +After we loop over counter, answer will be the power set of nums. + +Time complexity: `O(2^N)`, space complexity: `O(2^N)`. +""" +from collections import Counter + +class Solution(object): + def subsetsWithDup(self, nums): + counter = Counter(nums) + answer = [[]] + + for num, count in counter.items(): + power_set = [[num]*c for c in xrange(1, count+1)] + for i in xrange(len(answer)): + for s in power_set: + answer.append(answer[i]+s) + return answer diff --git a/problems/subsets.py b/problems/subsets.py new file mode 100644 index 0000000..6d8a328 --- /dev/null +++ b/problems/subsets.py @@ -0,0 +1,74 @@ +""" +For every number in `nums` you either take (O) or not take it (X). +So for example +``` +nums = [1,2,3] + +Subset [] is [X,X,X] +Subset [1] is [O,X,X] => [1,X,X] +Subset [2] is [X,O,X] => [X,2,X] +Subset [3] is [X,X,O] => [X,X,3] +Subset [1,2] is [O,O,X] => [1,2,X] +Subset [1,3] is [O,X,O] => [1,X,3] +. +. +. + +Subset [1,2,3] is [O,O,O] => [1,2,3] +``` +So there are total 2x2x2 posibilities (subsets). +Because for each number, it has two choices, take (O) or not take (X). +""" + + +class Solution(object): + def subsets(self, nums): + def helper(i, combination): + answer.add(tuple(combination)) + if i>=len(nums): return + helper(i+1, combination+[nums[i]]) + helper(i+1, combination) + + answer = set() + helper(0, []) + return [list(combination) for combination in answer] +""" +`helper()` help add `combination` to the answer. +And if we have run through all the numbers, return. +If not, for this number at index `i`, there are two scenarios. +Add it to the combination, or not. + +And there might be duplicates, and I could not think of better way without using hash set on `answer`. + +The time complexity is O(2^N). The space complexity is O(2^N), too. +""" + + +class Solution(object): + def subsets(self, nums): + answer = [[]] + for n in nums: + new_subs = [] + for sub in answer: + new_subs.append(sub+[n]) + answer.extend(new_subs) + return answer +""" +So for each n in `nums`, what we do is +``` +new_subs = [] +for sub in answer: + new_subs.append(sub+[n]) +answer.extend(new_subs) +``` +We take all the subset in the `answer`, append n, put the new subset into `new_subs`. +And the answer become `subsets` + `new subsets`. +You can think of it as +`subsets` => the combination which we did not take n. +`new subsets` => the combination which we take n. + +Now if we have iterated the third element, then the `answer` now contains all the possible subsets, the combination which we took the third element, and the combination which we did not take the third element. + +The time complexity is O(2^N). The space complexity is O(2^N), too. +(This solution is in spired by @ZitaoWang's elegant solution) +""" From 3735871fadc48f375eebb189bdb21b9aea97f8c1 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 22 Sep 2019 21:52:24 +0800 Subject: [PATCH 014/187] no message --- README.md | 2 +- problems/combination-sum-iii.py | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 problems/combination-sum-iii.py diff --git a/README.md b/README.md index 9b8406b..a6d2bad 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Leetcode Python Solution -1. This is my Python solution on Leetcode. The question is at `problems/the-file-name/`. For example, `merge-sorted-array.py`'s question is at `https://leetcode.com/problems/merge-sorted-array/`. +1. This is my Python (2.7) solution on Leetcode. The question is at `problems/the-file-name/`. For example, `merge-sorted-array.py`'s question is at `https://leetcode.com/problems/merge-sorted-array/`. 2. I really take time tried to make the best solution or explaination. Because I wanted to help others like me. diff --git a/problems/combination-sum-iii.py b/problems/combination-sum-iii.py new file mode 100644 index 0000000..0b35874 --- /dev/null +++ b/problems/combination-sum-iii.py @@ -0,0 +1,27 @@ +""" +If you haven't seen [this problem](https://leetcode.com/problems/combinations/), I suggest you do that first! +And here is the [explaination](https://leetcode.com/problems/combinations/discuss/387753) for that problem. + +This problem is basically the same as [that problem](https://leetcode.com/problems/combinations/) with its N=9. +The difference is we have to find the combination that sum up as N. +So all we have to do is change the condition of [0]. And the condition for backtracking [1]. +""" +class Solution(object): + def combinationSum3(self, K, N): + answer = [] + ans = [] + first = 1 + total = 0 + while True: + if len(ans)==K and total==N: #[0] + answer.append(ans[:]) + + if len(ans)==K or total>N or first>9: #[1] + if not ans: return answer + first = ans.pop() #backtrack + total-=first + first+=1 + else: + ans.append(first) + total+=first + first+=1 From e63def21492418b8dcc1378ba38702d68b7d7b84 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 24 Sep 2019 00:14:45 +0800 Subject: [PATCH 015/187] no message --- problems/combination-sum-ii.py | 18 ++++++++++++++ problems/combination-sum-iii.py | 13 ++++++++++ problems/combination-sum.py | 44 +++++++++++++++++++++++++++++++++ problems/combinations.py | 16 ++++++++++++ problems/subsets-ii.py | 18 ++++++++++++++ problems/subsets.py | 13 ++++++++++ 6 files changed, 122 insertions(+) diff --git a/problems/combination-sum-ii.py b/problems/combination-sum-ii.py index a307029..68f7f48 100644 --- a/problems/combination-sum-ii.py +++ b/problems/combination-sum-ii.py @@ -36,3 +36,21 @@ def helper(combination, start, target_remain): candidates.sort() helper([], 0, target) return [list(combination) for combination in answer] + +#DFS +class Solution(object): + def combinationSum2(self, candidates, T): + def dfs(index, target, path): + if target<0: + return + elif target==0: + opt.append(path) + else: + for i in xrange(index, len(candidates)): + if i>index and candidates[i]==candidates[i-1]: continue + num = candidates[i] + dfs(i+1, target-num, path+[num]) + opt = [] + candidates.sort() + dfs(0, T, []) + return opt diff --git a/problems/combination-sum-iii.py b/problems/combination-sum-iii.py index 0b35874..c5fa010 100644 --- a/problems/combination-sum-iii.py +++ b/problems/combination-sum-iii.py @@ -25,3 +25,16 @@ def combinationSum3(self, K, N): ans.append(first) total+=first first+=1 + +#DFS +class Solution(object): + def combinationSum3(self, K, N): + def dfs(path, min_num): + if len(path)==K and sum(path)==N: + opt.append(path) + for num in xrange(min_num, 10): + dfs(path+[num], num+1) + opt = [] + dfs([], 1) + return opt + diff --git a/problems/combination-sum.py b/problems/combination-sum.py index 0102ca3..423f3c1 100644 --- a/problems/combination-sum.py +++ b/problems/combination-sum.py @@ -74,3 +74,47 @@ def helper(candidates, target, combination): else: return helper(candidates, target-n, combination+[n]) + helper(candidates[1:], target, combination) return helper(sorted(candidates), target, []) + + +# 2019/9/12 Update +class Solution(object): + def combinationSum(self, candidates, T): + answer = [] + ans = [] + first = 0 + total = 0 + + candidates.sort() + + memo = {} + for i, num in enumerate(candidates): + memo[num] = i + + while True: + if total==T: + answer.append(ans[:]) + if total>=T or first>=len(candidates): + if not ans: return answer + num = ans.pop() + first = memo[num]+1 + total-=num + else: + ans.append(candidates[first]) + total+=candidates[first] + +# DFS +class Solution(object): + def combinationSum(self, candidates, T): + def dfs(index, target, path): + if target<0: + return + elif target==0: + opt.append(path) + else: + for i in xrange(index, len(candidates)): + num = candidates[i] + dfs(i, target-num, path+[num]) + opt = [] + candidates.sort() + dfs(0, T, []) + return opt diff --git a/problems/combinations.py b/problems/combinations.py index 6be147c..49f7ebf 100644 --- a/problems/combinations.py +++ b/problems/combinations.py @@ -66,6 +66,22 @@ def combine(self, N, K): +#DFS +class Solution(object): + def combine(self, N, K): + def dfs(n_min, path): + if len(path)==K: + opt.append(path) + return + else: + for n in xrange(n_min, N+1): + dfs(n+1, path+[n]) + opt = [] + dfs(1, []) + return opt + + + diff --git a/problems/subsets-ii.py b/problems/subsets-ii.py index 026f681..a423521 100644 --- a/problems/subsets-ii.py +++ b/problems/subsets-ii.py @@ -51,3 +51,21 @@ def subsetsWithDup(self, nums): for s in power_set: answer.append(answer[i]+s) return answer + + +#DFS +class Solution(object): + def subsetsWithDup(self, nums): + nums.sort() + + def dfs(path, nums): + opt.append(path) + if len(nums)==0: return + for i, num in enumerate(nums): + if i>0 and nums[i]==nums[i-1]: continue + dfs(path+[num], nums[i+1:]) + opt = [] + dfs([], nums) + return opt + + diff --git a/problems/subsets.py b/problems/subsets.py index 6d8a328..b718897 100644 --- a/problems/subsets.py +++ b/problems/subsets.py @@ -72,3 +72,16 @@ def subsets(self, nums): The time complexity is O(2^N). The space complexity is O(2^N), too. (This solution is in spired by @ZitaoWang's elegant solution) """ + +#DFS +class Solution(object): + def subsets(self, nums): + def dfs(path, nums): + opt.append(path) + if len(nums)==0: return + for i, num in enumerate(nums): + dfs(path+[num], nums[i+1:]) + + opt = [] + dfs([], nums) + return opt From 9ddb4dd2091e4adba6ab15ebfc90e393250be48f Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 29 Sep 2019 23:09:25 +0800 Subject: [PATCH 016/187] no message --- README.md | 4 +- problems/generate-parentheses.py | 22 ++++++++ problems/letter-case-permutation.py | 24 +++++++++ problems/permutations-ii.py | 26 ++++++++++ problems/permutations.py | 29 +++++++++++ problems/word-search.py | 78 +++++++++++++++++++++++++++++ 6 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 problems/generate-parentheses.py create mode 100644 problems/letter-case-permutation.py create mode 100644 problems/permutations-ii.py create mode 100644 problems/permutations.py create mode 100644 problems/word-search.py diff --git a/README.md b/README.md index a6d2bad..8160248 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ https://github.com/wuduhren/leetcode-python # Similar Problems -I found it make sense to do similar problems together, so that we can recognize the problem faster when we encounter a new one. +I found it make sense to do similar problems together, so that we can recognize the problem faster when we encounter a new one. My suggestion is to skip the HARD problems when you first go through these list. ### Two Pointers | Id | Name | Difficulty | Comments | @@ -36,7 +36,7 @@ I found it make sense to do similar problems together, so that we can recognize | 46 | [Permutations](https://leetcode.com/problems/permutations/ "Permutations") | ★★ | [47](https://leetcode.com/problems/permutations-ii/ "47") | [784](https://leetcode.com/problems/letter-case-permutation/ "784") | [943](https://leetcode.com/problems/find-the-shortest-superstring "943") | [996](https://leetcode.com/problems/number-of-squareful-arrays/ "996") | | | Permutation | | 22 | [Generate Parentheses](https://leetcode.com/problems/generate-parentheses/ "Generate Parentheses") | ★★★ | [301](https://leetcode.com/problems/remove-invalid-parentheses/ "301") | | | | | | DFS | | 37 | [Sudoku Solver](https://leetcode.com/problems/sudoku-solver "Sudoku Solver") | ★★★ | [51](https://leetcode.com/problems/n-queens "51") | [52](https://leetcode.com/problems/n-queens-ii "52") | | | | | DFS | -| 79 | [Word Search](https://leetcode.com/problems/word-search/ "Word Search") | ★★★ | [212](https://leetcode.com/problems/word-search-ii/submissions/ "212") | | | | | | DFS | +| 79 | [Word Search](https://leetcode.com/problems/word-search/ "Word Search") | ★★★ | [212](https://leetcode.com/problems/word-search-ii/ "212") | | | | | | DFS | | 127 | [Word Ladder](https://leetcode.com/problems/word-ladder/ "Word Ladder") | ★★★★ | [126](https://leetcode.com/problems/word-ladder-ii/ "126") | [752](https://leetcode.com/problems/open-the-lock/ "752") | | | | | BFS | | 542 | [01 Matrix](https://leetcode.com/problems/01-matrix/ "01 Matrix") | ★★★ | [675](https://leetcode.com/problems/cut-off-trees-for-golf-event/ "675") | [934](https://leetcode.com/problems/shortest-bridge/ "934") | | | | | BFS | | 698 | [Partition to K Equal Sum Subsets](https://leetcode.com/problems/partition-to-k-equal-sum-subsets "Partition to K Equal Sum Subsets") | ★★★ | [93](https://leetcode.com/problems/restore-ip-addresses/ "93") | [131](https://leetcode.com/problems/palindrome-partitioning/ "131") | [241](https://leetcode.com/problems/different-ways-to-add-parentheses/ "241") | [282](https://leetcode.com/problems/expression-add-operators/ "282") | [842](https://leetcode.com/problems/split-array-into-fibonacci-sequence/ "842") | | Partition | diff --git a/problems/generate-parentheses.py b/problems/generate-parentheses.py new file mode 100644 index 0000000..fb3ba3b --- /dev/null +++ b/problems/generate-parentheses.py @@ -0,0 +1,22 @@ +""" +If we need `N` pairs of parentheses, we need to use `N` open parenthesis (`open_remain`) and `N` close parenthesis (`close_remain`). +We use `dfs()` to explore all kinds of possiblities. +`open_count` keeps track of how many open parenthesis is in the `path` now. Because number of close parenthesis may not exceed open parenthesis in any given point. + +The time complexity is O(2^N), since we can roughly see every position has two options, open or close. +The space complexity is O(2^N), too. And the recuresion level is O(N). +""" +class Solution(object): + def generateParenthesis(self, N): + def dfs(path, open_count, open_remain, close_remain): + if open_remain==0 and close_remain==0: + opt.append(path) + return + if open_count>0 and close_remain>0: + dfs(path+')', open_count-1, open_remain, close_remain-1) + if open_remain>0: + dfs(path+'(', open_count+1, open_remain-1, close_remain) + + opt = [] + dfs('', 0, N, N) + return opt diff --git a/problems/letter-case-permutation.py b/problems/letter-case-permutation.py new file mode 100644 index 0000000..604bc14 --- /dev/null +++ b/problems/letter-case-permutation.py @@ -0,0 +1,24 @@ +""" +For each character in the `S` (if it is not a number), it has 2 possibilities, upper or lower. +So starting from an empty string +We explore all the possibilities for the character at index i is upper or lower. + +The time complexity is `O(2^N)`. +The space took `O(2^N), too. And the recursion level has N level. +""" +class Solution(object): + def letterCasePermutation(self, S): + def dfs(path, i): + if i>=len(S): + opt.append(path) + return + if S[i] not in num_char: + dfs(path+S[i].upper(), i+1) + dfs(path+S[i].lower(), i+1) + else: + dfs(path+S[i], i+1) + + num_char = set(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) + opt = [] + dfs('', 0) + return opt diff --git a/problems/permutations-ii.py b/problems/permutations-ii.py new file mode 100644 index 0000000..89ba9ee --- /dev/null +++ b/problems/permutations-ii.py @@ -0,0 +1,26 @@ +""" +This is the extended question of the [first one](https://leetcode.com/problems/permutations/submissions/). +The differece is there will be duplicates in the `nums`. + +```python +if i>0 and options[i]==options[i-1]: continue +``` +Above lets us skip exploring the same path. +We can directly skip the `i` if the value is the same with `i-1`, because `dfs()` on `i-1` has already cover up all the possiblities. + +The time complexity is `O(N!)`. +The space complexity is `O(N!)`, too. +""" +class Solution(object): + def permuteUnique(self, nums): + def dfs(path, options): + if len(path)==len(nums): + opt.append(path) + return + for i, n in enumerate(options): + if i>0 and options[i]==options[i-1]: continue + dfs(path+[n], options[:i]+options[i+1:]) + opt = [] + nums.sort() + dfs([], nums) + return opt diff --git a/problems/permutations.py b/problems/permutations.py new file mode 100644 index 0000000..6659d57 --- /dev/null +++ b/problems/permutations.py @@ -0,0 +1,29 @@ +""" +`nums = [1, 2, 3, 4, 5]` +The first time you choose you can either choose 1 or 2 or 3 or 4 or 5. Lets say you choose 2. So the path so far is `[2]`. +The second time you choose you can only choose 1 or 3 or 4 or 5. Lets say you choose 3. So the path so far is `[2, 3]`. +The third time you choose you can only choose 1 or 4 or 5. Lets say you choose 1. So the path so far is `[2, 3, 1]`. +The third time you choose you can only choose 4 or 5... +. +. +. + +We put the numbers we can choose in the `options` parameter. And the path so far in the `path` parameter. +In each `dfs()` we check if the path has used up all the numbers in the `nums`. If true. Append it in the output. +If not, we explore all the posible path in the `options` by `dfs()`. + +The time complexity is O(N!). Since in this example our choices is 5 at the beginning, then 4, then 3, then 2, then 1. +The space complexity is O(N!), too. And the recursion takes N level of recursion. +""" +class Solution(object): + def permute(self, nums): + def dfs(path, options): + if len(nums)==len(path): + opt.append(path) + return + for i, nums in enumerate(options): + dfs(path+[nums], options[:i]+options[i+1:]) + + opt = [] + dfs([], nums) + return opt diff --git a/problems/word-search.py b/problems/word-search.py new file mode 100644 index 0000000..b4544c4 --- /dev/null +++ b/problems/word-search.py @@ -0,0 +1,78 @@ +""" +Iterate through the board. +When we spot a starting point, we `dfs()` to see if it can finish the word. +To prevent travel to the visited node, we use a hash-set `set()` to keep track of what we have visited. +`l` is the index of the character in the `word` we are checking. +Note that we need to use `visited.copy()` to copy a whole new hash-set, or all the `dfs()` will use the same hash-set, which is not what we want. + +The time complexity is `O(N^2)`, `N` is the number of nodes. You can think of it as for each node, we have to decided to go ot not to go, and we need to make the decision `MN` times. +The space complexity is `O(W*N)`, `W` is the length of `word`. Because the recursion level is `W`, and for each recursion we need to keep track of `visited`, which potensially takes `O(N)`. +""" +class Solution(object): + def exist(self, board, word): + def getNeighbor(i, j): + opt = [] + if i+1=0: opt.append((i-1, j)) + if j-1>=0: opt.append((i, j-1)) + return opt + + def dfs(i, j, l, visited): + if l==len(word)-1: return True + visited.add((i, j)) + for ni, nj in getNeighbor(i, j): + if (ni, nj) not in visited and board[ni][nj]==word[l+1]: + if dfs(ni, nj, l+1, visited.copy()): return True + return False + + M = len(board) + N = len(board[0]) + + for i in xrange(M): + for j in xrange(N): + if board[i][j]==word[0]: + if dfs(i, j, 0, set()): return True + + return False + +""" +As you see, the above solution takes lots of space. +Another way is to change the character on the `board` to `#` to represent it as visited. +After the `dfs()` call we need to change it back. Because other branch of `dfs()` might not need visit this node, or haven't visit this node. + +The time complexity is `O(N^2)`, `N` is the number of nodes. +The space complexity is `O(W)`, `W` is the length of `word`. Because the recursion level is `W`. +This answer is inspired by @caikehe's [solution](https://leetcode.com/problems/word-search/discuss/27660/). +""" +class Solution(object): + def exist(self, board, word): + def getNeighbor(i, j): + opt = [] + if i+1=0: opt.append((i-1, j)) + if j-1>=0: opt.append((i, j-1)) + return opt + + def dfs(i, j, l): + if l==len(word)-1 and board[i][j]==word[l]: return True + if board[i][j]!=word[l]: return False + + char = board[i][j] + board[i][j] = '#' + + for ni, nj in getNeighbor(i, j): + if dfs(ni, nj, l+1): return True + + board[i][j] = char + return False + + M = len(board) + N = len(board[0]) + + for i in xrange(M): + for j in xrange(N): + if dfs(i, j, 0): return True + + return False From f1ddcfc60dac1a0823f010ee658687a0caccd3eb Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 30 Sep 2019 21:26:49 +0800 Subject: [PATCH 017/187] no message --- README.md | 2 +- problems/word-ladder.py | 97 ++++++++++++++++++++++++++++++++++++++ problems/word-search-ii.py | 50 ++++++++++++++++++++ 3 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 problems/word-ladder.py create mode 100644 problems/word-search-ii.py diff --git a/README.md b/README.md index 8160248..8cf4c7d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Leetcode Python Solution -1. This is my Python (2.7) solution on Leetcode. The question is at `problems/the-file-name/`. For example, `merge-sorted-array.py`'s question is at `https://leetcode.com/problems/merge-sorted-array/`. +1. This is my Python (2.7) Leetcode solution. The question is at `problems/the-file-name/`. For example, `merge-sorted-array.py`'s question is at `https://leetcode.com/problems/merge-sorted-array/`. 2. I really take time tried to make the best solution or explaination. Because I wanted to help others like me. diff --git a/problems/word-ladder.py b/problems/word-ladder.py new file mode 100644 index 0000000..bc2272d --- /dev/null +++ b/problems/word-ladder.py @@ -0,0 +1,97 @@ +""" +This problem is better using BFS. Because we need to find the shortest step. +Using DFS, we may eventually find the `endWord` but not the shortest path. + +First, build a memo so that we can find the related word without going through a~z every time we pop out a new word from queue. +So for example +``` +wordList = ["hot","dot","dog","lot","log","cog"] + +memo = { + 'lo#': ['lot', 'log'], + 'l#t': ['lot'], + '#ot': ['hot', 'dot', 'lot'], + 'h#t': ['hot'], + 'do#': ['dot', 'dog'], + 'l#g': ['log'], + 'co#': ['cog'], + '#og': ['dog', 'log', 'cog'], + 'd#g': ['dog'], + 'd#t': ['dot'], + 'c#g': ['cog'], + 'ho#': ['hot'] +} +``` + +Second build a queue to BFS from `beginWord` to `endWord`. +Everytime we pop a word we first check if it is visited. +Then check if it is `endWord`, if true, return the steps. +If not, put all the neighbor to the queue. + +If the queue ended and we did not find the `endWord`, return 0. + +The time complexity is O(W*C), W is the word count, C is the character count in each word. +The space complexity is also O(W*C). +""" +class Solution(object): + def ladderLength(self, beginWord, endWord, wordList): + memo = collections.defaultdict(list) + for word in wordList: + for i in xrange(len(word)): + memo[word[:i]+'#'+word[i+1:]].append(word) + + seen = set() + q = collections.deque([(beginWord, 1)]) + while q: + word, steps = q.popleft() + if word==endWord: return steps + seen.add(word) + + for i in xrange(len(word)): + for next_word in memo[word[:i]+'#'+word[i+1:]]: + if next_word not in seen: + q.append((next_word, steps+1)) + return 0 + +""" +When comparing to other solution, I made some changes. +Which is the timing of adding the word to the `visited` hash-set. +I think by adding the word to the hash-set in the for loop, makes the queue smaller, so it would be slightly faster. +But the time complexity is totally the same. +""" +class Solution(object): + def ladderLength(self, beginWord, endWord, wordList): + memo = collections.defaultdict(list) + for word in wordList: + for i in xrange(len(word)): + memo[word[:i]+'#'+word[i+1:]].append(word) + + seen = set() + q = collections.deque([(beginWord, 1)]) + while q: + word, steps = q.popleft() + if word==endWord: return steps + + for i in xrange(len(word)): + for next_word in memo[word[:i]+'#'+word[i+1:]]: + if next_word not in seen: + q.append((next_word, steps+1)) + seen.add(next_word) + return 0 + +class Solution(object): + def ladderLength(self, beginWord, endWord, wordList): + wordList = set(wordList) + seen = set() + q = collections.deque([(beginWord, 1)]) + while q: + word, steps = q.popleft() + if word==endWord: return steps + + for i in xrange(len(word)): + for alphabet in 'abcdefghijklmnopqrstuvwxyz': + next_word = word[:i]+alphabet+word[i+1:] + if next_word not in seen and next_word in wordList: + q.append((next_word, steps+1)) + seen.add(next_word) + return 0 diff --git a/problems/word-search-ii.py b/problems/word-search-ii.py new file mode 100644 index 0000000..e7d7b91 --- /dev/null +++ b/problems/word-search-ii.py @@ -0,0 +1,50 @@ +# TLE +class Solution(object): + def findWords(self, board, words): + def getNeighbor(i, j): + opt = [] + if i+1=0: opt.append((i-1, j)) + if j-1>=0: opt.append((i, j-1)) + return opt + + def dfs(i, j, l, word): + if word in found: return + if board[i][j]!=word[l]: return + + if l==len(word)-1 and board[i][j]==word[l]: + opt.append(word) + found.add(word) + return + + char = board[i][j] + board[i][j] = '#' + + for ni, nj in getNeighbor(i, j): + dfs(ni, nj, l+1, word) + + board[i][j] = char + + opt = [] + M = len(board) + N = len(board[0]) + found = set() + + for i in xrange(M): + for j in xrange(N): + for word in words: + if word not in found: + dfs(i, j, 0, word) + return opt + + +board = [ + ['o','a','a','n'], + ['e','t','a','e'], + ['i','h','k','r'], + ['i','f','l','v'] +] +words = ["oath","pea","eat","rain"] + +print Solution().findWords(board, words) From 69e895376fd3b440dbfe55b2a38eb9d3c47e717c Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 5 Oct 2019 14:59:17 +0800 Subject: [PATCH 018/187] no message --- problems/01-matrix.py | 79 +++++++++++++++++++++++++++++++++++++++++ problems/word-ladder.py | 6 ++-- 2 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 problems/01-matrix.py diff --git a/problems/01-matrix.py b/problems/01-matrix.py new file mode 100644 index 0000000..a9925b2 --- /dev/null +++ b/problems/01-matrix.py @@ -0,0 +1,79 @@ +""" +First, set the distance to 0 when `i` and `j` in the `matrix` is 0. [0] + +Second, when an `(i, j)` in the `opt` is 0, its neighbor's distance is 0+1, so +we set all the `i` and `j` in the `opt` where its distance is 1. +then set all the `i` and `j` in the `opt` where its distance is 2. +then set all the `i` and `j` in the `opt` where its distance is 3. +then set all the `i` and `j` in the `opt` where its distance is 4. +... + +the `count` is the number of distance that we found. +While we haven't find all the answer, we keep on doing above operation. [1] + +The time comlexity is `O(N^2)`, **N is the number of element in the 2D matrix**. +The space complexity is `O(N)`, where we store the `opt`. +""" +class Solution(object): + def updateMatrix(self, matrix): + def setDistance(i, j, dis): + if i<0 or i>=M: return False + if j<0 or j>=N: return False + if opt[i][j]!=-1: return False #opt[i][j]==-1 means the value is set already, skip. + opt[i][j] = dis + return True + + M, N = len(matrix), len(matrix[0]) + opt = [[-1]*N for _ in xrange(M)] + dis = 0 + count = 0 + + #[0] + for i in xrange(M): + for j in xrange(N): + if matrix[i][j]==0: + count+=1 + opt[i][j] = 0 + + while count=M: continue + if j<0 or j>=N: continue + if opt[i][j]!=-1: continue + opt[i][j] = dis + + for ni, nj in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]: + q.append((ni, nj, dis+1)) + + return opt + + + diff --git a/problems/word-ladder.py b/problems/word-ladder.py index bc2272d..e6dec9c 100644 --- a/problems/word-ladder.py +++ b/problems/word-ladder.py @@ -4,7 +4,7 @@ First, build a memo so that we can find the related word without going through a~z every time we pop out a new word from queue. So for example -``` +```python wordList = ["hot","dot","dog","lot","log","cog"] memo = { @@ -30,8 +30,8 @@ If the queue ended and we did not find the `endWord`, return 0. -The time complexity is O(W*C), W is the word count, C is the character count in each word. -The space complexity is also O(W*C). +The time complexity is `O(W*C)`, W is the word count, C is the character count in each word. +The space complexity is also `O(W*C)`. """ class Solution(object): def ladderLength(self, beginWord, endWord, wordList): From 6ac9019e5dedab21716cc043b549b3d44d44f785 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 5 Oct 2019 22:09:35 +0800 Subject: [PATCH 019/187] no message --- problems/3sum.py | 77 ++++++++++++++++++------------------- problems/shortest-bridge.py | 50 ++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 40 deletions(-) create mode 100644 problems/shortest-bridge.py diff --git a/problems/3sum.py b/problems/3sum.py index 229e64e..1f9dd52 100644 --- a/problems/3sum.py +++ b/problems/3sum.py @@ -1,43 +1,40 @@ -class Solution(object): - #this is the answer from caikehe and all the comments below - - """ - This is the answer from caikehe and all the comments below +""" +This is the answer from @caikehe and all the comments below - The main idea is to iterate every number in nums. - We use the number as a target to find two other numbers which make total zero. - For those two other numbers, we move pointers, l and r, to try them. +The main idea is to iterate every number in nums. +We use the number as a target to find two other numbers which make total zero. +For those two other numbers, we move pointers, `l` and `r`, to try them. - l start from left to right - r start from right to left +`l` start from left to right. +`r` start from right to left. - First, we sort the array, so we can easily move i around and know how to adjust l and r. - If the number is the same as the number before, we have used it as target already, continue. [1] - We always start the left pointer from i+1 because the combination of 0~i has already been tried. [2] +First, we sort the array, so we can easily move i around and know how to adjust l and r. +If the number is the same as the number before, we have used it as target already, continue. [1] +We always start the left pointer from `i+1` because the combination of 0~`i` has already been tried. [2] - Now we calculate the total: - If the total is less than zero, we need it to be larger, so we move the left pointer. [3] - If the total is greater than zero, we need it to be smaller, so we move the right pointer. [4] - If the total is zero, bingo! [5] - We need to move the left and right pointers to the next different numbers, so we do not get repeating result. [6] +Now we calculate the total: +If the total is less than zero, we need it to be larger, so we move the left pointer. [3] +If the total is greater than zero, we need it to be smaller, so we move the right pointer. [4] +If the total is zero, bingo! [5] +We need to move the left and right pointers to the next different numbers, so we do not get repeating result. [6] - We do not need to consider i after nums[i]>0, since sum of 3 positive will be always greater than zero. [7] - We do not need to try the last two, since there are no rooms for l and r pointers. - You can think of it as The last two have been tried by all others. [8] +We do not need to consider `i` after `nums[i]>0`, since sum of 3 positive will be always greater than zero. [7] +We do not need to try the last two, since there are no rooms for `l` and `r` pointers. +You can think of it as The last two have been tried by all others. [8] - For time complexity - Sorting takes O(NlogN) - Now, we need to think as if the 'nums' is really really big - We iterate through the 'nums' once, and each time we iterate the whole array again by a while loop - So it is O(NlogN+N^2)~=O(N^2) - - For space complexity - We didn't use extra space except the 'res' - Since we may store the whole 'nums' in it - So it is O(N) - N is the length of 'nums' - """ +For time complexity +Sorting takes `O(NlogN)` +Now, we need to think as if the `nums` is really really big +We iterate through the `nums` once, and each time we iterate the whole array again by a while loop +So it is `O(NlogN+N^2)~=O(N^2)` +For space complexity +We didn't use extra space except the `res` +Since we may store the whole 'nums' in it +So it is `O(N)` +`N` is the length of `nums` +""" +class Solution(object): def threeSum(self, nums): res = [] nums.sort() @@ -63,7 +60,7 @@ def threeSum(self, nums): l+=1 r-=1 return res - + """ def threeSum(self, nums): def twoSum(target, nums): @@ -77,12 +74,12 @@ def twoSum(target, nums): seen[n2]+=1 res.append([target*-1, n1, n2]) return res - + res = [] zero = 0 positive = collections.Counter() negative = collections.Counter() - + for n in nums: if n>0: positive[n]+=1 @@ -90,18 +87,18 @@ def twoSum(target, nums): zero+=1 else: negative[n]+=1 - + if zero>=3: res.append([0, 0, 0]) if zero>=1: for p in positive: if p*-1 in negative: res.append([0, p, p*-1]) - + for p in positive: res+=twoSum(p*-1, negative) for n in negative: res+=twoSum(n*-1, positive) - + return res - """ \ No newline at end of file + """ diff --git a/problems/shortest-bridge.py b/problems/shortest-bridge.py new file mode 100644 index 0000000..00ac1b6 --- /dev/null +++ b/problems/shortest-bridge.py @@ -0,0 +1,50 @@ +import collections +class Solution(object): + def shortestBridge(self, A): + def findFirst(): + for i in xrange(M): + for j in xrange(N): + if A[i][j]==1: return (i, j) + + M, N = len(A), len(A[0]) + opt = float('inf') + + q1 = collections.deque([findFirst()]) + while q1: + i, j = q1.popleft() + if i<0 or i>=M: continue + if j<0 or j>=N: continue + if A[i][j]==2 or A[i][j]==0: continue + if A[i][j]==1: A[i][j] = 2 + q1.extend([(i+1, j), (i-1, j), (i, j+1), (i, j-1)]) + + i0, j0 = findFirst() + q2 = collections.deque([(i0, j0, 0)]) + while q2: + i, j, dis = q2.popleft() + if A[i][j]==3 or A[i][j]==4: + continue + if A[i][j]==2: + opt = min(opt, dis) + continue + + if A[i][j]==1: A[i][j] = 3 + if A[i][j]==0: A[i][j] = 4 + for ni, nj in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]: + if ni<0 or ni>=M: continue + if nj<0 or nj>=N: continue + if A[ni][nj]==1: + q2.append((ni, nj, 0)) + elif A[ni][nj]==0: + q2.append((ni, nj, dis+1)) + elif A[ni][nj]==2: + q2.append((ni, nj, dis)) + + return opt + +A = [[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,0],[0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,0],[0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0],[0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0],[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0],[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0]] +print Solution().shortestBridge(A) + + + + From 4868d0f74deb0b395881eb066e9be9bdc17a6ad9 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 6 Oct 2019 00:51:25 +0800 Subject: [PATCH 020/187] no message --- problems/shortest-bridge.py | 86 +++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/problems/shortest-bridge.py b/problems/shortest-bridge.py index 00ac1b6..e77f487 100644 --- a/problems/shortest-bridge.py +++ b/problems/shortest-bridge.py @@ -1,50 +1,70 @@ -import collections +""" +First, identify one of the island by marking its value by 2 (island2). [0] + +Second ([1]), use BFS to go through another island (island1). When we encounter 0 we put it on `q2`, otherwise `q`. +When q is finished, it means that the island1 is completely explored (all `(i, j)` is in the `visied`). +Now we make put `q2` to the `q` and clear `q2`. [2] + +When q is finished, it means that all of the one-tile outward `(i, j)` is explored (in the `visited`). +Now we make put `q2` to the `q` and clear `q2`. + +When q is finished, it means that all of the two-tile outward `(i, j)` is explored (in the `visited`). +Now we make put `q2` to the `q` and clear `q2`. + +... + +We keep on doing this until we find the island2. [3] + +The time complexity is `O(N)`, `N` is the number of element in `A`. +The space complexity is `O(N)`, too. Since we might put most of the `(i, j)` in the `visited`. + +Of course, we can optimize the space, by changing the value in the `A`. +The code would be a little bit harder the read and understand. +I challenge you to try it out! +""" class Solution(object): def shortestBridge(self, A): - def findFirst(): + def findFirst(target): for i in xrange(M): for j in xrange(N): - if A[i][j]==1: return (i, j) + if A[i][j]==target: return (i, j) M, N = len(A), len(A[0]) - opt = float('inf') - q1 = collections.deque([findFirst()]) - while q1: - i, j = q1.popleft() + #[0] + q = collections.deque([findFirst(1)]) + while q: + i, j = q.popleft() if i<0 or i>=M: continue if j<0 or j>=N: continue if A[i][j]==2 or A[i][j]==0: continue if A[i][j]==1: A[i][j] = 2 - q1.extend([(i+1, j), (i-1, j), (i, j+1), (i, j-1)]) - - i0, j0 = findFirst() - q2 = collections.deque([(i0, j0, 0)]) - while q2: - i, j, dis = q2.popleft() - if A[i][j]==3 or A[i][j]==4: - continue - if A[i][j]==2: - opt = min(opt, dis) - continue - - if A[i][j]==1: A[i][j] = 3 - if A[i][j]==0: A[i][j] = 4 - for ni, nj in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]: - if ni<0 or ni>=M: continue - if nj<0 or nj>=N: continue - if A[ni][nj]==1: - q2.append((ni, nj, 0)) - elif A[ni][nj]==0: - q2.append((ni, nj, dis+1)) - elif A[ni][nj]==2: - q2.append((ni, nj, dis)) + q.extend([(i+1, j), (i-1, j), (i, j+1), (i, j-1)]) - return opt + #[1] + q.append(findFirst(1)) + q2 = [] + tile = 0 + visited = set() + while q or q2: + if not q: #[2] + q.extend(q2) + q2 = [] + tile+=1 -A = [[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,0],[0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,0],[0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0],[0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0],[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0],[0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0]] -print Solution().shortestBridge(A) + i, j = q.popleft() + if (i, j) in visited: continue + visited.add((i, j)) + if A[i][j]==2: return tile #[3] + for ni, nj in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]: + if ni<0 or ni>=M: continue + if nj<0 or nj>=N: continue + if A[ni][nj]==0: + q2.append((ni, nj)) + else: + q.append((ni, nj)) + return tile #should not comes here From a916ecef716dc59e108ab8267c20bd7e8fb392ac Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 20 Oct 2019 17:28:27 +0800 Subject: [PATCH 021/187] no message --- README.md | 78 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 8cf4c7d..489e702 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,49 @@ # Leetcode Python Solution 1. This is my Python (2.7) Leetcode solution. The question is at `problems/the-file-name/`. For example, `merge-sorted-array.py`'s question is at `https://leetcode.com/problems/merge-sorted-array/`. -2. I really take time tried to make the best solution or explaination. +2. I really take time tried to make the best solution or explanation. Because I wanted to help others like me. If you like my answer, a star on GitHub means a lot to me. -https://github.com/wuduhren/leetcode-python +https://github.com/wuduhren/leetcode-python + +``` +* Software Engineer Interview + * Overall Mindset + * Prepare in a Structural Way + * I Know Nothing About Data Structures and Algorithms +* Leetcode Similar Problems +* System Design +* Knowledge Base Question +* Others + * Resume + * Interview Question Survey +``` + +# Software Engineer Interview +## Overall Mindset +1. Having a right mindset is the most important one. It keeps you going when you are tired after work. Studying when everyone else are out having fun. Reminding you that your goals are not going to come easy, it takes time, self-discipline, mental and physical toughness... + +2. This is a speech from Sean Lee on "How to Get a Job at the Big 4". I highly recommend this because it gives me the right mindset on how to put in the work. + + +3. CS DoJo on "How I Got a Job at Google as a Software Engineer". There are also lots of technique on coding interview in his channel. + + +4. The #1 Daily Habit of Those Who Dominate with Andy Frisella (Also on Spotify or Youtube, just google it.) + + +## Prepare in a Structural Way +1. + +2. + +3. +## I Know Nothing About Data Structures and Algorithms +If you are new or know nothing about data structures and algorithms, I recommend [this course](). This course is taught in Python and design to help you find job and do well in the interview. -# Similar Problems + +# Leetcode Similar Problems I found it make sense to do similar problems together, so that we can recognize the problem faster when we encounter a new one. My suggestion is to skip the HARD problems when you first go through these list. ### Two Pointers @@ -155,42 +191,16 @@ This [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO3 -# Other Resources -These are the interview resources I personally used and only if it is really helpful I will put it here. - -## Overall Mindset -1. Haveing a right mindset is the most important one. It keeps you going when you are tired after work. Studying when everyone else are out having fun. Reminding you that your goals are not going to come easy, it takes time, self-discipline, mental and physical toughness... - -2. This is a speech from Sean Lee on "How to Get a Job at the Big 4". I highly recommend this because it gives me the right mindset on how to put in the work. - - -3. CS DoJo on "How I Got a Job at Google as a Software Engineer". There are also lots of technique on coding interview in his channel. - - -4. The #1 Daily Habit of Those Who Dominate with Andy Frisella (Also on Spotify or Youtube, just google it.) - - - -## Prepare in a Structural Way -1. - -2. +# Knowledge Base Question +1. [Session vs Cookie](https://medium.com/@chriswrite/session-vs-cookie-software-engineer-top-asked-question-1-9bdbc0766739) +2. [Token Authentication](https://medium.com/@chriswrite/token-authentication-software-engineer-top-asked-question-2-76dd2ed7c2d5) +Will continue to grow soon... -3. +# Others ## Resume -## Data Structure and Algorithm Basics -Basic data structure and algorithm online course taught in Python. This course is design to help you find job and do well in the interview. - - ## Interview Question Survey 1. 2. - - -# Interview Knowledge Base Quesion -1. [Session vs Cookie](https://medium.com/@chriswrite/session-vs-cookie-software-engineer-top-asked-question-1-9bdbc0766739) -2. [Token Authentication](https://medium.com/@chriswrite/token-authentication-software-engineer-top-asked-question-2-76dd2ed7c2d5) -... From 8815100d7afad75b5ccf7260009c7a9afd13c553 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 20 Oct 2019 17:36:44 +0800 Subject: [PATCH 022/187] no message --- README.md | 65 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 489e702..6ca146c 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,35 @@ -# Leetcode Python Solution -1. This is my Python (2.7) Leetcode solution. The question is at `problems/the-file-name/`. For example, `merge-sorted-array.py`'s question is at `https://leetcode.com/problems/merge-sorted-array/`. +# About +1. This is my Python (2.7) Leetcode solution. +As time grows, this also become a guide to prepare for software engineer interview. -2. I really take time tried to make the best solution or explanation. +2. I really take time tried to make the best solution and collect the best resource that I found. Because I wanted to help others like me. If you like my answer, a star on GitHub means a lot to me. https://github.com/wuduhren/leetcode-python +3. The solution is at `problems/the-file-name/`. +For example, `merge-sorted-array.py`'s solution is at `https://leetcode.com/problems/merge-sorted-array/`. + ``` +* Leetcode Similar Problems + * Software Engineer Interview * Overall Mindset * Prepare in a Structural Way * I Know Nothing About Data Structures and Algorithms -* Leetcode Similar Problems + * System Design + * Knowledge Base Question + * Others * Resume * Interview Question Survey ``` -# Software Engineer Interview -## Overall Mindset -1. Having a right mindset is the most important one. It keeps you going when you are tired after work. Studying when everyone else are out having fun. Reminding you that your goals are not going to come easy, it takes time, self-discipline, mental and physical toughness... - -2. This is a speech from Sean Lee on "How to Get a Job at the Big 4". I highly recommend this because it gives me the right mindset on how to put in the work. - - -3. CS DoJo on "How I Got a Job at Google as a Software Engineer". There are also lots of technique on coding interview in his channel. - - -4. The #1 Daily Habit of Those Who Dominate with Andy Frisella (Also on Spotify or Youtube, just google it.) - - -## Prepare in a Structural Way -1. - -2. - -3. - -## I Know Nothing About Data Structures and Algorithms -If you are new or know nothing about data structures and algorithms, I recommend [this course](). This course is taught in Python and design to help you find job and do well in the interview. - # Leetcode Similar Problems -I found it make sense to do similar problems together, so that we can recognize the problem faster when we encounter a new one. My suggestion is to skip the HARD problems when you first go through these list. +I found it makes sense to solve similar problems together, so that we can recognize the problem faster when we encounter a new one. My suggestion is to skip the HARD problems when you first go through these list. ### Two Pointers | Id | Name | Difficulty | Comments | @@ -177,6 +162,30 @@ I found it make sense to do similar problems together, so that we can recognize This [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO31DBjfeMoA0dlfIA/edit#gid=126913158) is made by **huahua**, I found this on his [youtube](https://www.youtube.com/user/xxfflower/videos). +# Software Engineer Interview +## Overall Mindset +1. Having a right mindset is the most important one. It keeps you going when you are tired after work. Studying when everyone else are out having fun. Reminding you that your goals are not going to come easy, it takes time, self-discipline, mental and physical toughness... + +2. This is a speech from Sean Lee on "How to Get a Job at the Big 4". I highly recommend this because it gives me the right mindset on how to put in the work. + + +3. CS DoJo on "How I Got a Job at Google as a Software Engineer". There are also lots of technique on coding interview in his channel. + + +4. The #1 Daily Habit of Those Who Dominate with Andy Frisella (Also on Spotify or Youtube, just google it.) + + +## Prepare in a Structural Way +1. + +2. + +3. + +## I Know Nothing About Data Structures and Algorithms +If you are new or know nothing about data structures and algorithms, I recommend [this course](). This course is taught in Python and design to help you find job and do well in the interview. + + # System Design 1. More resource From 5e538aac80f4ccca027c40881c61fb3777200a28 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 20 Oct 2019 17:39:35 +0800 Subject: [PATCH 023/187] no message --- README.md | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/README.md b/README.md index 6ca146c..c2ceb2c 100644 --- a/README.md +++ b/README.md @@ -10,23 +10,6 @@ https://github.com/wuduhren/leetcode-python 3. The solution is at `problems/the-file-name/`. For example, `merge-sorted-array.py`'s solution is at `https://leetcode.com/problems/merge-sorted-array/`. -``` -* Leetcode Similar Problems - -* Software Engineer Interview - * Overall Mindset - * Prepare in a Structural Way - * I Know Nothing About Data Structures and Algorithms - -* System Design - -* Knowledge Base Question - -* Others - * Resume - * Interview Question Survey -``` - # Leetcode Similar Problems I found it makes sense to solve similar problems together, so that we can recognize the problem faster when we encounter a new one. My suggestion is to skip the HARD problems when you first go through these list. From 50a4d485bb4e914724782ad4b994a1f00818ba48 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 20 Oct 2019 17:40:17 +0800 Subject: [PATCH 024/187] no message --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c2ceb2c..9132e9d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# About +# Overview 1. This is my Python (2.7) Leetcode solution. As time grows, this also become a guide to prepare for software engineer interview. From 0d91f0bbbb95facfa16408917808f4764a9c1717 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 20 Oct 2019 17:42:10 +0800 Subject: [PATCH 025/187] no message --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9132e9d..42ce953 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ If you are new or know nothing about data structures and algorithms, I recommend # Knowledge Base Question 1. [Session vs Cookie](https://medium.com/@chriswrite/session-vs-cookie-software-engineer-top-asked-question-1-9bdbc0766739) 2. [Token Authentication](https://medium.com/@chriswrite/token-authentication-software-engineer-top-asked-question-2-76dd2ed7c2d5) -Will continue to grow soon... +... # Others @@ -194,5 +194,5 @@ Will continue to grow soon... ## Interview Question Survey -1. -2. + + From 8fd6ac1d3abe4a7c939a31e710c72e5b4e495ab5 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 21 Oct 2019 16:48:17 +0800 Subject: [PATCH 026/187] no message --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 42ce953..77ed259 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,22 @@ If you are new or know nothing about data structures and algorithms, I recommend # Knowledge Base Question 1. [Session vs Cookie](https://medium.com/@chriswrite/session-vs-cookie-software-engineer-top-asked-question-1-9bdbc0766739) -2. [Token Authentication](https://medium.com/@chriswrite/token-authentication-software-engineer-top-asked-question-2-76dd2ed7c2d5) +2. [Token Authentication](https://medium.com/@chriswrite/token-authentication-software-engineer-top-asked-question-2-76dd2ed7c2d5) +3. [TCP/UDP](https://www.youtube.com/watch?v=Vdc8TCESIg8) + * Transport Layer + * Application Layer (HTTP, FTP) + * Transport Layer (UDP/TCP, Slice data to small packages) + * Network Layer (IP) + * Link Layer (Wifi) + * Physical Layer (Coaxial Ethernet Cable) + * UDP has smaller package size (8 bytes), while TCP needs 20 bytes due to it has larger header. + * UDP are not order guaranteed. TCP are in order. + * They both have error messages, but TCP will resent it again, UDP does not. + * TCP needs a three-way handshake to initiate a connection between ports. It’s like a phone call. While UDP is like a mail. + * In short, UDP is smaller and faster while TCP is reliable and ordered. + * UDP example, video streaming, DNS lookups. +4. [HTTPS, CA, PKI](https://www.youtube.com/watch?v=i-rtxrEz_E8) +5. HTTP, [Socket](https://www.youtube.com/watch?v=Y0g3M4VG6Ns), [WebSocket](https://www.youtube.com/watch?v=i5OVcTdt_OU), [HTTP KeepAlive](https://www.youtube.com/watch?v=j8lgFaIajko), HTTP2 ... From 63a19f11f81d5507ebf60870ae4687af7f4adea9 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 22 Oct 2019 16:50:45 +0800 Subject: [PATCH 027/187] no message --- README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 77ed259..9d0a724 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,24 @@ If you are new or know nothing about data structures and algorithms, I recommend * In short, UDP is smaller and faster while TCP is reliable and ordered. * UDP example, video streaming, DNS lookups. 4. [HTTPS, CA, PKI](https://www.youtube.com/watch?v=i-rtxrEz_E8) -5. HTTP, [Socket](https://www.youtube.com/watch?v=Y0g3M4VG6Ns), [WebSocket](https://www.youtube.com/watch?v=i5OVcTdt_OU), [HTTP KeepAlive](https://www.youtube.com/watch?v=j8lgFaIajko), HTTP2 +5. HTTP, HTTP Code, [Socket](https://www.youtube.com/watch?v=Y0g3M4VG6Ns), [WebSocket](https://www.youtube.com/watch?v=i5OVcTdt_OU), [HTTP KeepAlive](https://www.youtube.com/watch?v=j8lgFaIajko), HTTP2 +6. DNS, CNAME, NS, A, AAAA, IPv4, IPv6 +7. Code, Process, Thread +8. [Stack memory vs Heap memory](https://www.gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html) + Stack memory + 1. Stores temporary variable created by functions. + 2. Memory is managed by CPU for you. No need to allocate and free it by hand. + 3. L.I.F.O. + 4. Stacks has limit (That is why we seldom use recursion real life) + 5. Stacks variable are local variable in nature. + + Heap memory + 1. Larger. + 2. Slightly slower. Because we has to use "pointers" to access. + 3. We are responsible to free() the memory. + 4. Heap variable is global variable in nature. +9. GET vs POST +10. [CORS](https://www.youtube.com/watch?v=eWEgUcHPle0) ... From baa9a9eb6daf849ddce5f14ebd19cd11f0ae0a75 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 22 Oct 2019 16:51:53 +0800 Subject: [PATCH 028/187] no message --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d0a724..3f36436 100644 --- a/README.md +++ b/README.md @@ -204,14 +204,14 @@ If you are new or know nothing about data structures and algorithms, I recommend 6. DNS, CNAME, NS, A, AAAA, IPv4, IPv6 7. Code, Process, Thread 8. [Stack memory vs Heap memory](https://www.gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html) - Stack memory + * Stack memory 1. Stores temporary variable created by functions. 2. Memory is managed by CPU for you. No need to allocate and free it by hand. 3. L.I.F.O. 4. Stacks has limit (That is why we seldom use recursion real life) 5. Stacks variable are local variable in nature. - Heap memory + * Heap memory 1. Larger. 2. Slightly slower. Because we has to use "pointers" to access. 3. We are responsible to free() the memory. From 73c780ef072c6dd93be2505c1117fca8e8b0902f Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 22 Oct 2019 16:52:55 +0800 Subject: [PATCH 029/187] no message --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3f36436..ea7a87a 100644 --- a/README.md +++ b/README.md @@ -205,17 +205,17 @@ If you are new or know nothing about data structures and algorithms, I recommend 7. Code, Process, Thread 8. [Stack memory vs Heap memory](https://www.gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html) * Stack memory - 1. Stores temporary variable created by functions. - 2. Memory is managed by CPU for you. No need to allocate and free it by hand. - 3. L.I.F.O. - 4. Stacks has limit (That is why we seldom use recursion real life) - 5. Stacks variable are local variable in nature. + 1. Stores temporary variable created by functions. + 2. Memory is managed by CPU for you. No need to allocate and free it by hand. + 3. L.I.F.O. + 4. Stacks has limit (That is why we seldom use recursion real life) + 5. Stacks variable are local variable in nature. * Heap memory - 1. Larger. - 2. Slightly slower. Because we has to use "pointers" to access. - 3. We are responsible to free() the memory. - 4. Heap variable is global variable in nature. + 1. Larger. + 2. Slightly slower. Because we has to use "pointers" to access. + 3. We are responsible to free() the memory. + 4. Heap variable is global variable in nature. 9. GET vs POST 10. [CORS](https://www.youtube.com/watch?v=eWEgUcHPle0) ... From 19f4cbad929424dc1cb4022183626f709262d6c4 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 22 Oct 2019 16:56:02 +0800 Subject: [PATCH 030/187] no message --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ea7a87a..eb4efe9 100644 --- a/README.md +++ b/README.md @@ -205,17 +205,17 @@ If you are new or know nothing about data structures and algorithms, I recommend 7. Code, Process, Thread 8. [Stack memory vs Heap memory](https://www.gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html) * Stack memory - 1. Stores temporary variable created by functions. - 2. Memory is managed by CPU for you. No need to allocate and free it by hand. - 3. L.I.F.O. - 4. Stacks has limit (That is why we seldom use recursion real life) - 5. Stacks variable are local variable in nature. + * Stores temporary variable created by functions. + * Memory is managed by CPU for you. No need to allocate and free it by hand. + * L.I.F.O. + * Stacks has limit (That is why we seldom use recursion real life) + * Stacks variable are local variable in nature. * Heap memory - 1. Larger. - 2. Slightly slower. Because we has to use "pointers" to access. - 3. We are responsible to free() the memory. - 4. Heap variable is global variable in nature. + * Larger. + * Slightly slower. Because we has to use "pointers" to access. + * We are responsible to free() the memory. + * Heap variable is global variable in nature. 9. GET vs POST 10. [CORS](https://www.youtube.com/watch?v=eWEgUcHPle0) ... From 1da1169395fd05c20c8413c202f4b16c64145099 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Wed, 6 Nov 2019 22:38:56 +0800 Subject: [PATCH 031/187] no message --- README.md | 33 +++++++++---------- problems/different-ways-to-add-parentheses.py | 23 +++++++++++++ problems/palindrome-partitioning.py | 14 ++++++++ problems/partition-to-k-equal-sum-subsets.py | 18 ++++++++++ problems/restore-ip-addresses.py | 14 ++++++++ .../split-array-into-fibonacci-sequence.py | 28 ++++++++++++++++ 6 files changed, 112 insertions(+), 18 deletions(-) create mode 100644 problems/different-ways-to-add-parentheses.py create mode 100644 problems/palindrome-partitioning.py create mode 100644 problems/partition-to-k-equal-sum-subsets.py create mode 100644 problems/restore-ip-addresses.py create mode 100644 problems/split-array-into-fibonacci-sequence.py diff --git a/README.md b/README.md index eb4efe9..c5f0b6b 100644 --- a/README.md +++ b/README.md @@ -149,38 +149,31 @@ This [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO3 ## Overall Mindset 1. Having a right mindset is the most important one. It keeps you going when you are tired after work. Studying when everyone else are out having fun. Reminding you that your goals are not going to come easy, it takes time, self-discipline, mental and physical toughness... -2. This is a speech from Sean Lee on "How to Get a Job at the Big 4". I highly recommend this because it gives me the right mindset on how to put in the work. - +2. This is a speech from Sean Lee on [How to Get a Job at the Big 4](https://youtu.be/YJZCUhxNCv8). I highly recommend this because it gives me the right mindset on how to put in the work. -3. CS DoJo on "How I Got a Job at Google as a Software Engineer". There are also lots of technique on coding interview in his channel. - +3. CS DoJo on [How I Got a Job at Google as a Software Engineer](https://www.youtube.com/watch?v=UPO-9iMjBpc). There are also lots of technique on coding interview in his channel. -4. The #1 Daily Habit of Those Who Dominate with Andy Frisella (Also on Spotify or Youtube, just google it.) - +4. [The #1 Daily Habit of Those Who Dominate with Andy Frisella](https://podcasts.apple.com/tw/podcast/the-mfceo-project/id1012570406?i=1000412624447) (Also on Spotify or Youtube, just google it.) ## Prepare in a Structural Way -1. +1. [How should I prepare for my Google interview if I have 1 month left and I’m applying for a software engineer role?](https://www.quora.com/How-should-I-prepare-for-my-Google-interview-if-I-have-1-month-left-and-I%E2%80%99m-applying-for-a-software-engineer-role/answer/Anthony-D-Mays?ch=10&share=5c488000&srid=W0jqp) -2. +2. [How can I get a job at Facebook or Google in 6 months? I need a concise work-plan to build a good enough skill set. Should I join some other start-up or build my own projects/start-up? Should I just focus on practicing data structures and algorithms?](https://www.quora.com/How-can-I-get-a-job-at-Facebook-or-Google-in-6-months-I-need-a-concise-work-plan-to-build-a-good-enough-skill-set-Should-I-join-some-other-start-up-or-build-my-own-projects-start-up-Should-I-just-focus-on-practicing-data-structures-and-algorithms/answer/Jimmy-Saade) -3. +3. [What should I know from the CLRS 3rd edition book if my aim is to get into Google?](https://www.quora.com/What-should-I-know-from-the-CLRS-3rd-edition-book-if-my-aim-is-to-get-into-Google/answer/Jimmy-Saade) -## I Know Nothing About Data Structures and Algorithms +## Data Structures and Algorithms for beginners If you are new or know nothing about data structures and algorithms, I recommend [this course](). This course is taught in Python and design to help you find job and do well in the interview. # System Design -1. More resource - +1. [More resource](https://github.com/shashank88/system_design) -2. Architecture 101 - +2. [Architecture 101](https://engineering.videoblocks.com/web-architecture-101-a3224e126947) -3. How to scale up? There are also lots of tech interview related topic in his channel. - +3. [How to scale up?](https://www.youtube.com/watch?v=yPF94QiI2qk&t=385s) There are also lots of tech interview related topic in his channel. -4. Narendra talks about many system design. - +4. [Narendra's Youtube Channel](https://www.youtube.com/channel/UCn1XnDWhsLS5URXTi5wtFTA/playlists) # Knowledge Base Question @@ -228,3 +221,7 @@ If you are new or know nothing about data structures and algorithms, I recommend ## Interview Question Survey + +## Offer Negotiation + + diff --git a/problems/different-ways-to-add-parentheses.py b/problems/different-ways-to-add-parentheses.py new file mode 100644 index 0000000..d4ceaf9 --- /dev/null +++ b/problems/different-ways-to-add-parentheses.py @@ -0,0 +1,23 @@ +class Solution(object): + def diffWaysToCompute(self, S): + def calculate(operator, n1, n2): + if operator=="+": + return n1+n2 + elif operator=='-': + return n1-n2 + elif operator=='*': + return n1*n2 + else: + return None + + if S.isdigit(): return [int(S)] + + opt = [] + for i in xrange(len(S)): + if S[i]=='+' or S[i]=='-' or S[i]=='*': + left = self.diffWaysToCompute(S[:i]) + right = self.diffWaysToCompute(S[i+1:]) + for n1 in left: + for n2 in right: + opt.append(calculate(S[i], n1, n2)) + return opt diff --git a/problems/palindrome-partitioning.py b/problems/palindrome-partitioning.py new file mode 100644 index 0000000..cf4536b --- /dev/null +++ b/problems/palindrome-partitioning.py @@ -0,0 +1,14 @@ +class Solution(object): + def partition(self, S): + def isPalindrome(s): + return len(s)==1 or (len(s)>0 and s==s[::-1]) + def search(s, pal_list): + if len(s)==0: + opt.append(pal_list) + return + for i in xrange(1, len(s)+1): + if isPalindrome(s[:i]): + search(s[i:], pal_list+[s[:i]]) + opt = [] + search(S, []) + return opt diff --git a/problems/partition-to-k-equal-sum-subsets.py b/problems/partition-to-k-equal-sum-subsets.py new file mode 100644 index 0000000..5d98491 --- /dev/null +++ b/problems/partition-to-k-equal-sum-subsets.py @@ -0,0 +1,18 @@ +class Solution(object): + def canPartitionKSubsets(self, nums, k): + def search(subs): + if not nums: return True + n = nums.pop() + for i, sub in enumerate(subs): + if sub+n<=target: + subs[i]+=n + if search(subs): return True + subs[i]-=n + if not sub: break + nums.append(n) + return False + + if sum(nums)%k!=0: return False + target = sum(nums)/k + nums.sort() + return search([0]*k) diff --git a/problems/restore-ip-addresses.py b/problems/restore-ip-addresses.py new file mode 100644 index 0000000..906f96a --- /dev/null +++ b/problems/restore-ip-addresses.py @@ -0,0 +1,14 @@ +class Solution(object): + def restoreIpAddresses(self, s): + def search(digit, ip): + if len(ip)==4: + if len(digit)==0: opt.append(ip) + return + + for i in xrange(1, len(digit)+1): + num = int(digit[:i]) + if 0<=num and num<=255 and len(digit[:i])==len(str(num)): + search(digit[i:], ip+[digit[:i]]) + opt = [] + search(s, []) + return ['.'.join(ip) for ip in opt] diff --git a/problems/split-array-into-fibonacci-sequence.py b/problems/split-array-into-fibonacci-sequence.py new file mode 100644 index 0000000..4f691f7 --- /dev/null +++ b/problems/split-array-into-fibonacci-sequence.py @@ -0,0 +1,28 @@ +class Solution(object): + def splitIntoFibonacci(self, S): + def findIndex(s, num): + for i, c in enumerate(num): + if i>=len(s): break + if c!=s[i]: break + if i==len(num)-1: return i+1 + return -1 + + def search(fab, s): + if len(s)==0: return fab + if len(fab)<2: return [] + + target = fab[-1]+fab[-2] + if target>2147483648: return [] + i = findIndex(s, str(target)) + if i>0: return search(fab+[target], s[i:]) + return [] + + for i in xrange(1, len(S)-2): + for j in xrange(i+1, len(S)-1): + #skip leading zero + if (S[:i][0]!='0' and S[:i][0]=='0') or (S[i:j][0]!='0' and S[i:j][0]=='0'): continue + opt = search([int(S[:i]), int(S[i:j])], S[j:]) + if len(opt)>0: return opt + return [] + + From 4c7270e149e72a8e3212757b2a640eeb12702c97 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Wed, 6 Nov 2019 22:42:02 +0800 Subject: [PATCH 032/187] no message --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c5f0b6b..38fd0c0 100644 --- a/README.md +++ b/README.md @@ -149,11 +149,11 @@ This [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO3 ## Overall Mindset 1. Having a right mindset is the most important one. It keeps you going when you are tired after work. Studying when everyone else are out having fun. Reminding you that your goals are not going to come easy, it takes time, self-discipline, mental and physical toughness... -2. This is a speech from Sean Lee on [How to Get a Job at the Big 4](https://youtu.be/YJZCUhxNCv8). I highly recommend this because it gives me the right mindset on how to put in the work. +2. [How to Get a Job at the Big 4](https://youtu.be/YJZCUhxNCv8). -3. CS DoJo on [How I Got a Job at Google as a Software Engineer](https://www.youtube.com/watch?v=UPO-9iMjBpc). There are also lots of technique on coding interview in his channel. +3. [How I Got a Job at Google as a Software Engineer](https://www.youtube.com/watch?v=UPO-9iMjBpc). -4. [The #1 Daily Habit of Those Who Dominate with Andy Frisella](https://podcasts.apple.com/tw/podcast/the-mfceo-project/id1012570406?i=1000412624447) (Also on Spotify or Youtube, just google it.) +4. [The #1 Daily Habit of Those Who Dominate](https://podcasts.apple.com/tw/podcast/the-mfceo-project/id1012570406?i=1000412624447) with Andy Frisella. It is also avaliable on Spotify or Youtube, just google it. ## Prepare in a Structural Way 1. [How should I prepare for my Google interview if I have 1 month left and I’m applying for a software engineer role?](https://www.quora.com/How-should-I-prepare-for-my-Google-interview-if-I-have-1-month-left-and-I%E2%80%99m-applying-for-a-software-engineer-role/answer/Anthony-D-Mays?ch=10&share=5c488000&srid=W0jqp) From f1c7477168ee2a618e01523b629f8638d6bdeb62 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Wed, 6 Nov 2019 22:44:51 +0800 Subject: [PATCH 033/187] no message --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 38fd0c0..a0907a4 100644 --- a/README.md +++ b/README.md @@ -158,12 +158,12 @@ This [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO3 ## Prepare in a Structural Way 1. [How should I prepare for my Google interview if I have 1 month left and I’m applying for a software engineer role?](https://www.quora.com/How-should-I-prepare-for-my-Google-interview-if-I-have-1-month-left-and-I%E2%80%99m-applying-for-a-software-engineer-role/answer/Anthony-D-Mays?ch=10&share=5c488000&srid=W0jqp) -2. [How can I get a job at Facebook or Google in 6 months? I need a concise work-plan to build a good enough skill set. Should I join some other start-up or build my own projects/start-up? Should I just focus on practicing data structures and algorithms?](https://www.quora.com/How-can-I-get-a-job-at-Facebook-or-Google-in-6-months-I-need-a-concise-work-plan-to-build-a-good-enough-skill-set-Should-I-join-some-other-start-up-or-build-my-own-projects-start-up-Should-I-just-focus-on-practicing-data-structures-and-algorithms/answer/Jimmy-Saade) +2. [How can I get a job at Facebook or Google in 6 months?](https://www.quora.com/How-can-I-get-a-job-at-Facebook-or-Google-in-6-months-I-need-a-concise-work-plan-to-build-a-good-enough-skill-set-Should-I-join-some-other-start-up-or-build-my-own-projects-start-up-Should-I-just-focus-on-practicing-data-structures-and-algorithms/answer/Jimmy-Saade) 3. [What should I know from the CLRS 3rd edition book if my aim is to get into Google?](https://www.quora.com/What-should-I-know-from-the-CLRS-3rd-edition-book-if-my-aim-is-to-get-into-Google/answer/Jimmy-Saade) ## Data Structures and Algorithms for beginners -If you are new or know nothing about data structures and algorithms, I recommend [this course](). This course is taught in Python and design to help you find job and do well in the interview. +If you are new or know nothing about data structures and algorithms, I recommend [this course](). This course is taught in Python and design to help you find job and do well in the interview. # System Design From 7ab0909acde2fdac32d583253e005b8f10afb726 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 15 Nov 2019 07:17:56 +0800 Subject: [PATCH 034/187] no message --- problems/decode-string.py | 58 +++++++++++++++++++ .../split-array-into-fibonacci-sequence.py | 54 +++++++++-------- 2 files changed, 88 insertions(+), 24 deletions(-) create mode 100644 problems/decode-string.py diff --git a/problems/decode-string.py b/problems/decode-string.py new file mode 100644 index 0000000..965c2d0 --- /dev/null +++ b/problems/decode-string.py @@ -0,0 +1,58 @@ +#recursion +#the main idea is to only calculate the mosr outer layer. (which is when stack is empty.) +#we put all the inner layer to another `decodeString()` to get its value. +#time: O(N), N is the length of the string. +#space: O(N). +class Solution(object): + def decodeString(self, s): + opt = '' + k = '' + stack = [] + + for i, c in enumerate(s): + if c=='[': + stack.append(i) + elif c==']': + i_start = stack.pop() + if not stack: + opt += int(k)*self.decodeString(s[i_start+1:i]) + k = '' + elif c.isdigit() and not stack: + k+=c + elif not stack: + opt+=c + return opt or s + +#stack +#as we iterate the string, we will dive into different level of brackets. +#we store the value of the current level in the `opt` +#and store the outer level in the stack +#when we get out of this level, we calculate the value. +#time: O(N), N is the length of the string. +#space: O(N). +class Solution(object): + def decodeString(self, s): + opt = '' + stack = [] + k = '' + + for c in s: + if c=='[': + stack.append(opt) + stack.append(k) + opt = '' + k = '' + elif c==']': + n = stack.pop() + pre = stack.pop() + opt = pre+int(n)*opt + elif c.isdigit(): + k+=c + else: + opt+=c + return opt + + + + + diff --git a/problems/split-array-into-fibonacci-sequence.py b/problems/split-array-into-fibonacci-sequence.py index 4f691f7..700c47c 100644 --- a/problems/split-array-into-fibonacci-sequence.py +++ b/problems/split-array-into-fibonacci-sequence.py @@ -1,28 +1,34 @@ class Solution(object): def splitIntoFibonacci(self, S): - def findIndex(s, num): - for i, c in enumerate(num): - if i>=len(s): break - if c!=s[i]: break - if i==len(num)-1: return i+1 - return -1 - - def search(fab, s): - if len(s)==0: return fab - if len(fab)<2: return [] - - target = fab[-1]+fab[-2] - if target>2147483648: return [] - i = findIndex(s, str(target)) - if i>0: return search(fab+[target], s[i:]) - return [] - - for i in xrange(1, len(S)-2): - for j in xrange(i+1, len(S)-1): - #skip leading zero - if (S[:i][0]!='0' and S[:i][0]=='0') or (S[i:j][0]!='0' and S[i:j][0]=='0'): continue - opt = search([int(S[:i]), int(S[i:j])], S[j:]) - if len(opt)>0: return opt - return [] + def is_bibonacci(opt, num): + return num == opt[-1]+opt[-2] + + def helper(s, first): + if first==len(s) and len(opt)>=3: + return True + + for i in xrange(first, len(s)): + if s[first]=='0' and i!=first: break #skip leading zero + num = int(s[first:i+1]) + + if num>2147483648: break + + #early termination + if len(opt)>=2 and num>opt[-1]+opt[-2]: + break + + if len(opt)<=1 or is_bibonacci(opt, num): + opt.append(int(num)) + if helper(s, i+1): return True + opt.pop() + return False + + opt = [] + helper(S, 0) + return opt + + + + From 4431aab0da7a539536de87987131010e463b96ae Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 17 Nov 2019 11:58:31 +0800 Subject: [PATCH 035/187] no message --- problems/add-two-numbers.py | 59 +++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/problems/add-two-numbers.py b/problems/add-two-numbers.py index 648ddb0..d60714e 100644 --- a/problems/add-two-numbers.py +++ b/problems/add-two-numbers.py @@ -1,3 +1,44 @@ +""" +Add numbers, units to units digit, tens to tens digit... +If the added number is greater than 9 +We will add 1 to next digit (`temp`) and only take the units digit of the added value. + +For example, if we are adding units digits, 3 and 9, the sum is 12. +12 is greater than the 9, so we set `temp` to 1, so when we are calculating tens digits it will `+1`. +And we only take the units digit of 12, which is `12 - 10 = 2`. + +The time complexity is O(N), N is the length of two linked list. +Space complexity is O(N), since we need to store a new linked list. +""" +class Solution(object): + def addTwoNumbers(self, l1, l2): + temp = 0 + pre_head = ListNode(-1) + curr = pre_head + while l1 or l2 or temp: + val = (l1.val if l1 else 0) + (l2.val if l2 else 0) + temp + + if val>9: + temp = 1 + val = val-10 + else: + temp = 0 + + curr.next = ListNode(val) + + if l1: l1 = l1.next + if l2: l2 = l2.next + curr = curr.next + return pre_head.next + + + + + + + + + class Solution(object): #I like this better and it's faster @@ -14,18 +55,18 @@ def getTotal(l): x+=1 l = l.next return total - + total = getTotal(l1)+getTotal(l2) #put the number back into linked list num_string = str(total)[::-1] pre = ListNode(None) curr = pre - + for n in num_string: curr.next = ListNode(int(n)) curr = curr.next - + return pre.next @@ -45,27 +86,27 @@ def addTwoNumbers(self, l1, l2): while l1 or l2: total = carry - + if l1: total+=l1.val l1 = l1.next if l2: total+=l2.val l2 = l2.next - + if total>=10: carry=1 curr.next = ListNode(total%10) else: carry = 0 curr.next = ListNode(total) - + curr = curr.next - + #check if there is carry left behind, for example #[5]+[5]=[0,1] #both linked list are done iterate, but still haven't finish adding if carry!=0: curr.next = ListNode(carry) - - return pre.next \ No newline at end of file + + return pre.next From f83a22c299bb6bffc1d23f6b755654d546fa1440 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 17 Nov 2019 15:00:34 +0800 Subject: [PATCH 036/187] no message --- problems/add-two-numbers-ii.py | 62 ++++++++++++++++++++++++++++++++++ problems/add-two-numbers.py | 10 ++---- 2 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 problems/add-two-numbers-ii.py diff --git a/problems/add-two-numbers-ii.py b/problems/add-two-numbers-ii.py new file mode 100644 index 0000000..44879f4 --- /dev/null +++ b/problems/add-two-numbers-ii.py @@ -0,0 +1,62 @@ +""" +First, if you haven't done the [first problem](https://leetcode.com/problems/add-two-numbers/) please do it first. And here is its [answer](https://leetcode.com/problems/add-two-numbers/discuss/43105). +We can just reverse the linked list, and we can use the solution of the [first problem](https://leetcode.com/problems/add-two-numbers/). +So I do this problem without reversing the linked list. + +We need to know the length of each linked list. So we can know when do we start adding the `val`. +We need to set the answer to a double linked list. Because we might need to modify the upper digits. +For example 999 + 1. + +The time complexity is `O(N)`, `N` is the length of the input linked list. +The space complexity is `O(N)`, too. +""" +class ListNode(object): + def __init__(self, x): + self.val = x + self.next = None + self.prev = None + +class Solution(object): + def addTwoNumbers(self, A, B): + l1 = self.getLength(A) + l2 = self.getLength(B) + head = ListNode(0) + curr = head + while A or B: + if l1>l2: + self.addDigit(curr, A.val) + l1-=1 + A = A.next + elif l2>l1: + self.addDigit(curr, B.val) + l2-=1 + B = B.next + else: + val = (A.val if A else 0) + (B.val if B else 0) + self.addDigit(curr, val) + if l1: l1-=1 + if l2: l2-=1 + if A: A = A.next + if B: B = B.next + curr = curr.next + return head if head.val else head.next #remove leading zero + + def getLength(self, L): + length = 0 + while L: + length+=1 + L = L.next + return length + + def addDigit(self, node, val): + if val<10: + node.next = ListNode(val) + node.next.prev = node + else: + node.next = ListNode(val-10) + node.next.prev = node + node.val+=1 + while node.val>=10: + node.prev.val+=1 + node.val-=10 + node = node.prev diff --git a/problems/add-two-numbers.py b/problems/add-two-numbers.py index d60714e..dc2a931 100644 --- a/problems/add-two-numbers.py +++ b/problems/add-two-numbers.py @@ -1,3 +1,4 @@ +#2019/11/17 Update """ Add numbers, units to units digit, tens to tens digit... If the added number is greater than 9 @@ -18,7 +19,7 @@ def addTwoNumbers(self, l1, l2): while l1 or l2 or temp: val = (l1.val if l1 else 0) + (l2.val if l2 else 0) + temp - if val>9: + if val>=10: temp = 1 val = val-10 else: @@ -32,13 +33,6 @@ def addTwoNumbers(self, l1, l2): return pre_head.next - - - - - - - class Solution(object): #I like this better and it's faster From 6cc435b18ccf80062667d3253a2475c2a3b8482f Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 17 Nov 2019 18:18:18 +0800 Subject: [PATCH 037/187] no message --- problems/swap-nodes-in-pairs.py | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 problems/swap-nodes-in-pairs.py diff --git a/problems/swap-nodes-in-pairs.py b/problems/swap-nodes-in-pairs.py new file mode 100644 index 0000000..8eb4fd8 --- /dev/null +++ b/problems/swap-nodes-in-pairs.py @@ -0,0 +1,57 @@ +class Solution(object): + def swapPairs(self, head): + pre_head = ListNode(-1) + curr = head + prev = pre_head + + if not curr or not curr.next: return head + + while curr and curr.next: + temp_next = curr.next.next + + prev.next = curr.next + curr.next.next = curr + curr.next = temp_next + + prev = curr + curr = temp_next + + return pre_head.next + + +from collections import deque +class Solution(object): + def swapPairs(self, head): + curr = head + q1 = deque([]) + q2 = deque([]) + seq = 0 + while curr: + if seq%2==0: + q2.append(curr) + else: + q1.append(curr) + + temp = curr.next + curr.next = None #clear old link + curr = temp + seq+=1 + + if seq==1: + return head + + use_q1 = True + pre_head = ListNode(-1) + curr = pre_head + while q1 or q2: + if use_q1: + if not q1: break + curr.next = q1.popleft() + else: + curr.next = q2.popleft() + curr = curr.next + use_q1 = not use_q1 + + if q2: curr.next = q2.popleft() #odd length of linked list + + return pre_head.next From ae5228865698f02f82aaa2c7f97fc804c80056e2 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 26 Nov 2019 22:38:43 +0800 Subject: [PATCH 038/187] no message --- problems/reverse-linked-list.py | 61 ++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/problems/reverse-linked-list.py b/problems/reverse-linked-list.py index 47a1b19..46eedea 100644 --- a/problems/reverse-linked-list.py +++ b/problems/reverse-linked-list.py @@ -1,24 +1,45 @@ #https://leetcode.com/problems/reverse-linked-list/ -class Solution(object): - #iterative - def reverseList(self, head): - prev = None - current = head - while current: - temp = current.next - current.next = prev - prev = current - current = temp +# class Solution(object): +# #iterative +# def reverseList(self, head): +# prev = None +# current = head +# while current: +# temp = current.next +# current.next = prev +# prev = current +# current = temp + +# return prev - return prev +# #recursive +# def reverseList(self, head): +# if head is None or head.next is None: +# return head - #recursive - def reverseList(self, head): - if head is None or head.next is None: - return head +# new_head = self.reverseList(head.next) +# n = head.next +# n.next = head +# head.next = None +# return new_head - new_head = self.reverseList(head.next) - n = head.next - n.next = head - head.next = None - return new_head +#recursive +class Solution(object): + def reverseList(self, node): + if node and node.next: + new_head = self.reverseList(node.next) + node.next.next = node + node.next = None + return new_head + return node + +#iterative +class Solution(object): + def reverseList(self, node): + pre = None + while node: + next_node = node.next + node.next = pre + if not next_node: return node + pre = node + node = next_node From 54afc6afd6b41d10d42a6dd5c0288b1c99a3b929 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 26 Nov 2019 23:01:39 +0800 Subject: [PATCH 039/187] no message --- problems/linked-list-cycle.py | 38 +++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/problems/linked-list-cycle.py b/problems/linked-list-cycle.py index 3a3d09b..6cf5c3c 100644 --- a/problems/linked-list-cycle.py +++ b/problems/linked-list-cycle.py @@ -1,4 +1,7 @@ -#https://leetcode.com/problems/linked-list-cycle/ +#Two Pointers +#If the linked list has cycle, the fast pointer will eventually catch up. +#time: O(N). +#space: O(1). class Solution(object): def hasCycle(self, head): fast = head @@ -6,6 +9,33 @@ def hasCycle(self, head): while fast and fast.next: fast = fast.next.next slow = slow.next - if (fast==slow): - return True - return False \ No newline at end of file + if fast==slow: return True + return False + +#Flag +#Use a flag that stores on the nodes to know if we visited or not. +#time: O(N). +#space: O(N), for each node we use O(1) and there are N nodes. +class Solution(object): + def hasCycle(self, head): + curr = head + while curr: + if hasattr(curr, 'visited') and curr.visited: return True + curr.visited = True + curr = curr.next + return False + +#HashTable +#Use a hash-table to store the visited nodes +#time: O(N). +#space: O(N). +class Solution(object): + def hasCycle(self, head): + visited = {} + curr = head + while curr: + if curr in visited: return True + visited[curr] = None + curr = curr.next + return False + From 0831e257b0e94f09f32901625e49d315ec3fad2b Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 26 Nov 2019 23:19:13 +0800 Subject: [PATCH 040/187] no message --- problems/linked-list-cycle-ii.py | 18 ++++++++++++++++++ problems/linked-list-cycle.py | 10 +++++----- 2 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 problems/linked-list-cycle-ii.py diff --git a/problems/linked-list-cycle-ii.py b/problems/linked-list-cycle-ii.py new file mode 100644 index 0000000..a483d34 --- /dev/null +++ b/problems/linked-list-cycle-ii.py @@ -0,0 +1,18 @@ +class Solution(object): + def detectCycle(self, head): + curr = head + while curr: + if hasattr(curr, 'visited') and curr.visited: return curr + curr.visited = True + curr = curr.next + return None + +class Solution(object): + def detectCycle(self, head): + visited = set() + curr = head + while curr: + if curr in visited: return True + visited.add(curr) + curr = curr.next + return False \ No newline at end of file diff --git a/problems/linked-list-cycle.py b/problems/linked-list-cycle.py index 6cf5c3c..b210e48 100644 --- a/problems/linked-list-cycle.py +++ b/problems/linked-list-cycle.py @@ -9,7 +9,7 @@ def hasCycle(self, head): while fast and fast.next: fast = fast.next.next slow = slow.next - if fast==slow: return True + if fast is slow: return True return False #Flag @@ -25,17 +25,17 @@ def hasCycle(self, head): curr = curr.next return False -#HashTable -#Use a hash-table to store the visited nodes +#HashSet +#Use a hash-set to store the visited nodes #time: O(N). #space: O(N). class Solution(object): def hasCycle(self, head): - visited = {} + visited = set() curr = head while curr: if curr in visited: return True - visited[curr] = None + visited.add(curr) curr = curr.next return False From 9b00e00722919d1f18cfb360b538314326a39a38 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Wed, 27 Nov 2019 11:21:11 +0800 Subject: [PATCH 041/187] no message --- problems/linked-list-cycle-ii.py | 12 ++++++++++-- problems/merge-two-sorted-lists.py | 26 +++++++++----------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/problems/linked-list-cycle-ii.py b/problems/linked-list-cycle-ii.py index a483d34..6c859f1 100644 --- a/problems/linked-list-cycle-ii.py +++ b/problems/linked-list-cycle-ii.py @@ -1,3 +1,7 @@ +#Flag +#Use a flag that stores on the nodes to know if we visited or not. +#time: O(N). +#space: O(N), for each node we use O(1) and there are N nodes. class Solution(object): def detectCycle(self, head): curr = head @@ -7,12 +11,16 @@ def detectCycle(self, head): curr = curr.next return None +#HashSet +#Use a hash-set to store the visited nodes +#time: O(N). +#space: O(N). class Solution(object): def detectCycle(self, head): visited = set() curr = head while curr: - if curr in visited: return True + if curr in visited: return curr visited.add(curr) curr = curr.next - return False \ No newline at end of file + return None \ No newline at end of file diff --git a/problems/merge-two-sorted-lists.py b/problems/merge-two-sorted-lists.py index aed5042..a36ab4d 100644 --- a/problems/merge-two-sorted-lists.py +++ b/problems/merge-two-sorted-lists.py @@ -1,28 +1,20 @@ #https://leetcode.com/problems/merge-two-sorted-lists/ + class Solution(object): def mergeTwoLists(self, l1, l2): - if l1==None and l2==None: - return None - elif l1 and l2==None: - return l1 - elif l1==None and l2: - return l2 - - pre = ListNode - curr = pre + pre_head = ListNode(-1) + curr = pre_head while l1 and l2: - if l1.val<=l2.val: + if l1.val Date: Wed, 27 Nov 2019 12:29:15 +0800 Subject: [PATCH 042/187] insettion-sort-list --- problems/insertion-sort-list.py | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 problems/insertion-sort-list.py diff --git a/problems/insertion-sort-list.py b/problems/insertion-sort-list.py new file mode 100644 index 0000000..057ef1f --- /dev/null +++ b/problems/insertion-sort-list.py @@ -0,0 +1,41 @@ +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, x): + self.val = x + self.next = None + + +class Solution(object): + def insertionSortList(self, node): + """ + `pre_head` is a common technique that used in linked list problem. + So we don't need to handle the edge case all the time. + """ + pre_head = ListNode(float('-inf')) + pre_head.next = node + pre = pre_head + while node: + if node.val>=pre.val: #see if node need to shift, if true, no need to shift this node + pre = node + node = node.next + else: + next_node = node.next + self.remove(pre, node) + self.insert(pre_head, node) + node = next_node + return pre_head.next + + def remove(self, pre, node): + pre.next = node.next + + def insert(self, pre_head, node): + curr = pre_head.next + pre = pre_head + while curr: + if node.val Date: Mon, 16 Dec 2019 00:23:17 +0800 Subject: [PATCH 043/187] no message --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a0907a4..819bebe 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,7 @@ If you are new or know nothing about data structures and algorithms, I recommend 2. [Architecture 101](https://engineering.videoblocks.com/web-architecture-101-a3224e126947) -3. [How to scale up?](https://www.youtube.com/watch?v=yPF94QiI2qk&t=385s) There are also lots of tech interview related topic in his channel. +3. [Systems Design Interview Concepts](https://www.youtube.com/watch?v=REB_eGHK_P4). There are also lots of tech interview related topic in his channel. 4. [Narendra's Youtube Channel](https://www.youtube.com/channel/UCn1XnDWhsLS5URXTi5wtFTA/playlists) From 85c9fe8dbd8ef43037c1e6339cb4dd1595353603 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Wed, 1 Jan 2020 00:13:54 +0800 Subject: [PATCH 044/187] no message --- problems/design-linked-list.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 problems/design-linked-list.py diff --git a/problems/design-linked-list.py b/problems/design-linked-list.py new file mode 100644 index 0000000..998f14c --- /dev/null +++ b/problems/design-linked-list.py @@ -0,0 +1,25 @@ +class Node(object): + def __init__(self, val): + self.val = val + self.next = None + +class MyLinkedList(object): + def __init__(self): + self.l = [] + + def get(self, index): + if index<0 or index>=len(self.l): + return -1 + return self.l[index].val + + def addAtHead(self, val): + self.l = [Node(val)]+self.l + + def addAtTail(self, val): + self.l = self.l+[Node(val)] + + def addAtIndex(self, index, val): + self.l = self.l[:index]+[Node(val)]+self.l[index:] + + def deleteAtIndex(self, index): + self.l = self.l[:index]+self.l[index+1:] From 39d651a9efab80cf0e651d97de7ed7edc208f8ff Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 4 Jan 2020 17:45:01 +0800 Subject: [PATCH 045/187] no message --- problems/binary-tree-inorder-traversal.py | 18 ++++++++++++++++++ problems/design-linked-list.py | 12 ++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 problems/binary-tree-inorder-traversal.py diff --git a/problems/binary-tree-inorder-traversal.py b/problems/binary-tree-inorder-traversal.py new file mode 100644 index 0000000..a1e2247 --- /dev/null +++ b/problems/binary-tree-inorder-traversal.py @@ -0,0 +1,18 @@ +""" +In-order traversal means that: if there is a left node, visit it first; visit the current node; then if there is right node, visit it. +In-order: Left->Current->Right +Pre-order: Current->Left->Right +Post-order: Left->Right->Current +""" +class Solution(object): + def inorderTraversal(self, root): + def helper(node): + if not node: return + helper(node.left) + opt.append(node.val) + helper(node.right) + + opt = [] + helper(root) + return opt + \ No newline at end of file diff --git a/problems/design-linked-list.py b/problems/design-linked-list.py index 998f14c..866f312 100644 --- a/problems/design-linked-list.py +++ b/problems/design-linked-list.py @@ -5,21 +5,21 @@ def __init__(self, val): class MyLinkedList(object): def __init__(self): - self.l = [] + self.l = [] #trade space for speed - def get(self, index): + def get(self, index): #O(1) if index<0 or index>=len(self.l): return -1 return self.l[index].val - def addAtHead(self, val): + def addAtHead(self, val): #O(N), list extend takes O(N), . self.l = [Node(val)]+self.l - def addAtTail(self, val): + def addAtTail(self, val): #O(N) self.l = self.l+[Node(val)] - def addAtIndex(self, index, val): + def addAtIndex(self, index, val): #O(N) self.l = self.l[:index]+[Node(val)]+self.l[index:] - def deleteAtIndex(self, index): + def deleteAtIndex(self, index): #O(N) self.l = self.l[:index]+self.l[index+1:] From fa67f08732b737c20e79d251e1be69a3634aa6d6 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 4 Jan 2020 18:22:18 +0800 Subject: [PATCH 046/187] no message --- problems/n-ary-tree-preorder-traversal.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 problems/n-ary-tree-preorder-traversal.py diff --git a/problems/n-ary-tree-preorder-traversal.py b/problems/n-ary-tree-preorder-traversal.py new file mode 100644 index 0000000..2cd64d2 --- /dev/null +++ b/problems/n-ary-tree-preorder-traversal.py @@ -0,0 +1,16 @@ +""" +Pre-order traversal means that: visit the current node; if there is a left node, visit it; then if there is right node, visit it. +In-order: Left->Current->Right +Pre-order: Current->Left->Right +Post-order: Left->Right->Current +""" +class Solution(object): + def preorder(self, root): + def helper(node): + if not node: return + opt.append(node.val) + for child in node.children: + helper(child) + opt = [] + helper(root) + return opt \ No newline at end of file From 3ee6d5f03e65a150a14fb8cf750b6f4419b35aca Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 4 Jan 2020 18:28:34 +0800 Subject: [PATCH 047/187] no message --- problems/n-ary-tree-postorder-traversal.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 problems/n-ary-tree-postorder-traversal.py diff --git a/problems/n-ary-tree-postorder-traversal.py b/problems/n-ary-tree-postorder-traversal.py new file mode 100644 index 0000000..41d4757 --- /dev/null +++ b/problems/n-ary-tree-postorder-traversal.py @@ -0,0 +1,16 @@ +""" +Post-order traversal means that: if there is a left node, visit it; then if there is right node, visit it; visit the current node. +In-order: Left->Current->Right +Pre-order: Current->Left->Right +Post-order: Left->Right->Current +""" +class Solution(object): + def postorder(self, root): + def helper(node): + if not node: return + for child in node.children: + helper(child) + opt.append(node.val) + opt = [] + helper(root) + return opt \ No newline at end of file From edacbcc9b0558efd5e07f227a62b5f4ae6434ad3 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 6 Apr 2020 09:00:24 +0800 Subject: [PATCH 048/187] no message --- problems/same-tree.py | 23 +++++++++++++++++++++++ problems/symmetric-tree.py | 18 ++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 problems/same-tree.py create mode 100644 problems/symmetric-tree.py diff --git a/problems/same-tree.py b/problems/same-tree.py new file mode 100644 index 0000000..e17c40c --- /dev/null +++ b/problems/same-tree.py @@ -0,0 +1,23 @@ +from collections import deque + +class Solution(object): + def isSameTree(self, p, q): + q1 = deque([p]) + q2 = deque([q]) + while q1 or q2: + if not q1 or not q2: return False + n1 = q1.popleft() + n2 = q2.popleft() + + if n1 and n2: + if n1.val!=n2.val: return False + q1.append(n1.left) + q1.append(n1.right) + q2.append(n2.left) + q2.append(n2.right) + elif n1 and not n2: + return False + elif not n1 and n2: + return False + return True + diff --git a/problems/symmetric-tree.py b/problems/symmetric-tree.py new file mode 100644 index 0000000..11a0ae4 --- /dev/null +++ b/problems/symmetric-tree.py @@ -0,0 +1,18 @@ +from collections import deque + +class Solution(object): + def isSymmetric(self, root): + if not root: return True + + q = deque() + q.append((root.left, root.right)) + while q: + left_node, right_node = q.popleft() + if not left_node and right_node: return False + if not right_node and left_node: return False + + if left_node and right_node: + if left_node.val!=right_node.val: return False + q.append((left_node.right, right_node.left)) + q.append((left_node.left, right_node.right)) + return True \ No newline at end of file From ce8a3868316678dbc7f83c521dde1fc6c0b76128 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 6 Apr 2020 11:08:13 +0800 Subject: [PATCH 049/187] no message --- problems/symmetric-tree.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/problems/symmetric-tree.py b/problems/symmetric-tree.py index 11a0ae4..86330bb 100644 --- a/problems/symmetric-tree.py +++ b/problems/symmetric-tree.py @@ -15,4 +15,22 @@ def isSymmetric(self, root): if left_node.val!=right_node.val: return False q.append((left_node.right, right_node.left)) q.append((left_node.left, right_node.right)) - return True \ No newline at end of file + return True + + +# class Solution(object): +# def isSymmetric(self, root): +# if not root: return True + +# stack = [] +# stack.append((root.left, root.right)) +# while stack: +# left_node, right_node = stack.pop() +# if not left_node and right_node: return False +# if not right_node and left_node: return False + +# if left_node and right_node: +# if left_node.val!=right_node.val: return False +# stack.append((left_node.right, right_node.left)) +# stack.append((left_node.left, right_node.right)) +# return True \ No newline at end of file From d2624ef677874d43d6ae7bb679fdf3abc6aef913 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Thu, 9 Apr 2020 07:16:38 +0800 Subject: [PATCH 050/187] no message --- problems/balanced-binary-tree.py | 27 ++++++++++++++++++++++++ problems/maximum-depth-of-binary-tree.py | 21 ++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 problems/balanced-binary-tree.py create mode 100644 problems/maximum-depth-of-binary-tree.py diff --git a/problems/balanced-binary-tree.py b/problems/balanced-binary-tree.py new file mode 100644 index 0000000..3061e57 --- /dev/null +++ b/problems/balanced-binary-tree.py @@ -0,0 +1,27 @@ +""" +The tree is balanced if +1. Left child and right child are balanced +2. |left_max_depth - right_max_depth| must smaller or equal to 1 + +So the helper() will check condition 1. and 2. by `if l!=-1 and r!=-1 and abs(l-r)<=1` +if true, the node is balanced, return the depth +if not, the node is not balanced, return -1 +""" +class Solution(object): + def isBalanced(self, root): + + def helper(node, depth): + if not node.left and not node.right: return depth + + l = r = depth #l: left_max_depth, r: right_max_depth + if node.left: + l = helper(node.left, depth+1) + if node.right: + r = helper(node.right, depth+1) + + if l!=-1 and r!=-1 and abs(l-r)<=1: + return max(l, r) + return -1 + + if not root: return True + return helper(root, 0)!=-1 \ No newline at end of file diff --git a/problems/maximum-depth-of-binary-tree.py b/problems/maximum-depth-of-binary-tree.py new file mode 100644 index 0000000..020d153 --- /dev/null +++ b/problems/maximum-depth-of-binary-tree.py @@ -0,0 +1,21 @@ +""" +Time complexity: O(N), N is the number of nodes. Becasue we use DFS to traverse all the nodes. +Space complexity: O(N), N is the number of nodes. Becasue the stack may potentially store all the nodes. +""" +class Solution(object): + def maxDepth(self, root): + if not root: return 0 + + stack = [] + stack.append((root, 1)) + max_depth = 0 + + while stack: + node, depth = stack.pop() + max_depth = max(max_depth, depth) + if node.left: + stack.append((node.left, depth+1)) + if node.right: + stack.append((node.right, depth+1)) + return max_depth + \ No newline at end of file From 1c401fb996e7e675189819a936d33d3821699b99 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 10 Apr 2020 07:37:05 +0800 Subject: [PATCH 051/187] Update problem collection. --- README.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 819bebe..ae3fa11 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ I found it makes sense to solve similar problems together, so that we can recogn ### Recursion | Id | Name | Difficulty | | | | ---: | --- | :---: | :---: | --- | -| 726 | [Number of Atoms](https://leetcode.com/problems/number-of-atoms "Number of Atoms") | ★★★ | [736](https://leetcode.com/problems/parse-lisp-expression/ "736") | [394](https://zxi.mytechroad.com/blog/recursion/leetcode-394-decode-string/ "394") | +| 726 | [Number of Atoms](https://leetcode.com/problems/number-of-atoms "Number of Atoms") | ★★★ | [736](https://leetcode.com/problems/parse-lisp-expression/ "736") | [394](https://leetcode.com/problems/decode-string/ "394") | | 856 | [Score of Parentheses](https://leetcode.com/problems/score-of-parentheses/ "Score of Parentheses") | ★★★ | | | ### Divide and Conquer @@ -84,6 +84,7 @@ I found it makes sense to solve similar problems together, so that we can recogn | 33 | [Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array "Search in Rotated Sorted Array") | ★★★ | [81](https://leetcode.com/problems/search-in-rotated-sorted-array-ii/ "81") | [153](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/ "153") | [154](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii "154") | [162](https://leetcode.com/problems/find-peak-element "162") | [852](https://leetcode.com/problems/peak-index-in-a-mountain-array/ "852") | rotated / peak | | 69 | [Sqrt(x)](https://leetcode.com/problems/sqrtx "Sqrt(x)") | ★★★ | | | | | | upper_bound | | 74 | [Search a 2D Matrix](https://leetcode.com/problems/search-a-2d-matrix/ "Search a 2D Matrix") | ★★★ | | | | | | treat 2d as 1d | +| 875 | [Koko Eating Bananas](https://leetcode.com/problems/koko-eating-bananas/ "Koko Eating Bananas") | ★★★ | [1011](https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/ "1011") | | | | | guess ans and check | | 378 | [Kth Smallest Element in a Sorted Matrix](https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/ "Kth Smallest Element in a Sorted Matrix") | ★★★ | [668](https://leetcode.com/problems/kth-smallest-number-in-multiplication-table/ "668") | | | | | kth + matrix | | 778 | [Swim in Rising Water](https://leetcode.com/problems/swim-in-rising-water/ "Swim in Rising Water") | ★★★ | [174](https://leetcode.com/problems/dungeon-game/ "174") | [875](https://leetcode.com/problems/koko-eating-bananas/ "875") | | | | guess ans and check | | 4 | [Median of Two Sorted Arrays](https://leetcode.com/problems/median-of-two-sorted-arrays/ "Median of Two Sorted Arrays") | ★★★★ | | | | | | | @@ -114,6 +115,9 @@ I found it makes sense to solve similar problems together, so that we can recogn | 847 | [Shortest Path Visiting All Nodes](https://leetcode.com/problems/shortest-path-visiting-all-nodes/ "Shortest Path Visiting All Nodes") | ★★★★ | [815](https://leetcode.com/problems/bus-routes/ "815") | [864](https://leetcode.com/problems/shortest-path-to-get-all-keys/ "864") | [924](https://leetcode.com/problems/minimize-malware-spread/ "924") | | BFS | | 943 | [Find the Shortest Superstring](https://leetcode.com/problems/find-the-shortest-superstring/ "Find the Shortest Superstring") | ★★★★ | [980](https://leetcode.com/problems/unique-paths-iii/ "980") | [996](https://leetcode.com/problems/number-of-squareful-arrays/ "996") | | | Hamiltonian path (DFS / DP) | | 959 | [Regions Cut By Slashes](https://leetcode.com/problems/regions-cut-by-slashes/ "Regions Cut By Slashes") | ★★★★ | | | | | union find / grid + connected component | +| 332 | [Reconstruct Itinerary](https://leetcode.com/problems/reconstruct-itinerary/ "Reconstruct Itinerary") | ★★★★ | | | | | Eulerian path | +| 1192 | [Critical Connections in a Network](https://leetcode.com/problems/critical-connections-in-a-network/ "Critical Connections in a Network") | ★★★★ | | | | | Tarjan | + ### Dynamic Programming | Id | Name | Difficulty | | | | | | | Comments | @@ -134,15 +138,24 @@ I found it makes sense to solve similar problems together, so that we can recogn | 62 | [Unique Paths](https://leetcode.com/problems/unique-paths "Unique Paths") | ★★ | [63](https://leetcode.com/problems/unique-paths-ii "63") | [64](https://leetcode.com/problems/minimum-path-sum "64") | [120](https://leetcode.com/problems/triangle "120") | [174](https://leetcode.com/problems/dungeon-game "174") | [931](https://leetcode.com/problems/minimum-falling-path-sum/ "931") | | I: O(mn), S = O(mn), T = O(mn) | | 85 | [Maximal Rectangle](https://leetcode.com/problems/delete-operation-for-two-strings/ "Maximal Rectangle") | ★★★ | [221](https://leetcode.com/problems/maximal-square/ "221") | [304](https://leetcode.com/problems/range-sum-query-2d-immutable "304") | | | | | | | 688 | [Knight Probability in Chessboard](https://leetcode.com/problems/knight-probability-in-chessboard/ "Knight Probability in Chessboard") | ★★★ | [576](https://leetcode.com/problems/out-of-boundary-paths/ "576") | [935](https://leetcode.com/problems/knight-dialer/ "935") | | | | | I: O(mn) + k, S = O(kmn) T = O(kmn) | +| 322 | [Coin Change](https://leetcode.com/problems/reconstruct-itinerary/ "Coin Change") | ★★★ | [377](https://leetcode.com/problems/combination-sum-iv/ "377") | [416](https://leetcode.com/problems/partition-equal-subset-sum/ "416") | [494](https://leetcode.com/problems/target-sum/ "494") | [1043](https://leetcode.com/problems/partition-array-for-maximum-sum/ "1043") | [1049](https://leetcode.com/problems/last-stone-weight-ii/ "1049") | | I: O(n) + k, S = O(n), T = O(kn) | +| | | | [1220](https://leetcode.com/problems/count-vowels-permutation/ "1220") | [1230](https://leetcode.com/problems/toss-strange-coins/ "1230") | [1262](https://leetcode.com/problems/greatest-sum-divisible-by-three/ "1262") | [1269](https://leetcode.com/problems/number-of-ways-to-stay-in-the-same-place-after-some-steps/ "1269") | | | +| 813 | [Largest Sum of Averages](https://leetcode.com/problems/largest-sum-of-averages/ "Largest Sum of Averages") | ★★★★ | [1278](https://leetcode.com/problems/palindrome-partitioning-iii/ "1278") | [1335](https://leetcode.com/problems/minimum-difficulty-of-a-job-schedule/ "1335") | [410](https://leetcode.com/problems/split-array-largest-sum/ "410") | | | | I: O(n) + k
S = O(n*k), T = O(kn^2) | +| 1223 | [Dice Roll Simulation](https://leetcode.com/problems/dice-roll-simulation/ "Dice Roll Simulation") | ★★★★ | | | | | | | I: O(n) + k + p
S = O(k*p), T = O(n^2kp) | +| 312 | [Burst Balloons](https://leetcode.com/problems/burst-balloons/ "Burst Balloons") | ★★★★ | [664](https://leetcode.com/problems/strange-printer/ "664") | [1024](https://leetcode.com/problems/video-stitching/ "1024") | [1039](https://leetcode.com/problems/minimum-score-triangulation-of-polygon/ "1039") | [1140](https://leetcode.com/problems/stone-game-ii/ "1140") | [1130](https://leetcode.com/problems/minimum-cost-tree-from-leaf-values/ "1130") | | I: O(n), S = O(n^2), T = O(n^3) | +| 741 | [Cherry Pickup](https://leetcode.com/problems/cherry-pickup/ "Cherry Pickup") | ★★★★ | | | | | | | I: O(n^2), S = O(n^3), T = O(n^3) | +| 546 | [Remove Boxes](https://leetcode.com/problems/remove-boxes/ "Remove Boxes") | ★★★★★ | | | | | | | I: O(n), S = O(n^3), T = O(n^4) | +| 943 | [Find the Shortest Superstring](https://leetcode.com/problems/find-the-shortest-superstring/ "Find the Shortest Superstring") | ★★★★★ | [980](https://leetcode.com/problems/unique-paths-iii/ "980") | [996](https://leetcode.com/problems/number-of-squareful-arrays/ "996") | [1125](https://leetcode.com/problems/smallest-sufficient-team/ "1125") | | | | I: O(n)
S = O(n*2^n), T = (n^2*2^n) | ### Advanced | Id | Name | Difficulty | | | | | | Comments | | ---: | --- | :---: | :---: | --- | --- | --- | --- | --- | | 208 | [Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree "Implement Trie (Prefix Tree)") | ★★★ | [648](https://leetcode.com/problems/replace-words/ "648") | [676](https://leetcode.com/problems/implement-magic-dictionary "676") | [677](https://leetcode.com/problems/map-sum-pairs "677") | [720](https://leetcode.com/problems/longest-word-in-dictionary "720") | [745](https://leetcode.com/problems/prefix-and-suffix-search "745") | Trie | | 307 | [Range Sum Query - Mutable](https://leetcode.com/problems/range-sum-query-mutable "Range Sum Query - Mutable") | ★★★ | | | | | | BIT/Segment Tree | -| 901 | [Online Stock Span](https://leetcode.com/problems/online-stock-span "Online Stock Span") | ★★★ | [907](https://leetcode.com/problems/sum-of-subarray-minimums "907") | | | | 1019 | monotonic stack | +| 901 | [Online Stock Span](https://leetcode.com/problems/online-stock-span "Online Stock Span") | ★★★ | [907](https://leetcode.com/problems/sum-of-subarray-minimums "907") | [1019](https://leetcode.com/problems/next-greater-node-in-linked-list/ "1019") | | | | Monotonic Stack | +| 239 | [Sliding Window Maximum](https://leetcode.com/problems/sliding-window-maximum/ "Sliding Window Maximum") | ★★★ | | | | | | Monotonic Queue | -This [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO31DBjfeMoA0dlfIA/edit#gid=126913158) is made by **huahua**, I found this on his [youtube](https://www.youtube.com/user/xxfflower/videos). +This [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO31DBjfeMoA0dlfIA/edit#gid=126913158) is made by **huahua**, I found this on his [youtube](https://www.youtube.com/user/xxfflower/videos). Please visit his [website](https://zxi.mytechroad.com/blog/leetcode-problem-categories/) for more. # Software Engineer Interview From 3f898b45bffd767cd1c68b724a46321cf41591a6 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 12 Apr 2020 20:57:48 +0800 Subject: [PATCH 052/187] no message --- problems/minimum-depth-of-binary-tree.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 problems/minimum-depth-of-binary-tree.py diff --git a/problems/minimum-depth-of-binary-tree.py b/problems/minimum-depth-of-binary-tree.py new file mode 100644 index 0000000..b919ab1 --- /dev/null +++ b/problems/minimum-depth-of-binary-tree.py @@ -0,0 +1,21 @@ +""" +We use BFS, so as soon as we touch a leaf; we can return it. +Because BFS traverse the tree level by level. We can be sure that the first leaf we touch is the nearest leaf. +Note that, a leaf is a node with no children. +""" +from collections import deque + +class Solution(object): + def minDepth(self, root): + if not root: return 0 + q = deque() + q.append((root, 1)) + + while q: + node, depth = q.popleft() + if not node.left and not node.right: + return depth + if node.left: + q.append((node.left, depth+1)) + if node.right: + q.append((node.right, depth+1)) \ No newline at end of file From 6c8d6cb6fc5ba10391702031308be64608049650 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 13 Apr 2020 07:06:07 +0800 Subject: [PATCH 053/187] no message --- problems/subtree-of-another-tree.py | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 problems/subtree-of-another-tree.py diff --git a/problems/subtree-of-another-tree.py b/problems/subtree-of-another-tree.py new file mode 100644 index 0000000..0883c99 --- /dev/null +++ b/problems/subtree-of-another-tree.py @@ -0,0 +1,44 @@ +""" +We use DFS to traverse `s`. (Or you can use BFS) +If we encounter a node and `node.val==t.val`. +We check if the node and t are the same tree, using `isSameTree()`. + +In `isSameTree()` we use BFS to traverse both tree to check if they are exactly the same. +We use BFS because. If some nodes are not the same, we can return early at higher level. +Do need to go deep. Imagine the node that is not the same is at the bottom of the tree... + +Time complexity is O(M*N). M is the number of nodes in s. N is the number of nodes in t. +Traversing s takes O(M). +`isSameTree()` takes O(N) to check all nodes in t. +In the worst case, we might need to execute `isSameTree()` on every node in s. + +Space complexity is O(M+N), since we might store all the nodes in memory. +""" +from collections import deque + +class Solution(object): + def isSubtree(self, s, t): + def isSameTree(root1, root2): + q1 = deque([root1]) + q2 = deque([root2]) + while q1 and q2: + n1 = q1.popleft() + n2 = q2.popleft() + if n1.val!=n2.val: return False + if n1.left: q1.append(n1.left) + if n1.right: q1.append(n1.right) + if n2.left: q2.append(n2.left) + if n2.right: q2.append(n2.right) + + #check if both queue are empty. + #if both queue are empty, all nodes are checked. + return not q1 and not q2 + + stack = [] + stack.append(s) + while stack: + node = stack.pop() + if node.val==t.val and isSameTree(node, t): return True + if node.left: stack.append(node.left) + if node.right: stack.append(node.right) + return False \ No newline at end of file From b214d55112cd56aff8904df32757a698ff94bac4 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 14 Apr 2020 07:26:46 +0800 Subject: [PATCH 054/187] no message --- .../binary-tree-level-order-traversal-ii.py | 20 +++++++++++++ problems/binary-tree-level-order-traversal.py | 25 +++++++++++++++++ problems/n-ary-tree-level-order-traversal.py | 26 +++++++++++++++++ problems/univalued-binary-tree.py | 11 ++++++++ ...rtical-order-traversal-of-a-binary-tree.py | 28 +++++++++++++++++++ 5 files changed, 110 insertions(+) create mode 100644 problems/binary-tree-level-order-traversal-ii.py create mode 100644 problems/binary-tree-level-order-traversal.py create mode 100644 problems/n-ary-tree-level-order-traversal.py create mode 100644 problems/univalued-binary-tree.py create mode 100644 problems/vertical-order-traversal-of-a-binary-tree.py diff --git a/problems/binary-tree-level-order-traversal-ii.py b/problems/binary-tree-level-order-traversal-ii.py new file mode 100644 index 0000000..db49ccd --- /dev/null +++ b/problems/binary-tree-level-order-traversal-ii.py @@ -0,0 +1,20 @@ +from collections import deque + +class Solution(object): + def levelOrderBottom(self, root): + opt = [] + + if not root: return opt + + q = deque() + q.append((root, 0)) + + while q: + node, depth = q.popleft() + if depth Date: Wed, 15 Apr 2020 07:03:29 +0800 Subject: [PATCH 055/187] no message --- problems/binary-tree-pruning.py | 27 +++++++++++++++++++ ...rtical-order-traversal-of-a-binary-tree.py | 12 ++++----- 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 problems/binary-tree-pruning.py diff --git a/problems/binary-tree-pruning.py b/problems/binary-tree-pruning.py new file mode 100644 index 0000000..f013c29 --- /dev/null +++ b/problems/binary-tree-pruning.py @@ -0,0 +1,27 @@ +class Solution(object): + def pruneTree(self, root): + def hasOne(node): + if not node: return False + + left_has_one = hasOne(node.left) + right_has_one = hasOne(node.right) + + if not left_has_one: node.left = None + if not right_has_one: node.right = None + + return node.val==1 or left_has_one or right_has_one + + return root if hasOne(root) else None + +class Solution(object): + def pruneTree(self, node): + if not node: return None + node.left = self.pruneTree(node.left) + node.right = self.pruneTree(node.right) + if not node.left and not node.right and node.val==0: return None + return node + +""" +Time complexity is O(N). Because we traverse all the nodes. +Space complexity is O(LogN). The tree's height is about O(LogN), so we have O(LogN) level of recursion and used up O(LogN) of stack memory +""" \ No newline at end of file diff --git a/problems/vertical-order-traversal-of-a-binary-tree.py b/problems/vertical-order-traversal-of-a-binary-tree.py index b56a223..9cc1849 100644 --- a/problems/vertical-order-traversal-of-a-binary-tree.py +++ b/problems/vertical-order-traversal-of-a-binary-tree.py @@ -1,28 +1,28 @@ """ The description wants us to report from left to right, top to bottom. Thus, we keep add value into `temp` with `x_position` as the key and `(y_position, node.val)` as the value. -And maintain `min_index`, `max_index` at the same time. So we know how to iterate the `temp`. +And maintain `min_x`, `max_x` at the same time. So we know how to iterate the `temp`. """ from collections import defaultdict class Solution(object): def verticalTraversal(self, root): temp = defaultdict(list) - min_index = 0 - max_index = 0 + min_x = 0 + max_x = 0 stack = [] stack.append((root, 0, 0)) while stack: node, x, y = stack.pop() temp[x].append((y, node.val)) #append the value of height, so we can sort by height later on - min_index = min(min_index, x) - max_index = max(max_index, x) + min_x = min(min_x, x) + max_x = max(max_x, x) if node.left: stack.append((node.left, x-1, y+1)) if node.right: stack.append((node.right, x+1, y+1)) opt = [] - for i in range(min_index, max_index+1): + for i in range(min_x, max_x+1): opt.append([v for y, v in sorted(temp[i])]) #the temp[i] will be sorted by y_position then sorted by node.val return opt \ No newline at end of file From f2f8f2aa3c69159ea8edf93de0ce8b064abda9fe Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Wed, 15 Apr 2020 12:12:14 +0800 Subject: [PATCH 056/187] no message --- .gitignore | 3 ++- problems/binary-tree-pruning.py | 2 +- problems/path-sum-ii.py | 20 ++++++++++++++++++++ problems/path-sum.py | 14 ++++++++++++++ problems/trim-a-binary-search-tree.py | 17 +++++++++++++++++ 5 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 problems/path-sum-ii.py create mode 100644 problems/path-sum.py create mode 100644 problems/trim-a-binary-search-tree.py diff --git a/.gitignore b/.gitignore index 9c44842..3c8f0bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -_doc/* \ No newline at end of file +_doc/* +.vscode \ No newline at end of file diff --git a/problems/binary-tree-pruning.py b/problems/binary-tree-pruning.py index f013c29..242e0d9 100644 --- a/problems/binary-tree-pruning.py +++ b/problems/binary-tree-pruning.py @@ -23,5 +23,5 @@ def pruneTree(self, node): """ Time complexity is O(N). Because we traverse all the nodes. -Space complexity is O(LogN). The tree's height is about O(LogN), so we have O(LogN) level of recursion and used up O(LogN) of stack memory +Space complexity is O(N). In the worst case, the recursion will go O(N) level deep. """ \ No newline at end of file diff --git a/problems/path-sum-ii.py b/problems/path-sum-ii.py new file mode 100644 index 0000000..a900baa --- /dev/null +++ b/problems/path-sum-ii.py @@ -0,0 +1,20 @@ +class Solution(object): + def pathSum(self, root, S): + if not root: return False + + opt = [] + stack = [] + stack.append((root, 0, [])) + + while stack: + node, s, path = stack.pop() + s += node.val + path = path + [node.val] + if not node.left and not node.right and s==S: opt.append(path) + if node.left: stack.append((node.left, s, path)) + if node.right: stack.append((node.right, s, path)) + return opt +""" +Time complexity is O(N), because we traverse all the nodes. +Space complexity is O(N^2), because in the worst case, all node could carry all the other nodes in the `path`. +""" \ No newline at end of file diff --git a/problems/path-sum.py b/problems/path-sum.py new file mode 100644 index 0000000..cd2ae5a --- /dev/null +++ b/problems/path-sum.py @@ -0,0 +1,14 @@ +class Solution(object): + def hasPathSum(self, root, S): + if not root: return False + + stack = [] + stack.append((root, 0)) + + while stack: + node, s = stack.pop() + s += node.val + if not node.left and not node.right and s==S: return True + if node.left: stack.append((node.left, s)) + if node.right: stack.append((node.right, s)) + return False \ No newline at end of file diff --git a/problems/trim-a-binary-search-tree.py b/problems/trim-a-binary-search-tree.py new file mode 100644 index 0000000..d524885 --- /dev/null +++ b/problems/trim-a-binary-search-tree.py @@ -0,0 +1,17 @@ +class Solution(object): + def trimBST(self, root, L, R): + if not root: return root + root.left = self.trimBST(root.left, L, R) + root.right = self.trimBST(root.right, L, R) + return root if L<=root.val and root.val<=R else root.left or root.right + +""" +First, trim left child and right child. +Second, if the root is in range, return the root. +if not, return the trimed left child. +if not trimed left child, return the trimed right child. +if both left and right child is None, it will return None anyway. + +Time complexity is O(N). For we simply just traverse all the nodes. +Space complexity is O(N). In the worst case, the recursion will go O(N) level deep. +""" \ No newline at end of file From 50b11c2bc5d7ee4cb9c3b8db95affc639cc4b7c7 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 17 Apr 2020 07:11:50 +0800 Subject: [PATCH 057/187] no message --- path-sum-iii.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 path-sum-iii.py diff --git a/path-sum-iii.py b/path-sum-iii.py new file mode 100644 index 0000000..8766586 --- /dev/null +++ b/path-sum-iii.py @@ -0,0 +1,50 @@ +from collections import Counter + +class Solution(object): + def pathSum(self, root, sum): + def helper(node, sum_from_root, record): + sum_from_root += node.val + sum_to_p = sum_from_root-sum + self.ans += record[sum_to_p] + + record[sum_from_root] += 1 #1 + if node.left: + helper(node.left, sum_from_root, record) + if node.right: + helper(node.right, sum_from_root, record) + record[sum_from_root] -= 1 #2 + + self.ans = 0 + if not root: return self.ans + record = Counter() + record[0] = 1 #3 + helper(root, 0, record) + return self.ans + +""" +This answer is inspired by @gabbu +Some variable and function: +1. `self.ans` stores the number of paths that sum to a given value. +2. `helper()` will traverse the tree and increase `self.ans` along the way. +3. `sum_from_root` is the sum from the `node` to the `root`. Note that, there maybe multiple ways to get to a node. +4. `record` is the number of ways that paths sums up to a number. In short, `record[any_sum]` you get **number of ways to have any_sum**. + +0. +`record` is the hardest part to understand, you need to see the main idea below first. +Imagine we are now at a node in the tree, N. The sum of the path from root to N (including `N.val`) is `sum_from_root`. +Imagine a predecessor of N, we call it P. The sum of the path root->P (including N.val) is `sum_to_p`. Given a node N, there maybe multiple or no P. +`sum_to_p + sum(P->N) == sum_from_root`, thus `sum(P->N) == sum_from_root - sum_to_p` +This problem we are looking for **the number of ways P->N, where `sum == sum(P->N)`** (where `sum == sum_from_root - sum_to_p`). +Thus, we are basically looking for the number of ways root->P, where `sum_to_p == sum_from_root - sum`. +So that is why we have `record`. We can find the number of ways root->P by record[sum_to_p] (record[sum_from_root - sum]). + +1. +Maintain the `record`. + +2. +Remove the case from the `record` after all the children are done calculating. +This prevent other node counts the irerlevant `record`. + +Time complexity is O(N). Since we only traverse each node once. +Space complexity O(N). Since in the worst case, we might go N-level of recursion. +""" \ No newline at end of file From cebd5c6f2c88a50d71483fa9ace41e919aca9a6a Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 20 Apr 2020 19:50:40 +0800 Subject: [PATCH 058/187] no message --- problems/diameter-of-binary-tree.py | 57 +++++++++++++++++++++++++++- problems/sum-root-to-leaf-numbers.py | 18 +++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 problems/sum-root-to-leaf-numbers.py diff --git a/problems/diameter-of-binary-tree.py b/problems/diameter-of-binary-tree.py index 28dead6..527596b 100644 --- a/problems/diameter-of-binary-tree.py +++ b/problems/diameter-of-binary-tree.py @@ -24,4 +24,59 @@ def traverse(node): #iterate through the tree traverse(root) - return self.diameter \ No newline at end of file + return self.diameter + +#2020 +class Solution(object): + def diameterOfBinaryTree(self, root): + def getMaxDepth(node): + if not node: return 0 + + l, r = getMaxDepth(node.left), getMaxDepth(node.right) + self.ans = max(self.ans, l+r) + return max(l, r)+1 #add the node it self + + if not root: return 0 + self.ans = float('-inf') + getMaxDepth(root) + return self.ans +""" +What we want to find? +From an unknown node, that its max_depth_from_left (`l`) + max_depth_from_right (`r`) is the biggest. +The node that generate this number could be from any node, so we iterate through every node to update `ans`. +In other words, to find the answer, we need to check every node, if the max diameter pass through here. +""" + +# from collections import defaultdict +# class Solution(object): +# def diameterOfBinaryTree(self, root): +# def getLeftLength(node): +# if not node: return -1 +# if not (node in record and 'left' in record[node]): +# record[node]['left'] = max(getLeftLength(node.left), getRightLength(node.left))+1 +# return record[node]['left'] + +# def getRightLength(node): +# if not node: return -1 +# if not (node in record and 'right' in record[node]): +# record[node]['right'] = max(getLeftLength(node.right), getRightLength(node.right))+1 +# return record[node]['right'] + +# if not root: return 0 + +# record = defaultdict(dict) +# ans = float('-inf') +# stack = [] +# stack.append(root) + +# while stack: +# node = stack.pop() +# if not node: continue + +# d = getLeftLength(node)+getRightLength(node) +# ans = max(ans, d) +# stack.append(node.left) +# stack.append(node.right) + +# return ans + diff --git a/problems/sum-root-to-leaf-numbers.py b/problems/sum-root-to-leaf-numbers.py new file mode 100644 index 0000000..a4c763e --- /dev/null +++ b/problems/sum-root-to-leaf-numbers.py @@ -0,0 +1,18 @@ +class Solution(object): + def sumNumbers(self, root): + if not root: return 0 + ans = 0 + stack = [] + stack.append((root, '')) + + while stack: + node, total = stack.pop() + total += str(node.val) + if not node.left and not node.right: + ans += int(total) + continue + if node.left: + stack.append((node.left, total)) + if node.right: + stack.append((node.right, total)) + return ans From 82e5f936d98a26c54f64ab245e4b9ba437bbf00b Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 20 Apr 2020 19:59:00 +0800 Subject: [PATCH 059/187] no message --- problems/diameter-of-binary-tree.py | 3 +++ problems/sum-root-to-leaf-numbers.py | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/problems/diameter-of-binary-tree.py b/problems/diameter-of-binary-tree.py index 527596b..f30ea33 100644 --- a/problems/diameter-of-binary-tree.py +++ b/problems/diameter-of-binary-tree.py @@ -45,6 +45,9 @@ def getMaxDepth(node): From an unknown node, that its max_depth_from_left (`l`) + max_depth_from_right (`r`) is the biggest. The node that generate this number could be from any node, so we iterate through every node to update `ans`. In other words, to find the answer, we need to check every node, if the max diameter pass through here. + +Time complexity is O(N), where N is the number of nodes. +Space complexity is O(LogN), since we might got to LogN level on recursion. """ # from collections import defaultdict diff --git a/problems/sum-root-to-leaf-numbers.py b/problems/sum-root-to-leaf-numbers.py index a4c763e..81ecb33 100644 --- a/problems/sum-root-to-leaf-numbers.py +++ b/problems/sum-root-to-leaf-numbers.py @@ -8,7 +8,7 @@ def sumNumbers(self, root): while stack: node, total = stack.pop() total += str(node.val) - if not node.left and not node.right: + if not node.left and not node.right: #is_leaf ans += int(total) continue if node.left: @@ -16,3 +16,8 @@ def sumNumbers(self, root): if node.right: stack.append((node.right, total)) return ans + +""" +Time complexity: O(N), since we use DFS to traverse each node once. +Space complexity: O(NLogN), since each node (at the very bottom), may carry all the digit from its ancestor, LogN. +""" \ No newline at end of file From 3d9c64cff8e5ed43b4a7b3d8f185437ae476a37a Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 15 May 2020 17:53:23 +0800 Subject: [PATCH 060/187] no message --- path-sum-iii.py => problems/path-sum-iii.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename path-sum-iii.py => problems/path-sum-iii.py (100%) diff --git a/path-sum-iii.py b/problems/path-sum-iii.py similarity index 100% rename from path-sum-iii.py rename to problems/path-sum-iii.py From 0f0ce63b3b774090f0c520711008d235d7ea21b7 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 11 Jul 2020 10:51:33 +0800 Subject: [PATCH 061/187] no message --- problems/binary-tree-paths.py | 18 ++++++++++++++++++ problems/longest-univalue-path.py | 23 +++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 problems/binary-tree-paths.py create mode 100644 problems/longest-univalue-path.py diff --git a/problems/binary-tree-paths.py b/problems/binary-tree-paths.py new file mode 100644 index 0000000..c8bfb99 --- /dev/null +++ b/problems/binary-tree-paths.py @@ -0,0 +1,18 @@ +class Solution(object): + def binaryTreePaths(self, root): + if not root: return [] + + arrow = '->' + + ans = [] + stack = [] + stack.append((root, '')) + + while stack: + node, path = stack.pop() + path += arrow+str(node.val) if path else str(node.val) #add arrow except beginnings + if not node.left and not node.right: ans.append(path) #if isLeaf, append path. + if node.left: stack.append((node.left, path)) + if node.right: stack.append((node.right, path)) + + return ans \ No newline at end of file diff --git a/problems/longest-univalue-path.py b/problems/longest-univalue-path.py new file mode 100644 index 0000000..028d465 --- /dev/null +++ b/problems/longest-univalue-path.py @@ -0,0 +1,23 @@ +class Solution(object): + def longestUnivaluePath(self, root): + def getUnivalueLength(node, val): + if not node: return 0 + + l, r = getUnivalueLength(node.left, node.val), getUnivalueLength(node.right, node.val) + self.ans = max(self.ans, l+r) + + if node.val==val: return 1+max(l, r) + return 0 + + if not root: return 0 + self.ans = float('-inf') + getUnivalueLength(root, root.val) + return self.ans + +""" +The main I idea is simple. +Traverse all the node. +Each node, we assume that the longestUnivaluePath will pass through it. +So we can update the `self.ans` if `l+r` is larger. +At the same time, `getUnivalueLength()` will return the max length of the path (start from itself) which has the value `val`. +""" \ No newline at end of file From 2d73e483bcf1fbacd6a50c07e287a41357e5f0c3 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 12 Jul 2020 10:15:39 +0800 Subject: [PATCH 062/187] no message --- ...west-common-ancestor-of-a-binary-search.py | 44 ++++++ ...lowest-common-ancestor-of-a-binary-tree.py | 132 ++++++++++++++++++ problems/sum-root-to-leaf-numbers.py | 39 +++++- 3 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 problems/lowest-common-ancestor-of-a-binary-search.py create mode 100644 problems/lowest-common-ancestor-of-a-binary-tree.py diff --git a/problems/lowest-common-ancestor-of-a-binary-search.py b/problems/lowest-common-ancestor-of-a-binary-search.py new file mode 100644 index 0000000..491baa5 --- /dev/null +++ b/problems/lowest-common-ancestor-of-a-binary-search.py @@ -0,0 +1,44 @@ +class Solution(object): + def lowestCommonAncestor(self, root, p, q): + def find_ancestors(target): + ancestors = [] + curr = root + while curr: + ancestors.append(curr) + + if curr is target: break + + if target.val>curr.val: + curr = curr.right + else: + curr = curr.left + + ancestors.reverse() + return ancestors + + def find_lowest_common(a1, a2): + if len(a1)>len(a2): + a2 = set(a2) + for node in a1: + if node in a2: + return node + else: + a1 = set(a1) + for node in a2: + if node in a1: + return node + + p_ancestors = find_ancestors(p) + q_ancestors = find_ancestors(q) + return find_lowest_common(p_ancestors, q_ancestors) +""" +The idea is simple +Find all the ancestors of `p` and `q`. +After that, we see if the lowest node exist in both `p_ancestor` and `q_ancestor`. +To make sure we start from the lowest node, we need to start from the larger `p_ancestor` or `q_ancestor`. + +Time complexity: O(LogN). +find_ancestors() is O(LogN). +find_lowest_common is O(LogN). +Space complexity is O(N), since `p_ancestors` or `q_ancestors` is carry LogN of nodes. +""" \ No newline at end of file diff --git a/problems/lowest-common-ancestor-of-a-binary-tree.py b/problems/lowest-common-ancestor-of-a-binary-tree.py new file mode 100644 index 0000000..fdbabd3 --- /dev/null +++ b/problems/lowest-common-ancestor-of-a-binary-tree.py @@ -0,0 +1,132 @@ +class Solution(object): + def lowestCommonAncestor(self, root, p, q): + p_ancestor = [] + q_ancestor = [] + + stack = [] + stack.append((root, [])) + while stack: + node, path = stack.pop() + if node is p: p_ancestor = path+[p] + if node is q: q_ancestor = path+[q] + if p_ancestor and q_ancestor: break #[0] + if node.left: stack.append((node.left, path+[node])) + if node.right: stack.append((node.right, path+[node])) + + if len(p_ancestor)>len(q_ancestor): #[1] + s = set(q_ancestor) + for node in reversed(p_ancestor): #[2] + if node in s: return node #[3] + else: #[1] + s = set(p_ancestor) + for node in reversed(q_ancestor): #[2] + if node in s: return node #[3] + return None + + + +class Solution(object): + def lowestCommonAncestor(self, root, p, q): + def helper(node): + if not node: return False + l, r = helper(node.left), helper(node.right) + curr = node is p or node is q + if (int(l)+int(r)+int(curr) >= 2): self.ans = node + return l or r or curr + + self.ans = None + helper(root) + return self.ans + + + +class Solution(object): + def lowestCommonAncestor(self, root, p, q): + stack = [] + stack.append(root) + + parent = {} + parent[root] = None + + while p not in parent or q not in parent: + node = stack.pop() + if node.left: + parent[node.left] = node + stack.append(node.left) + if node.right: + parent[node.right] = node + stack.append(node.right) + + p_ancestor = p + q_ancestor = q + p_ancestors = set() + while p_ancestor: + p_ancestors.add(p_ancestor) + p_ancestor = parent[p] + while q_ancestor: + if q_ancestor in p_ancestors: return q_ancestor + q_ancestor = parent[q] + + return None + + +#2020/7/11 +class Solution(object): + def lowestCommonAncestor(self, root, p, q): + def find_genealogy(): + genealogy = {} + stack = [] + stack.append(root) + p_found = q_found = False + while stack: + node = stack.pop() + if node.left: + genealogy[node.left] = node + stack.append(node.left) + if node.right: + genealogy[node.right] = node + stack.append(node.right) + + if node is p: p_found = True + if node is q: q_found = True + if p_found and q_found: break + return genealogy + + def find_ancestors(target, genealogy): + ancestors = [] + curr_node = target + while curr_node: + ancestors.append(curr_node) + curr_node = genealogy[curr_node] if curr_node in genealogy else None + return ancestors + + def find_lowest_common(a1, a2): + if len(a1)>len(a2): + a2 = set(a2) + for node in a1: + if node in a2: + return node + else: + a1 = set(a1) + for node in a2: + if node in a1: + return node + + genealogy = find_genealogy() + p_ancestors = find_ancestors(p, genealogy) + q_ancestors = find_ancestors(q, genealogy) + return find_lowest_common(p_ancestors, q_ancestors) + +""" +The idea is simple +Find all the ancestors of `p` and `q`. +To find ancestors of `p` and `q`, we need to generate a `genealogy`, where we can find the parant of each node. (genealogy[child] = parant) +After that, we see if the lowest node exist in both `p_ancestor` and `q_ancestor`. +To make sure we start from the lowest node, we need to start from the larger `p_ancestor` or `q_ancestor`. + +Time complexity: O(N). +find_genealogy() is O(N), because we use DFS to travel all nodes. +find_ancestors() is O(LogN). +find_lowest_common is O(LogN). +Space complexity is O(N), since `genealogy` may carry all the nodes. +""" \ No newline at end of file diff --git a/problems/sum-root-to-leaf-numbers.py b/problems/sum-root-to-leaf-numbers.py index 81ecb33..2c85693 100644 --- a/problems/sum-root-to-leaf-numbers.py +++ b/problems/sum-root-to-leaf-numbers.py @@ -17,7 +17,42 @@ def sumNumbers(self, root): stack.append((node.right, total)) return ans +#2020/7/11 +class Solution(object): + def sumNumbers(self, root): + if not root: return 0 + + ans = 0 + stack = [] + stack.append((root, 0)) + + while stack: + node, n = stack.pop() + n = n*10+node.val + if not node.left and not node.right: ans+=n + if node.left: stack.append((node.left, n)) + if node.right: stack.append((node.right, n)) + + return ans + """ Time complexity: O(N), since we use DFS to traverse each node once. -Space complexity: O(NLogN), since each node (at the very bottom), may carry all the digit from its ancestor, LogN. -""" \ No newline at end of file +Space complexity: O(LogN). +Most of the memory we use is in the stack. +tack will at most carry one path (root to leaf), each node containing one digit. O(LogN) +""" + + + + + + + + + + + + + + + From 71dc13f7144c12b6d98db058fcba2849284721e8 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 14 Jul 2020 18:02:10 +0800 Subject: [PATCH 063/187] no message --- problems/most-frequent-subtree-sum.py | 20 +++++++ problems/serialize-and-deserialize-bst.py | 66 +++++++++++++++++++---- 2 files changed, 76 insertions(+), 10 deletions(-) create mode 100644 problems/most-frequent-subtree-sum.py diff --git a/problems/most-frequent-subtree-sum.py b/problems/most-frequent-subtree-sum.py new file mode 100644 index 0000000..ce457fc --- /dev/null +++ b/problems/most-frequent-subtree-sum.py @@ -0,0 +1,20 @@ +from collections import Counter +class Solution(object): + def findFrequentTreeSum(self, root): + def dfs(node): + if not node: return 0 + s = dfs(node.left)+node.val+dfs(node.right) + counter[s] += 1 + return s + + if not root: return [] + counter = Counter() + dfs(root) #start counting + + max_freq = max(counter.values()) + return [v for v, freq in counter.items() if freq==max_freq] + +""" +Time: O(N) +Space: O(N) +""" \ No newline at end of file diff --git a/problems/serialize-and-deserialize-bst.py b/problems/serialize-and-deserialize-bst.py index a3cd41c..2cebdb9 100644 --- a/problems/serialize-and-deserialize-bst.py +++ b/problems/serialize-and-deserialize-bst.py @@ -1,12 +1,3 @@ -""" -perform BFS to traverse the whole tree -after we add the entire level to the string, then we go to the next level - -by doing this, we can always convert the serialized tree back -because when you build the tree back -the order doesn't matter as long as you insert each parent before child -""" - from collections import deque class Codec: def serialize(self, root): @@ -42,4 +33,59 @@ def deserialize(self, data): break else: node = node.left - return root \ No newline at end of file + return root + +#2020/7/13 +from collections import deque +class Codec: + + def serialize(self, root): + s = '' + if not root: return s + + q = deque([root]) + while q: + node = q.popleft() + s += str(node.val)+',' + if node.left: q.append(node.left) + if node.right: q.append(node.right) + return s[:-1] + + def deserialize(self, data): + def insert(root, node): + if node.val<=root.val: + if not root.left: + root.left = node + else: + insert(root.left, node) + else: + if not root.right: + root.right = node + else: + insert(root.right, node) + + if not data: return None + + vals = [int(val) for val in data.split(',')] + root = TreeNode(vals[0]) + for i in xrange(1, len(vals)): + val = vals[i] + insert(root, TreeNode(val)) + + return root + +""" +Perform BFS to traverse the whole tree. +After we add the entire level to the string, then we go to the next level. + +By doing this, we can always convert the serialized tree back. +Because when you build the tree back. +The order doesn't matter as long as you insert each parent before child. + +For serialize(), the time and space complexity is O(N). +Because we use BFS to trverse each node once and store its val in string. + +For deserialize(), the time complexity is O(NlogN). +Because we for every node, we perform insert(), which takes O(LogN) on a BST. +The space complexity is O(LogN), because the recusion will be LogN level deep. +""" \ No newline at end of file From 2a00678d48b385a150041c1e4bdbf5b9f04928ee Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 19 Jul 2020 17:53:27 +0800 Subject: [PATCH 064/187] no message --- problems/binary-search.py | 26 ++++++++++++ problems/distribute-coins-in-binary-tree.py | 20 +++++++++ ...ast-position-of-element-in-sorted-array.py | 42 +++++++++++++++++++ problems/house-robber-iii.py | 3 +- problems/search-insert-position.py | 32 ++++++++++++++ 5 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 problems/distribute-coins-in-binary-tree.py diff --git a/problems/binary-search.py b/problems/binary-search.py index b528b63..42ac46b 100644 --- a/problems/binary-search.py +++ b/problems/binary-search.py @@ -42,3 +42,29 @@ def search(self, nums, target): #check if target in `nums` if nums[i]==target: return i else: return -1 + + +# 2020/7/19 +class Solution(object): + def search(self, nums, target): + if not nums: return -1 + + l = 0 + r = len(nums)-1 + + while True: + if l>r: break + if targetr: break + if targetnums[r]: return [-1, -1] + + if target==nums[l]: return find_range(l, nums) + if target==nums[r]: return find_range(r, nums) + + m = (l+r)/2 + if target==nums[m]: + return find_range(m, nums) + elif targetr: break + if targetnums[r]: return r+1 + + if target==nums[l]: return l + if target==nums[r]: return r + + m = int((l+r)/2) + + if target==nums[m]: + return m + elif target>nums[m]: + l = m+1 + else: + r = m-1 + return 0 + + + + + From 02cbe893583d93e5252d4cbc13f0ab49ffb60d9b Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Thu, 23 Jul 2020 12:07:54 +0800 Subject: [PATCH 065/187] no message --- .../find-minimum-in-rotated-sorted-array.py | 39 ++++++++ problems/find-peak-element.py | 26 ++++++ problems/search-in-rotated-sorted-array-ii.py | 35 +++++++ problems/search-in-rotated-sorted-array.py | 43 +++++++++ problems/sqrtx.py | 25 +++++ problems/time-based-key-value-store.py | 91 ++++++++++++++----- 6 files changed, 237 insertions(+), 22 deletions(-) diff --git a/problems/find-minimum-in-rotated-sorted-array.py b/problems/find-minimum-in-rotated-sorted-array.py index 3e7b02a..db5880e 100644 --- a/problems/find-minimum-in-rotated-sorted-array.py +++ b/problems/find-minimum-in-rotated-sorted-array.py @@ -34,3 +34,42 @@ def findMin(self, nums): else: break return m + + + +""" +Pointer l and r is at the start and at the end of the list. [0] +We only consider the numbers between l and r. + +If the list is already sorted, return the left most element. [1] + +Now, we cut the rotated array into half. l~m and m~r. +Normally, one part will be sorted, the other half is not. +The min must be in the unsorted part. +So we move the pointer and do the same thing on the unsorted part. [2] + +One scenario to consider is that the cutting point, m, being the smallest element. +This will cause both l~m and m~r to both be sorted. +So we need to check it. [3] + +Time: O(LogN) +Space: O(1) +""" + +class Solution(object): + def findMin(self, nums): + if not nums: return 0 + l = 0 #[0] + r = len(nums)-1 #[0] + + while l<=r: + if nums[l]<=nums[r]: return nums[l] #[1] + + m = (l+r)/2 + if m-1>=0 and nums[m-1]>nums[m]: return nums[m] #[3] + + if nums[l]<=nums[m]: + l = m+1 #[2] + else: + r = m-1 #[2] + return 0 \ No newline at end of file diff --git a/problems/find-peak-element.py b/problems/find-peak-element.py index 8dbd257..5b9a8b3 100644 --- a/problems/find-peak-element.py +++ b/problems/find-peak-element.py @@ -30,3 +30,29 @@ def findPeakElement(self, nums): r = nums[i+1] if (i+1)l and nums[i]>r: return i return None + + +#2020/7/23 +class Solution(object): + def findPeakElement(self, nums): + l = 0 + r = len(nums)-1 + + while l<=r: + if l==r: return l + if nums[l]>nums[l+1]: return l #check l is peak + if nums[r-1]nums[m+1]: + #m is in the rising slope + r = m + return l + + + + \ No newline at end of file diff --git a/problems/search-in-rotated-sorted-array-ii.py b/problems/search-in-rotated-sorted-array-ii.py index a8f03cc..43e913b 100644 --- a/problems/search-in-rotated-sorted-array-ii.py +++ b/problems/search-in-rotated-sorted-array-ii.py @@ -35,3 +35,38 @@ def search(self, nums, t): r = r-1 l = l+1 return False + + +#2020/7/20, recursive. +class Solution(object): + def search(self, nums, target): + def binary_search(l, r): + if l>r: return False + if nums[l]==target: return True + if nums[r]==target: return True + + m = (l+r)/2 + if nums[m]==target: + return m + if targetr: return False + if nums[l]==target: return True + if nums[r]==target: return True + if nums[l]r: return -1 + if nums[l]==target: return l + if nums[r]==target: return r + + m = (l+r)/2 + if nums[m]==target: + return m + if targetr: return -1 + if nums[l]==target: return l + if nums[r]==target: return r + if nums[l]<=nums[r]: return binary_search(l+1, r-1) + + m = (l+r)/2 + if nums[m]==target: return m + + if nums[l]0`: it means `i` is the index where its value just exceed the `timestamp`, return the value at `i-1`. - -We can also implement our own `bisect` by binary search. -The implementation assume there are no duplicate value in the array. - -Time Complexity, O(1) for `set()`. O(LogN) for `get()`. -Space complexity is O(N) -N is the number of value stored. -""" import collections import bisect @@ -74,6 +52,29 @@ def bisect(self, A, x): l = p+1 return l +""" +We need a hash-table to store the key-value information. +For every key, there are multiple values and we need it to sort by`timestamp`. + +First, we use two array, `t` and `v` to store timestamp and value separately. +And becuase the problem says **The timestamps for all TimeMap.set operations are strictly increasing.** +So for the `set()` method, we only need to simply append `value` and `timestamp` to the end of `v` and `t`. +The array `t` and its corresponding `v` is sorted already. + +[bisect](https://docs.python.org/2/library/bisect.html) can help us implement our `get()` method. +It returns an insertion point which comes after (to the right of) any existing entries, if we insert the **`timestamp` we are going to get()** into a the array, `t`. +So `bisect(t, timestamp)` returns `i`: + * If `i==0`: it means that there are no value samller than the `timestamp`, `return ""`. + * If `i>0`: it means `i` is the index where its value just exceed the `timestamp`, return the value at `i-1`. + +We can also implement our own `bisect` by binary search. +The implementation assume there are no duplicate value in the array. + +Time Complexity, O(1) for `set()`. O(LogN) for `get()`. +Space complexity is O(N) +N is the number of value stored. +""" + t = TimeMap() t.set('love', 'low', 10) t.set('love', 'high', 20) @@ -85,3 +86,49 @@ def bisect(self, A, x): +#2020/7/20 +from collections import defaultdict +class TimeMap(object): + + def __init__(self): + self.v = defaultdict(list) + self.t = defaultdict(list) + + + def set(self, key, value, timestamp): + self.v[key].append(value) + self.t[key].append(timestamp) + + + def get(self, key, timestamp): + if key not in self.t: return "" + i = self.bisect(self.t[key], timestamp) + return self.v[key][i-1] if i>0 else "" + + + #return an insertion point right to an index + #where the target's value just exceed the index's value + def bisect(self, L, target): + if not L: return 0 + + l = 0 + r = len(L)-1 + + while l<=r: + if target=L[r]: return r+1 + + m = (l+r)/2 + + if target==L[m]: + return m+1 + elif target Date: Thu, 23 Jul 2020 12:09:19 +0800 Subject: [PATCH 066/187] no message --- problems/sqrtx.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/problems/sqrtx.py b/problems/sqrtx.py index 546e3a7..f1910bc 100644 --- a/problems/sqrtx.py +++ b/problems/sqrtx.py @@ -27,14 +27,8 @@ def isAns(a): return -1 -""" -The answer must always be in l~r. -In every iteration, we test the m, `m_sqr==x or (m_sqr Date: Fri, 24 Jul 2020 16:02:45 +0800 Subject: [PATCH 067/187] no message --- ...capacity-to-ship-packages-within-d-days.py | 48 +++++++++++++++++++ problems/koko-eating-bananas.py | 46 ++++++++++++++++++ problems/search-a-2d-matrix.py | 48 +++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 problems/capacity-to-ship-packages-within-d-days.py diff --git a/problems/capacity-to-ship-packages-within-d-days.py b/problems/capacity-to-ship-packages-within-d-days.py new file mode 100644 index 0000000..8444e0a --- /dev/null +++ b/problems/capacity-to-ship-packages-within-d-days.py @@ -0,0 +1,48 @@ +class Solution(object): + def shipWithinDays(self, weights, D): + l = max(weights) + r = sum(weights) + + while lD: + #K cannot be the answer. + #next round we don't need to put K in l~r. + l = c+1 + else: + #K might ot might not be the answer. + #next round we still need to put K in l~r. + r = c + return l + +""" +This is a binary search problem. +If you do not understand binary search yet, please study it first. + +[0] +Lets define the possible range, `l` and `r`, of our answer, the least weight capacity of the ship that can diliver all packages within D days. +The ship must at least carry the heaviest package, so `l = max(weights)`. +The best ship scenario is that we can carry all packages at once, so `r = sum(weights)`. + +[1] +For every iteration, we try a `c` (capacity) and adjust `l` and `r`. +Note that, even if `d<=D`, we still need to see if there are any smaller `d`. + +[2] +So the boundary of our answer, `l` and `r`, will collides together (`l==r`) and jump out of the loop. + +Time complexity: `O(NlogN)`. There will be `O(LogN)` iteration. For every iteration we need O(N) to calculate the `t`. `N` is the length of `piles`. +Space complexity is O(N). For calculating `t`. +""" \ No newline at end of file diff --git a/problems/koko-eating-bananas.py b/problems/koko-eating-bananas.py index 4787787..8031880 100644 --- a/problems/koko-eating-bananas.py +++ b/problems/koko-eating-bananas.py @@ -29,3 +29,49 @@ def canEatAll(time): else: l = m+1 return l + + +#2020/7/23 +class Solution(object): + def minEatingSpeed(self, piles, H): + if not piles: return 0 + + l = 1 + r = max(piles) #[0] + + while lH: + #K cannot be the answer. + #next round we don't need to put K in l~r. + l = K+1 + else: + #K might ot might not be the answer. + #next round we still need to put K in l~r. + r = K + + return l #[2] + +""" +This is a binary search problem. +If you do not understand binary search yet, please study it first. + +[0] +Lets define the possible range, `l` and `r`, of our answer, the minimum integer `K` such that Koko can eat all the bananas within `H` hours. +The best scenario is that Koko can eat the whole pile at once. +So `K` must be between 1 ~ `max(piles)`. `l = 1`, `r = max(piles)`. + +[1] +For every iteration, we try a `K` and adjust `l` and `r`. +Note that, even if `t<=H`, we still need to see if there are any smaller `K`. + +[2] +So the boundary of our answer, `l` and `r`, will collides together (`l==r`) and jump out of the loop. + +Time complexity: `O(NlogN)`. There will be `O(LogN)` iteration. For every iteration we need O(N) to calculate the `t`. `N` is the length of `piles`. +Space complexity is O(N). For calculating `t`. +""" \ No newline at end of file diff --git a/problems/search-a-2d-matrix.py b/problems/search-a-2d-matrix.py index 453f2a7..9dde18d 100644 --- a/problems/search-a-2d-matrix.py +++ b/problems/search-a-2d-matrix.py @@ -47,3 +47,51 @@ def getMatrix(i): else: l = p+1 return False + + +#2020/7/23 +class Solution(object): + def searchMatrix(self, matrix, target): + if not matrix or not matrix[0]: return False + + #if you do not understand binary search yet, please study it first. + #use binary search to find the list that has target. + #if found, asign it to A. + l = 0 + r = len(matrix)-1 + A = None + while l<=r: + if matrix[l][0]<=target and target<=matrix[l][-1]: + A = matrix[l] + break + if matrix[r][0]<=target and target<=matrix[r][-1]: + A = matrix[r] + break + + m = (l+r)/2 + + if matrix[m][0]<=target and target<=matrix[m][-1]: + A = matrix[m] + break + elif target Date: Fri, 31 Jul 2020 10:09:37 +0800 Subject: [PATCH 068/187] no message --- ...capacity-to-ship-packages-within-d-days.py | 20 +++++--- problems/insert-into-a-binary-search-tree.py | 26 +++++++++++ problems/kth-smallest-element-in-a-bst.py | 32 +++++++++++++ ...kth-smallest-element-in-a-sorted-matrix.py | 35 ++++++++++++++ .../minimum-absolute-difference-in-bst.py | 46 +++++++++++++++++++ problems/search-in-a-binary-search-tree.py | 19 ++++++++ problems/validate-binary-search-tree.py | 14 ++---- 7 files changed, 176 insertions(+), 16 deletions(-) create mode 100644 problems/insert-into-a-binary-search-tree.py create mode 100644 problems/kth-smallest-element-in-a-bst.py create mode 100644 problems/minimum-absolute-difference-in-bst.py create mode 100644 problems/search-in-a-binary-search-tree.py diff --git a/problems/capacity-to-ship-packages-within-d-days.py b/problems/capacity-to-ship-packages-within-d-days.py index 8444e0a..e396aa6 100644 --- a/problems/capacity-to-ship-packages-within-d-days.py +++ b/problems/capacity-to-ship-packages-within-d-days.py @@ -18,15 +18,17 @@ def shipWithinDays(self, weights, D): if daily_weight: d += 1 if d>D: - #K cannot be the answer. - #next round we don't need to put K in l~r. + #c cannot be the answer. + #next round we don't need to put c in l~r. l = c+1 else: - #K might ot might not be the answer. - #next round we still need to put K in l~r. + #c might ot might not be the answer. + #next round we still need to put c in l~r. r = c return l + + """ This is a binary search problem. If you do not understand binary search yet, please study it first. @@ -43,6 +45,12 @@ def shipWithinDays(self, weights, D): [2] So the boundary of our answer, `l` and `r`, will collides together (`l==r`) and jump out of the loop. -Time complexity: `O(NlogN)`. There will be `O(LogN)` iteration. For every iteration we need O(N) to calculate the `t`. `N` is the length of `piles`. -Space complexity is O(N). For calculating `t`. +Time complexity: `O(NlogW)`. +`N` is the number of `weights`. +`W` is the max weight. +There will be `O(LogW)` iteration. For every iteration we need O(N) to calculate the `d`. +Space complexity is O(1). + +Also take a look at problem, 875, very similar. +https://leetcode.com/problems/koko-eating-bananas/discuss/750699/ """ \ No newline at end of file diff --git a/problems/insert-into-a-binary-search-tree.py b/problems/insert-into-a-binary-search-tree.py new file mode 100644 index 0000000..2670175 --- /dev/null +++ b/problems/insert-into-a-binary-search-tree.py @@ -0,0 +1,26 @@ +class Solution(object): + def insertIntoBST(self, root, val): + if not root: return TreeNode(val) + + node = root + while node: + if valval: + node = node.left + else: + node = node.right + + return None + + +""" +Time complexity: O(LogN) +Space complexity: O(1) +""" \ No newline at end of file diff --git a/problems/validate-binary-search-tree.py b/problems/validate-binary-search-tree.py index 2d0c4e9..6331c4b 100644 --- a/problems/validate-binary-search-tree.py +++ b/problems/validate-binary-search-tree.py @@ -29,16 +29,10 @@ class Solution(object): #recursive def isValidBST(self, root): def helper(node, min_val, max_val): - if node==None: - return True - if node.val<=min_val or node.val>=max_val: - return False - - left_valid = helper(node.left, min_val, node.val) - if not left_valid: return False - right_valid = helper(node.right, node.val, max_val) - if not right_valid: return False - + if not node: return True + if node.val<=min_val or node.val>=max_val:return False + if not helper(node.left, min_val, node.val): return False + if not helper(node.right, node.val, max_val): return False return True return helper(root, float('-inf'), float('inf')) From 8c11b0d7ca1ad9552adf90abf2dc74a5707dbbbf Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 7 Aug 2020 10:49:32 +0800 Subject: [PATCH 069/187] no message --- ...vert-sorted-array-to-binary-search-tree.py | 22 +++++ problems/delete-node-in-a-bst.py | 61 +++++++++++++ problems/find-mode-in-binary-search-tree.py | 87 +++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 problems/convert-sorted-array-to-binary-search-tree.py create mode 100644 problems/delete-node-in-a-bst.py create mode 100644 problems/find-mode-in-binary-search-tree.py diff --git a/problems/convert-sorted-array-to-binary-search-tree.py b/problems/convert-sorted-array-to-binary-search-tree.py new file mode 100644 index 0000000..d0f2fd8 --- /dev/null +++ b/problems/convert-sorted-array-to-binary-search-tree.py @@ -0,0 +1,22 @@ +class Solution(object): + def sortedArrayToBST(self, nums): + if not nums: return None + + m = len(nums)/2 + root = TreeNode(nums[m], self.sortedArrayToBST(nums[:m]), self.sortedArrayToBST(nums[m+1:])) + return root + + +""" +`nums` is a sorted array. +To construct the most balanced BST, we must use the median number in `nums` as root. +So the number of elements under left subtree and right subtree will be the same. + +Now we know which element in the `nums` will be root. +For `root.left` we only need to consider `nums[:m]`. +For `root.right` we only need to consider `nums[m+1:]`. +Which needs to be a balanced BST, too. So we apply the same logic. + +Time: O(N). Because there will be N element being construct. +Space: O(LogN). There will be LogN level of recursive call. +""" \ No newline at end of file diff --git a/problems/delete-node-in-a-bst.py b/problems/delete-node-in-a-bst.py new file mode 100644 index 0000000..de1101a --- /dev/null +++ b/problems/delete-node-in-a-bst.py @@ -0,0 +1,61 @@ +class Solution(object): + def deleteNode(self, root, key): + def find_min(root): + curr = root + while curr.left: curr = curr.left + return curr.val#[5] + + def remove(node): + if node.left and node.right: + node.val = find_min(node.right) + node.right = self.deleteNode(node.right, node.val) + return node #[4] + elif node.left and not node.right: + return node.left #[3] + elif node.right and not node.left: + return node.right #[3] + else: + return None #[2] + + if not root: return root + node = root + + while node: #[0] + if node.val==key: + return remove(node) #[1] + elif node.left and node.left.val==key: + node.left = remove(node.left) #[1] + return root + elif node.right and node.right.val==key: + node.right = remove(node.right) #[1] + return root + + if key>node.val and node.right: + node = node.right + elif keymax_count: + ans = [curr.val] + max_count = curr_count + elif curr_count==max_count: + ans.append(curr.val) + + curr = curr.right + + return ans + +""" +To use the feature of BST, we are going to inorder traverse the BST. +So it will be like we are iterating a sorted array. + +[1] +While iterating, we can put only the element count that is greater or equal than `max_count` to `ans`. +If we encounter a new element with larger `curr_count`, we reset the `ans`. + +[0] +With the help of `prev_val` we can know that `curr_node` is the same to the previous or not. +If not, its a new element, we need to reset the `curr_count`. + +Time: O(N). Space: O(1) + +For better understanding, below is a template for inorder traverse. +""" + +#inorder traversal of BST +def inorder_traverse(root): + curr = root + stack = [] + while curr or stack: + while curr: + stack.append(curr) + curr = curr.left + curr = stack.pop() + + #do something to the current node + print curr.val + + curr = curr.right From 6ef0afe1950dc069585bbf1072dc59a3cfd7aa54 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 11 Aug 2020 18:11:27 +0800 Subject: [PATCH 070/187] no message --- problems/clone-graph.py | 24 ++++++++++++++++++-- problems/copy-list-with-random-pointer.py | 27 ++++++++++++++++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/problems/clone-graph.py b/problems/clone-graph.py index b311acf..b82f0f8 100644 --- a/problems/clone-graph.py +++ b/problems/clone-graph.py @@ -54,8 +54,28 @@ def cloneGraph(self, start): return clone[start] - - +#2020/8/7, similar to 2 +class Solution(object): + def cloneGraph(self, node): + if not node: return node + + visited = set() + clones = {} + stack = [] + + stack.append(node) + while stack: + curr = stack.pop() + if curr in visited: continue + visited.add(curr) + clones[curr] = Node(curr.val) + stack.extend(curr.neighbors) + + for curr in clones: + clones[curr].neighbors = [clones[c] for c in curr.neighbors] + + return clones[node] + diff --git a/problems/copy-list-with-random-pointer.py b/problems/copy-list-with-random-pointer.py index 7ad802c..0790e26 100644 --- a/problems/copy-list-with-random-pointer.py +++ b/problems/copy-list-with-random-pointer.py @@ -31,4 +31,29 @@ def copyRandomList(self, head): curr = curr.next curr_copy = curr_copy.next - return head_copy \ No newline at end of file + return head_copy + +# 2020/8/11 +class Solution(object): + def copyRandomList(self, head): + if not head: return head + + clones = {} + + curr = head + while curr: + clones[curr] = Node(curr.val) + curr = curr.next + + curr = head + while curr: + if curr.next: clones[curr].next = clones[curr.next] + if curr.random: clones[curr].random = clones[curr.random] + curr = curr.next + + return clones[head] + +""" +Time: O(N). Two iteration. First iteration make a the clones. Second iteration setup the links. +Space: O(1). No extra space except the cloned node. +""" \ No newline at end of file From f6c92a281e28dc2a0edf034436ae70a2e38056cb Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Thu, 13 Aug 2020 18:17:30 +0800 Subject: [PATCH 071/187] no message --- problems/flood-fill.py | 17 +++++++++++++ problems/friend-circles.py | 36 +++++++++++++++++++++++++++- problems/max-area-of-island.py | 44 ++++++++++++++++++++++++++++++++++ problems/number-of-islands.py | 42 ++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 problems/flood-fill.py create mode 100644 problems/max-area-of-island.py diff --git a/problems/flood-fill.py b/problems/flood-fill.py new file mode 100644 index 0000000..fcba3ac --- /dev/null +++ b/problems/flood-fill.py @@ -0,0 +1,17 @@ +class Solution(object): + def floodFill(self, image, sr, sc, newColor): + stack = [(sr, sc)] + originColor = image[sr][sc] + + while stack: + i, j = stack.pop() + + if image[i][j]==newColor or image[i][j]!=originColor: continue + + image[i][j] = newColor + if i+1 Date: Thu, 13 Aug 2020 18:30:13 +0800 Subject: [PATCH 072/187] no message --- problems/flood-fill.py | 12 +++++++++++- problems/keys-and-rooms.py | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 problems/keys-and-rooms.py diff --git a/problems/flood-fill.py b/problems/flood-fill.py index fcba3ac..a18a13f 100644 --- a/problems/flood-fill.py +++ b/problems/flood-fill.py @@ -14,4 +14,14 @@ def floodFill(self, image, sr, sc, newColor): if j+1 Date: Thu, 20 Aug 2020 18:02:48 +0800 Subject: [PATCH 073/187] no message --- problems/course-schedule-ii.py | 50 ++++++++++++++ problems/course-schedule.py | 73 ++++++++++----------- problems/find-mode-in-binary-search-tree.py | 2 +- 3 files changed, 87 insertions(+), 38 deletions(-) create mode 100644 problems/course-schedule-ii.py diff --git a/problems/course-schedule-ii.py b/problems/course-schedule-ii.py new file mode 100644 index 0000000..9715692 --- /dev/null +++ b/problems/course-schedule-ii.py @@ -0,0 +1,50 @@ +from collections import defaultdict, deque + +class Solution(object): + def findOrder(self, numCourses, prerequisites): + graph = defaultdict(list) + inbound = defaultdict(int) + q = deque() + order = deque() + + #building graph as adjacency list + for c1, c2 in prerequisites: + graph[c2].append(c1) + inbound[c1] += 1 + + #find the starting point + for c in xrange(numCourses): + if inbound[c]==0: + q.append(c) + + #traverse the directed graph + while q: + c = q.popleft() + + for nei in graph[c]: + inbound[nei] -= 1 + if inbound[nei]==0: + q.append(nei) + + order.append(c) + + return order if len(order)==numCourses else [] + +""" +Topological sort works only in directed graph. +We can use it to know which node comes after which or detect cycles. +The algorithm is easy to understand. +First, we build the adjacent list (`graph`) and count all the inbound of the node. +Then we start from the node whose inbound count is 0, adding it in to the `q`. +For every node we pop out from `q` + * We remove the node's outbound by decrease 1 on all its neighbor's inbound. + * Put the node's neighbor to `q` if it has no inbound + * Put the node into the `order` +Repeat the process until there is no more node. +The order in the `order` is the order we are going to encounter when we run through the directed graph. +If we cannot sort all the nodes in the graph, it means that there are some nodes we couldn't find its starting point, in other words, there are cycles in the graph. + +Time: O(E+2V) ~= O(E+V) +we used O(E) to build the graph #[1], O(V) to find the starting point #[2], then traverse all the nodes again #[3]. +Space: O(E+3V) ~= O(E+V), O(E+V) for the adjacent list. O(V) for the `q`, O(V) for the `q_next`. +""" \ No newline at end of file diff --git a/problems/course-schedule.py b/problems/course-schedule.py index 9121ee2..3e05d6d 100644 --- a/problems/course-schedule.py +++ b/problems/course-schedule.py @@ -1,23 +1,3 @@ -""" -First, we build a graph of adjacency list #[0] -0->[2,4,5] -1->[3,4] -Meaning before taking 2,4,5 we need to take 0, before taking 3,4 we need to take 1 -if we find a loop back to itself then it is impossible, for example -0->[2,4,5] -1->[3,4] -2->[0,3] -0->2->0, which is imposible. - -Now we iterate every course to see if it can loop back to itself in anyway #[1] -we do this by dfs and search for it self -if we find itself we find loop - -The time efficiency is O(V^2+VE), because each dfs in adjacency list is O(V+E) and we do it V times -Space efficiency is O(E). -V is the numCourses (Vertices). -E is the number of prerequisites (Edges). -""" class Solution(object): def canFinish(self, numCourses, prerequisites): graph = {n:[] for n in xrange(numCourses)} #[0] @@ -36,25 +16,27 @@ def canFinish(self, numCourses, prerequisites): if ajc not in visited: stack.append(ajc) return True - """ -Topological sort works only in directed graph. -We can use it to know which node comes after which or detect cycles. -The algorithm is easy to understand. -First, we build the adjacent list and count all the inbound of the node. -Then we start from the node whose inbound count is 0, adding it in to the `q_next`. -For every node we pop out from q_next - * We remove the node's outbound by decrease 1 on all its neighbor's inbound. - * Put the node's neighbor to `q_next` if it has no inbound - * Put the node into the `q` -Repeat the process until there is no more node. -The order in the `q` is the order we are going to encounter when we run through the directed graph. -If we cannot sort all the nodes in the graph, it means that there are some nodes we couldn't find its starting point, in other words, there are cycles in the graph. +First, we build a graph of adjacency list #[0] +0->[2,4,5] +1->[3,4] +Meaning before taking 2,4,5 we need to take 0, before taking 3,4 we need to take 1 +if we find a loop back to itself then it is impossible, for example +0->[2,4,5] +1->[3,4] +2->[0,3] +0->2->0, which is imposible. -Time: O(E+2V) ~= O(E+V) -we used O(E) to build the graph #[1], O(V) to find the starting point #[2], then traverse all the nodes again #[3]. -Space: O(E+3V) ~= O(E+V), O(E+V) for the adjacent list. O(V) for the `q`, O(V) for the `q_next`. +Now we iterate every course to see if it can loop back to itself in anyway #[1] +we do this by dfs and search for it self +if we find itself we find loop + +The time efficiency is O(V^2+VE), because each dfs in adjacency list is O(V+E) and we do it V times +Space efficiency is O(E). +V is the numCourses (Vertices). +E is the number of prerequisites (Edges). """ + class Solution(object): def canFinish(self, numCourses, prerequisites): graph = collections.defaultdict(list) @@ -78,5 +60,22 @@ def canFinish(self, numCourses, prerequisites): q_next.append(nei) q.append(n) return len(q)==numCourses + +""" +Topological sort works only in directed graph. +We can use it to know which node comes after which or detect cycles. +The algorithm is easy to understand. +First, we build the adjacent list and count all the inbound of the node. +Then we start from the node whose inbound count is 0, adding it in to the `q_next`. +For every node we pop out from q_next + * We remove the node's outbound by decrease 1 on all its neighbor's inbound. + * Put the node's neighbor to `q_next` if it has no inbound + * Put the node into the `q` +Repeat the process until there is no more node. +The order in the `q` is the order we are going to encounter when we run through the directed graph. +If we cannot sort all the nodes in the graph, it means that there are some nodes we couldn't find its starting point, in other words, there are cycles in the graph. - +Time: O(E+2V) ~= O(E+V) +we used O(E) to build the graph #[1], O(V) to find the starting point #[2], then traverse all the nodes again #[3]. +Space: O(E+3V) ~= O(E+V), O(E+V) for the adjacent list. O(V) for the `q`, O(V) for the `q_next`. +""" \ No newline at end of file diff --git a/problems/find-mode-in-binary-search-tree.py b/problems/find-mode-in-binary-search-tree.py index 55dc1e8..4705a77 100644 --- a/problems/find-mode-in-binary-search-tree.py +++ b/problems/find-mode-in-binary-search-tree.py @@ -66,7 +66,7 @@ def findMode(self, root): With the help of `prev_val` we can know that `curr_node` is the same to the previous or not. If not, its a new element, we need to reset the `curr_count`. -Time: O(N). Space: O(1) +Time: O(N). Space: O(LogN) For better understanding, below is a template for inorder traverse. """ From c198584546600ea8ed3c2dc52c0a3bc2074604db Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 23 Aug 2020 20:52:57 +0800 Subject: [PATCH 074/187] no message --- problems/evaluate-division.py | 39 +++++++++++++ problems/find-eventual-safe-states.py | 29 ++++++++++ .../satisfiability-of-equality-equations.py | 57 +++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 problems/find-eventual-safe-states.py create mode 100644 problems/satisfiability-of-equality-equations.py diff --git a/problems/evaluate-division.py b/problems/evaluate-division.py index c126cca..447f3b6 100644 --- a/problems/evaluate-division.py +++ b/problems/evaluate-division.py @@ -56,3 +56,42 @@ def addEdge(n1, n2, val): return [findVal(query) for query in queries] + +from collections import defaultdict + +class Solution(object): + def calcEquation(self, equations, values, queries): + #using DFS + def find_val(n1, n2): + if n1 not in graph or n2 not in graph: return -1 + if n1==n2: return 1 + if n2 in graph[n1]: return graph[n1][n2] + + stack = [(n1, 1)] + visited = set() + + while stack: + n, v = stack.pop() #v is the val of n1/n + + if n in visited: continue + visited.add(n) + + if n==n2: + graph[n1][n2] = v + return v + + stack.extend([(next_n, v*graph[n][next_n]) for next_n in graph[n]]) + return -1 + + #build graph + graph = defaultdict(dict) + for i, v in enumerate(values): + n1, n2 = equations[i][0], equations[i][1] + graph[n1][n2] = v + graph[n2][n1] = 1/v + + ans = [] + for n1, n2 in queries: + ans.append(find_val(n1, n2)) + + return ans \ No newline at end of file diff --git a/problems/find-eventual-safe-states.py b/problems/find-eventual-safe-states.py new file mode 100644 index 0000000..ab0c1c1 --- /dev/null +++ b/problems/find-eventual-safe-states.py @@ -0,0 +1,29 @@ +from collections import defaultdict, deque + +class Solution(object): + def eventualSafeNodes(self, graph): + inbounds = defaultdict(list) + outbondsCounter = defaultdict(int) + q = deque() + ans = [] + + for n, nei_list in enumerate(graph): + outbondsCounter[n] = len(nei_list) + for nei in nei_list: + inbounds[nei].append(n) + + for n in outbondsCounter: + if outbondsCounter[n]==0: + q.append(n) + + while q: + n = q.popleft() + + for nei in inbounds[n]: + outbondsCounter[nei] -= 1 + if outbondsCounter[nei]==0: + q.append(nei) + + ans.append(n) + + return ans.sort() \ No newline at end of file diff --git a/problems/satisfiability-of-equality-equations.py b/problems/satisfiability-of-equality-equations.py new file mode 100644 index 0000000..2c02d16 --- /dev/null +++ b/problems/satisfiability-of-equality-equations.py @@ -0,0 +1,57 @@ +from collections import defaultdict + +class Solution(object): + def equationsPossible(self, equations): + def isConnected(n1, n2): + if n1==n2: return True + + stack = [n1] + visited = set() + + while stack: + n = stack.pop() + if n in visited: continue + visited.add(n) + + if n==n2: return True + + stack.extend(graph[n]) + return False + + not_equals = set() + graph = defaultdict(list) + + #build graph + for e in equations: + if e[1:3]=='==': + graph[e[0]].append(e[3]) + graph[e[3]].append(e[0]) + elif e[1:3]=='!=': + if (e[0], e[3]) not in not_equals and (e[3], e[0]) not in not_equals: + not_equals.add((e[0], e[3])) + + #find contradiction + for n1, n2 in not_equals: + if isConnected(n1, n2): return False + + return True + +""" +For each `!=` equation, if we find two variables are equal (`isConnected()`), we return `False`. +Otherwise, we return `True`. + +[build graph] +First, lets build the graph. +Variables in the same graph means they are all equal. + +[find contradiction] +Second, we find if any "!=" variables (`n1` and `n2`) exist in the same graph. +Starting from `n1`, if we can find `n2` through DFS, they have the same value. + +Time: O(EV). +Building the graph takes O(E). Finding contradiction takes O(EV). +E is the number of edges, in this case, `len(equations)`. +V is the number of nodes, in this case, the unique variables in the equations. + +Space: O(V). For the graph. +""" \ No newline at end of file From cd008660a64d0dc01d98506316827bcc7c68a773 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 24 Aug 2020 19:25:40 +0800 Subject: [PATCH 075/187] no message --- problems/accounts-merge.py | 52 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 problems/accounts-merge.py diff --git a/problems/accounts-merge.py b/problems/accounts-merge.py new file mode 100644 index 0000000..cc553dc --- /dev/null +++ b/problems/accounts-merge.py @@ -0,0 +1,52 @@ +from collections import defaultdict + +class Solution(object): + def accountsMerge(self, accounts): + graph = defaultdict(list) + merged = set() + ans = [] + + #[0] + for data in accounts: + emails = data[1:] + for i, email in enumerate(emails): + graph[email].extend(emails[:i]) + graph[email].extend(emails[i+1:]) + + for data in accounts: + name = data[0] + visited = set() + stack = [data[1]] + + if data[1] in merged: continue #[1] + + while stack: + e = stack.pop() + if e in visited: continue + visited.add(e) + stack.extend(graph[e]) + + merged.update(visited) + ans.append([name]+sorted(list(visited))) + + return ans + +""" +Treat each email as a node. +Build an adjacency graph. [0] + +For every account's data +First, lets check if the first email is already merged. [1] +If the first email is already merged to other groups, then other emails will be in another group as well. +So don't need to check. + +Second, do a DFS starting from the first email. Put all the connected nodes into visited. +And append it to the ans with name. + +Let N be the total number of emails. M be the total number of final groups. +Build the graph takes O(N). +For each final groups, we make a DFS to all nodes, taking O(MN). +Sort the group takes O((N/M)*Log(N/M)) -> O((N/M)*(logN-LogM)) +Time: O(MN) +Space: O(N) +""" \ No newline at end of file From f05cd5118f53ff6f41f15fb72176c926fcb676ce Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 24 Aug 2020 19:26:06 +0800 Subject: [PATCH 076/187] no message --- problems/accounts-merge.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/problems/accounts-merge.py b/problems/accounts-merge.py index cc553dc..30e4787 100644 --- a/problems/accounts-merge.py +++ b/problems/accounts-merge.py @@ -16,7 +16,7 @@ def accountsMerge(self, accounts): for data in accounts: name = data[0] visited = set() - stack = [data[1]] + stack = [data[1]] #[2] if data[1] in merged: continue #[1] @@ -27,7 +27,7 @@ def accountsMerge(self, accounts): stack.extend(graph[e]) merged.update(visited) - ans.append([name]+sorted(list(visited))) + ans.append([name]+sorted(list(visited))) #[3] return ans @@ -40,8 +40,8 @@ def accountsMerge(self, accounts): If the first email is already merged to other groups, then other emails will be in another group as well. So don't need to check. -Second, do a DFS starting from the first email. Put all the connected nodes into visited. -And append it to the ans with name. +Second, do a DFS starting from the first email. Put all the connected nodes into visited. [2] +And append the sorted(visited) to the ans with name. [3] Let N be the total number of emails. M be the total number of final groups. Build the graph takes O(N). From 8fe6976fa2062f2071bb3f1af67db2cee09c70ef Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 9 Oct 2020 19:00:05 +0800 Subject: [PATCH 077/187] no message --- problems/is-graph-bipartite.py | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 problems/is-graph-bipartite.py diff --git a/problems/is-graph-bipartite.py b/problems/is-graph-bipartite.py new file mode 100644 index 0000000..1ef6a4d --- /dev/null +++ b/problems/is-graph-bipartite.py @@ -0,0 +1,38 @@ +from collections import defaultdict + +class Solution(object): + def isBipartite(self, graph): + if not graph: return True + + A, B = set(), set() + stack = [] + + for node in xrange(len(graph)): #[1] + #check if visited, if not start DFS by putting it to stack + if node not in A and node not in B: + stack.append(node) + A.add(node) + + while stack: #[0] + n = stack.pop() + if n in A: + for nei in graph[n]: + if nei in A: return False + if nei not in B: + stack.append(nei) + B.add(nei) + elif n in B: + for nei in graph[n]: + if nei in B: return False + if nei not in A: + stack.append(nei) + A.add(nei) + return True +""" +Use DFS to travserse each node [0] +If the node is in A, all its children should be in B. +If the node is in B, all its children should be in A. + +Not necessary all the nodes in graph are connected. [1] +So we still need to loop the node to check if it is visited. +""" \ No newline at end of file From 0441347f53f2c52d4e35be1cbfa18ca3b773030e Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 13 Oct 2020 10:31:31 +0800 Subject: [PATCH 078/187] no message --- problems/redundant-connection.py | 112 +++++++++++++++++++++++-------- 1 file changed, 85 insertions(+), 27 deletions(-) diff --git a/problems/redundant-connection.py b/problems/redundant-connection.py index 3f7d013..fb938e2 100644 --- a/problems/redundant-connection.py +++ b/problems/redundant-connection.py @@ -1,37 +1,95 @@ +#DFS """ -We use the `roots` to store the root of each node. -For example, at index 1 value is 5, means that node1's root is node5. +For each edge (u, v), traverse the graph with a depth-first search to see if we can connect u to v. If we can, then it must be the duplicate edge. +Time Complexity: O(N^2) +Space Complexity: O(N) +""" +from collections import defaultdict -We use `find()` to find the node's root. In other words, the node's parent's parent's ... -Every node we encounter along the way, we update their root value in `roots` to the up most root. (This technique is called path compression). +class Solution(object): + def findRedundantConnection(self, edges): + def dfs(u, v): + seen = set() + stack = [] + stack.append(u) + + while stack: + node = stack.pop() + seen.add(node) + + if v in G[node]: return True + + for nei in G[node]: + if nei not in seen: + stack.append(nei) + return False + + G = defaultdict(set) + + for u, v in edges: + if u in G and v in G and dfs(u, v): return u, v + G[u].add(v) + G[v].add(u) -So, for every edge, we unify `u` and `v` them. #[1] -Which means u and v and all of their parents all lead to one root. +#Disjoint Set Union +""" +For Disjoint Set Union, see +https://www.youtube.com/watch?v=ID00PMy0-vE +Time Complexity: O(N) +Space Complexity: O(N) +""" +class DSU(object): + def __init__(self): + self.parant = range(1001) + self.rank = [0]*1001 + + def find(self, x): + if self.parant[x]!=x: + self.parant[x] = self.find(self.parant[x]) + return self.parant[x] -If u's root (`ur`) and v's root (`vr`) are already the same before we unify them. -This edge is redundant. + def union(self, x, y): + xr, yr = self.find(x), self.find(y) + if xr==yr: + return False + elif self.rank[xr]>self.rank[yr]: + self.parant[yr] = xr + self.rank[xr] += 1 + else: + self.parant[xr] = yr + self.rank[yr] += 1 + return True -This algorithm is called Union Find, often used in undirected graph cycle detect or grouping. -If you wanted to detect cycles in directed graph, you need to use Topological sort. -""" class Solution(object): def findRedundantConnection(self, edges): - def find(x): - if x != roots[x]: - roots[x] = find(roots[x]) - return roots[x] + dsu = DSU() + for edge in edges: + if not dsu.union(*edge): + return edge - opt = [] - roots = range(len(edges)) - - for u, v in edges: - # union - ur = find(u) - vr = find(v) +#Disjoint Set Union without Ranking +""" +Time Complexity: O(N) +Space Complexity: O(N) +""" +class DSU(object): + def __init__(self): + self.parant = range(1001) + + def find(self, x): + if self.parant[x]!=x: + self.parant[x] = self.find(self.parant[x]) + return self.parant[x] - if ur == vr: #[2] - opt = [u, v] - else: - roots[vr] = ur #[1] + def union(self, x, y): + xr, yr = self.find(x), self.find(y) + if xr==yr: return False + self.parant[yr] = xr + return True - return opt \ No newline at end of file +class Solution(object): + def findRedundantConnection(self, edges): + dsu = DSU() + for edge in edges: + if not dsu.union(*edge): + return edge \ No newline at end of file From 67e86e57ae00aa43ed97c6e8616a620cda544cf9 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 17 Oct 2020 18:38:21 +0800 Subject: [PATCH 079/187] no message --- problems/network-delay-time.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/problems/network-delay-time.py b/problems/network-delay-time.py index 8f016a1..89d9195 100644 --- a/problems/network-delay-time.py +++ b/problems/network-delay-time.py @@ -53,3 +53,28 @@ def networkDelayTime(self, times, N, K): return max(dis.values()) if len(dis)==N else -1 #[5] + +#2020/10/17 +class Solution(object): + def networkDelayTime(self, times, N, K): + ans = float('-inf') + h = [(0, K)] + visited = set() + G = collections.defaultdict(list) + + for u, v, w in times: + G[u].append((v, w)) + + while h: + time, node = heapq.heappop(h) + + if node in visited: continue + visited.add(node) + ans = max(ans, time) + + if len(visited)==N: return time + for nei, time_to_nei in G[node]: + heapq.heappush(h, (time+time_to_nei, nei)) + + return -1 + From 3920ee2548974627eb8ff04487e15dd738cdd24d Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 18 Oct 2020 10:44:02 +0800 Subject: [PATCH 080/187] no message --- problems/egions-cut-by-slashes.py | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 problems/egions-cut-by-slashes.py diff --git a/problems/egions-cut-by-slashes.py b/problems/egions-cut-by-slashes.py new file mode 100644 index 0000000..d53e182 --- /dev/null +++ b/problems/egions-cut-by-slashes.py @@ -0,0 +1,44 @@ +class Solution(object): + def regionsBySlashes(self, grid): + region = 1 + dsu = DSU() + N = len(grid) + + #Union the border lines + for i in xrange(N): + dsu.union((i, 0), (i+1, 0)) + dsu.union((i, N), (i+1, N)) + for j in xrange(N): + dsu.union((0, j), (0, j+1)) + dsu.union((N, j), (N, j+1)) + + #Iterate through slashes and connect the dots + #If the slash connects two already connected dots, the region will increament by one + for i, row in enumerate(grid): + for j, slash in enumerate(row): + if slash=='/': + if not dsu.union((j+1, i), (j, i+1)): + region += 1 + elif slash=='\\': + if not dsu.union((j, i), (j+1, i+1)): + region += 1 + return region + +class DSU(object): + def __init__(self): + self.parant = {} + + def find(self, x): + if x not in self.parant: + self.parant[x] = x + + if self.parant[x]!=x: + self.parant[x] = self.find(self.parant[x]) + + return self.parant[x] + + def union(self, x, y): + xr, yr = self.find(x), self.find(y) + if xr==yr: return False + self.parant[yr] = xr + return True \ No newline at end of file From f96764ad074ade23828e7f37ffce29f213aa1a10 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 9 Nov 2020 15:16:17 +0800 Subject: [PATCH 081/187] no message --- problems/climbing-stairs.py | 22 ++++++++++++- problems/min-cost-climbing-stairs.py | 21 +++++++++++- problems/reconstruct-itinerary.py | 48 ++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 problems/reconstruct-itinerary.py diff --git a/problems/climbing-stairs.py b/problems/climbing-stairs.py index eb207ee..25d973d 100644 --- a/problems/climbing-stairs.py +++ b/problems/climbing-stairs.py @@ -43,4 +43,24 @@ def factorial(int_num): int_num-=1 return counter - return factorial(m)/(factorial(n)*factorial(m-n)) \ No newline at end of file + return factorial(m)/(factorial(n)*factorial(m-n)) + +#2020/11/9 +class Solution(object): + def climbStairs(self, n): + def helper(n): + if n in history: return history[n] + + if n==0 or n==1: + history[n] = 1 + elif n==2: + return 2 + elif n>2: + #combination count of n stairs equals to + #(the combination after you make 1 step as first move) + (the combination after you make 2 steps as first move) + history[n] = helper(n-1) + helper(n-2) + + return history[n] + + history = {} + return helper(n) \ No newline at end of file diff --git a/problems/min-cost-climbing-stairs.py b/problems/min-cost-climbing-stairs.py index 5e2fc97..8579cff 100644 --- a/problems/min-cost-climbing-stairs.py +++ b/problems/min-cost-climbing-stairs.py @@ -20,4 +20,23 @@ def minCostClimbingStairs(self, cost): else: memo[i] = min(memo[i-1]+cost[i-1], memo[i-2]+cost[i-2]) - return memo[-1] \ No newline at end of file + return memo[-1] + +#2020/11/9 +class Solution(object): + def minCostClimbingStairs(self, cost): + def helper(i): + if i in history: return history[i] + + if i>len(cost)-1: + history[i] = 0 + elif i==len(cost)-1 or i==len(cost)-2: + history[i] = cost[i] + elif i Date: Wed, 10 Feb 2021 10:44:21 +0800 Subject: [PATCH 082/187] no message --- ...ime-to-buy-and-sell-stock-with-cooldown.py | 47 +++++++++++++++++++ problems/best-time-to-buy-and-sell-stock.py | 16 +++++++ problems/house-robber-ii.py | 21 ++++++++- problems/house-robber.py | 29 +++++++++++- problems/maximum-subarray.py | 15 +++++- problems/range-sum-query-immutable.py | 13 +++++ 6 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 problems/best-time-to-buy-and-sell-stock-with-cooldown.py create mode 100644 problems/best-time-to-buy-and-sell-stock.py create mode 100644 problems/range-sum-query-immutable.py diff --git a/problems/best-time-to-buy-and-sell-stock-with-cooldown.py b/problems/best-time-to-buy-and-sell-stock-with-cooldown.py new file mode 100644 index 0000000..896caf3 --- /dev/null +++ b/problems/best-time-to-buy-and-sell-stock-with-cooldown.py @@ -0,0 +1,47 @@ +class Solution(object): + def maxProfit(self, prices): + if not prices or len(prices)<=1: return 0 + N = len(prices) + + buy = [-prices[0], max(-prices[1], -prices[0])] + sell = [0, max(prices[1]+buy[0], 0)] + + for i in xrange(2, N): + buy.append(max(sell[i-2]-prices[i], buy[i-1])) + sell.append(max(prices[i]+buy[i-1], sell[i-1])) + + return max(buy[-1], sell[-1], 0) + +""" +Three rules: +1. Need to buy before sell. +2. After sell, next day need to rest (cannot buy). +3. When buying, we spend money, which is a negative profit. + +There are two possible end state. buy or sell. So we need to consider both. +Only considering prices 0~i, buy[i] stores the max profit that the last action is "buy". +Only considering prices 0~i, sell[i] stores the max profit that the last action is "sell". + +Let's sort this out. +When i==0: +buy: -prices[0] +sell: 0, since we cannot sell at i==0. + +When i==1: +buy: max(-prices[1], -prices[0]) +Now, we must not have sell yet. So no need to consider it. +If we buy at i==1, the profit will be `-prices[1]`. But we also had the option not to buy. buy[0] is the max profit if we don't buy at i==1. +Again, we are considering, when the end state is "buy", what is the max profit? +Thus, `max(-prices[1], buy[0])`. + +sell: max(prices[1]+buy[0], 0) +If we sell at i==1, the profit will be `prices[1]+buy[0]`. But we also had the option not to sell. 0 is the max profit if we don't sell at i==1. +Again, we are considering, when the end state is "sell", what is the max profit? +Thus, `max(prices[1]+buy[0], sell[0])` + +When i>=2: + + + + +""" \ No newline at end of file diff --git a/problems/best-time-to-buy-and-sell-stock.py b/problems/best-time-to-buy-and-sell-stock.py new file mode 100644 index 0000000..b4a9abc --- /dev/null +++ b/problems/best-time-to-buy-and-sell-stock.py @@ -0,0 +1,16 @@ +""" +To accomplish 0(N) solution: +For each i and price in the iteration, we need to keep track of the loest price before i. +Also, update the max_profit in the iteration. +""" +class Solution(object): + def maxProfit(self, prices): + if not prices: return 0 + max_profit = 0 + lowest = prices[0] + + for i in xrange(len(prices)): + if i==0: continue + max_profit = max(max_profit, prices[i]-lowest) + lowest = min(lowest, prices[i]) + return max_profit \ No newline at end of file diff --git a/problems/house-robber-ii.py b/problems/house-robber-ii.py index 70c2086..5bdc6b3 100644 --- a/problems/house-robber-ii.py +++ b/problems/house-robber-ii.py @@ -39,4 +39,23 @@ def rob(self, nums): else: K[i] = K[i-1]+nums[i] v2 = K[-1] - return max(v1, v2) \ No newline at end of file + return max(v1, v2) + +#2020/11/15 +class Solution(object): + def rob(self, nums): + if not nums: return 0 + if len(nums)==0 or len(nums)==1: return max(nums) + N = len(nums) + + v1 = nums[0] + v2 = nums[0] + for i in xrange(2, N-1): + v1, v2 = max(nums[i]+v2, v1), v1 + + w1 = nums[1] + w2 = 0 + for i in xrange(2, N): + w1, w2 = max(nums[i]+w2, w1), w1 + + return max(v1, w1) \ No newline at end of file diff --git a/problems/house-robber.py b/problems/house-robber.py index f3cb34b..f93f238 100644 --- a/problems/house-robber.py +++ b/problems/house-robber.py @@ -26,4 +26,31 @@ def rob(self, nums): K[i] = max(K[i-2]+nums[i], K[i-1]) else: #[2] K[i] = K[i-1]+nums[i] - return K[-1] \ No newline at end of file + return K[-1] + +#2020/11/14 +class Solution(object): + def rob(self, nums): + def helper(i): + if i>=len(nums): return 0 + if i in history: return history[i] + history[i] = max(nums[i]+helper(i+2), helper(i+1)) + return history[i] + + history = {} + return helper(0) + +#2020/11/14 +class Solution(object): + def rob(self, nums): + if not nums: return 0 + if len(nums)==0 or len(nums)==1: return max(nums) + + last1 = max(nums[0], nums[1]) + last2 = nums[0] + + for i in xrange(len(nums)): + if i==0 or i==1: continue + last2, last1 = last1, max(nums[i]+last2, last1) + + return last1 \ No newline at end of file diff --git a/problems/maximum-subarray.py b/problems/maximum-subarray.py index b04bc92..5b02f03 100644 --- a/problems/maximum-subarray.py +++ b/problems/maximum-subarray.py @@ -19,4 +19,17 @@ def maxSubArray(self, nums): maxCurrent = [nums[0]] #[1] for i in xrange(1, len(nums)): maxCurrent.append(max(nums[i], nums[i]+maxCurrent[-1])) #[0] - return max(maxCurrent) #[2] \ No newline at end of file + return max(maxCurrent) #[2] + +# 2020/11/14 +class Solution(object): + def maxSubArray(self, nums): + ans = nums[0] + last_max = nums[0] + + for i in xrange(len(nums)): + if i==0: continue + last_max = max(nums[i], nums[i]+last_max) + ans = max(ans, last_max) + + return ans \ No newline at end of file diff --git a/problems/range-sum-query-immutable.py b/problems/range-sum-query-immutable.py new file mode 100644 index 0000000..74a0e06 --- /dev/null +++ b/problems/range-sum-query-immutable.py @@ -0,0 +1,13 @@ +class NumArray(object): + def __init__(self, nums): + #total[i] = nums[0]+nums[1]+...+nums[i] + self.total = [] + + #initialize total + temp = 0 + for num in nums: + temp += num + self.total.append(temp) + + def sumRange(self, i, j): + return self.total[j] - self.total[i-1] if i>0 else self.total[j] \ No newline at end of file From 48e14b0a2c22014026adb709f855010ce5b3253b Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 19 Feb 2021 18:42:19 +0800 Subject: [PATCH 083/187] no message --- problems/delete-and-earn.py | 14 +++++++ problems/domino-and-tromino-tiling.py | 11 ++++++ ...imum-swaps-to-make-sequences-increasing.py | 19 +++++++++ problems/perfect-squares.py | 39 +++++++++++++++++++ problems/word-break.py | 17 ++++++++ 5 files changed, 100 insertions(+) create mode 100644 problems/delete-and-earn.py create mode 100644 problems/domino-and-tromino-tiling.py create mode 100644 problems/minimum-swaps-to-make-sequences-increasing.py create mode 100644 problems/perfect-squares.py create mode 100644 problems/word-break.py diff --git a/problems/delete-and-earn.py b/problems/delete-and-earn.py new file mode 100644 index 0000000..90804f3 --- /dev/null +++ b/problems/delete-and-earn.py @@ -0,0 +1,14 @@ +import collections + +class Solution(object): + def deleteAndEarn(self, nums): + if not nums: return 0 + m = min(nums) + M = max(nums) + c = collections.Counter(nums) + + prev = 0 + curr = 0 + for n in xrange(m, M+1): + prev, curr = curr, max(prev+n*c[n], curr) + return curr \ No newline at end of file diff --git a/problems/domino-and-tromino-tiling.py b/problems/domino-and-tromino-tiling.py new file mode 100644 index 0000000..9f9e04a --- /dev/null +++ b/problems/domino-and-tromino-tiling.py @@ -0,0 +1,11 @@ +class Solution(object): + def numTilings(self, N): + H = [[0, 0] for _ in xrange(N+1)] + H[0][0] = 1 + H[1][0] = 1 + + for i in xrange(2, N+1): + H[i][0] = (H[i-1][0] + H[i-2][0] + H[i-1][1]*2) % 1000000007 + H[i][1] = (H[i-2][0] + H[i-1][1]) % 1000000007 + + return H[N][0] \ No newline at end of file diff --git a/problems/minimum-swaps-to-make-sequences-increasing.py b/problems/minimum-swaps-to-make-sequences-increasing.py new file mode 100644 index 0000000..73ac97b --- /dev/null +++ b/problems/minimum-swaps-to-make-sequences-increasing.py @@ -0,0 +1,19 @@ +class Solution(object): + def minSwap(self, A, B): + keep = [float('inf') for _ in xrange(len(A))] + swap = [float('inf') for _ in xrange(len(A))] + + keep[0] = 0 + swap[0] = 1 + + for i in xrange(1, len(A)): + + if A[i]>A[i-1] and B[i]>B[i-1]: + keep[i] = keep[i-1] + swap[i] = swap[i-1]+1 + + if A[i]>B[i-1] and B[i]>A[i-1]: + keep[i] = min(keep[i], swap[i-1]) + swap[i] = min(swap[i], keep[i-1]+1) + + return min(keep[-1], swap[-1]) \ No newline at end of file diff --git a/problems/perfect-squares.py b/problems/perfect-squares.py new file mode 100644 index 0000000..8123dc9 --- /dev/null +++ b/problems/perfect-squares.py @@ -0,0 +1,39 @@ +#Recursive +class Solution(object): + def numSquares(self, n): + def helper(n): + if not n: return 0 + if n in history: return history[n] + + elements = [e**2 for e in range(2, int(n**0.5)+1)] + ans = n + + for e in reversed(elements): + count_of_element = int(n/e) + n_approximate = count_of_element*e + ans = min(ans, count_of_element+helper(n-n_approximate)) + + history[n] = ans + return history[n] + + history = {1:1, 2:2, 3:3} + return helper(n) + +#DP +class Solution(object): + def numSquares(self, N): + squares = [s**2 for s in range(2, int(N**0.5)+1)] + + dp = [n for n in xrange(N+1)] + + for n in xrange(N+1): + for square in squares: + if square>n: + break + elif square==n: + dp[n] = 1 + break + else: + dp[n] = min(dp[n], dp[square]+dp[n-square]) + return dp[N] + \ No newline at end of file diff --git a/problems/word-break.py b/problems/word-break.py new file mode 100644 index 0000000..b2fd2de --- /dev/null +++ b/problems/word-break.py @@ -0,0 +1,17 @@ +class Solution(object): + def wordBreak(self, s, wordDict): + def helper(s_left): + if not s_left: return True + if s_left in history: return history[s_left] + + for word in wordDict: + if len(s_left) Date: Wed, 3 Mar 2021 09:42:15 +0800 Subject: [PATCH 084/187] no message --- problems/delete-operation-for-two-strings.py | 28 ++++++++ problems/filling-bookcase-shelves.py | 25 +++++++ problems/longest-increasing-subsequence.py | 34 ++++++++++ problems/longest-string-chain.py | 68 +++++++++++++++++++ ...umber-of-longest-increasing-subsequence.py | 29 ++++++++ problems/palindrome-partitioning.py | 2 +- problems/unique-binary-search-trees.py | 14 ++++ 7 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 problems/delete-operation-for-two-strings.py create mode 100644 problems/filling-bookcase-shelves.py create mode 100644 problems/longest-increasing-subsequence.py create mode 100644 problems/longest-string-chain.py create mode 100644 problems/number-of-longest-increasing-subsequence.py create mode 100644 problems/unique-binary-search-trees.py diff --git a/problems/delete-operation-for-two-strings.py b/problems/delete-operation-for-two-strings.py new file mode 100644 index 0000000..24ddeb1 --- /dev/null +++ b/problems/delete-operation-for-two-strings.py @@ -0,0 +1,28 @@ +class Solution(object): + def minDistance(self, word1, word2): + N = len(word1) + M = len(word2) + + dp = [[float('inf') for _ in xrange(M+1)] for _ in xrange(N+1)] + + + for i in xrange(1, N+1): dp[i][0] = i #need i deletion for word1[0:i-1] to be "" + for j in xrange(1, M+1): dp[0][j] = j #need i deletion for word1[0:j-1] to be "" + dp[0][0] = 0 + + for i in xrange(1, N+1): + for j in xrange(1, M+1): + #dp[i][j] := min operation count for dp[0:i] and dp[0:j-1] to be the same. + + #if char at i-1 and j-1 are the same, no deletion needed. + if word1[i-1]==word2[j-1]: + dp[i][j] = min(dp[i][j], dp[i-1][j-1]) + + dp[i][j] = min(dp[i][j], dp[i][j-1]+1) #remove char on word2[j-1] + dp[i][j] = min(dp[i][j], dp[i-1][j]+1) #remove char on word1[i-1] + return dp[N][M] + +""" +Time: O(MN) +Space: O(MN) +""" \ No newline at end of file diff --git a/problems/filling-bookcase-shelves.py b/problems/filling-bookcase-shelves.py new file mode 100644 index 0000000..3aa50a8 --- /dev/null +++ b/problems/filling-bookcase-shelves.py @@ -0,0 +1,25 @@ +""" +dp[i] := min height when storing books 0~i +for each j try to add a new line at i, see the min height. + +Time: O(N^2) +Space: O(N) +""" +class Solution(object): + def minHeightShelves(self, books, shelf_width): + N = len(books) + dp = [float('inf')]*N + + for j in xrange(N): + w = 0 + h = 0 + for i in xrange(j, -1, -1): + w+=books[i][0] + if w>shelf_width: break + + h = max(h, books[i][1]) + if i==0: + dp[j] = min(dp[j], h) + else: + dp[j] = min(dp[j], dp[i-1]+h) + return dp[-1] \ No newline at end of file diff --git a/problems/longest-increasing-subsequence.py b/problems/longest-increasing-subsequence.py new file mode 100644 index 0000000..0f61189 --- /dev/null +++ b/problems/longest-increasing-subsequence.py @@ -0,0 +1,34 @@ +from bisect import bisect_left + +class Solution(object): + def lengthOfLIS(self, nums): + dp = [1 for _ in nums] + + for i in xrange(1, len(nums)): + for j in xrange(i-1, -1, -1): + if nums[j]nums[j]: + if L[j]+1==L[i]: + # If L[j]+1==L[i], it means that the combination of L[j] can simply append nums[i] and reach L[i] + # So add the C[j] to C[i] + C[i] += C[j] + elif L[j]+1>L[i]: + # If L[j]+1==L[i], it means that the combination of L[j] can simply append nums[i] and exceed L[i] + # So update L[i] to L[j]+1 and C[i] to C[j] + L[i] = L[j]+1 + C[i] = C[j] + + max_length = max(L) + max_length_count = 0 + for i, count in enumerate(C): + if L[i]==max_length: + max_length_count+=count + return max_length_count + +""" +Time: O(N^2) +Spance: O(1) +""" \ No newline at end of file diff --git a/problems/palindrome-partitioning.py b/problems/palindrome-partitioning.py index cf4536b..e9000db 100644 --- a/problems/palindrome-partitioning.py +++ b/problems/palindrome-partitioning.py @@ -11,4 +11,4 @@ def search(s, pal_list): search(s[i:], pal_list+[s[:i]]) opt = [] search(S, []) - return opt + return opt \ No newline at end of file diff --git a/problems/unique-binary-search-trees.py b/problems/unique-binary-search-trees.py new file mode 100644 index 0000000..65dd64e --- /dev/null +++ b/problems/unique-binary-search-trees.py @@ -0,0 +1,14 @@ + +# Implement from https://www.youtube.com/watch?v=GgP75HAvrlY +class Solution(object): + def numTrees(self, n): + dp = [1, 1, 2] + + if n<=2: return dp[n] + + for i in xrange(3, n+1): + dp.append(0) + for root in xrange(1, i+1): + dp[i] += dp[root-1]*dp[i-root] + + return dp[n] \ No newline at end of file From e18641c5605b275b703966677a15ef87ace3443c Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 6 Mar 2021 10:29:47 +0800 Subject: [PATCH 085/187] no message --- problems/longest-common-subsequence.py | 20 +++++++++++++++ .../maximum-length-of-repeated-subarray.py | 13 ++++++++++ ...inimum-ascii-delete-sum-for-two-strings.py | 25 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 problems/longest-common-subsequence.py create mode 100644 problems/maximum-length-of-repeated-subarray.py create mode 100644 problems/minimum-ascii-delete-sum-for-two-strings.py diff --git a/problems/longest-common-subsequence.py b/problems/longest-common-subsequence.py new file mode 100644 index 0000000..450c2bc --- /dev/null +++ b/problems/longest-common-subsequence.py @@ -0,0 +1,20 @@ +class Solution(object): + def longestCommonSubsequence(self, text1, text2): + M, N = len(text1), len(text2) + + #dp[i][j] := logest subsequence of text1[0:i-1] and text[0:j-1] + dp = [[0 for _ in xrange(N+1)] for _ in xrange(M+1)] + + for i in xrange(1, M+1): + for j in xrange(1, N+1): + if text1[i-1]==text2[j-1]: + dp[i][j] = dp[i-1][j-1]+1 + else: + dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + + return dp[M][N] + +""" +Time: O(MN) +Space: O(MN) +""" \ No newline at end of file diff --git a/problems/maximum-length-of-repeated-subarray.py b/problems/maximum-length-of-repeated-subarray.py new file mode 100644 index 0000000..dc099ec --- /dev/null +++ b/problems/maximum-length-of-repeated-subarray.py @@ -0,0 +1,13 @@ +class Solution(object): + def findLength(self, A, B): + M, N = len(A), len(B) + + #dp[i][j] := the logest length of sub array that needs to involve A[i] and B[j] + dp = [[0 for _ in xrange(N+1)] for _ in xrange(M+1)] + + for i in xrange(1, M+1): + for j in xrange(1, N+1): + if A[i-1]==B[j-1]: + dp[i][j] = dp[i-1][j-1]+1 + + return max(max(row) for row in dp) \ No newline at end of file diff --git a/problems/minimum-ascii-delete-sum-for-two-strings.py b/problems/minimum-ascii-delete-sum-for-two-strings.py new file mode 100644 index 0000000..6618413 --- /dev/null +++ b/problems/minimum-ascii-delete-sum-for-two-strings.py @@ -0,0 +1,25 @@ +class Solution(object): + def minimumDeleteSum(self, s1, s2): + N, M = len(s1), len(s2) + dp = [[float('inf') for _ in xrange(M+1)] for _ in xrange(N+1)] + + dp[0][0] = 0 + + for i in xrange(1, N+1): + dp[i][0] = dp[i-1][0]+ord(s1[i-1]) + + for j in xrange(1, M+1): + dp[0][j] = dp[0][j-1]+ord(s2[j-1]) + + for i in xrange(1, N+1): + for j in xrange(1, M+1): + if s1[i-1]==s2[j-1]: + dp[i][j] = min(dp[i][j], dp[i-1][j-1]) + dp[i][j] = min(dp[i][j], dp[i][j-1]+ord(s2[j-1]), dp[i-1][j]+ord(s1[i-1])) + + return dp[N][M] + +""" +Time: O(MN) +Space: O(MN) +""" \ No newline at end of file From dc8487397ec361887aa1321b345b16b043bbbf12 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 7 Mar 2021 17:15:49 +0800 Subject: [PATCH 086/187] no message --- problems/maximal-square.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 problems/maximal-square.py diff --git a/problems/maximal-square.py b/problems/maximal-square.py new file mode 100644 index 0000000..4ba17d6 --- /dev/null +++ b/problems/maximal-square.py @@ -0,0 +1,13 @@ +class Solution(object): + def maximalSquare(self, grid): + if not grid or not grid[0]: return + M, N = len(grid), len(grid[0]) + + dp = [[0 for _ in xrange(N+1)] for _ in xrange(M+1)] + ans = 0 + for i in xrange(M): + for j in xrange(N): + if grid[i][j]=='1': + dp[i+1][j+1] = min(dp[i][j], dp[i][j+1], dp[i+1][j])+1 + ans = max(ans, dp[i+1][j+1]) + return ans**2 \ No newline at end of file From 464fe6bc3c06aad9d10c5ba0d3e39b8eb198e8cb Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 10 Apr 2021 17:39:43 +0800 Subject: [PATCH 087/187] no message --- problems/coin-change.py | 39 ++++++++++++ problems/generate-parentheses.py | 14 +++++ problems/knight-dialer.py | 65 ++++++++++++++++++++ problems/knight-probability-in-chessboard.py | 27 ++++++++ problems/largest-1-bordered-square.py | 46 ++++++++++++++ problems/out-of-boundary-paths.py | 26 ++++++++ 6 files changed, 217 insertions(+) create mode 100644 problems/coin-change.py create mode 100644 problems/knight-dialer.py create mode 100644 problems/knight-probability-in-chessboard.py create mode 100644 problems/largest-1-bordered-square.py create mode 100644 problems/out-of-boundary-paths.py diff --git a/problems/coin-change.py b/problems/coin-change.py new file mode 100644 index 0000000..2c0d299 --- /dev/null +++ b/problems/coin-change.py @@ -0,0 +1,39 @@ +# DP +class Solution(object): + def coinChange(self, coins, amount): + dp = [float('inf')]*(amount+1) + + if amount==0: return 0 + + dp[0] = 0 + for coin in coins: + if coin<=amount: + dp[coin] = 1 + + for a in xrange(amount+1): + for coin in coins: + if a-coin>=0: + dp[a] = min(dp[a], dp[a-coin]+1) + + return dp[amount] if dp[amount]!=float('inf') else -1 + +# BFS +import collections +class Solution(object): + def coinChange(self, coins, amount): + visited = set() + + coins.sort(reverse=True) + q = collections.deque([(0, 0)]) + + while q: + current_amount, count = q.popleft() + + if current_amount==amount: return count + if current_amount>amount: continue + if current_amount in visited: continue + visited.add(current_amount) + + for coin in coins: + q.append((current_amount+coin, count+1)) + return -1 \ No newline at end of file diff --git a/problems/generate-parentheses.py b/problems/generate-parentheses.py index fb3ba3b..b2d5b70 100644 --- a/problems/generate-parentheses.py +++ b/problems/generate-parentheses.py @@ -20,3 +20,17 @@ def dfs(path, open_count, open_remain, close_remain): opt = [] dfs('', 0, N, N) return opt + + +class Solution(object): + def generateParenthesis(self, N): + def helper(open_remain, close_remain, s): + if open_remain==0 and close_remain==0: + ans.append(s) + if close_remain>open_remain and close_remain>0: + helper(open_remain, close_remain-1, s+')') + if open_remain>0: + helper(open_remain-1, close_remain, s+'(') + ans = [] + helper(N, N, '') + return ans diff --git a/problems/knight-dialer.py b/problems/knight-dialer.py new file mode 100644 index 0000000..1342ed0 --- /dev/null +++ b/problems/knight-dialer.py @@ -0,0 +1,65 @@ +class Solution(object): + def knightDialer(self, n): + def helper(initial, n): + # return the number of posible count starting from initial with n steps left + + if str(initial)+'-'+str(n) in history: return history[str(initial)+'-'+str(n)] + count = 0 + + if n==0: return 1 + for next_number in memo[initial]: + count += helper(next_number, n-1) + + history[str(initial)+'-'+str(n)] = count + return count + + memo = { + 1: [6, 8], + 2: [7, 9], + 3: [4, 8], + 4: [0, 3, 9], + 5: [], + 6: [0, 1, 7], + 7: [2, 6], + 8: [1, 3], + 9: [2, 4], + 0: [4, 6] + } + + history = {} + count = 0 + + for i in xrange(10): + count += helper(i, n-1) + return count % 1000000007 + +""" +dp[n][i] := number of ways to ends at number i after n moves. + +Time: O(N). +Space: O(N). Can reduce to O(1). +""" +class Solution(object): + def knightDialer(self, n): + dp = [[0 for _ in xrange(10)] for _ in xrange(n)] + for i in xrange(10): dp[0][i] = 1 #initialize + + memo = { + 1: [6, 8], + 2: [7, 9], + 3: [4, 8], + 4: [0, 3, 9], + 5: [], + 6: [0, 1, 7], + 7: [2, 6], + 8: [1, 3], + 9: [2, 4], + 0: [4, 6] + } + + for j in xrange(n-1): + for i in xrange(10): + for next_n in memo[i]: + dp[j+1][next_n] += dp[j][i] + + return sum(dp[n-1]) % 1000000007 \ No newline at end of file diff --git a/problems/knight-probability-in-chessboard.py b/problems/knight-probability-in-chessboard.py new file mode 100644 index 0000000..427e3fb --- /dev/null +++ b/problems/knight-probability-in-chessboard.py @@ -0,0 +1,27 @@ +class Solution(object): + def knightProbability(self, N, K, r, c): + if K==0: return 1 + + dp = [[[0 for _ in xrange(N)] for _ in xrange(N)] for _ in xrange(K+1)] + + dp[0][r][c] = 1 + possible = float(0) + + for k in xrange(1, K+1): + for i in xrange(N): + for j in xrange(N): + if dp[k-1][i][j]>0: + for x, y in [(i+1, j+2), (i-1, j+2), (i+1, j-2), (i-1, j-2), (i+2, j+1), (i-2, j+1), (i+2, j-1), (i-2, j-1)]: + if 0<=x and x=k and dp[i+1][j+1-k+1][0]>=k: + ans = max(ans, k**2) + break + + elif grid[i][j]==0: + #[0] + dp[i+1][j+1][0] = 0 + dp[i+1][j+1][1] = 0 + + return ans + +""" +[0] +dp[i+1][j+1][0] := number of the vertical continuous `1`s above grid[i][j] +dp[i+1][j+1][0] := number of the vertical continuous `1`s left to grid[i][j] + +For each i and j + Imagine (i, j) is the bottom-right dot of the square. + [1] First, check the max length of the square: K. (through min(number of the vertical continuous `1`s above the bottom-right dot, number of the vertical continuous `1`s left to the bottom-right dot).) + [2] Then, for each possible k, checking from large to small + Get the number of the vertical continuous `1`s above the bottom-left dot. + Get the number of the vertical continuous `1`s left to the top-right dot. + See if they are large enough to form square with border==k. + +Time: O(N^3) assume that the N is the length of the grid and grid[0]. +Space: O(N^2) +""" \ No newline at end of file diff --git a/problems/out-of-boundary-paths.py b/problems/out-of-boundary-paths.py new file mode 100644 index 0000000..03fbd63 --- /dev/null +++ b/problems/out-of-boundary-paths.py @@ -0,0 +1,26 @@ +""" +dp[k][i][j] := number of ways to get to (i, j) +dp[k+1][i][j] = sum(dp[k][x][y]) for all (x, y) that can get to (i, j) +For each k and i and j, also accumulate the ans + +Time: O(KMN) +Space: O(KMN) +""" + +class Solution(object): + def findPaths(self, M, N, K, i, j): + ans = 0 + + dp = [[[0 for _ in xrange(N)] for _ in xrange(M)] for _ in xrange(K+1)] + dp[0][i][j] = 1 + + for k in xrange(K): + for i in xrange(M): + for j in xrange(N): + if dp[k][i][j]>0: + for x, y in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]: + if x<0 or x>=M or y<0 or y>=N: + ans+=dp[k][i][j] + else: + dp[k+1][x][y]+=dp[k][i][j] + return ans % (1000000007) \ No newline at end of file From a0aaa90151df1e0ecf698f5ceafb4a7eba09ab98 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 19 Apr 2021 16:27:19 +0800 Subject: [PATCH 088/187] no message --- problems/combination-sum-iv.py | 24 ++++++++++++++++ problems/last-stone-weight-ii.py | 29 +++++++++++++++++++ problems/last-stone-weight.py | 26 +++++++++++++++++ problems/partition-array-for-maximum-sum.py | 14 ++++++++++ problems/target-sum.py | 31 +++++++++++++++++++++ 5 files changed, 124 insertions(+) create mode 100644 problems/combination-sum-iv.py create mode 100644 problems/last-stone-weight-ii.py create mode 100644 problems/last-stone-weight.py create mode 100644 problems/partition-array-for-maximum-sum.py create mode 100644 problems/target-sum.py diff --git a/problems/combination-sum-iv.py b/problems/combination-sum-iv.py new file mode 100644 index 0000000..9aa59b3 --- /dev/null +++ b/problems/combination-sum-iv.py @@ -0,0 +1,24 @@ +class Solution(object): + def combinationSum4(self, nums, target): + def helper(t): + if t<0: return 0 + if dp[t]>=0: return dp[t] + + ans = 0 + for num in nums: + ans += helper(t-num) + + dp[t] = ans + return ans + + dp = [-1]*(target+1) + dp[0] = 1 + + for i in xrange(target+1): + helper(i) + return dp[target] + +""" +Time: O(TN), T is the value of target and N is the count of nums. +Space: O(T) +""" \ No newline at end of file diff --git a/problems/last-stone-weight-ii.py b/problems/last-stone-weight-ii.py new file mode 100644 index 0000000..8fa2fde --- /dev/null +++ b/problems/last-stone-weight-ii.py @@ -0,0 +1,29 @@ +""" +dp[i][t] = considering stones[0~i-1], if it can sum up to target t + +Time: O(SN), S is the sum of stone weight. N is the number of stones. +Space: O(SN), can reduce to O(S). +""" +class Solution(object): + def lastStoneWeightII(self, stones): + total = sum(stones) + target = total/2 + dp = [[False for _ in xrange(target+1)] for _ in xrange(len(stones)+1)] + dp[0][0] = True + + maxSum = 0 + # Keep trace of the max sum that stones can sum up to. + + for i in xrange(1, len(stones)+1): + for t in xrange(target+1): + if (dp[i-1][t] or (t-stones[i-1]>=0 and dp[i-1][t-stones[i-1]])): + # it can sum up to t considering stones[0~i-2] + # OR + # it can sum up to t considering stones[0~i-1] + dp[i][t] = True + maxSum = max(maxSum, t) + if t==target: return total-maxSum*2 + + # Two collection of stones will be total-maxSum and maxSum + # (total-maxSum) - maxSum => total-maxSum*2 + return total-maxSum*2 diff --git a/problems/last-stone-weight.py b/problems/last-stone-weight.py new file mode 100644 index 0000000..dcfaadc --- /dev/null +++ b/problems/last-stone-weight.py @@ -0,0 +1,26 @@ +import bisect +class Solution(object): + def lastStoneWeight(self, stones): + stones.sort() + + while len(stones)>1: + x = stones.pop() + y = stones.pop() + bisect.insort_left(stones, abs(x-y)) + + return 0 if not stones else stones[0] + +import heapq +class Solution(object): + def lastStoneWeight(self, stones): + h = [] + + for stone in stones: + heapq.heappush(h, stone*-1) + + while len(h)>1: + x = heapq.heappop(h) + y = heapq.heappop(h) + heapq.heappush(h, abs(x-y)*-1) + + return 0 if not h else abs(h[0]) \ No newline at end of file diff --git a/problems/partition-array-for-maximum-sum.py b/problems/partition-array-for-maximum-sum.py new file mode 100644 index 0000000..b4d8f3b --- /dev/null +++ b/problems/partition-array-for-maximum-sum.py @@ -0,0 +1,14 @@ +""" +dp[i] = maxSumAfterPartitioning(A[0~i-1], K) and must contain A[i-1] +""" +class Solution(object): + def maxSumAfterPartitioning(self, A, K): + dp = [0 for _ in xrange(len(A)+1)] + + for i in xrange(1, len(A)+1): + m = float('-inf') # max in A[i-k]~A[i-1] + for k in xrange(1, min(i+1, K+1)): + m = max(m, A[i-k]) + dp[i] = max(dp[i], m*k + dp[i-k]) + + return dp[-1] \ No newline at end of file diff --git a/problems/target-sum.py b/problems/target-sum.py new file mode 100644 index 0000000..bccb65c --- /dev/null +++ b/problems/target-sum.py @@ -0,0 +1,31 @@ +class Solution(object): + def findTargetSumWays(self, nums, S): + stack = [(0, 0)] + ans = 0 + + while stack: + i, s = stack.pop() + if i==len(nums) and s==S: ans += 1 + if i>=len(nums): continue + + stack.append((i+1, s+nums[i])) + stack.append((i+1, s-nums[i])) + + return ans + +import collections + + + +class Solution(object): + def findTargetSumWays(self, nums, target): + S = sum(nums) + dp = [collections.Counter() for _ in xrange(len(nums)+1)] + dp[0][0] = 1 + + for i in xrange(1, len(nums)+1): + for j in xrange(-S, S+1): + dp[i][j] = dp[i-1][j+nums[i-1]] + dp[i-1][j-nums[i-1]] + + return dp[len(nums)][target] + \ No newline at end of file From 3fd9514ab99c4fc18abded0ac9a834572faec458 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 16 May 2021 15:11:32 +0800 Subject: [PATCH 089/187] no message --- README.md | 5 ++ problems/greatest-sum-divisible-by-three.py | 66 +++++++++++++++++++ .../minimum-score-triangulation-of-polygon.py | 16 +++++ problems/partition-array-for-maximum-sum.py | 2 +- problems/stone-game-ii.py | 17 +++++ problems/target-sum.py | 8 ++- 6 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 problems/greatest-sum-divisible-by-three.py create mode 100644 problems/minimum-score-triangulation-of-polygon.py create mode 100644 problems/stone-game-ii.py diff --git a/README.md b/README.md index ae3fa11..9f316ce 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,9 @@ https://github.com/wuduhren/leetcode-python For example, `merge-sorted-array.py`'s solution is at `https://leetcode.com/problems/merge-sorted-array/`. +# Leetcode 74 Classic Problem +https://leetcode.com/list/?selectedList=535ukjh5 + # Leetcode Similar Problems I found it makes sense to solve similar problems together, so that we can recognize the problem faster when we encounter a new one. My suggestion is to skip the HARD problems when you first go through these list. @@ -188,6 +191,8 @@ If you are new or know nothing about data structures and algorithms, I recommend 4. [Narendra's Youtube Channel](https://www.youtube.com/channel/UCn1XnDWhsLS5URXTi5wtFTA/playlists) +5. [System Design Primer](https://github.com/donnemartin/system-design-primer) + # Knowledge Base Question 1. [Session vs Cookie](https://medium.com/@chriswrite/session-vs-cookie-software-engineer-top-asked-question-1-9bdbc0766739) diff --git a/problems/greatest-sum-divisible-by-three.py b/problems/greatest-sum-divisible-by-three.py new file mode 100644 index 0000000..948e01b --- /dev/null +++ b/problems/greatest-sum-divisible-by-three.py @@ -0,0 +1,66 @@ +#DP +""" +Time: O(N) +Space: O(N). Can reduce to O(1). + +dp[i][0] max number n, which n%3==0, considering nums[0~i-1] +dp[i][1] max number n, which n%3==1, considering nums[0~i-1] +dp[i][2] max number n, which n%3==2, considering nums[0~i-1] +""" +class Solution(object): + def maxSumDivThree(self, nums): + dp = [[0]*3 for _ in xrange(len(nums)+1)] + + for i in xrange(len(nums)+1): + if i==0: + dp[i][0] = 0 + dp[i][1] = float('-inf') + dp[i][2] = float('-inf') + continue + + n = nums[i-1] + + if n%3==0: + dp[i][0] = max(dp[i-1][0], dp[i-1][0]+n) + dp[i][1] = max(dp[i-1][1], dp[i-1][1]+n) + dp[i][2] = max(dp[i-1][2], dp[i-1][2]+n) + elif n%3==1: + dp[i][0] = max(dp[i-1][0], dp[i-1][2]+n) + dp[i][1] = max(dp[i-1][1], dp[i-1][0]+n) + dp[i][2] = max(dp[i-1][2], dp[i-1][1]+n) + elif n%3==2: + dp[i][0] = max(dp[i-1][0], dp[i-1][1]+n) + dp[i][1] = max(dp[i-1][1], dp[i-1][2]+n) + dp[i][2] = max(dp[i-1][2], dp[i-1][0]+n) + + return dp[-1][0] + +# Greedy +class Solution(object): + def videoStitching(self, clips, T): + if T==0: return 0 + if not clips: return -1 + + clips.sort() + print clips + + if clips[0][0]!=0: return -1 + if clips[0][1]>=T: return 1 + + count = 0 + i = 0 + rightMost = 0 + + while i= T: return count + + return -1 \ No newline at end of file diff --git a/problems/minimum-score-triangulation-of-polygon.py b/problems/minimum-score-triangulation-of-polygon.py new file mode 100644 index 0000000..96c60a3 --- /dev/null +++ b/problems/minimum-score-triangulation-of-polygon.py @@ -0,0 +1,16 @@ +class Solution(object): + def minScoreTriangulation(self, values): + N = len(values) + dp = [[float('inf')]*N for _ in xrange(N)] + + for i in xrange(N-1): + dp[i][i+1] = 0 + + for l in xrange(3, N+1): + for i in xrange(N-l+1): + j = i+l-1 + + for k in xrange(i+1, j): + dp[i][j] = min(dp[i][j], dp[i][k]+values[i]*values[k]*values[j]+dp[k][j]) + return dp[0][N-1] + \ No newline at end of file diff --git a/problems/partition-array-for-maximum-sum.py b/problems/partition-array-for-maximum-sum.py index b4d8f3b..d941484 100644 --- a/problems/partition-array-for-maximum-sum.py +++ b/problems/partition-array-for-maximum-sum.py @@ -1,5 +1,5 @@ """ -dp[i] = maxSumAfterPartitioning(A[0~i-1], K) and must contain A[i-1] +dp[i] = max(k*max(A[i-k]~A[i]) + dp[i-k]) for k in 1~K. """ class Solution(object): def maxSumAfterPartitioning(self, A, K): diff --git a/problems/stone-game-ii.py b/problems/stone-game-ii.py new file mode 100644 index 0000000..a213646 --- /dev/null +++ b/problems/stone-game-ii.py @@ -0,0 +1,17 @@ +class Solution(object): + def stoneGameII(self, piles): + def helper(start, m): + if (start, m) in history: return history[(start, m)] + + if start>=len(piles): return 0 + if start+m*2>=len(piles): return sum(piles[start:]) + + stones = float('-inf') + for x in xrange(1, m*2+1): + stones = max(stones, sum(piles[start:])-helper(start+x, max(m, x))) + + history[(start, m)] = stones + return history[(start, m)] + + history = {} + return helper(0, 1) \ No newline at end of file diff --git a/problems/target-sum.py b/problems/target-sum.py index bccb65c..5dd86f1 100644 --- a/problems/target-sum.py +++ b/problems/target-sum.py @@ -13,10 +13,14 @@ def findTargetSumWays(self, nums, S): return ans -import collections - +""" +dp[i][j] = number of ways to sum to j using nums[0~i-1] +Time: O(SN) +Space: O(SN) +""" +import collections class Solution(object): def findTargetSumWays(self, nums, target): S = sum(nums) From 11a12fb930014f74056f02d3177ed95114c6efd2 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 16 May 2021 15:12:43 +0800 Subject: [PATCH 090/187] no message --- problems/stone-game-ii.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/problems/stone-game-ii.py b/problems/stone-game-ii.py index a213646..1674449 100644 --- a/problems/stone-game-ii.py +++ b/problems/stone-game-ii.py @@ -6,12 +6,17 @@ def helper(start, m): if start>=len(piles): return 0 if start+m*2>=len(piles): return sum(piles[start:]) - stones = float('-inf') + max_stones = float('-inf') for x in xrange(1, m*2+1): - stones = max(stones, sum(piles[start:])-helper(start+x, max(m, x))) + max_stones = max(max_stones, sum(piles[start:])-helper(start+x, max(m, x))) - history[(start, m)] = stones + history[(start, m)] = max_stones return history[(start, m)] history = {} - return helper(0, 1) \ No newline at end of file + return helper(0, 1) + +""" +helper(start, m) := the max stones that the first player will get with given piles[start:] and M. +max_stones = MAX{ (sum of all the stones) - (max_stones the other player will get) } = MAX{ sum(piles[start:]) - helper(start+x, max(m, x)) } +""" \ No newline at end of file From 4ceb3e12dc0b70df849730e322f1c3f2ba5049ee Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Wed, 2 Jun 2021 17:18:11 +0800 Subject: [PATCH 091/187] no message --- .../best-time-to-buy-and-sell-stock-iii.py | 28 ++++++++++ problems/distinct-subsequences.py | 18 +++++++ problems/edit-distance.py | 20 +++++++ problems/filling-bookcase-shelves.py | 26 ++++++++- problems/interleaving-string.py | 22 ++++++++ problems/largest-sum-of-averages.py | 44 +++++++++++++++ problems/longest-common-subsequence.py | 4 +- problems/longest-increasing-subsequence.py | 16 ++++++ ...-substring-without-repeating-characters.py | 16 +++++- .../maximum-subarray-sum-with-one-deletion.py | 29 ++++++++++ problems/minimum-falling-path-sum-ii.py | 48 +++++++++++++++++ ...umber-of-longest-increasing-subsequence.py | 35 +++++++++++- problems/palindrome-partitioning-iii.py | 53 +++++++++++++++++++ problems/shortest-common-supersequence.py | 41 ++++++++++++++ problems/two-sum.py | 12 +++++ 15 files changed, 408 insertions(+), 4 deletions(-) create mode 100644 problems/best-time-to-buy-and-sell-stock-iii.py create mode 100644 problems/distinct-subsequences.py create mode 100644 problems/edit-distance.py create mode 100644 problems/interleaving-string.py create mode 100644 problems/largest-sum-of-averages.py create mode 100644 problems/maximum-subarray-sum-with-one-deletion.py create mode 100644 problems/minimum-falling-path-sum-ii.py create mode 100644 problems/palindrome-partitioning-iii.py create mode 100644 problems/shortest-common-supersequence.py diff --git a/problems/best-time-to-buy-and-sell-stock-iii.py b/problems/best-time-to-buy-and-sell-stock-iii.py new file mode 100644 index 0000000..f8f808c --- /dev/null +++ b/problems/best-time-to-buy-and-sell-stock-iii.py @@ -0,0 +1,28 @@ +""" +dp[i][0~3] = max profit in ith day in 0~3 state. + +0 hold the stock from 1th transaction. +1 sold the stock from 1th transaction. +2 hold the stock from 2nd transaction. +3 sold the stock from 2nd transaction. + +dp[i][0] = max(-prices[i], dp[i-1][0]) +dp[i][1] = max(dp[i-1][0]+prices[i], dp[i-1][1]) +dp[i][2] = max(dp[i-1][1]-prices[i], dp[i-1][2]) +dp[i][3] = max(dp[i-1][2]+prices[i], dp[i-1][3]) + +Time: O(N) +Space: O(N), can further reduce to O(1). +""" +class Solution(object): + def maxProfit(self, prices): + dp = [[0, 0, 0, 0] for _ in xrange(len(prices))] + dp[0] = [-prices[0], 0, -prices[0], 0] + + for i in xrange(1, len(prices)): + dp[i][0] = max(-prices[i], dp[i-1][0]) + dp[i][1] = max(dp[i-1][0]+prices[i], dp[i-1][1]) + dp[i][2] = max(dp[i-1][1]-prices[i], dp[i-1][2]) + dp[i][3] = max(dp[i-1][2]+prices[i], dp[i-1][3]) + + return max(dp[-1]) \ No newline at end of file diff --git a/problems/distinct-subsequences.py b/problems/distinct-subsequences.py new file mode 100644 index 0000000..1bb3f40 --- /dev/null +++ b/problems/distinct-subsequences.py @@ -0,0 +1,18 @@ +""" +dp[i][j] := the number of distinct subsequences of s[:i] which equals t[:j] +""" +class Solution(object): + def numDistinct(self, s, t): + M, N = len(s), len(t) + + dp = [[0 for _ in xrange(N+1)] for _ in xrange(M+1)] + for i in xrange(M+1): dp[i][0] = 1 + + for i in xrange(1, M+1): + for j in xrange(1, N+1): + if s[i-1]==t[j-1]: + dp[i][j] = dp[i-1][j-1] + dp[i-1][j] + else: + dp[i][j] = dp[i-1][j] + + return dp[-1][-1] \ No newline at end of file diff --git a/problems/edit-distance.py b/problems/edit-distance.py new file mode 100644 index 0000000..9b010b8 --- /dev/null +++ b/problems/edit-distance.py @@ -0,0 +1,20 @@ +""" +dp[i][j] := minimum number of operations required to convert w1[:i] to w2[:j] +""" +class Solution(object): + def minDistance(self, w1, w2): + M, N = len(w1), len(w2) + + dp = [[0 for _ in xrange(N+1)] for _ in xrange(M+1)] + + for i in xrange(M+1): dp[i][0] = i + for j in xrange(N+1): dp[0][j] = j + + for i in xrange(1, M+1): + for j in xrange(1, N+1): + if w1[i-1]==w2[j-1]: + dp[i][j] = dp[i-1][j-1] + else: + dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i-1][j-1]+1) + + return dp[-1][-1] \ No newline at end of file diff --git a/problems/filling-bookcase-shelves.py b/problems/filling-bookcase-shelves.py index 3aa50a8..e9605b6 100644 --- a/problems/filling-bookcase-shelves.py +++ b/problems/filling-bookcase-shelves.py @@ -22,4 +22,28 @@ def minHeightShelves(self, books, shelf_width): dp[j] = min(dp[j], h) else: dp[j] = min(dp[j], dp[i-1]+h) - return dp[-1] \ No newline at end of file + return dp[-1] + + +""" +dp[i] := smallest height that the last book on book shelve is books[i] +dp[i] = min { dp[j]+max(books[j+1:i]) where sumWidth(books[j+1:i])<=W, j = 0~i-1} +""" +class Solution(object): + def minHeightShelves(self, books, W): + dp = [float('inf')]*len(books) + + dp[0] = books[0][1] + + for i in xrange(1, len(books)): + topLevelWidth = 0 + topLevelMaxHeight = 0 + + for j in xrange(i, -1, -1): + topLevelWidth += books[j][0] + topLevelMaxHeight = max(topLevelMaxHeight, books[j][1]) + if topLevelWidth>W: break + dp[i] = min(dp[i], (dp[j-1] if j-1>=0 else 0) + topLevelMaxHeight) + + return dp[-1] + \ No newline at end of file diff --git a/problems/interleaving-string.py b/problems/interleaving-string.py new file mode 100644 index 0000000..b389452 --- /dev/null +++ b/problems/interleaving-string.py @@ -0,0 +1,22 @@ +""" +dp[i][j] := whether s3[:i+j] is formed by an interleaving of s1[:i] and s2[:j] +""" +class Solution(object): + def isInterleave(self, s1, s2, s3): + if len(s1)+len(s2)!=len(s3): return False + + M, N = len(s1), len(s2) + dp = [[False for _ in xrange(N+1)] for _ in xrange(M+1)] + + for i in xrange(M+1): dp[i][0] = s1[:i] == s3[:i] + for j in xrange(N+1): dp[0][j] = s2[:j] == s3[:j] + + for i in xrange(1, M+1): + for j in xrange(1, N+1): + if s1[i-1]==s3[i+j-1] and dp[i-1][j]: + dp[i][j] = True + elif s2[j-1]==s3[i+j-1] and dp[i][j-1]: + dp[i][j] = True + + return dp[-1][-1] + \ No newline at end of file diff --git a/problems/largest-sum-of-averages.py b/problems/largest-sum-of-averages.py new file mode 100644 index 0000000..775f3ec --- /dev/null +++ b/problems/largest-sum-of-averages.py @@ -0,0 +1,44 @@ +""" +dp[i][k] := max score of nums[:i] using k partition. +""" +class Solution(object): + def largestSumOfAverages(self, nums, K): + N = len(nums) + + dp = [[0 for _ in xrange(K+1)] for _ in xrange(N+1)] + for i in xrange(1, N+1): dp[i][0] = float('-inf') + + for i in xrange(1, N+1): + for k in xrange(1, min(i, K)+1): + for j in xrange(k, i+1): + dp[i][k] = max(dp[i][k], dp[j-1][k-1] + float(sum(nums[j-1:i]))/(i-j+1)) + + return max(dp[N]) + + +""" +dp[i][k] := max score of nums[:i] using k partition. +avg[i][j] := average fro nums[i:j+1] +""" +class Solution(object): + def largestSumOfAverages(self, nums, K): + N = len(nums) + + avg = [[0 for _ in xrange(N)] for _ in xrange(N)] + for i in xrange(N): avg[i][i] = float(nums[i]) + + for l in xrange(2, N+1): + for i in xrange(N): + j = i+l-1 + if j>=N: continue + avg[i][j] = float((avg[i+1][j-1]*((j-1)-(i+1)+1)+nums[i]+nums[j]))/(j-i+1) + + dp = [[0 for _ in xrange(K+1)] for _ in xrange(N+1)] + for i in xrange(1, N+1): dp[i][0] = float('-inf') + + for i in xrange(1, N+1): + for k in xrange(1, min(i, K)+1): + for j in xrange(k, i+1): + dp[i][k] = max(dp[i][k], dp[j-1][k-1] + avg[j-1][i-1]) + + return max(dp[N]) \ No newline at end of file diff --git a/problems/longest-common-subsequence.py b/problems/longest-common-subsequence.py index 450c2bc..76f262b 100644 --- a/problems/longest-common-subsequence.py +++ b/problems/longest-common-subsequence.py @@ -17,4 +17,6 @@ def longestCommonSubsequence(self, text1, text2): """ Time: O(MN) Space: O(MN) -""" \ No newline at end of file +""" + + \ No newline at end of file diff --git a/problems/longest-increasing-subsequence.py b/problems/longest-increasing-subsequence.py index 0f61189..27e222f 100644 --- a/problems/longest-increasing-subsequence.py +++ b/problems/longest-increasing-subsequence.py @@ -31,4 +31,20 @@ def lengthOfLIS(self, nums): """ dp[i] := the smallest ending number that has length i+1 +""" + + +class Solution(object): + def lengthOfLIS(self, nums): + dp = [1]*len(nums) + + for i in xrange(1, (len(nums))): + for j in xrange(i-1, -1, -1): + if nums[i]>nums[j]: + dp[i] = max(dp[i], dp[j]+1) + + return max(dp) +""" +dp[i] := longest increasing subsequence that ends at nums[i] +dp[i] = max{ dp[j] where j = 0~i-1 } + 1 """ \ No newline at end of file diff --git a/problems/longest-substring-without-repeating-characters.py b/problems/longest-substring-without-repeating-characters.py index ed7a83c..ccb545a 100644 --- a/problems/longest-substring-without-repeating-characters.py +++ b/problems/longest-substring-without-repeating-characters.py @@ -32,4 +32,18 @@ def lengthOfLongestSubstring(self, s): counter = max(counter, i-start+1) mark[char_now] = i - return counter \ No newline at end of file + return counter + + +#2021/5/17 +class Solution(object): + def lengthOfLongestSubstring(self, s): + lastSeen = {} + start = 0 + maxLength = 0 + for i, c in enumerate(s): + if c in lastSeen: start = max(start, lastSeen[c]+1) + lastSeen[c] = i + maxLength = max(maxLength, i-start+1) + + return maxLength \ No newline at end of file diff --git a/problems/maximum-subarray-sum-with-one-deletion.py b/problems/maximum-subarray-sum-with-one-deletion.py new file mode 100644 index 0000000..d713751 --- /dev/null +++ b/problems/maximum-subarray-sum-with-one-deletion.py @@ -0,0 +1,29 @@ +""" +dp[i][0] = max sum that ends at arr[i], not yet done any deletion +dp[i][1] = max sum that ends at arr[i], already done the deletion + +dp[i][0] = max(dp[i-1][0]+arr[i], arr[i]) +dp[i][1] = max(dp[i-1][0], dp[i-1][1]+arr[i], arr[i]) + +Time: O(N). +Space: O(N), can further reduce to O(1). +""" + +class Solution(object): + def maximumSum(self, arr): + if not arr: return arr + if len(arr)==1: return arr[0] + + dp = [[0, 0] for _ in xrange(len(arr))] + subarrayMaxSum = arr[0] + + for i in xrange(len(arr)): + if i==0: + dp[i][0] = arr[i] + dp[i][1] = arr[i] + else: + dp[i][0] = max(dp[i-1][0]+arr[i], arr[i]) + dp[i][1] = max(dp[i-1][0], dp[i-1][1]+arr[i], arr[i]) + subarrayMaxSum = max(subarrayMaxSum, dp[i][0], dp[i][1]) + + return subarrayMaxSum \ No newline at end of file diff --git a/problems/minimum-falling-path-sum-ii.py b/problems/minimum-falling-path-sum-ii.py new file mode 100644 index 0000000..cace34d --- /dev/null +++ b/problems/minimum-falling-path-sum-ii.py @@ -0,0 +1,48 @@ +""" +dp[i][j] = minimum sum of falling path that chooeses A[i][j] as ending +dp[i][j] = (min(dp[i-1]) except dp[i-1][j]) + A[i][j] + +implement min(dp[i-1]) except dp[i-1][j] by getMin() +Can further optimize getMin() by memorization. + +Time: O(NM). +Space: O(NM), can further reduce to O(M). +""" + +import collections +import heapq + +class Solution(object): + def minFallingPathSum(self, A): + def getMin(i, j): + minN = float('inf') + for idx, n in enumerate(dp[i]): + if j==idx: continue + minN = min(minN, n) + return minN + + if not A or not A[0]: return 0 + if len(A)==1: return min(A) + + history = collections.defaultdict(list) + + dp = [[0 for _ in xrange(len(A[0]))] for _ in xrange(len(A))] + + for i in xrange(len(A)): + for j in xrange(len(A[0])): + dp[i][j] = getMin(i-1, j) + A[i][j] + + return min(dp[-1]) +class Solution(object): + def minFallingPathSum(self, A): + if not A or not A[0]: return 0 + if len(A)==1: return min(A) + + dp = [[0 for _ in xrange(len(A[0]))] for _ in xrange(len(A))] + + for i in xrange(len(A)): + h = heapq.nsmallest(2, dp[i-1]) if i>0 else [0, 0] + for j in xrange(len(A[0])): + dp[i][j] = (h[1] if h[0]==dp[i-1][j] else h[0]) + A[i][j] + + return min(dp[-1]) \ No newline at end of file diff --git a/problems/number-of-longest-increasing-subsequence.py b/problems/number-of-longest-increasing-subsequence.py index 1f86ffb..2a0aafe 100644 --- a/problems/number-of-longest-increasing-subsequence.py +++ b/problems/number-of-longest-increasing-subsequence.py @@ -25,5 +25,38 @@ def findNumberOfLIS(self, nums): """ Time: O(N^2) -Spance: O(1) +Spance: O(N) +""" + + +class Solution(object): + def findNumberOfLIS(self, nums): + dp = [1]*len(nums) + count = [1]*len(nums) + count[0] = 1 + + for i in xrange(1, (len(nums))): + for j in xrange(i-1, -1, -1): + if nums[i]>nums[j]: + if dp[j]+1>dp[i]: + count[i] = count[j] + dp[i] = dp[j]+1 + elif dp[j]+1==dp[i]: + count[i]+=count[j] + print count + + maxLis = max(dp) + ans = 0 + for i, lis in enumerate(dp): + if lis==maxLis: ans += count[i] + + return ans +""" +dp[i] := longest increasing subsequence that ends at nums[i] +count[i] := number of comfination that ends up dp[i]. + +dp[i] = max{ dp[j] where nums[i]>nums[j], j = 0~i-1 } + 1 + +Time: O(N^2) +Space: O(N) """ \ No newline at end of file diff --git a/problems/palindrome-partitioning-iii.py b/problems/palindrome-partitioning-iii.py new file mode 100644 index 0000000..65fc55b --- /dev/null +++ b/problems/palindrome-partitioning-iii.py @@ -0,0 +1,53 @@ +""" +dp[i][k] := the minimal number of characters that needed to change for s[:i] with k disjoint substrings +""" +class Solution(object): + def palindromePartition(self, s, K): + def count(r, l): + c = 0 + + while r>l: + if s[r]!=s[l]: c += 1 + r -= 1 + l += 1 + return c + + N = len(s) + + dp = [[float('inf') for _ in xrange(K+1)] for _ in xrange(N+1)] + dp[0][0] = 0 + + for i in xrange(1, N+1): + for k in xrange(1, min(K, i)+1): + for j in xrange(k, i+1): + dp[i][k] = min(dp[i][k], dp[j-1][k-1] + count(i-1, j-1)) + + return dp[N][K] + +""" +The above `count()` are able to use dp technique to optimize. +dp[i][k] := the minimal number of characters that needed to change for s[:i] with k disjoint substrings +count[i][j] := the operation needed for s[i:j+1] become palindrome. +""" +class Solution(object): + def palindromePartition(self, s, K): + N = len(s) + + count = [[0 for _ in xrange(N)] for _ in xrange(N)] + for i in xrange(N): count[i][i] = 0 + + for l in xrange(2, N+1): + for i in xrange(N): + j = i+l-1 + if j>=N: continue + count[j][i] = count[j-1][i+1] + (0 if s[i]==s[j] else 1) + + dp = [[float('inf') for _ in xrange(K+1)] for _ in xrange(N+1)] + dp[0][0] = 0 + + for i in xrange(1, N+1): + for k in xrange(1, min(K, i)+1): + for j in xrange(k, i+1): + dp[i][k] = min(dp[i][k], dp[j-1][k-1] + count[i-1][j-1]) + + return dp[N][K] \ No newline at end of file diff --git a/problems/shortest-common-supersequence.py b/problems/shortest-common-supersequence.py new file mode 100644 index 0000000..1b4e582 --- /dev/null +++ b/problems/shortest-common-supersequence.py @@ -0,0 +1,41 @@ +""" +dp[i][j] := length of the scs of s1[:i] and s2[:j] +""" +class Solution(object): + def shortestCommonSupersequence(self, s1, s2): + N, M = len(s1), len(s2) + + if not s1: return s2 + if not s2: return s1 + + dp = [[0 for _ in xrange(M+1)] for _ in xrange(N+1)] + for i in range(1, N+1): dp[i][0] = i + for j in range(1, M+1): dp[0][j] = j + + for i in xrange(1, N+1): + for j in xrange(1, M+1): + if s1[i-1]==s2[j-1]: + dp[i][j] = dp[i-1][j-1]+1 + else: + dp[i][j] = min(dp[i-1][j]+1, dp[i][j-1]+1) + + i, j = N, M + ans = '' + + while i>0 and j>0: + if s1[i-1]==s2[j-1]: + ans = s1[i-1] + ans + i -= 1 + j -= 1 + else: + if dp[i][j-1]0: ans = s1[:i] + ans + if j>0: ans = s2[:j] + ans + + return ans \ No newline at end of file diff --git a/problems/two-sum.py b/problems/two-sum.py index 1af95a8..ed91942 100644 --- a/problems/two-sum.py +++ b/problems/two-sum.py @@ -19,3 +19,15 @@ def twoSum(self, nums, target): wanted[target-n] = i #[0] return [] + + +#2021/5/17 +class Solution(object): + def twoSum(self, nums, target): + M = {} #counter part number needed by index i: i + + for i, num in enumerate(nums): + if num in M: return (M[num], i) + M[target-num] = i + + return False \ No newline at end of file From c39681e5975898a7e2f6bc0e7202577d7111ae9f Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 7 Jun 2021 08:38:10 +0800 Subject: [PATCH 092/187] no message --- problems/burst-balloons.py | 28 ++++++++++++ problems/guess-number-higher-or-lower-ii.py | 18 ++++++++ problems/longest-palindromic-subsequence.py | 17 +++++++ .../minimum-difficulty-of-a-job-schedule.py | 29 ++++++++++++ problems/split-array-largest-sum.py | 45 +++++++++++++++++++ 5 files changed, 137 insertions(+) create mode 100644 problems/burst-balloons.py create mode 100644 problems/guess-number-higher-or-lower-ii.py create mode 100644 problems/longest-palindromic-subsequence.py create mode 100644 problems/minimum-difficulty-of-a-job-schedule.py create mode 100644 problems/split-array-largest-sum.py diff --git a/problems/burst-balloons.py b/problems/burst-balloons.py new file mode 100644 index 0000000..97d37aa --- /dev/null +++ b/problems/burst-balloons.py @@ -0,0 +1,28 @@ +""" +dp[i][j] := max coins gains from nums[i+1:j] +Assume k is the last balloon that get burst within nums[i:j+1], try different k and get the max dp[i][j]. + +max coins gains from nums[i+1:j] will be the sum of +1. max coins gains from nums[i:k]: `dp[i][k-1] if k-1>=0 else 0` +2. coins gains from bursring k: `(nums[i-1] if 0<=i-1 else 1) * nums[k] * (nums[j+1] if j+1=N: continue + for k in xrange(i, j+1): + dp[i][j] = max(dp[i][j], + (dp[i][k-1] if k-1>=0 else 0) + + (nums[i-1] if 0<=i-1 else 1) * nums[k] * (nums[j+1] if j+1=N: continue + for k in xrange(i, j+1): + dp[i][j] = min(dp[i][j], max(dp[i][k-1] if k-1>=0 else 0, dp[k+1][j] if k+1=N: continue + dp[i][j] = dp[i+1][j-1]+2 if s[i]==s[j] else max(dp[i+1][j], dp[i][j-1]) + + return dp[0][N-1] \ No newline at end of file diff --git a/problems/minimum-difficulty-of-a-job-schedule.py b/problems/minimum-difficulty-of-a-job-schedule.py new file mode 100644 index 0000000..5ba8179 --- /dev/null +++ b/problems/minimum-difficulty-of-a-job-schedule.py @@ -0,0 +1,29 @@ +""" +dp[i][k] := minimum difficulty of a k days job schedule, D[:i]. +maxInRange[i][j] := max(D[i:j+1]) +""" + +class Solution(object): + def minDifficulty(self, D, K): + if not D or not K or K>len(D): return -1 + N = len(D) + + maxInRange = [[0 for _ in xrange(N)] for _ in xrange(N)] + for i in xrange(N): maxInRange[i][i] = D[i] + for l in xrange(2, N+1): + for i in xrange(N): + j = i+l-1 + if j>=N: continue + maxInRange[i][j] = max(maxInRange[i+1][j-1], D[i], D[j]) + + dp = [[float('inf') for _ in xrange(K+1)] for _ in xrange(N+1)] + dp[0][0] = 0 + + for i in xrange(1, N+1): + for k in xrange(1, min(i, K)+1): + for j in xrange(k, i+1): + dp[i][k] = min(dp[i][k], dp[j-1][k-1]+maxInRange[j-1][i-1]) + + #if you don't pre-calculate maxInRange + #dp[i][k] = min(dp[i][k], dp[j-1][k-1]+max(D[j-1:i])) + return dp[N][K] \ No newline at end of file diff --git a/problems/split-array-largest-sum.py b/problems/split-array-largest-sum.py new file mode 100644 index 0000000..3239503 --- /dev/null +++ b/problems/split-array-largest-sum.py @@ -0,0 +1,45 @@ +""" +TLE +dp[i][k] := min of the largest sum among k subarrays from nums[:i] +""" +class Solution(object): + def splitArray(self, nums, K): + N = len(nums) + + dp = [[float('inf') for _ in xrange(K+1)] for _ in xrange(N+1)] + dp[0][0] = 0 + + for i in xrange(1, N+1): + for k in xrange(1, min(i, K)+1): + for j in xrange(k, i+1): + dp[i][k] = min(dp[i][k], max(dp[j-1][k-1], sum(nums[j-1:i]))) + + return dp[N][K] + + +""" +TLE +dp[i][k] := min of the largest sum among k subarrays from nums[:i] +s[i][j] := sum of nums[i:j+1] +""" +class Solution(object): + def splitArray(self, nums, K): + N = len(nums) + + s = [[0 for _ in xrange(N)] for _ in xrange(N)] + for i in xrange(N): s[i][i] = nums[i] + for l in xrange(2, N): + for i in xrange(N): + j = i+l-1 + if j>=N: continue + s[i][j] = s[i+1][j-1]+nums[i]+nums[j] + + dp = [[float('inf') for _ in xrange(K+1)] for _ in xrange(N+1)] + dp[0][0] = 0 + + for i in xrange(1, N+1): + for k in xrange(1, min(i, K)+1): + for j in xrange(k, i+1): + dp[i][k] = min(dp[i][k], max(dp[j-1][k-1], s[j-1][i-1])) + + return dp[N][K] \ No newline at end of file From b7dfe9cee6df75cf61e24aad2085cdea36545377 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 19 Jun 2021 11:05:19 +0800 Subject: [PATCH 093/187] no message --- problems/last-stone-weight-ii.py | 22 ++++++++++++++++ problems/longest-palindromic-substring.py | 24 +++++++++++++++++- problems/ones-and-zeroes.py | 22 ++++++++++++++++ problems/profitable-schemes.py | 19 ++++++++++++++ .../remove-duplicates-from-sorted-array.py | 12 +++++++++ problems/tallest-billboard.py | 15 +++++++++++ problems/target-sum.py | 25 ++++++++++++++++++- 7 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 problems/ones-and-zeroes.py create mode 100644 problems/profitable-schemes.py create mode 100644 problems/remove-duplicates-from-sorted-array.py create mode 100644 problems/tallest-billboard.py diff --git a/problems/last-stone-weight-ii.py b/problems/last-stone-weight-ii.py index 8fa2fde..c757f1f 100644 --- a/problems/last-stone-weight-ii.py +++ b/problems/last-stone-weight-ii.py @@ -27,3 +27,25 @@ def lastStoneWeightII(self, stones): # Two collection of stones will be total-maxSum and maxSum # (total-maxSum) - maxSum => total-maxSum*2 return total-maxSum*2 + + +""" +dp[i][w] := if weight w is achievable using stones[:i] +Find the smallest achivable w where w>=0. +""" +import collections +class Solution(object): + def lastStoneWeightII(self, stones): + N = len(stones) + W = sum(stones) + dp = [collections.defaultdict(bool) for _ in xrange(N+1)] + dp[0][0] = True + + for i in xrange(1, N+1): + for w in xrange(-W, W+1): + dp[i][w] = dp[i-1][w+stones[i-1]] or dp[i-1][w-stones[i-1]] + + for w, b in dp[N].iteritems(): + if b and w>=0: return w + + return 0 \ No newline at end of file diff --git a/problems/longest-palindromic-substring.py b/problems/longest-palindromic-substring.py index 9b916f1..93b76a1 100644 --- a/problems/longest-palindromic-substring.py +++ b/problems/longest-palindromic-substring.py @@ -41,4 +41,26 @@ def findPalindorome(mid, mid2=None): max_pal = p2 if len(p2)>len(max_pal) else max_pal return max_pal - \ No newline at end of file + + +#2021/6/18 DP TLE +""" +dp[i][j] := if s[i:j+1] is palindrom +""" +class Solution(object): + def longestPalindrome(self, s): + if not s: return s + + N = len(s) + dp = [[False for _ in xrange(N+1)] for _ in xrange(N+1)] + for i in xrange(N+1): dp[i][i] = True + ans = s[0] + + for l in xrange(2, N+1): + for i in xrange(1, N+1): + j = i+l-1 + if j>N: continue + dp[i][j] = s[i-1]==s[j-1] and (dp[i+1][j-1] or j-1=count0 and n>=count1 else 0) + + ans = 0 + for n in xrange(N+1): + for m in xrange(M+1): + ans = max(ans, dp[-1][n][m]) + + return ans \ No newline at end of file diff --git a/problems/profitable-schemes.py b/problems/profitable-schemes.py new file mode 100644 index 0000000..ead8e92 --- /dev/null +++ b/problems/profitable-schemes.py @@ -0,0 +1,19 @@ +""" +TLE +dp[i][n][p] := considering profit[:i], what is the number of ways produce profit p with n people. +""" +class Solution(object): + def profitableSchemes(self, maxMember, minProfit, group, profit): + P = sum(profit) + N = sum(group) + dp = [[[0 for _ in xrange(P+1)] for _ in xrange(N+1)] for _ in xrange(len(profit)+1)] + dp[0][0][0] = 1 + + count = 0 + for i in xrange(1, len(profit)+1): + for n in xrange(N+1): + for p in xrange(P+1): + dp[i][n][p] = (dp[i-1][n-group[i-1]][p-profit[i-1]] if p-profit[i-1]>=0 and n-group[i-1]>=0 else 0) + dp[i-1][n][p] + if i==len(profit) and p>=minProfit and n<=maxMember: count += dp[i][n][p] + return count + \ No newline at end of file diff --git a/problems/remove-duplicates-from-sorted-array.py b/problems/remove-duplicates-from-sorted-array.py new file mode 100644 index 0000000..7fbef36 --- /dev/null +++ b/problems/remove-duplicates-from-sorted-array.py @@ -0,0 +1,12 @@ +""" +j is the index to insert when a new number are found. +j will never catch up i, so j will not mess up the check. +""" +class Solution(object): + def removeDuplicates(self, nums): + j = 1 + for i in xrange(1, len(nums)): + if nums[i]!=nums[i-1]: + nums[j] = nums[i] + j += 1 + return j \ No newline at end of file diff --git a/problems/tallest-billboard.py b/problems/tallest-billboard.py new file mode 100644 index 0000000..587d1f6 --- /dev/null +++ b/problems/tallest-billboard.py @@ -0,0 +1,15 @@ +#TLE +class Solution(object): + def tallestBillboard(self, rods): + D = sum(rods) + N = len(rods) + + dp = [[float('-inf') for _ in xrange(-D, D+1)] for _ in xrange(N+1)] + dp[0][D] = 0 + + for i in xrange(1, N+1): + for d in xrange(-D, D+1): + h = rods[i-1] + dp[i][d+D] = max(dp[i-1][d+D], (dp[i-1][d+D-h]+h) if d+D-h>=0 else float('-inf'), dp[i-1][d+D+h] if d+D+h<2*D+1 else float('-inf')) + + return dp[N][D] \ No newline at end of file diff --git a/problems/target-sum.py b/problems/target-sum.py index 5dd86f1..75d9abe 100644 --- a/problems/target-sum.py +++ b/problems/target-sum.py @@ -32,4 +32,27 @@ def findTargetSumWays(self, nums, target): dp[i][j] = dp[i-1][j+nums[i-1]] + dp[i-1][j-nums[i-1]] return dp[len(nums)][target] - \ No newline at end of file + + +#2021/6/7 +""" +dp[i][t] := number of ways nums[:i] can sum up to t applying + or -. +For all i, calculate all posible target (From minTarget~maxTarget) +""" +class Solution(object): + def findTargetSumWays(self, nums, target): + N = len(nums) + maxTarget = sum(nums) + minTarget = -maxTarget + + if targetmaxTarget: return 0 + + dp = [[0 for _ in xrange(minTarget, maxTarget+1)] for _ in xrange(N+1)] + + dp[0][0] = 1 + + for i in xrange(1, N+1): + for t in xrange(minTarget, maxTarget+1): + dp[i][t] = (dp[i-1][t-nums[i-1]] if t-nums[i-1]>=minTarget else 0) + (dp[i-1][t+nums[i-1]] if t+nums[i-1]<=maxTarget else 0) + + return dp[N][target] \ No newline at end of file From 39884b777f7027f3c1ce83783604847fa196d51b Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 19 Jun 2021 11:11:27 +0800 Subject: [PATCH 094/187] Update README. --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9f316ce..88c8aec 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,13 @@ https://github.com/wuduhren/leetcode-python For example, `merge-sorted-array.py`'s solution is at `https://leetcode.com/problems/merge-sorted-array/`. -# Leetcode 74 Classic Problem -https://leetcode.com/list/?selectedList=535ukjh5 +# Leetcode Problem Lists +* https://leetcode.com/list/?selectedList=535ukjh5 (Only 74 problems) +* https://www.programcreek.com/2013/08/leetcode-problem-classification/ +* https://github.com/wisdompeak/LeetCode +* Below [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO31DBjfeMoA0dlfIA/edit#gid=126913158) is made by **huahua**, I found this on his [youtube](https://www.youtube.com/user/xxfflower/videos). Please visit his [website](https://zxi.mytechroad.com/blog/leetcode-problem-categories/) for more. -# Leetcode Similar Problems +# Similar Problems I found it makes sense to solve similar problems together, so that we can recognize the problem faster when we encounter a new one. My suggestion is to skip the HARD problems when you first go through these list. ### Two Pointers @@ -158,8 +161,6 @@ I found it makes sense to solve similar problems together, so that we can recogn | 901 | [Online Stock Span](https://leetcode.com/problems/online-stock-span "Online Stock Span") | ★★★ | [907](https://leetcode.com/problems/sum-of-subarray-minimums "907") | [1019](https://leetcode.com/problems/next-greater-node-in-linked-list/ "1019") | | | | Monotonic Stack | | 239 | [Sliding Window Maximum](https://leetcode.com/problems/sliding-window-maximum/ "Sliding Window Maximum") | ★★★ | | | | | | Monotonic Queue | -This [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO31DBjfeMoA0dlfIA/edit#gid=126913158) is made by **huahua**, I found this on his [youtube](https://www.youtube.com/user/xxfflower/videos). Please visit his [website](https://zxi.mytechroad.com/blog/leetcode-problem-categories/) for more. - # Software Engineer Interview ## Overall Mindset From de66880641f44a5faf49297227c90c685e782e6f Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 19 Jun 2021 12:02:56 +0800 Subject: [PATCH 095/187] no message --- problems/move-zeroes.py | 21 ++++++++++++++++++- .../remove-duplicates-from-sorted-array-ii.py | 14 +++++++++++++ problems/remove-element.py | 12 +++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 problems/remove-duplicates-from-sorted-array-ii.py create mode 100644 problems/remove-element.py diff --git a/problems/move-zeroes.py b/problems/move-zeroes.py index 9f1eb92..3fd2eac 100644 --- a/problems/move-zeroes.py +++ b/problems/move-zeroes.py @@ -18,4 +18,23 @@ def moveZeroes(self, nums): temp = nums[cursor] nums[cursor] = nums[i] nums[i] = temp - cursor+=1 \ No newline at end of file + cursor+=1 + + +""" +j is the index to insert when a number not equal to 0. +After all the non-zero numbers are inplace, the rests are all zeros. +""" +class Solution(object): + def moveZeroes(self, nums): + j = 0 + + for n in nums: + if n!=0: + nums[j] = n + j += 1 + + for i in xrange(j, len(nums)): + nums[i] = 0 + + return nums \ No newline at end of file diff --git a/problems/remove-duplicates-from-sorted-array-ii.py b/problems/remove-duplicates-from-sorted-array-ii.py new file mode 100644 index 0000000..d7665be --- /dev/null +++ b/problems/remove-duplicates-from-sorted-array-ii.py @@ -0,0 +1,14 @@ +""" +j is the index to insert when a "new" number are found. +For each iteration, nums[:j] is the output result we currently have. +So nums[i] should check with nums[j-1] and nums[j-2]. +""" +class Solution(object): + def removeDuplicates(self, nums): + j = 2 + + for i in xrange(2, len(nums)): + if not (nums[i]==nums[j-1] and nums[i]==nums[j-2]): + nums[j] = nums[i] + j += 1 + return j \ No newline at end of file diff --git a/problems/remove-element.py b/problems/remove-element.py new file mode 100644 index 0000000..52999e8 --- /dev/null +++ b/problems/remove-element.py @@ -0,0 +1,12 @@ +""" +j is the index to insert when a number not equal to val. +j will never catch up i, so j will not mess up the check. +""" +class Solution(object): + def removeElement(self, nums, val): + j = 0 + for n in nums: + if n!=val: + nums[j] = n + j += 1 + return j \ No newline at end of file From 28f997a2a511a381abbd79357b316f38e4ebc4d2 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 21 Jun 2021 19:13:56 +0800 Subject: [PATCH 096/187] no message --- problems/candy.py | 21 +++++++++++++++++++++ problems/trapping-rain-water.py | 26 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 problems/candy.py create mode 100644 problems/trapping-rain-water.py diff --git a/problems/candy.py b/problems/candy.py new file mode 100644 index 0000000..e77a631 --- /dev/null +++ b/problems/candy.py @@ -0,0 +1,21 @@ +class Solution(object): + def candy(self, ratings): + N = len(ratings) + + l2r = [1]*N + r2l = [1]*N + + for i in xrange(1, N): + if ratings[i]>ratings[i-1]: + l2r[i] = l2r[i-1]+1 + + for i in xrange(N-2, -1, -1): + if ratings[i]>ratings[i+1]: + r2l[i] = r2l[i+1]+1 + + ans = 0 + for i in xrange(N): + ans += max(l2r[i], r2l[i]) + + return ans + \ No newline at end of file diff --git a/problems/trapping-rain-water.py b/problems/trapping-rain-water.py new file mode 100644 index 0000000..7791f4e --- /dev/null +++ b/problems/trapping-rain-water.py @@ -0,0 +1,26 @@ +""" +Let's calculate the answer considering only the left boandary. +The water each i can contain is wall[i-1]-height[i] +if no water at i-1 the wall[i-1] will be height[i-1], else it should be height[i-1]+water[i-1] +=> water[i] = (height[i-1] + water[i-1]) - height[i] (l2r below) + +Do the same from right to left, this time considering only the right boandary. + +The amount of water at i considering both left and right wall will be min(l2r[i], r2l[i]) +""" +class Solution(object): + def trap(self, height): + N = len(height) + l2r = [0]*N #water + r2l = [0]*N #water + + for i in xrange(1, N): + l2r[i] = max(l2r[i-1]+height[i-1]-height[i], 0) + + for i in xrange(N-2, -1, -1): + r2l[i] = max(r2l[i+1]+height[i+1]-height[i], 0) + + ans = 0 + for i in xrange(N): + ans += min(l2r[i], r2l[i]) + return ans \ No newline at end of file From ac0ddec34ca38d68cd789c5689deb24275ef0515 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Fri, 25 Jun 2021 07:33:52 +0800 Subject: [PATCH 097/187] no message --- problems/find-and-replace-in-string.py | 23 +++++++++++ problems/insert-interval.py | 20 +++++++++ problems/merge-intervals.py | 21 ++++++++-- problems/minimum-size-subarray-sum.py | 20 +++++++++ problems/partition-labels.py | 52 ++++++++++++++++++++++++ problems/product-of-array-except-self.py | 47 ++++++++++++++++++++- problems/summary-ranges.py | 18 ++++++++ 7 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 problems/find-and-replace-in-string.py create mode 100644 problems/insert-interval.py create mode 100644 problems/minimum-size-subarray-sum.py create mode 100644 problems/partition-labels.py create mode 100644 problems/summary-ranges.py diff --git a/problems/find-and-replace-in-string.py b/problems/find-and-replace-in-string.py new file mode 100644 index 0000000..ed407d1 --- /dev/null +++ b/problems/find-and-replace-in-string.py @@ -0,0 +1,23 @@ +""" +`p` is the index on s which already processed. +""" +class Solution(object): + def findReplaceString(self, s, indices, sources, targets): + p = -1 + ans = '' + + memo = {} + for i, index in enumerate(indices): + memo[index] = (sources[i], targets[i]) + + for i in xrange(len(s)): + if i<=p: continue + + if i in memo and (s[i:i+len(memo[i][0])] if i+len(memo[i][0])0 and result[-1].end>=inter.start: #[2] - result[-1].end = max(result[-1].end, inter.end) #[3] + if len(result)>0 and result[-1][1]>=inter[0]: #[2] + result[-1][1] = max(result[-1][1], inter[1]) #[3] else: #[4] result.append(inter) - return result \ No newline at end of file + return result + + +class Solution(object): + def merge(self, intervals): + intervals.sort() + + i = 0 + while i=intervals[i+1][0]: + intervals = intervals[:i] + [[min(intervals[i][0], intervals[i+1][0]), max(intervals[i][1], intervals[i+1][1])]] + intervals[i+2:] + else: + i += 1 + return intervals \ No newline at end of file diff --git a/problems/minimum-size-subarray-sum.py b/problems/minimum-size-subarray-sum.py new file mode 100644 index 0000000..71e6aa7 --- /dev/null +++ b/problems/minimum-size-subarray-sum.py @@ -0,0 +1,20 @@ +""" +As we move right the i and increament s, if the s >= target, we + +""" +class Solution(object): + def minSubArrayLen(self, target, nums): + s = 0 + l = 0 + ans = float('inf') + + for i in xrange(len(nums)): + s += nums[i] + + while s>=target: + ans = min(i-l+1, ans) + s -= nums[l] + l += 1 + + return ans if ans!=float('inf') else 0 + \ No newline at end of file diff --git a/problems/partition-labels.py b/problems/partition-labels.py new file mode 100644 index 0000000..baf6c11 --- /dev/null +++ b/problems/partition-labels.py @@ -0,0 +1,52 @@ +""" +1. Find each char's ranges. Store into `charRange`. +2. Merge the ranges. Store into `r`. +3. Change the `r` format. + +For example: +The input is "ababcbacadefegdehijhklij" +charRange will be: `{'a': [0, 8], 'c': [4, 7], 'b': [1, 5], 'e': [10, 15], 'd': [9, 14], 'g': [13, 13], 'f': [11, 11], 'i': [17, 22], 'h': [16, 19], 'k': [20, 20], 'j': [18, 23], 'l': [21, 21]}` +After merging above the range should be `[[0, 8], [9, 15], [16, 23]]`. And store it in `r`: `[8, 15, 23]`. +`ans` will be `[9,7,8]` +""" +class Solution(object): + def partitionLabels(self, s): + charRange = {} + r = [] + + for i, c in enumerate(s): + if c not in charRange: + charRange[c] = [i, i] + else: + charRange[c][1] = i + + for i, c in enumerate(s): + if i==0 or charRange[c][0]>r[-1]: + r.append(charRange[c][1]) + else: + r[-1] = max(r[-1], charRange[c][1]) + + ans = [] + for i in xrange(len(r)): + if i==0: + ans.append(r[i]+1) + else: + ans.append(r[i]-r[i-1]) + return ans + +""" +This offical answer is even cleaner. +""" +class Solution(object): + def partitionLabels(self, s): + lastSeen = {} + for i, c in enumerate(s): lastSeen[c] = i + + ans = [] + start = end = 0 + for i, c in enumerate(s): + end = max(end, lastSeen[c]) + if i==end: + ans.append(end-start+1) + start = i+1 + return ans \ No newline at end of file diff --git a/problems/product-of-array-except-self.py b/problems/product-of-array-except-self.py index 006e06f..76e8b48 100644 --- a/problems/product-of-array-except-self.py +++ b/problems/product-of-array-except-self.py @@ -36,4 +36,49 @@ def productExceptSelf(self, nums): output[i] = output[i]*t #[5] t = t*nums[i] #[4] - return output \ No newline at end of file + return output + +""" +Time: O(N) +Space: O(N) + +left[i] := product of all the element left to nums[i] +right[i] := product of all the element right to nums[i] +""" +class Solution(object): + def productExceptSelf(self, nums): + N = len(nums) + + left = [1]*N + for i in xrange(1, len(nums)): + left[i] = left[i-1] * nums[i-1] + + right = [1]*N + for i in xrange(N-2, -1, -1): + right[i] = right[i+1] * nums[i+1] + + ans = [] + for i in xrange(N): + ans.append(left[i]*right[i]) + return ans + +""" +Time: O(N) +Space: O(1) +""" +class Solution(object): + def productExceptSelf(self, nums): + N = len(nums) + + #[1] + opt = [1]*N + for i in xrange(1, len(nums)): + opt[i] = opt[i-1] * nums[i-1] + + #[2] + t = 1 + for i in xrange(N-2, -1, -1): + t *= nums[i+1] + opt[i] *= t + + return opt \ No newline at end of file diff --git a/problems/summary-ranges.py b/problems/summary-ranges.py new file mode 100644 index 0000000..800cda7 --- /dev/null +++ b/problems/summary-ranges.py @@ -0,0 +1,18 @@ +""" +For each iteration, if we found a new starting point we will append previous range to the opt. +The range start from index s to index i-1. +""" +class Solution(object): + def summaryRanges(self, nums): + nums.append('#') + opt = [] + s = 0 + + for i in xrange(1, len(nums)): + if nums[i-1]+1!=nums[i]: + if i-1>s: + opt.append(str(nums[s])+'->'+str(nums[i-1])) + else: + opt.append(str(nums[s])) + s = i + return opt \ No newline at end of file From 7cba34782299253039f6dee8d338816afc35a957 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sun, 4 Jul 2021 00:51:07 +0800 Subject: [PATCH 098/187] no message --- problems/backspace-string-compare.py | 46 +++++++++++++++++++++++++- problems/container-with-most-water.py | 18 ++++++++++ problems/is-subsequence.py | 9 +++++ problems/my-calendar-ii.py | 27 +++++++++++++++ problems/repeated-string-match.py | 32 ++++++++++++++++++ problems/reverse-vowels-of-a-string.py | 20 +++++++++++ problems/valid-palindrome.py | 19 +++++++++++ 7 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 problems/is-subsequence.py create mode 100644 problems/my-calendar-ii.py create mode 100644 problems/repeated-string-match.py create mode 100644 problems/reverse-vowels-of-a-string.py create mode 100644 problems/valid-palindrome.py diff --git a/problems/backspace-string-compare.py b/problems/backspace-string-compare.py index 9c9c8f5..f3df6d2 100644 --- a/problems/backspace-string-compare.py +++ b/problems/backspace-string-compare.py @@ -38,4 +38,48 @@ def getChar(self, s, i): else: hashtag-=1 i-=1 - return c, i \ No newline at end of file + return c, i +""" +Time: O(N) +Space: O(1) +""" +class Solution(object): + def backspaceCompare(self, s1, s2): + i = len(s1)-1 + j = len(s2)-1 + c1 = 0 #s1 unprocessed backspace count + c2 = 0 #s2 unprocessed backspace count + + while i>=0 or j>=0: + while i>=0: + if s1[i]=='#': + c1 += 1 + i -= 1 + elif c1>0: + c1 -= 1 + i -= 1 + else: + break + + while j>=0: + if s2[j]=='#': + c2 += 1 + j -= 1 + elif c2>0: + c2 -= 1 + j -= 1 + else: + break + + # if one of the string is finished, the other one should be finished, too. + if i<0: return j<0 + if j<0: return i<0 + + + if s1[i]!=s2[j]: return False + + i -= 1 + j -= 1 + + return True + \ No newline at end of file diff --git a/problems/container-with-most-water.py b/problems/container-with-most-water.py index e5f49f4..6f7a531 100644 --- a/problems/container-with-most-water.py +++ b/problems/container-with-most-water.py @@ -31,3 +31,21 @@ def maxArea(self, H): else: r = r-1 return ans + + +class Solution(object): + def maxArea(self, height): + i = 0 + j = len(height)-1 + ans = 0 + + while i=len(s): break + if s[i]==c: i += 1 + + return i==len(s) \ No newline at end of file diff --git a/problems/my-calendar-ii.py b/problems/my-calendar-ii.py new file mode 100644 index 0000000..8d76f69 --- /dev/null +++ b/problems/my-calendar-ii.py @@ -0,0 +1,27 @@ +""" +self.booked := booked times. +self.overlaps := overlaped times. + +For each new book, +1. check if the new book overlaps with the times in self.overlaps, if so, return False. +2. check if the new book overlaps with the times in self.booked, if so, store the overlaped time in self.overlaps. +3. store the new book in self.booked. +""" +class MyCalendarTwo(object): + + def __init__(self): + self.overlaps = [] + self.booked = [] + + + def book(self, start, end): + for s, e in self.overlaps: + if not (e<=start or end<=s): + return False + + for s, e in self.booked: + if not (e<=start or end<=s): + self.overlaps.append((max(start, s), min(end, e))) + + self.booked.append((start, end)) + return True \ No newline at end of file diff --git a/problems/repeated-string-match.py b/problems/repeated-string-match.py new file mode 100644 index 0000000..95c1f66 --- /dev/null +++ b/problems/repeated-string-match.py @@ -0,0 +1,32 @@ +class Solution(object): + def repeatedStringMatch(self, a, b): + """ + compare a[i] and b[j] + if a[i]!=b[j], return -1 + if a new set of "a" is needed, count += 1 + """ + def helper(i): + count = 1 + j = 0 + + while j0: return -1 + + #the index of the starting point need to be as small as posible. So that we can get the minimum answer. + for i in xrange(len(a)): + if a[i]==b[0]: + ans = helper(i) + if ans>0: return ans + + return -1 \ No newline at end of file diff --git a/problems/reverse-vowels-of-a-string.py b/problems/reverse-vowels-of-a-string.py new file mode 100644 index 0000000..19fde25 --- /dev/null +++ b/problems/reverse-vowels-of-a-string.py @@ -0,0 +1,20 @@ +class Solution(object): + def reverseVowels(self, s): + i = 0 + j = len(s)-1 + vowels = set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']) + s = list(s) + + while i Date: Fri, 9 Jul 2021 10:31:31 +0800 Subject: [PATCH 099/187] no message --- problems/3sum-closest.py | 24 +++++ problems/3sum.py | 101 ++++++++++++++++++++++ problems/4sum.py | 64 ++++++++++++++ problems/intersection-of-two-arrays-ii.py | 43 +++++++++ problems/intersection-of-two-arrays.py | 10 ++- problems/two-sum.py | 14 ++- problems/wiggle-subsequence.py | 64 ++++++++++++++ 7 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 problems/3sum-closest.py create mode 100644 problems/4sum.py create mode 100644 problems/intersection-of-two-arrays-ii.py create mode 100644 problems/wiggle-subsequence.py diff --git a/problems/3sum-closest.py b/problems/3sum-closest.py new file mode 100644 index 0000000..11b2dc1 --- /dev/null +++ b/problems/3sum-closest.py @@ -0,0 +1,24 @@ +class Solution(object): + def threeSumClosest(self, nums, target): + ans = float('inf') + N = len(nums) + + nums.sort() + + for i in xrange(N): + l = i+1 + r = N-1 + + while ltarget: + r -= 1 + elif s0, means that we need to reduce the s and it can only be done by decreasing k. +if s<0, means that we need to increase the s and it can only be done by increasing j. +""" +class Solution(object): + def threeSum(self, nums): + nums.sort() + ans = set() + N = len(nums) + + for i in xrange(N): + j = i+1 + k = N-1 + + while j0: + k -= 1 + elif s<0: + j += 1 + else: + ans.add(tuple(sorted([nums[i], nums[j], nums[k]]))) + k -= 1 + j += 1 + + return ans + +""" +Two Pointers +Time: O(N^2) +Space: O(1) + +Same as above. Move pointers to avoid repeation. Faster. +""" +class Solution(object): + def threeSum(self, nums): + nums.sort() + ans = [] + N = len(nums) + + for i in xrange(N): + j = i+1 + k = N-1 + + if i>0 and nums[i]==nums[i-1]: continue #[1] + + while j0: + k -= 1 + elif s<0: + j += 1 + else: + ans.append([nums[i], nums[j], nums[k]]) + + while jtarget: + d -= 1 + elif s0 and nums[a]==nums[a-1]: continue + for b in xrange(a+1, N): + if b>0 and nums[b]==nums[b-1] and a!=b-1: continue + c = b+1 + d = N-1 + + while ctarget: + d -= 1 + elif snums2[j]: + j += 1 + else: + i += 1 + return ans + +""" +Time: O(N) +Space: O(N) +""" +class Solution(object): + def intersect(self, nums1, nums2): + c = {} #nums1 counter + ans = [] + + for n in nums1: + if n in c: + c[n] += 1 + else: + c[n] = 1 + + for n in nums2: + if n in c and c[n]>0: + ans.append(n) + c[n] -= 1 + return ans \ No newline at end of file diff --git a/problems/intersection-of-two-arrays.py b/problems/intersection-of-two-arrays.py index 68bac01..585d8a3 100644 --- a/problems/intersection-of-two-arrays.py +++ b/problems/intersection-of-two-arrays.py @@ -19,4 +19,12 @@ def intersection(self, nums1, nums2): #element in set is not repeated #set has some convenient build-in operator def intersection(self, nums1, nums2): - return list(set(nums1) & set(nums2)) \ No newline at end of file + return list(set(nums1) & set(nums2)) + + +class Solution(object): + def intersection(self, nums1, nums2): + nums1 = set(nums1) + nums2 = set(nums2) + + return nums1.intersection(nums2) \ No newline at end of file diff --git a/problems/two-sum.py b/problems/two-sum.py index ed91942..4ded939 100644 --- a/problems/two-sum.py +++ b/problems/two-sum.py @@ -30,4 +30,16 @@ def twoSum(self, nums, target): if num in M: return (M[num], i) M[target-num] = i - return False \ No newline at end of file + return False + +#2021/7/4 +class Solution(object): + def twoSum(self, nums, target): + memo = {} #{key : value} := {"counter part needed for n" : "index of n"} + + for i, n in enumerate(nums): + if n in memo: + return [memo[n], i] + else: + memo[target-n] = i + return [] \ No newline at end of file diff --git a/problems/wiggle-subsequence.py b/problems/wiggle-subsequence.py new file mode 100644 index 0000000..e44e632 --- /dev/null +++ b/problems/wiggle-subsequence.py @@ -0,0 +1,64 @@ +""" +dp[0][0 or 1] is considering no num in nums. +dp[1][0 or 1] is considering the first num in nums. +dp[2][0 or 1] is considering the second num in nums. +dp[3][0 or 1] is considering the third num in nums. +... + +dp[i][0] := longest length of wiggle seq that ends at nums[i-1] and diff ends in positive number. +dp[i][1] := longest length of wiggle seq that ends at nums[i-1] and diff ends in negative number. + +Time: O(N) +Space: O(N) +""" +class Solution(object): + def wiggleMaxLength(self, nums): + ans = 1 + N = len(nums) + + dp = [[0, 0] for _ in xrange(N+1)] + dp[1][0] = 1 + dp[1][1] = 1 + + for i in xrange(2, N+1): + if nums[i-1]-nums[i-2]>0: + dp[i][0] = dp[i-1][1]+1 + dp[i][1] = dp[i-1][1] + elif nums[i-1]-nums[i-2]<0: + dp[i][1] = dp[i-1][0]+1 + dp[i][0] = dp[i-1][0] + else: + dp[i][1] = dp[i-1][1] + dp[i][0] = dp[i-1][0] + + ans = max(ans, dp[i][0], dp[i][1]) + + return ans + +""" +From the above solution, we notice that we do not need whole array to keep track. +Just need two variables. +Use `up` and `down` to replace dp[i-1][0] and dp[i-1][1] + +Time: O(N) +Space: O(1) +""" +class Solution(object): + def wiggleMaxLength(self, nums): + N = len(nums) + + ans = 1 + up = 1 + down = 1 + + for i in xrange(2, N+1): + if nums[i-1]-nums[i-2]>0: + up, down = down+1, down + elif nums[i-1]-nums[i-2]<0: + down = up+1 + + ans = max(ans, up, down) + + return ans + + From 4e694d3062f60aa0994beaeb84a9f42bd8340741 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Thu, 22 Jul 2021 08:32:25 +0800 Subject: [PATCH 100/187] no message --- .../find-minimum-in-rotated-sorted-array.py | 39 +++++++++++- problems/longest-common-prefix.py | 18 +++++- problems/median-of-two-sorted-arrays.py | 18 +++--- problems/next-permutation.py | 32 ++++++++++ problems/search-in-rotated-sorted-array-ii.py | 61 ++++++++++++++++++- problems/search-insert-position.py | 38 ++++++++++++ 6 files changed, 193 insertions(+), 13 deletions(-) create mode 100644 problems/next-permutation.py diff --git a/problems/find-minimum-in-rotated-sorted-array.py b/problems/find-minimum-in-rotated-sorted-array.py index db5880e..2f52673 100644 --- a/problems/find-minimum-in-rotated-sorted-array.py +++ b/problems/find-minimum-in-rotated-sorted-array.py @@ -44,7 +44,7 @@ def findMin(self, nums): If the list is already sorted, return the left most element. [1] Now, we cut the rotated array into half. l~m and m~r. -Normally, one part will be sorted, the other half is not. +One part will be sorted, the other half is not. The min must be in the unsorted part. So we move the pointer and do the same thing on the unsorted part. [2] @@ -72,4 +72,39 @@ def findMin(self, nums): l = m+1 #[2] else: r = m-1 #[2] - return 0 \ No newline at end of file + return 0 + + +#2021/7/18 +""" +Pointer l and r is at the start and at the end of the list. +We only consider the numbers between l and r. + +If the list is already sorted, return the left most element. [0] +If the list is unsorted, one of the part l~m or m~r will be sorted and the other will be unsorted. + +The MIN will be in the unsorted part. +Adjust l and r and repeat the above process. + +Time: Log(N) +Space: O(1) +""" +class Solution(object): + def findMin(self, nums): + N = len(nums) + + l = 0 + r = N-1 + + while l<=r: + m = (l+r)/2 + + if nums[l]<=nums[m] and nums[m]<=nums[r]: return nums[l] #[0] + + if nums[l]>nums[m]: + #l~m is unsorted + r = m + else: + #m~r is unsorted + #in this case, we already sure that current m is not the MIN, so we can +1 to speed up and avoid infinitive loop + l = m+1 \ No newline at end of file diff --git a/problems/longest-common-prefix.py b/problems/longest-common-prefix.py index 083357e..b3d2e83 100644 --- a/problems/longest-common-prefix.py +++ b/problems/longest-common-prefix.py @@ -21,4 +21,20 @@ def longestCommonPrefix(self, strs): for s in strs: if s[:i]!=common_substring: #[2] return bench_mark[:i-1] - return bench_mark #[3] \ No newline at end of file + return bench_mark #[3] + +# 2021/7/10 +class Solution(object): + def longestCommonPrefix(self, strs): + j = 0 + minLen = float('inf') + for s in strs: minLen = min(minLen, len(s)) + if minLen==float('inf'): return "" + + while jlen(B): A, B = B, A #[0] M, N = len(A), len(B) - l, h = 0, M + l, r = 0, M - while l<=h: - i = (h+l)/2 + while l<=r: + i = (r+l)/2 j = (M+N)/2-i #[1] max_left_A = A[i-1] if i>0 else float('-inf') #[2] @@ -73,7 +73,7 @@ def findMedianSortedArrays(self, A, B): else: return min(min_right_A, min_right_B) #[1] elif min_right_B= Y[after-i-1]: - h = i + r = i else: l = i + 1 i = l diff --git a/problems/next-permutation.py b/problems/next-permutation.py new file mode 100644 index 0000000..f228cc4 --- /dev/null +++ b/problems/next-permutation.py @@ -0,0 +1,32 @@ +""" +This answer is the python version of the offical answer. + +Time: O(N) +Space: O(1) +""" +class Solution(object): + def nextPermutation(self, nums): + def reverse(start): + end = len(nums)-1 + + while start=0 and nums[i+1]<=nums[i]: + i -= 1 + + if i>=0: + j = len(nums)-1 + while nums[j]<=nums[i]: j -= 1 + swap(i, j) + + reverse(i+1) + return nums \ No newline at end of file diff --git a/problems/search-in-rotated-sorted-array-ii.py b/problems/search-in-rotated-sorted-array-ii.py index 43e913b..3a54f83 100644 --- a/problems/search-in-rotated-sorted-array-ii.py +++ b/problems/search-in-rotated-sorted-array-ii.py @@ -69,4 +69,63 @@ def helper(l, r): return False if not nums: return False - return helper(0, len(nums)-1) \ No newline at end of file + return helper(0, len(nums)-1) + + +""" +Time: O(LogN). Worse Case: O(N). +Space: O(1) + +The key idea for most rotated array question is that +If you cut the array into half, +One of the half will be rotated and one half will be in-order. +OR +Both of them are in-order (if you are lucky) +""" +class Solution(object): + def search(self, A, T): + N = len(A) + l = 0 + r = N-1 + + while l<=r: + + #skip repeated numbers + while r>0 and A[r]==A[r-1]: r -= 1 + while l0 and A[l]==A[r]: r -= 1 + while lA[r]: return False #out of range l~r + + if A[m] Date: Mon, 26 Jul 2021 09:39:10 +0800 Subject: [PATCH 101/187] no message --- ...ast-position-of-element-in-sorted-array.py | 34 ++++++++- ...find-minimum-in-rotated-sorted-array-ii.py | 35 +++++++++ problems/first-bad-version.py | 33 ++++++++ problems/guess-number-higher-or-lower.py | 31 ++++++++ problems/search-in-rotated-sorted-array-ii.py | 7 +- problems/search-in-rotated-sorted-array.py | 75 ++++++++++++++++++- 6 files changed, 209 insertions(+), 6 deletions(-) create mode 100644 problems/first-bad-version.py create mode 100644 problems/guess-number-higher-or-lower.py diff --git a/problems/find-first-and-last-position-of-element-in-sorted-array.py b/problems/find-first-and-last-position-of-element-in-sorted-array.py index c9495dc..513dda2 100644 --- a/problems/find-first-and-last-position-of-element-in-sorted-array.py +++ b/problems/find-first-and-last-position-of-element-in-sorted-array.py @@ -86,7 +86,39 @@ def find_range(i, nums): +#2021/7/23 +""" +Time: O(LogN). Worse case: 0(N). +Space: O(1) - +Standard binary search. Find the first and last by `rangeOf()` after we found it. +""" +class Solution(object): + def searchRange(self, A, T): + def rangeOf(i): + l = r = i + while 0 Date: Tue, 3 Aug 2021 17:19:22 +0800 Subject: [PATCH 102/187] no message --- problems/h-index-ii.py | 35 +++++++++++ problems/h-index.py | 52 ++++++++++++++++ problems/isomorphic-strings.py | 33 ++++++++++ ...-substring-without-repeating-characters.py | 25 +++++++- problems/palindrome-pairs.py | 62 +++++++++++++++++++ problems/russian-doll-envelopes.py | 61 ++++++++++++++++++ problems/subarray-sum-equals-k.py | 55 ++++++++++++++++ ...bstring-with-concatenation-of-all-words.py | 50 +++++++++++++++ problems/two-sum.py | 15 +++++ problems/valid-anagram.py | 22 ++++++- 10 files changed, 408 insertions(+), 2 deletions(-) create mode 100644 problems/h-index-ii.py create mode 100644 problems/h-index.py create mode 100644 problems/isomorphic-strings.py create mode 100644 problems/palindrome-pairs.py create mode 100644 problems/russian-doll-envelopes.py create mode 100644 problems/subarray-sum-equals-k.py create mode 100644 problems/substring-with-concatenation-of-all-words.py diff --git a/problems/h-index-ii.py b/problems/h-index-ii.py new file mode 100644 index 0000000..8c5f7e2 --- /dev/null +++ b/problems/h-index-ii.py @@ -0,0 +1,35 @@ +""" +Time: O(LogN) +Space: O(1) + +Since citations is sorted, +i = N-1, if 1<=citations[i], it means that at least 1 of the citations is larger than 1. h-index is 1. +i = N-2, if 2<=citations[i], it means that at least 2 of the citations is larger than 2. h-index is 2. +... +i = 0, if N<=citations[i], it means that at least N of the citations is larger than N. h-index is N. + +We can iterate from N-1 to 0. See what h-index ends up. Using O(N) of time. + +We can also binary search the i, see which i match the condition. +""" +class Solution(object): + def hIndex(self, citations): + N = len(citations) + + l = 0 + r = N-1 + + while l=h: + #h may be the h-index, check larger h. + r = i + else: + #h is not h-index, check smaller h. + l = i+1 + + #now, l is equal to r + + return N-l if citations[l]!=0 else 0 #take care of edge case [0], [0, 0] or [0, 0, 0] \ No newline at end of file diff --git a/problems/h-index.py b/problems/h-index.py new file mode 100644 index 0000000..08ef891 --- /dev/null +++ b/problems/h-index.py @@ -0,0 +1,52 @@ +""" +First, reverse sort the list and iterate though it. +i = 0, if 1>=citations[i], it means that at least 1 of the citations is larger than 1. +i = 1, if 2>=citations[i], it means that at least 2 of the citations is larger than 2. +i = 3, if 3>=citations[i], it means that at least 3 of the citations is larger than 3. +... +... +Keep iterating until we fail the condition. + +Time: O(NLogN) +Space: O(1) +""" +class Solution(object): + def hIndex(self, citations): + citations.sort(reverse=True) + + ans = 0 + for i in xrange(len(citations)): + if i+1>citations[i]: break + ans = i+1 + + return ans + + +""" +First, count each citation and store it in counter. +The citation that is larger than N will be stored to N. [0] +Since for citations, the max possible h-index will be N (the length of the citations). +This can greatly reduce the index we go through when we iterate through counter. + +Second, since the max possible h-index is N, we start from N and iterate to 0. +Check if any of them is answer + +Time: O(N) +Space: O(N) +""" +import collections + +class Solution(object): + def hIndex(self, citations): + counter = collections.Counter() #count for each citation + N = len(citations) + count = 0 + + for citation in citations: + counter[min(N, citation)] += 1 #[0] + + for n in xrange(N, -1, -1): + count += counter[n] #count of citation that is larger or equal to n + if count>=n: return n + + return 0 \ No newline at end of file diff --git a/problems/isomorphic-strings.py b/problems/isomorphic-strings.py new file mode 100644 index 0000000..8785c2c --- /dev/null +++ b/problems/isomorphic-strings.py @@ -0,0 +1,33 @@ +""" +The description of the problem is unclear, let me rephrase it. + +Given two strings s and t, determine if they are isomorphic. +Two strings s and t are isomorphic if the characters in s can be replaced to get t and t can be replaced to get s. + +For each replacement, the characters in the same string must be replaced with another character while preserving the order of characters. +No two characters in the same string may map to the same character, but a character may map to itself. + +Two replacement are independent from each other. In other words, s -> t and t -> s does not affect each other. +""" + +""" +Time: O(N) +Space: O(N) +""" +class Solution(object): + def isIsomorphic(self, s, t): + if len(s)!=len(t): return False + + # check if s1 chars could be replaced and become s2 + def helper(s1, s2): + memo = {} + + for i in xrange(len(s)): + c1 = s1[i] + c2 = s2[i] + + if c1 in memo and memo[c1]!=c2: return False + memo[c1] = c2 + return True + + return helper(s, t) and helper(t, s) \ No newline at end of file diff --git a/problems/longest-substring-without-repeating-characters.py b/problems/longest-substring-without-repeating-characters.py index ccb545a..3c1a2d3 100644 --- a/problems/longest-substring-without-repeating-characters.py +++ b/problems/longest-substring-without-repeating-characters.py @@ -46,4 +46,27 @@ def lengthOfLongestSubstring(self, s): lastSeen[c] = i maxLength = max(maxLength, i-start+1) - return maxLength \ No newline at end of file + return maxLength + + +""" +Time: O(N). +Space: O(N). + +Iterate throught s, while constantly update the "start" using "lastSeen". +start~i does not have repeated character. +Also, start should only be incremental [0] +consider case `s = abba`, some at some point `lastSeen[c]` might be smaller than current start. +""" +class Solution(object): + def lengthOfLongestSubstring(self, s): + ans = 0 + start = 0 + lastSeen = {} + + for i, c in enumerate(s): + if c in lastSeen: start = max(start, lastSeen[c]+1) #[0] + lastSeen[c] = i + ans = max(ans, i-start+1) + + return ans \ No newline at end of file diff --git a/problems/palindrome-pairs.py b/problems/palindrome-pairs.py new file mode 100644 index 0000000..75e5082 --- /dev/null +++ b/problems/palindrome-pairs.py @@ -0,0 +1,62 @@ +""" +Time: O(N x L^2), assume the average length of word is L. Note that, eversing the string takes O(L). +Space: O(L), beside from ans, need `left` and `right` constantly to store the word. +""" +class Solution(object): + def palindromePairs(self, words): + ans = set() + index = {word:i for i, word in enumerate(words)} + + for i, word in enumerate(words): + for j in xrange(len(word)+1): + left = word[:j] + right = word[j:] + + # check if any other word that concat to the left will make palindrome: "OTHER_WORD+`left`+`right`" + # The above will be palindrome only if + # 1. `left` is palindrome (left==left[::-1]) + # 2. Exsit an "OTHER_WORD" in word in words that equals to the reverse of `right` (right[::-1] in index and index[right[::-1]]!=i). + if left==left[::-1]: + if right[::-1] in index and index[right[::-1]]!=i: + ans.add((index[right[::-1]], i)) + + # check if any other word that concat to the right will make palindrome: "`left`+`right`+OTHER_WORD" + # The above will be palindrome only if + # 1. `rihgt` is palindrome (right==right[::-1]) + # 2. Exsit an "OTHER_WORD" in words that equals to the reverse of `left` (left[::-1] in index and index[left[::-1]]!=i). + if right==right[::-1]: + if left[::-1] in index and index[left[::-1]]!=i: + ans.add((i, index[left[::-1]])) + + return ans + + +""" +Time: O(N^2 x L), will cause TLE. +Space: O(L), can reduce to O(1) by improving isPalindrome() +""" +class Solution(object): + def palindromePairs(self, words): + N = len(words) + ans = [] + + for i in xrange(N): + for j in xrange(N): + if i==j: continue + if self.isPalindrome(words[i]+words[j]): + ans.append([i, j]) + return ans + + def isPalindrome(self, word): + l = 0 + r = len(word)-1 + + while l<=r: + if word[l]==word[r]: + l += 1 + r -= 1 + else: + return False + return True + + \ No newline at end of file diff --git a/problems/russian-doll-envelopes.py b/problems/russian-doll-envelopes.py new file mode 100644 index 0000000..9b89256 --- /dev/null +++ b/problems/russian-doll-envelopes.py @@ -0,0 +1,61 @@ +""" +dp[i] := number of envelopes that envelopes[i] can contains the most. +Very similar to LIS problem (Leetcode 300) +This method will get TLE + +Time: O(N^2) +Space: O(N) +""" +class Solution(object): + def maxEnvelopes(self, envelopes): + if not envelopes: return 0 + + N = len(envelopes) + dp = [1]*N + envelopes = sorted(envelopes) + ans = 1 + + for i in xrange(N): + for j in xrange(i): + if envelopes[i][0]>envelopes[j][0] and envelopes[i][1]>envelopes[j][1]: + dp[i] = max(dp[i], dp[j]+1) + ans = max(ans, dp[i]) + + return ans + +""" +dp[i] := the smallest ending number of a sequence that has length i+1 +First, sort the envelopes by width. (envelope[0]) +Second, return the LIS of heights ([envelope[1] for envelope in envelopes]). +This automatically gets the number of "russian dolls". + +However, we might choose [3,4], [3,7] as a valid solution. This is not correct because w1==w2. +So we do a quick fix by sorting the envelopes with w and h reversed. +So that getLIS() will not choose [3,4], [3,7] + +Time: O(NLogN) +Space: O(N) +""" +import bisect +class Solution(object): + def maxEnvelopes(self, envelopes): + if not envelopes: return 0 + + N = len(envelopes) + dp = [1]*N + envelopes = envelopes.sort(key=lambda x:(x[0], -x[1])) + + return self.getLIS([envelope[1] for envelope in envelopes]) + + def getLIS(self, A): + dp = [] + + for n in A: + i = bisect.bisect_left(dp, n) + + if i==len(dp): + dp.append(n) + else: + dp[i] = n + + return len(dp) diff --git a/problems/subarray-sum-equals-k.py b/problems/subarray-sum-equals-k.py new file mode 100644 index 0000000..3220cff --- /dev/null +++ b/problems/subarray-sum-equals-k.py @@ -0,0 +1,55 @@ +""" +Time: O(N^2), this will get TLE +Space: O(N) + +prefixSum[i] == sum(nums[:i]) (nums[0] + nums[1] + ... + nums[i-1]) +prefixSum[j]-prefixSum[i] == sum(nums[i:j]) (nums[i] + nums[i+1] + ... + nums[j-1]) +By iterating through all i and j possibilities, we get all the subarray sum that equals to k. +""" +class Solution(object): + def subarraySum(self, nums, k): + N = len(nums) + prefixSum = [0] + ans = 0 + + temp = 0 + for n in nums: + temp += n + prefixSum.append(temp) + + for i in xrange(N+1): + for j in xrange(i+1, N+1): + if prefixSum[j]-prefixSum[i]==k: ans += 1 + + return ans + + +""" +Time: O(N) +Space: O(N) + +Let's optimize from above solution. +Let prefixSum[j] as J. +Let prefixSum[i] as I. + +We are basically looking for J-I that equals to k. (J-I == k) +In other words, given a J we are actually looking for an I that eauals to J-k. +If there are, 3 I that equals to J-k exists beforehand, there are 3 J-I combinations that equal to k. +ans += 3 +""" +class Solution(object): + def subarraySum(self, nums, k): + N = len(nums) + ans = 0 + + prefixSumCount = collections.Counter() + prefixSumCount[0] = 1 + + J = 0 + for n in nums: + J += n + I = J-k #the I that we are looking for. + ans += prefixSumCount[I] #there are "prefixSumCount[I]" combinations of J-I that equals to k. + prefixSumCount[J] += 1 + + return ans \ No newline at end of file diff --git a/problems/substring-with-concatenation-of-all-words.py b/problems/substring-with-concatenation-of-all-words.py new file mode 100644 index 0000000..b11bb81 --- /dev/null +++ b/problems/substring-with-concatenation-of-all-words.py @@ -0,0 +1,50 @@ +""" +Time: O(N*wl), N is the length of the input string s; wl is the length of each word. +Space: O(N) + +For word count wc and word length wl, the string we are looking for will be between i and j (s[i:j]). +`test()` all s[i:j]. If pass, append into ans. + +Each `test()` will test the sub-string s[i:j]`. +If any "word" in the sub-string is not in the countExpected, the test failed. +If the word is used too many times (more than "countExpected"), the test failed. +Otherwise, the test pass. + +This is the solution I learn from @gabbu. +""" +import collections + +class Solution(object): + def findSubstring(self, s, words): + if not words: return [] + + wc = len(words) #word count + wl = len(words[0]) #word length + ans = [] + + i = 0 + j = wc*wl + + countExpected = collections.Counter(words) + + while j<=len(s): + if self.test(s[i:j], wl, countExpected): ans.append(i) + i += 1 + j += 1 + + return ans + + + def test(self, s, wl, countExpected): + counter = collections.Counter() #{word:how many time the word is used} + i = 0 + + while i=countExpected[word]: return False + i += wl + counter[word] += 1 + + return True + + \ No newline at end of file diff --git a/problems/two-sum.py b/problems/two-sum.py index 4ded939..3d8013e 100644 --- a/problems/two-sum.py +++ b/problems/two-sum.py @@ -42,4 +42,19 @@ def twoSum(self, nums, target): return [memo[n], i] else: memo[target-n] = i + return [] + +#2021/7/31 +""" +Time: O(N) +Space: O(N) +""" +class Solution(object): + def twoSum(self, nums, target): + memo = {} #{key : value} := {"counter part needed for n" : "index of n"} + + for i, n in enumerate(nums): + if n in memo: return [memo[n], i] + memo[target-n] = i + return [] \ No newline at end of file diff --git a/problems/valid-anagram.py b/problems/valid-anagram.py index 0dbf1fc..ece7dce 100644 --- a/problems/valid-anagram.py +++ b/problems/valid-anagram.py @@ -39,4 +39,24 @@ def isAnagram(self, s, t): for i in string.ascii_lowercase: if s.count(i) != t.count(i): return False - return True \ No newline at end of file + return True + + +#2021//7/29 +""" +Time: O(N) +Space: O(N) +""" +import collections + +class Solution(object): + def isAnagram(self, s, t): + counter = collections.Counter() + if len(t)>len(s): t, s = s, t + + for c in s: counter[c] += 1 + for c in t: counter[c] -= 1 + for c in counter: + if counter[c]>0: return False + return True + \ No newline at end of file From f682d592ff4828af4c2fcbeab5172701279fc3e6 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Sat, 7 Aug 2021 11:05:10 +0800 Subject: [PATCH 103/187] no message --- problems/longest-consecutive-sequence.py | 24 +++++ ...ng-with-at-least-k-repeating-characters.py | 97 +++++++++++++++++++ problems/majority-element-ii.py | 14 +++ problems/majority-element.py | 38 ++++++++ problems/minimum-window-substring.py | 42 ++++++++ problems/permutation-in-string.py | 32 ++++++ 6 files changed, 247 insertions(+) create mode 100644 problems/longest-consecutive-sequence.py create mode 100644 problems/longest-substring-with-at-least-k-repeating-characters.py create mode 100644 problems/majority-element-ii.py create mode 100644 problems/majority-element.py create mode 100644 problems/minimum-window-substring.py create mode 100644 problems/permutation-in-string.py diff --git a/problems/longest-consecutive-sequence.py b/problems/longest-consecutive-sequence.py new file mode 100644 index 0000000..541db3a --- /dev/null +++ b/problems/longest-consecutive-sequence.py @@ -0,0 +1,24 @@ +""" +Time: O(N), the while loop will only be executed if `n` is the beginning of a consecutive sequence. So each n will only be iterated once. +Space: O(N). + +For each `n` in the set, check if it is a beginning of a consecutive sequence. (`n-1 not in s`) +If so, get the length of the consecutive sequence (`c`) and update the `ans`. +""" +class Solution(object): + def longestConsecutive(self, nums): + s = set(nums) + ans = 0 + + for n in s: + if n-1 not in s: + c = 1 + curr = n + + while curr+1 in s: + curr = curr+1 + c += 1 + + ans = max(ans, c) + + return ans \ No newline at end of file diff --git a/problems/longest-substring-with-at-least-k-repeating-characters.py b/problems/longest-substring-with-at-least-k-repeating-characters.py new file mode 100644 index 0000000..5445529 --- /dev/null +++ b/problems/longest-substring-with-at-least-k-repeating-characters.py @@ -0,0 +1,97 @@ +""" +Time: O(N^2) (Worst case). O(N) (Best case) +Space: O(N) + +The "Substring" must be a continuous part of s. +If a certain char with index i does not have count>=k, the answer must be in `s[:i]` or `s[i+1:]`. +""" +import collections + +class Solution(object): + def longestSubstring(self, s, k): + if not s: return 0 + counter = collections.Counter(s) + + i = 0 + while i=k: + i += 1 + else: + return max(self.longestSubstring(s[:i], k), self.longestSubstring(s[i+1:], k)) + return i + +""" +Optimize the above solution to using O(1) space by pointers `l` and `r` +""" +class Solution(object): + def longestSubstring(self, s, k): + def helper(l, r): + if r-l==0: return 0 + counter = collections.Counter(s[l:r]) + + i = l + while i=k: + i += 1 + else: + return max(helper(l, i), helper(i+1, r)) + return i-l + + return helper(0, len(s)) + +""" +Time: O(N). Each `helper()` takes O(N), uniqueCount will be at most 26, O(26N) ~= O(N). +Space: O(N). + +Use a sliding window (`s[i:j+1]`) to go through `s`. +Givin a fixed i we move the j as right as possible. Then move the i right (Before we move the i, recalculate a those var tracking s[i:j+1]) [0] +For each sliding window if all the unique char has count>=k (`len(counter)==m and count==m`), update the answer. + +What is "m"? +Without "m", you will soon notice that we are not able to stop sliding window growing. +So we need to add the constraint: Get longestSubstring with m unique char. [1] +The final answer will be the max of: +longestSubstring with 1 unique char. +longestSubstring with 2 unique char. +... +... +longestSubstring with uniqueCount unique char. +""" +class Solution(object): + def longestSubstring(self, s, k): + ans = 0 + uniqueCount = len(set(s)) + + for m in xrange(1, uniqueCount+1): + ans = max(ans, self.helper(s, k, m)) + + return ans + + #[1] + def helper(self, s, k, m): + j = 0 + counter = collections.Counter() #count each char in s[i:j+1] + countOverK = 0 #number of char in s[i:j+1] count>=k + ans = 0 + + for i in xrange(len(s)): + while jrequiredCount: ans.append(n) + + return ans \ No newline at end of file diff --git a/problems/majority-element.py b/problems/majority-element.py new file mode 100644 index 0000000..dead6e3 --- /dev/null +++ b/problems/majority-element.py @@ -0,0 +1,38 @@ +""" +Time: O(N) +Space: O(N) +""" +class Solution(object): + def majorityElement(self, nums): + counter = {} + + for n in nums: + if n not in counter: counter[n] = 0 + counter[n] += 1 + if counter[n]>len(nums)/2.0: return n + + return 0 + +""" +Time: O(N) +Space: O(1) + +Boyer-Moore +If a number `n` is not majority number its `count` will certainly become 0 and `ans` will switch to another number `n`. +If a number `n` is majority number its `count` will certainly larger thans 0 at the end, since it is the "majority". +""" +class Solution(object): + def majorityElement(self, nums): + ans = nums[0] + count = 0 + + for n in nums: + if n==ans: + count += 1 + else: + count -= 1 + if count==0: + ans = n + count = 1 + return ans + \ No newline at end of file diff --git a/problems/minimum-window-substring.py b/problems/minimum-window-substring.py new file mode 100644 index 0000000..d5d0e07 --- /dev/null +++ b/problems/minimum-window-substring.py @@ -0,0 +1,42 @@ +""" +Time: O(S+T) +Space: O(S+T) + +Moving pointers l and r to change the window. +The window we desired is the one that `actual==required`. (`windowCounter` and `tCounter` help us to track required and actual) +If the window is not what we desired, keep expand right. +If the window is what we desired, contract the window from left, see if we can find shorter ans. +""" +import collections + +class Solution(object): + def minWindow(self, s, t): + ans = s + ansFound = False + windowCounter = collections.Counter() + tCounter = collections.Counter(t) + required = len(tCounter) #number of unique char in t + actual = 0 #number of unique char in t in the window that has the count needed in tCounter + r = l = 0 + + while r=len(s2): break + counter2[s2[j]] += 1 + + if counter1==counter2: return True + + counter2[s2[i]] -= 1 + if counter2[s2[i]]==0: counter2.pop(s2[i], None) + + return False \ No newline at end of file From 1642d02c60b86c3bfee67e1689cb8640167d2a29 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Mon, 9 Aug 2021 07:50:39 +0800 Subject: [PATCH 104/187] no message --- problems/increasing-triplet-subsequence.py | 24 +++++ problems/kth-largest-element-in-an-array.py | 44 +++++++++ problems/word-ladder.py | 104 ++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 problems/increasing-triplet-subsequence.py create mode 100644 problems/kth-largest-element-in-an-array.py diff --git a/problems/increasing-triplet-subsequence.py b/problems/increasing-triplet-subsequence.py new file mode 100644 index 0000000..60cecd7 --- /dev/null +++ b/problems/increasing-triplet-subsequence.py @@ -0,0 +1,24 @@ +""" +Time: O(N) +Space: O(1) + +Keep updating the minimum element (`min1`) and the second minimum element (`min2`). +When a new element comes up there are 3 possibilities. +0. Equals to min1 or min2 => do nothing. +1. Smaller than min1 => update min1. +2. Larger than min1 and smaller than min2 => update min2. +3. Larger than min2 => return True. +""" +class Solution(object): + def increasingTriplet(self, nums): + min1 = min2 = float('inf') + + for n in nums: + if n0: + ans = heapq.heappop(nums) + k -= 1 + + return ans + +""" +Quick Search + +Time: O(N) in average case, O(N^2) in worst case. +Spcae: O(1) +""" +class Solution(object): + def findKthLargest(self, nums, k): + #to be continued... + pass \ No newline at end of file diff --git a/problems/word-ladder.py b/problems/word-ladder.py index e6dec9c..1948487 100644 --- a/problems/word-ladder.py +++ b/problems/word-ladder.py @@ -95,3 +95,107 @@ def ladderLength(self, beginWord, endWord, wordList): q.append((next_word, steps+1)) seen.add(next_word) return 0 + + +#2021/8/9 +""" +Time: O(V^2), build the adjacent list takes V^2. BFS takes O(V+E). +Space: O(V). + +a = { + 'hit': ['hot'], + 'lot': ['hot', 'dot', 'lot', 'log'], + 'dog': ['dot', 'dog', 'log', 'cog'], + 'hot': ['hot', 'dot', 'lot'], + 'cog': ['dog', 'log', 'cog'], + 'dot': ['hot', 'dot', 'dog', 'lot'], + 'log': ['dog', 'lot', 'log', 'cog'] +} +""" +class Solution(object): + def ladderLength(self, beginWord, endWord, wordList): + #build an adjacent list + a = collections.defaultdict(list) + + for word in wordList+[beginWord]: + possible = set() + for i in xrange(len(word)): + for alphabet in 'abcdefghijklmnopqrstuvwxyz': + possible.add(word[:i]+alphabet+word[i+1:]) + for nextWord in wordList: + if nextWord in possible: + a[word].append(nextWord) + + #BFS + q = collections.deque([(beginWord, 1)]) + seen = set() + + while q: + word, steps = q.popleft() + if word in seen: continue + if word==endWord: return steps + seen.add(word) + for wordNext in a[word]: q.append((wordNext, steps+1)) + + return 0 + + +""" +Time: O(VL+E), build the adjacent list takes O(VL). BFS takes O(V+E). +Space: O(V). + +Make some adjust ment to the adjacent list: +a = { + 'lo#': ['lot', 'log'], + 'l#t': ['lot'], + '#ot': ['hot', 'dot', 'lot'], + 'h#t': ['hot'], + 'do#': ['dot', 'dog'], + 'l#g': ['log'], + 'co#': ['cog'], + '#og': ['dog', 'log', 'cog'], + 'd#g': ['dog'], + 'd#t': ['dot'], + 'c#g': ['cog'], + 'ho#': ['hot'] +} +""" +class Solution(object): + def ladderLength(self, beginWord, endWord, wordList): + #build an adjacent list + a = collections.defaultdict(list) + + for word in wordList+[beginWord]: + for i in xrange(len(word)): + s = word[:i]+'#'+word[i+1:] + a[s].append(word) + + #BFS + q = collections.deque([(beginWord, 1)]) + seen = set() + + while q: + word, steps = q.popleft() + if word in seen: continue + if word==endWord: return steps + seen.add(word) + + for i in xrange(len(word)): + s = word[:i]+'#'+word[i+1:] + for wordNext in a[s]: + q.append((wordNext, steps+1)) + + return 0 + + + + + + + + + + + + + \ No newline at end of file From 430b5092da76c17278c36f15febd3c083300a468 Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Tue, 10 Aug 2021 08:11:08 +0800 Subject: [PATCH 105/187] no message --- problems/word-ladder-ii.py | 94 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 problems/word-ladder-ii.py diff --git a/problems/word-ladder-ii.py b/problems/word-ladder-ii.py new file mode 100644 index 0000000..67081c6 --- /dev/null +++ b/problems/word-ladder-ii.py @@ -0,0 +1,94 @@ +class Solution(object): + def findLadders(self, beginWord, endWord, wordList): + #build an adjacent list + a = collections.defaultdict(list) + + for word in wordList+[beginWord]: + for i in xrange(len(word)): + s = word[:i]+'#'+word[i+1:] + a[s].append(word) + + #BFS + q = collections.deque([(beginWord, collections.OrderedDict())]) + ans = [] + shortest = float('inf') + + while q: + word, path = q.popleft() + + if word in path: continue + path[word] = None + if len(path)>shortest: break + + if word==endWord: + shortest = len(path) + ans.append(path.keys()) + continue + + for i in xrange(len(word)): + s = word[:i]+'#'+word[i+1:] + for wordNext in a[s]: + q.append((wordNext, path.copy())) + + return ans + +""" +Time: O(VL+E). +Building V ajacencyList takes O(V*L*26) => O(VL). DFS takes O(V+E) +V is the number of words. L is the length of each word. E is the number of edge of each vertext (word). +Space: O(V+E) + +Build a special ranked adjacency list. +Different from the normal adjacency list, the list will only contain the ones the is farther away from the beginWord. +In other words, the adjacency nodes you get will not will not cercle back to the direction of the beginWord. +This assures us the result will be "shortest" path. + +Next, only standard dfs is needed. + +If you did not build the special adjacency list, you might need to check if a new node is already in the path or not. +This will cause TLE. +Or cause MLE if you use a hashset for the visited node in the path... + +This solution is inspired by https://www.youtube.com/watch?v=mIZJIuMpI2M. +""" +class Solution(object): + def findLadders(self, beginWord, endWord, wordList): + ans = [] + wordSet = set(wordList) + ajacencyList = self.buildAjacencyList(beginWord, wordSet) + stack = [(beginWord, [beginWord])] + + while stack: + word, path = stack.pop() + if word==endWord: ans.append(path) + + for nextWord in ajacencyList[word]: + stack.append((nextWord, path+[nextWord])) + + return ans + + def buildAjacencyList(self, beginWord, wordSet): + ajacencyList = collections.defaultdict(list) + + rank = {} + rank[beginWord] = 0 + + q = collections.deque() + q.append(beginWord) + + while q: + word = q.popleft() + for i in xrange(len(word)): + for alphabet in 'abcdefghijklmnopqrstuvwxyz': + nextWord = word[:i]+alphabet+word[i+1:] + + if nextWord not in wordSet or word==nextWord: continue + + if nextWord not in rank: + rank[nextWord] = rank[word]+1 + ajacencyList[word].append(nextWord) + q.append(nextWord) + elif rank[word] Date: Wed, 11 Aug 2021 07:52:37 +0800 Subject: [PATCH 106/187] no message --- problems/meeting-rooms-ii.py | 12 +++++++----- problems/meeting-rooms.py | 16 ++++++++++++++++ problems/top-k-frequent-elements.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 problems/meeting-rooms.py diff --git a/problems/meeting-rooms-ii.py b/problems/meeting-rooms-ii.py index 7f6413a..cc1f835 100644 --- a/problems/meeting-rooms-ii.py +++ b/problems/meeting-rooms-ii.py @@ -29,11 +29,13 @@ def minMeetingRooms(self, intervals): return result - # Definition for an interval. - # class Interval(object): - # def __init__(self, s=0, e=0): - # self.start = s - # self.end = e + + +# Definition for an interval. +# class Interval(object): +# def __init__(self, s=0, e=0): +# self.start = s +# self.end = e class Solution(object): def minMeetingRooms(self, intervals): diff --git a/problems/meeting-rooms.py b/problems/meeting-rooms.py new file mode 100644 index 0000000..797b422 --- /dev/null +++ b/problems/meeting-rooms.py @@ -0,0 +1,16 @@ +""" +Time: O(NLogN) +Space: O(1) + +Sort the interval (mainly by start time), see if the end overlaps with the start of next. +""" +class Solution(object): + def canAttendMeetings(self, intervals): + intervals.sort() + + for i in xrange(len(intervals)-1): + end = intervals[i][1] + nextStart = intervals[i+1][0] + if end>nextStart: return False + + return True \ No newline at end of file diff --git a/problems/top-k-frequent-elements.py b/problems/top-k-frequent-elements.py index 1c5b9d7..fbb68a6 100644 --- a/problems/top-k-frequent-elements.py +++ b/problems/top-k-frequent-elements.py @@ -59,4 +59,33 @@ def topKFrequent(self, nums, k): return opt +""" +Time: O(N+KLogN). +Building numToCounts takes O(N). +Building heap takes O(N) (Yeah, I know. Some People thinks `heapify` takes O(NLogN) but it actually takes O(N). But that is another story...). +HeapPop takes O(LogN). + +Space: O(N) + +1. Form `[(-count1, num1), (-count2, num2)]`, in this case `h`. +Use "-count" its because heapq in python is min heap, so using negative value will make it pop out the most freq count. +2. Turn h into heap. (heapify) + +3. HeapPop h for k times. +""" +class Solution(object): + def topKFrequent(self, nums, k): + ans = [] + + numToCounts = collections.Counter(nums) + h = [(-numToCounts[num], num) for num in numToCounts] + + heapq.heapify(h) + + while k>0: + _, num = heapq.heappop(h) + ans.append(num) + k -= 1 + + return ans \ No newline at end of file From f16e6e92b3b3fc7eb5f809ac3eba2ec04f7195db Mon Sep 17 00:00:00 2001 From: Chris Wu Date: Thu, 12 Aug 2021 08:37:17 +0800 Subject: [PATCH 107/187] no message --- problems/meeting-rooms-ii.py | 28 ++++++++++++++++- problems/range-addition.py | 59 ++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 problems/range-addition.py diff --git a/problems/meeting-rooms-ii.py b/problems/meeting-rooms-ii.py index cc1f835..99d5a28 100644 --- a/problems/meeting-rooms-ii.py +++ b/problems/meeting-rooms-ii.py @@ -54,7 +54,33 @@ def minMeetingRooms(self, intervals): +#2021/8/12 +""" +Time: O(NLogN) +Space: O(N) +1. Sort the intervals by the start time. So we can check the starttime in order. +2. Declare `h`. Imagine we store the room (endtime) we need in the `h`. +If a meeting comes up, first we will check if any room avaliable. +If so, take the room. (Remove the old endtime from `h` and add the current endtime) +If not, start a new room. (Add the current endtime) +Use heap so it will be convinient for us to get the earliest endtime at h[0] (most avaliable room). - +3. At last, `h` will contain the rooms (endtimes) needed for all the intervals. +""" +class Solution(object): + def minMeetingRooms(self, intervals): + intervals.sort() + h = [intervals[0][1]] + + for i in xrange(1, len(intervals)): + start = intervals[i][0] + end = intervals[i][1] + + if start>=h[0]: + #the room at h[0] is avaliable + heapq.heappop(h) + heapq.heappush(h, end) + + return len(h) \ No newline at end of file diff --git a/problems/range-addition.py b/problems/range-addition.py new file mode 100644 index 0000000..9be6d1b --- /dev/null +++ b/problems/range-addition.py @@ -0,0 +1,59 @@ +""" +Time: O(N+K), N is the length. K is the updates count. +Space: O(N) + +The bottleneck of the naive solution is that each "update" takes O(N) time to traverse from s to e. +The to total time complexity will become O(NK). +So we need to find a way to summarize the updates and apply those at once... + +Declare updateSummary, I will store the all the updates in it. + +Given length equals to 10: [0,0,0,0,0,0,0,0,0,0] +For update (1,3,4), you can also see it as +[0,+4,+4,+4,+4,+4,+4,+4,+4,+4] (Add 4 to all element after and including) index 1) +[0,0,0,0,-4,-4,-4,-4,-4,-4] (Remove 4 to all element after index 3) +And we can summarize this in updateSummary as [0,4,0,0,-4,0,0,0,0,0] + +For update (0,2,-2), you can also see it as +[-2,-2,-2,-2,-2,-2,-2,-2,-2,-2] (Add -2 to all element after and including index 0) +[0,0,0,+2,+2,+2,+2,+2,+2,+2] (Remove -2 to all element after index 2) +And we can summarize this in updateSummary as [-2,0,0,+2,0,0,0,0,0,0] + +updateSummary[i] means adding value updateSummary[i] to all index after and including i in ans. +""" +class Solution(object): + def getModifiedArray(self, length, updates): + ans = [0]*length + updateSummary = [0]*length + + for s, e, v in updates: + updateSummary[s] += v + if e+1 Date: Wed, 25 Aug 2021 06:57:59 +0800 Subject: [PATCH 108/187] no message --- problems/contains-duplicate-ii.py | 14 +++ problems/contains-duplicate-iii.py | 34 +++++++ problems/contains-duplicate.py | 13 +++ problems/data-stream-as-disjoint-intervals.py | 91 +++++++++++++++++++ problems/find-median-from-data-stream.py | 40 ++++++++ problems/k-empty-slots.py | 65 +++++++++++++ problems/linked-list-random-node.py | 22 +++++ .../max-sum-of-rectangle-no-larger-than-k.py | 52 +++++++++++ problems/merge-k-sorted-lists.py | 27 ++++++ problems/minimum-cost-to-hire-k-workers.py | 45 +++++++++ problems/moving-average-from-data-stream.py | 19 ++++ problems/rearrange-string-k-distance-apart.py | 46 ++++++++++ problems/shuffle-an-array.py | 59 ++++++++++++ problems/sliding-window-maximum.py | 62 ++++++++++++- 14 files changed, 588 insertions(+), 1 deletion(-) create mode 100644 problems/contains-duplicate-ii.py create mode 100644 problems/contains-duplicate-iii.py create mode 100644 problems/contains-duplicate.py create mode 100644 problems/data-stream-as-disjoint-intervals.py create mode 100644 problems/find-median-from-data-stream.py create mode 100644 problems/k-empty-slots.py create mode 100644 problems/linked-list-random-node.py create mode 100644 problems/max-sum-of-rectangle-no-larger-than-k.py create mode 100644 problems/merge-k-sorted-lists.py create mode 100644 problems/minimum-cost-to-hire-k-workers.py create mode 100644 problems/rearrange-string-k-distance-apart.py create mode 100644 problems/shuffle-an-array.py diff --git a/problems/contains-duplicate-ii.py b/problems/contains-duplicate-ii.py new file mode 100644 index 0000000..0d727c4 --- /dev/null +++ b/problems/contains-duplicate-ii.py @@ -0,0 +1,14 @@ +""" +Time: O(N) +Space: O(N) +""" +class Solution(object): + def containsNearbyDuplicate(self, nums, k): + lastSeen = {} + + for i, num in enumerate(nums): + if num in lastSeen: + if i-lastSeen[num]<=k: return True + lastSeen[num] = i + + return False \ No newline at end of file diff --git a/problems/contains-duplicate-iii.py b/problems/contains-duplicate-iii.py new file mode 100644 index 0000000..a725932 --- /dev/null +++ b/problems/contains-duplicate-iii.py @@ -0,0 +1,34 @@ +""" +Time: O(N) +Space: O(K) + +Imagine there are several different buckets. Each bucket can only contain one number. +Bucket1 contains a number within [0, t] +Bucket2 contains a number within [t+1, 2t+1] +Bucket3 contains a number within [2t+2, 3t+2] +... + +For each num, put it in the bucket. +Before that. +If the bucket is already occupied, there must be another num that "abs(anotherNum - num) <= t", return True. +Check the neighbor buckets, the number within those might also "abs(anotherNum - num) <= t". If so, return True. + +We only consider k numbers before num. +So remove nums[i-k-1] from the bucket if we already have k elements in the buckets. +""" +class Solution(object): + def containsNearbyAlmostDuplicate(self, nums, k, t): + bucket = {} + + for i, num in enumerate(nums): + if len(bucket)>k: + bidToRemove = nums[i-k-1]//(t+1) + del bucket[bidToRemove] + + bid = num//(t+1) + if bid in bucket: return True + if bid+1 in bucket and abs(bucket[bid+1]-num)<=t: return True + if bid-1 in bucket and abs(bucket[bid-1]-num)<=t: return True + bucket[bid] = num + + return False \ No newline at end of file diff --git a/problems/contains-duplicate.py b/problems/contains-duplicate.py new file mode 100644 index 0000000..a27739c --- /dev/null +++ b/problems/contains-duplicate.py @@ -0,0 +1,13 @@ +""" +Time: O(N) +Space: O(N) +""" +class Solution(object): + def containsDuplicate(self, nums): + seen = set() + + for num in nums: + if num in seen: return True + seen.add(num) + + return False \ No newline at end of file diff --git a/problems/data-stream-as-disjoint-intervals.py b/problems/data-stream-as-disjoint-intervals.py new file mode 100644 index 0000000..50f47b4 --- /dev/null +++ b/problems/data-stream-as-disjoint-intervals.py @@ -0,0 +1,91 @@ +class SummaryRanges(object): + + def __init__(self): + self.nums = [] + + + def addNum(self, val): + bisect.insort_left(self.nums, val) + + + def getIntervals(self): + ans = [] + + for num in self.nums: + if not ans: + ans.append([num, num]) + elif ans[len(ans)-1][1]+1==num: + ans[len(ans)-1][1] = num + elif ans[len(ans)-1][1]0 and self.ans[i-1][1]+1==self.ans[i][0]: + self.ans[i][0] = self.ans[i-1][0] + self.ans.pop(i-1) + + return True + + elif val==self.ans[i][1]+1: + self.ans[i][1] = val + + #merge i and i+1 if needed + if i+11: + heapq.heappush(self.larger, -heapq.heappop(self.smaller)) + elif len(self.larger)-len(self.smaller)>=1: + heapq.heappush(self.smaller, -heapq.heappop(self.larger)) + + def findMedian(self): + return -self.smaller[0] if (len(self.smaller)-len(self.larger))%2!=0 else (-self.smaller[0]+self.larger[0])/2.0 \ No newline at end of file diff --git a/problems/k-empty-slots.py b/problems/k-empty-slots.py new file mode 100644 index 0000000..0b4e36e --- /dev/null +++ b/problems/k-empty-slots.py @@ -0,0 +1,65 @@ +""" +Let's look at the naive approach first. + +Each day we turn on a bulb by `bulbs[i] = 1` and +1. `check()` the bulb on i to i+(K+1), see if it matches the pattern 1,0,0,..1 +2. `check()` the bulb on i to i-(K+1), see if it matches the pattern 1,0,0,..1 +The `check()` will take O(K), so the time complexity will be O(NK), N is the number of bulbs. + +Since iterating the bulbs seems inevitable, the only thing we can avoid is the iteration between l and r in `check()` which is taking O(K) of time. +""" +class Solution(object): + def kEmptySlots(self, schedule, K): + def check(l, r): + if l<0 or r>=len(bulbs): return False + if bulbs[l]!=1 or bulbs[r]!=1: return False + for k in xrange(l+1, r): + if bulbs[k]!=0: return False + return True + + bulbs = [0]*len(schedule) + for day, x in enumerate(schedule): + i = x-1 + bulbs[i] = 1 + if check(i, i+K+1): return day+1 + if check(i-(K+1), i): return day+1 + return -1 + + +""" +The reason we iterate between l and r is because we need to check there are only "0" between l and r, no "1". +This is where we can use SortedSet (also known as TreeSet in Java). +For each day, we also add "1" index to the SortedSet. +So instead of checking if it is all "0" between l and r, we check if there is any "1" between l and r. + +i = ss.bisect_right(l). The insetion point to a sorted list. If exist the same, insert to the right. +j = ss.bisect_left(r). The insetion point to a sorted list. If exist the same, insert to the left. + +j==0 means that r is the smallest index in the SortedSet. +i==len(ss) means that l is the largest index in the SortedSet. +i==j means that there is no other "1" between l and r. + +The time complexity is will be O(NLogN) +""" +from sortedcontainers import SortedSet + +class Solution(object): + def kEmptySlots(self, schedule, K): + def check(l, r): + if l<0 or r>=len(bulbs): return False + if bulbs[l]!=1 or bulbs[r]!=1: return False + + i = ss.bisect_right(l) + j = ss.bisect_left(r) + + return j!=0 and i!=len(ss) and i==j + + bulbs = [0]*len(schedule) + ss = SortedSet() + for day, x in enumerate(schedule): + i = x-1 + bulbs[i] = 1 + ss.add(i) + if check(i, i+K+1): return day+1 + if check(i-(K+1), i): return day+1 + return -1 \ No newline at end of file diff --git a/problems/linked-list-random-node.py b/problems/linked-list-random-node.py new file mode 100644 index 0000000..1c9bcfb --- /dev/null +++ b/problems/linked-list-random-node.py @@ -0,0 +1,22 @@ +""" +Time: O(N) for __init__() and getRandom() +Space: O(1) +""" +class Solution(object): + + def __init__(self, head): + self.count = 1 + self.curr = head + + while self.curr.next: + self.curr = self.curr.next + self.count += 1 + self.curr.next = head + + + def getRandom(self): + rand = randrange(self.count) + while rand>0: + rand -= 1 + self.curr = self.curr.next + return self.curr.val \ No newline at end of file diff --git a/problems/max-sum-of-rectangle-no-larger-than-k.py b/problems/max-sum-of-rectangle-no-larger-than-k.py new file mode 100644 index 0000000..eed5131 --- /dev/null +++ b/problems/max-sum-of-rectangle-no-larger-than-k.py @@ -0,0 +1,52 @@ +""" +Time: O(min(M,N)^2 * max(M,N) * Log(max(M,N))) +Space: O(MN), can reduce to O(max(M,N)) by not using a new 2D array "matrixRotated". +Just change the iteration in `maxSumSubmatrix()`. + +This is the implementation of the offical solution 1 and 2. +""" +from sortedcontainers import SortedSet + +class Solution(object): + def maxSumSubmatrix(self, matrix, k): + if len(matrix)>len(matrix[0]): matrix = self.rotate(matrix) + + ans = float('-inf') + M = len(matrix) + N = len(matrix[0]) + + for start in xrange(M): + rowSum = [0]*N #row sum of rows from matrix[start] to row + for row in matrix[start:]: + for i, n in enumerate(row): rowSum[i] += n + ans = max(ans, self.maxSumRow(rowSum, k)) + if ans==k: return ans + return ans + + def maxSumRow(self, row, k): + ans = float('-inf') + total = 0 + + ss = SortedSet() + ss.add(0) + + for n in row: + total += n + i = ss.bisect_left(total-k) + if ik: + sumQ -= -heapq.heappop(paidGroup) + + if len(paidGroup)==k: + cost = min(cost, sumQ*r) + + return cost \ No newline at end of file diff --git a/problems/moving-average-from-data-stream.py b/problems/moving-average-from-data-stream.py index 1a2f3c9..6e80555 100644 --- a/problems/moving-average-from-data-stream.py +++ b/problems/moving-average-from-data-stream.py @@ -15,3 +15,22 @@ def next(self, val): return self.sum/float(len(self.queue)) +""" +Time: O(1) +Space: O(Size) +""" +class MovingAverage(object): + + def __init__(self, size): + self.size = size + self.q = collections.deque() + self.sum = 0 + + + def next(self, val): + if len(self.q)>=self.size: + self.sum -= self.q.popleft() + + self.sum += val + self.q.append(val) + return float(self.sum)/len(self.q) \ No newline at end of file diff --git a/problems/rearrange-string-k-distance-apart.py b/problems/rearrange-string-k-distance-apart.py new file mode 100644 index 0000000..785d464 --- /dev/null +++ b/problems/rearrange-string-k-distance-apart.py @@ -0,0 +1,46 @@ +""" +Time: O(N). N is the number of char in string s. See below explanation. +Space: O(1) + +The main idea is to add k different char to the ans every time. +The char with higher count will be used first. +So there will be more different kind of char left and will not be too close to each other. + +To do this, we need a counter to track count of each char. [0] +And a heap so we can get the char with highest count fast (LogH). [0] +For each time, add k different char to the ans. [1] +Char with count>0 will be put back to h. [2] + +If heap is drained before we add k element to the ans. It is not possible to form ans. Return emptry string. [3] + +Time complexity: +Contruct counter takes O(N). +Contruct the heap (heapify) takes O(H), H is the number of element in the heap. +In the while loop, each char in s will be pop once. O(NLogH). +Since the problem said that the string will only have lower case letters. So H will at most be 26. +So O(N+H+NlogH) ~= O(N+26+NLog26) ~= O(N) +""" +class Solution(object): + def rearrangeString(self, s, k): + if k==0: return s + ans = '' + + #[0] + counter = collections.Counter(s) + h = [(-counter[c], c) for c in counter] + heapq.heapify(h) + + while h: + l = [] + for i in xrange(k): + _, c = heapq.heappop(h) + ans += c + counter[c] -= 1 + if counter[c]!=0: l.append((-counter[c], c)) #[2] + + if len(ans)==len(s): return ans + if not h and i!=k-1: return '' #[3] + + for e in l: heapq.heappush(h, e) + + return ans #this line should never be executed \ No newline at end of file diff --git a/problems/shuffle-an-array.py b/problems/shuffle-an-array.py new file mode 100644 index 0000000..d76a9a7 --- /dev/null +++ b/problems/shuffle-an-array.py @@ -0,0 +1,59 @@ +class ListNode(object): + def __init__(self, val): + self.val = val + self.next = None + +class Solution(object): + + def __init__(self, nums): + self.nums = nums + self.curr = self.getLinkList(self.nums) + + def reset(self): + return self.nums + + #O(N^2) in time. + def shuffle(self): + ans = [] + + #new LinkList + head = None + curr = head + + while len(ans)0: + self.curr = self.curr.next + rand -= 1 + + #add self.curr.next's value to ans + ans.append(self.curr.next.val) + + #add self.curr.next to a new LinkList + if not curr: + head = self.curr.next + curr = head + else: + curr.next = self.curr.next + curr = curr.next + + #remove self.curr.next from the LinkList + self.curr.next = self.curr.next.next + + curr.next = head + self.curr = head + return ans + + def getLinkList(self, nums): + head = ListNode(nums[0]) + curr = head + for i in xrange(1, len(self.nums)): + curr.next = ListNode(nums[i]) + curr = curr.next + curr.next = head + return head \ No newline at end of file diff --git a/problems/sliding-window-maximum.py b/problems/sliding-window-maximum.py index a8e48a4..34098d8 100644 --- a/problems/sliding-window-maximum.py +++ b/problems/sliding-window-maximum.py @@ -16,4 +16,64 @@ def maxSlidingWindow(self, nums, k): #add the max to the output array after the first kth element if 1+i>=k: opt.append(nums[q[0]]) - return opt \ No newline at end of file + return opt + + +""" +Keep the element in sliding window in a heap, so we can get the max easily. +But we do not know whether which element in the heap is out of the window. +So we use a counter to track the count of the elements inside the window. + +Time: O(NLogK), the `heapq.heappop(h)` in the while-loop in the for-loop will only be execute once for each element. +Space: O(N) +""" +class Solution(object): + def maxSlidingWindow(self, nums, k): + if not nums or not k: return [] + if k==1: return nums + + ans = [] + + counter = collections.Counter(nums[:k]) + h = [-num for num in nums[:k]] + heapq.heapify(h) + + for i in xrange(len(nums)): + while counter[-h[0]]==0: heapq.heappop(h) + ans.append(-h[0]) + + if i+k>=len(nums): break + counter[nums[i]] -= 1 + heapq.heappush(h, -nums[i+k]) + counter[nums[i+k]] += 1 + + return ans + +""" +Use deque the slide the window through nums. +The deque will at most contain k elements. +Each time add the max element to ans. + +Time: O(N), the `q.pop()` in the while-loop in the for-loop will only execute once for each element. +Space: O(N) +""" +class Solution(object): + def maxSlidingWindow(self, nums, k): + ans = [] + q = collections.deque() + + for i, num in enumerate(nums): + #keep only the element in the window inside deque. + #the window lies between index i-k+1 to i. + if q and q[0][1]<=i-k: q.popleft() + + #keep the element in deque in descending order by popping the elements from rihgt that are smaller than num. + #by keeping the deque in descending order, we can get the largest element by just getting the first element. + #also since they are certainly not the max in the deque, we don't care. + while q and q[-1][0]<=num: q.pop() + q.append((num, i)) + + #wait until i>=k-1 when the window pass at least k elements. + if (i>=k-1): ans.append(q[0][0]) + + return ans \ No newline at end of file From 2d438e1901dc6e86e81657949cd767fa1056f526 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 31 Aug 2021 07:42:09 +0800 Subject: [PATCH 109/187] no message --- problems/kth-largest-element-in-an-array.py | 26 +++++++++++- problems/sort-colors.py | 45 +++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 problems/sort-colors.py diff --git a/problems/kth-largest-element-in-an-array.py b/problems/kth-largest-element-in-an-array.py index ffa613b..d12f59c 100644 --- a/problems/kth-largest-element-in-an-array.py +++ b/problems/kth-largest-element-in-an-array.py @@ -40,5 +40,27 @@ def findKthLargest(self, nums, k): """ class Solution(object): def findKthLargest(self, nums, k): - #to be continued... - pass \ No newline at end of file + def sortRange(A, l, r): + if l>=r: return A + + p = A[(l+r)/2] + i = partition(A, l, r, p) + if kp: r -= 1 + if l<=r: + A[l], A[r] = A[r], A[l] + l += 1 + r -= 1 + return l + + k = len(nums)-k #redefine the problem to find the kth nums when sorted + sortRange(nums, 0, len(nums)-1) + return nums[k] \ No newline at end of file diff --git a/problems/sort-colors.py b/problems/sort-colors.py new file mode 100644 index 0000000..b141228 --- /dev/null +++ b/problems/sort-colors.py @@ -0,0 +1,45 @@ +class Solution(object): + def sortColors(self, nums): + l = 0 + r = len(nums)-1 + + i = 0 + while i<=r: + if nums[i]==0: + nums[l], nums[i] = nums[i], nums[l] + l += 1 + i += 1 + elif nums[i]==2: + nums[i], nums[r] = nums[r], nums[i] + r -= 1 + elif nums[i]==1: + i += 1 + +# counting sort +class Solution(object): + def sortColors(self, nums): + count0 = count1 = count2 = 0 + + for num in nums: + if num==0: + count0 += 1 + elif num==1: + count1 += 1 + elif num==2: + count2 += 1 + + i = 0 + while count0>0: + nums[i] = 0 + i += 1 + count0 -= 1 + + while count1>0: + nums[i] = 1 + i += 1 + count1 -= 1 + + while count2>0: + nums[i] = 2 + i += 1 + count2 -= 1 \ No newline at end of file From 0c053b466c1bf3ce3e08769c7829355228079fd0 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Wed, 1 Sep 2021 08:03:05 +0800 Subject: [PATCH 110/187] no message --- "common/bellman\342\200\223ford.py" | 31 +++++++++ common/binary-search-tree.py | 97 +++++++++++++++++++++++++++++ common/dijkstra.py | 87 ++++++++++++++++++++++++++ common/heap-sort.py | 35 +++++++++++ common/insertion-sort.py | 19 ++++++ common/knapsack.py | 42 +++++++++++++ common/merge-sort-in-place.py | 22 +++++++ common/merge-sort.py | 58 +++++++++++++++++ common/min-heap.py | 81 ++++++++++++++++++++++++ common/quick-sort.py | 32 ++++++++++ common/radix-sort.py | 21 +++++++ common/trie.py | 87 ++++++++++++++++++++++++++ problems/maximum-gap.py | 33 ++++++++++ 13 files changed, 645 insertions(+) create mode 100644 "common/bellman\342\200\223ford.py" create mode 100644 common/binary-search-tree.py create mode 100644 common/dijkstra.py create mode 100644 common/heap-sort.py create mode 100644 common/insertion-sort.py create mode 100644 common/knapsack.py create mode 100644 common/merge-sort-in-place.py create mode 100644 common/merge-sort.py create mode 100644 common/min-heap.py create mode 100644 common/quick-sort.py create mode 100644 common/radix-sort.py create mode 100644 common/trie.py create mode 100644 problems/maximum-gap.py diff --git "a/common/bellman\342\200\223ford.py" "b/common/bellman\342\200\223ford.py" new file mode 100644 index 0000000..e5521b4 --- /dev/null +++ "b/common/bellman\342\200\223ford.py" @@ -0,0 +1,31 @@ +""" +First, we use `distance` to track the distance from start to all others. +For V nodes, it takes at least V-1 iteration to complete the algorithm. +For every iteration, +We use every node as the middle point to see if it can "loosen" the path from start to mid to mid's neighbors +If it can loosen the path, we update the `distance`. +The time complexity is O(VE) +""" +def min_path(G, N, start, end): + distance = [float('inf') for _ in xrange(N+1)] + distance[start] = 0 + + for _ in xrange(N-1): + for mid, dis in enumerate(distance): + if dis==float('inf'): continue + for dis_to_nei, nei in G[mid]: + distance[nei] = min(distance[nei], dis+dis_to_nei) + return distance[end] + + +G = { + 0: [(-2, 1), (4, 2)], + 1: [(5, 2)], + 2: [(12, 3), (5, 4)], + 3: [(-8, 4)], + 4: [] +} +N = 4 #nodes count +start = 0 +end = 4 +print min_path(G, N, start, end) diff --git a/common/binary-search-tree.py b/common/binary-search-tree.py new file mode 100644 index 0000000..667b0a9 --- /dev/null +++ b/common/binary-search-tree.py @@ -0,0 +1,97 @@ +class Node(object): + def __init__(self, val): + self.left = None + self.right = None + self.val = val + + +class BinarySearchTree(object): + def __init__(self, val): + self.root = Node(val) + + def insert(self, val): + def helper(node, val): + if val>node.val: + if node.right: + helper(node.right, val) + else: + node.right = Node(val) + elif valnode.val: + return helper(node.right, val) + elif valdis_to_mid+dis: + distance[nei] = dis_to_mid+dis + prev[nei] = mid + if nei not in visited: + heapq.heappush(pq, (distance[nei], nei)) + + curr = end + while True: + if curr not in prev: break + path_str = ' -> '+prev[curr]+path_str + curr = prev[curr] + + return path_str+' = '+str(distance[end]) + + + +#normal implementation +def min_path(G, start, end): + distance = {} #shortest distance from start + prev = {} + path_str = '' + visited = set() + + distance[start] = 0 + while True: + #find nearest unvisited node + mid = None + dis_to_mid = float('inf') + for node in distance: + if node not in visited and distance[node]=n: return + l, r = i*2+1, i*2+2 + left = A[l] if lA[i] or right>A[i]: + if left>right: + A[i], A[l] = A[l], A[i] + heapify(A, n, l) + else: + A[i], A[r] = A[r], A[i] + heapify(A, n, r) + + n = len(A) + + for i in reversed(xrange(n)): + heapify(A, n, i) + + for i in reversed(xrange(1, n)): + A[i], A[0] = A[0], A[i] + heapify(A, i, 0) + + + +A = [21, 4, 1, 3, 9, 20, 25, 6, 21, 14] +heapSort(A) +print A + +""" +Time Complexity O(NLogN) in best, average, worst case. +Space Complexity O(1) +""" \ No newline at end of file diff --git a/common/insertion-sort.py b/common/insertion-sort.py new file mode 100644 index 0000000..c5961f9 --- /dev/null +++ b/common/insertion-sort.py @@ -0,0 +1,19 @@ +def insertionSort(nums): + for i in xrange(len(nums)): + num = nums[i] + j = i-1 + while j>=0 and nummw: + K[i][mw] = K[i-1][mw] + else: + K[i][mw] = max(v+K[i-1][mw-w], K[i-1][mw]) + + max_value = K[-1][-1] + + w = max_weight + i = N + while i>0: + if K[i][w]-K[i-1][w]>0: + bag.append(i-1) + w = w - weight[i-1] + i = i-1 + + print 'bag: ', bag + print 'max_value', max_value + return max_value + + +value = [60, 100, 120] +weight = [10, 20, 30] +max_weight = 50 +get_max_value(value, weight, max_weight) + +value = [40, 100, 50, 60] +weight = [20, 10, 40, 30] +max_weight = 60 +get_max_value(value, weight, max_weight) + diff --git a/common/merge-sort-in-place.py b/common/merge-sort-in-place.py new file mode 100644 index 0000000..87916b2 --- /dev/null +++ b/common/merge-sort-in-place.py @@ -0,0 +1,22 @@ +def merge(A, start, mid, end): + L, R = A[start:mid], A[mid:end] + i = j = 0 + k = start + for l in xrange(k,end): + if j>=len(R) or (i 1: + mid = (p+r)/2 + mergeSort(A, p, mid) + mergeSort(A, mid, r) + merge(A, p, mid, r) + +A = [20, 30, 21, 15, 42, 45, 31, 0, 9] +mergeSort(A, 0, len(A)) +print A diff --git a/common/merge-sort.py b/common/merge-sort.py new file mode 100644 index 0000000..fae511f --- /dev/null +++ b/common/merge-sort.py @@ -0,0 +1,58 @@ +def mergeSort(A): + def merge(a1, a2): + opt = [] + i1 = i2 = 0 + while i1self.heap[i]: + self.heap[p], self.heap[i] = self.heap[i], self.heap[p] + bubbleUp(p) + + self.heap.append(x) + bubbleUp(self.size) + self.size += 1 + + def pop(): + if self.size<=0: return None + m = self.heap[0] + remove(0) + return m + + def remove(self, i): + def bubbleDown(i): + l = i*2+1 + r = i*2+2 + left_child = self.heap[l] if lleft_child or self.heap[i]>right_child: + if left_child=self.size: + return + elif i==self.size-1: + self.heap = self.heap[:-1] + self.size -= 1 + return + else: + self.heap[i], self.heap[-1] = self.heap[-1], self.heap[i] + self.heap = self.heap[:-1] + self.size -= 1 + bubbleDown(i) + return + + + + + + +min_heap = MinHeap() +min_heap.push(3) +min_heap.push(1) +min_heap.push(2) +min_heap.push(10) +min_heap.push(4) +min_heap.push(7) +min_heap.push(9) + +print min_heap.heap + +min_heap.remove(2) +print min_heap.heap + +min_heap.remove(2) +min_heap.remove(2) +min_heap.remove(2) +min_heap.remove(2) +print min_heap.heap + +min_heap.remove(2) +min_heap.remove(1) +min_heap.remove(0) +print min_heap.heap + + \ No newline at end of file diff --git a/common/quick-sort.py b/common/quick-sort.py new file mode 100644 index 0000000..e4f1fdc --- /dev/null +++ b/common/quick-sort.py @@ -0,0 +1,32 @@ +def quickSort(A): + def sortRange(A, l, r): + if l>=r: return A + + p = A[(l+r)/2] + i = partition(A, l, r, p) + sortRange(A, l, i-1) + sortRange(A, i, r) + return A + + def partition(A, l, r, p): + while l<=r: + while A[l]p: r -= 1 + if l<=r: + A[l], A[r] = A[r], A[l] + l += 1 + r -= 1 + return l + + return sortRange(A, 0, len(A)-1) + + +A = [5,2,4,1,3,6,0] +print quickSort(A) + + +""" +Time Complexity is O(NlogN) on best and average case. +O(N^2) on the worst case, because if you choose the smallest pivot everytime the array will decay in a linear time. +Space Complexity O(LogN), for we need to store the stack for the recursion. +""" \ No newline at end of file diff --git a/common/radix-sort.py b/common/radix-sort.py new file mode 100644 index 0000000..b9bb006 --- /dev/null +++ b/common/radix-sort.py @@ -0,0 +1,21 @@ +def radixSort(nums): + maxNumberOfDigits = len(str(max(nums))) + + for d in xrange(maxNumberOfDigits): + b = [[] for _ in xrange(10)] + + for num in nums: + n = (num//10**d)%10 + print num, d, n + b[n].append(num) + + i = 0 + for a in b: + for num in a: + nums[i] = num + i += 1 + + +test = [21, 4, 1, 3, 9, 20, 25, 6, 21, 14] +radixSort(test) +print test \ No newline at end of file diff --git a/common/trie.py b/common/trie.py new file mode 100644 index 0000000..d2bf79d --- /dev/null +++ b/common/trie.py @@ -0,0 +1,87 @@ +class Node(object): + def __init__(self): + self.children = {} + self.isEnd = False + + def get(self, char): + if char in self.children: + return self.children[char] + else: + return None + + def set(self, char): + if char in self.children: + return self.children[char] + else: + self.children[char] = Node() + return self.children[char] + + def remove(self, char): + self.children.pop(char, None) + return len(self.children)==0 + + +class Trie(object): + def __init__(self): + self.root = Node() + + def insert(self, word): + curr = self.root + for i in xrange(len(word)): + c = word[i] + node = curr.get(c) + if node is None: node = curr.set(c) + if i==len(word)-1: node.isEnd = True + curr = node + + def search(self, word): + curr = self.root + for i in xrange(len(word)): + c = word[i] + node = curr.get(c) + if node is None: return False + if i==len(word)-1: return node.isEnd + curr = node + + def remove(self, word): + curr = self.root + stack = [] + for i in xrange(len(word)): + c = word[i] + node = curr.get(c) + + #the word does not exist + if node is None: return + + stack.append((curr, c)) + curr = node + + #if the last node has other link + #just set isEnd to False + if len(curr.children)>0: + curr.isEnd = False + return + + while stack and len(stack)>0: + node, c = stack.pop() + emptyAfterRemove = node.remove(c) + if not emptyAfterRemove: break + + +trie = Trie() +trie.insert('abc') +trie.insert('abgl') +trie.insert('cdf') +trie.insert('abcd') +trie.insert('lmn') +print trie.search('abc') +print trie.search('abcd') + +trie.remove('abc') +print trie.search('abc') +trie.remove('abgl') +print trie.search('abgl') +trie.remove('abcd') +print trie.search('abcd') + + diff --git a/problems/maximum-gap.py b/problems/maximum-gap.py new file mode 100644 index 0000000..8d4af64 --- /dev/null +++ b/problems/maximum-gap.py @@ -0,0 +1,33 @@ +""" +Time: O(N). For radix sort, each digit runs 2 pass on the nums => O(dN). +Since the number of the digit is fixed in range 10 (stated in the problem) => O(dN) ~= O(N). + +Space: O(N) +""" +class Solution(object): + def maximumGap(self, nums): + if len(nums)<2: return 0 + + self.radixSort(nums) + + ans = 0 + for i in xrange(1, len(nums)): + ans = max(ans, abs(nums[i]-nums[i-1])) + return ans + + def radixSort(self, nums): + maxNumberOfDigits = len(str(max(nums))) + + for d in xrange(maxNumberOfDigits): + b = [[] for _ in xrange(10)] + + for num in nums: + n = (num//10**d)%10 + print num, d, n + b[n].append(num) + + i = 0 + for a in b: + for num in a: + nums[i] = num + i += 1 \ No newline at end of file From 0c70368baa4b5e2ca27755856ed4107d2f3f5277 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Thu, 2 Sep 2021 08:14:46 +0800 Subject: [PATCH 111/187] no message --- problems/group-anagrams.py | 20 ++++++++++++++++++++ problems/ugly-number-ii.py | 31 +++++++++++++++++++++++++++++++ problems/ugly-number.py | 9 +++++++++ 3 files changed, 60 insertions(+) create mode 100644 problems/ugly-number-ii.py create mode 100644 problems/ugly-number.py diff --git a/problems/group-anagrams.py b/problems/group-anagrams.py index 26763fe..68b066e 100644 --- a/problems/group-anagrams.py +++ b/problems/group-anagrams.py @@ -14,3 +14,23 @@ def groupAnagrams(self, strs): for c in s: hashkey[ord(c)-97] +=1 anagrams[''.join(hashkey)].append(s) return anagrams.values() + +""" +Time: O(NK), N is the number of strings, K is the number of characters in the string. +Space: O(NK). +""" +class Solution(object): + def groupAnagrams(self, strs): + anagrams = collections.defaultdict(list) + + for s in strs: + anagrams[self.getKey(s)].append(s) + + return anagrams.values() + + def getKey(self, s): + key = '' + counts = collections.Counter(s) + for c in 'abcdefghijklmnopqrstuvwxyz': + key += counts[c]*c + return key \ No newline at end of file diff --git a/problems/ugly-number-ii.py b/problems/ugly-number-ii.py new file mode 100644 index 0000000..38879f5 --- /dev/null +++ b/problems/ugly-number-ii.py @@ -0,0 +1,31 @@ +""" +`ans` contains sorted ugly numbers. +For each ugly number we can x2 or x3 or x5 to produce another ugly number. + +i2 points at the number that has been x2 yet. +i3 points at the number that has been x3 yet. +i5 points at the number that has been x5 yet. + +Each time we append one minimum ugly number and move the pointer. + +Time: O(N) +Space: O(N) +""" +class Solution(object): + def nthUglyNumber(self, k): + i2 = i3 = i5 = 0 + + ans = [1] + while len(ans) Date: Thu, 9 Sep 2021 09:17:07 +0800 Subject: [PATCH 112/187] no message --- problems/find-k-pairs-with-smallest-sums.py | 38 +++++++++++++++++++++ problems/find-the-duplicate-number.py | 24 +++++++++++++ problems/missing-number.py | 28 +++++++++++++++ problems/reverse-words-in-a-string.py | 13 ++++++- problems/rotate-array.py | 38 +++++++++++++++++++++ problems/super-ugly-number.py | 20 +++++++++++ 6 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 problems/find-k-pairs-with-smallest-sums.py create mode 100644 problems/find-the-duplicate-number.py create mode 100644 problems/missing-number.py create mode 100644 problems/rotate-array.py create mode 100644 problems/super-ugly-number.py diff --git a/problems/find-k-pairs-with-smallest-sums.py b/problems/find-k-pairs-with-smallest-sums.py new file mode 100644 index 0000000..85ab26c --- /dev/null +++ b/problems/find-k-pairs-with-smallest-sums.py @@ -0,0 +1,38 @@ +""" +Time: O(kLogk) +Space: O(N) + +[0] +Declare a min-heap. Which stores the (sum, index in nums1, index in nums2) for each combination. + +[1] +Each iteration, we get a min sum (i, j) from the heap and add it to the `ans`. +The next possible smallest combination will be either (i+1, j) or (j+1, i) or other combination previously added. +Add combination (i+1, j) and (j+1, i) to the heap. + +[2] +Use a set `seen` to avoid adding the same element to the heap. +For example (i+1, j) and (j+1, i) can both lead to (i+1, j+1). +""" +class Solution(object): + def kSmallestPairs(self, nums1, nums2, k): + if not nums1 or not nums2: return [] + if k>len(nums1)*len(nums2): k = len(nums1)*len(nums2) + + ans = [] + h = [(nums1[0]+nums2[0], 0, 0)] #[0] + seen = set([(0,0)]) #[2] + + while len(ans) Date: Fri, 10 Sep 2021 07:36:08 +0800 Subject: [PATCH 113/187] no message --- problems/first-missing-positive.py | 58 ++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 problems/first-missing-positive.py diff --git a/problems/first-missing-positive.py b/problems/first-missing-positive.py new file mode 100644 index 0000000..cf48a23 --- /dev/null +++ b/problems/first-missing-positive.py @@ -0,0 +1,58 @@ +class Solution(object): + def firstMissingPositive(self, nums): + N = len(nums) + + if 1 not in nums: return 1 + + for i, num in enumerate(nums): + if num<=0 or num>N: + nums[i] = 1 + + for i in xrange(N): + a = abs(nums[i]) + + if a==N: + nums[0] = -abs(nums[0]) + else: + nums[a] = -abs(nums[a]) + + for i in xrange(1, N): + if nums[i]>0: return i + if nums[0]>0: return N + + return N+1 + +""" +Time: O(N), each num is going to be swap once. +Space: O(1). + +For nums with length N, the answer must be in between 1~N+1. + +[1] So for number between 1~N, lets put them in the right place. +number 1 will be stored at index 0. +number 2 will be stored at index 1. +... +number n will be stored at index n-1. + + +[2] Check if any number are not in place. + +[3] If all the number are in place, then the ans must be N+1. +""" +class Solution(object): + def firstMissingPositive(self, nums): + N = len(nums) + + #[1] + for i in xrange(N): + while 1<=nums[i]<=N and nums[i]!=i+1: + j = nums[i]-1 + if nums[i]==nums[j]: break #otherwise they are going to keep swapping infinitely, because one of them is not inplace. + nums[i], nums[j] = nums[j], nums[i] + + #[2] + for i in xrange(N): + if nums[i]!=i+1: return i+1 + + #[3] + return N+1 \ No newline at end of file From ec536c0fefa8ff8f39c49554512d0860f147bc0f Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sat, 11 Sep 2021 07:51:46 +0800 Subject: [PATCH 114/187] no message --- problems/binary-watch.py | 14 ++++++++++++++ problems/queue-reconstruction-by-height.py | 15 +++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 problems/binary-watch.py create mode 100644 problems/queue-reconstruction-by-height.py diff --git a/problems/binary-watch.py b/problems/binary-watch.py new file mode 100644 index 0000000..616758d --- /dev/null +++ b/problems/binary-watch.py @@ -0,0 +1,14 @@ +""" +Time: O(1) +Space: O(1), no "extra" space are used. +""" +class Solution(object): + def readBinaryWatch(self, turnedOn): + ans = [] + if turnedOn>8: return ans #at most 8 LED are turned on for a valid time. + + for h in xrange(12): + for m in xrange(60): + if (bin(h) + bin(m)).count('1')==turnedOn: + ans.append('%d:%02d' % (h, m)) + return ans \ No newline at end of file diff --git a/problems/queue-reconstruction-by-height.py b/problems/queue-reconstruction-by-height.py new file mode 100644 index 0000000..7c76e18 --- /dev/null +++ b/problems/queue-reconstruction-by-height.py @@ -0,0 +1,15 @@ +""" +Time: O(N^2) +Space: O(N) + +People need to be exactly insert to index k, so that there are "exact" k people equal or taller to k. +Shorter person does not matter (invisible) to taller person, so insert taller person first. +People does not care about the people on their right, so insert the person with smaller k first. +""" +class Solution(object): + def reconstructQueue(self, people): + people.sort(key=lambda x: (-x[0], x[1])) + ans = [] + for h, k in people: + ans.insert(k, (h, k)) + return ans \ No newline at end of file From c9e8b168f41660a1ccf499798e365bbcc0f2cfe7 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 14 Sep 2021 07:54:33 +0800 Subject: [PATCH 115/187] no message --- common/bst-in-order.py | 15 +++++ .../binary-tree-level-order-traversal-ii.py | 49 ++++++++++++++- problems/binary-tree-level-order-traversal.py | 48 ++++++++++++++- ...inary-tree-longest-consecutive-sequence.py | 22 +++++++ .../binary-tree-vertical-order-traversal.py | 27 +++++++++ problems/invert-binary-tree.py | 16 +++++ problems/kth-smallest-element-in-a-bst.py | 59 ++++++++++++++++++- problems/next-closest-time.py | 43 ++++++++++++++ problems/validate-binary-search-tree.py | 59 ++++++++++++++----- 9 files changed, 320 insertions(+), 18 deletions(-) create mode 100644 common/bst-in-order.py create mode 100644 problems/binary-tree-longest-consecutive-sequence.py create mode 100644 problems/binary-tree-vertical-order-traversal.py create mode 100644 problems/invert-binary-tree.py create mode 100644 problems/next-closest-time.py diff --git a/common/bst-in-order.py b/common/bst-in-order.py new file mode 100644 index 0000000..0ffe82e --- /dev/null +++ b/common/bst-in-order.py @@ -0,0 +1,15 @@ +def inOrderTraverse(root): + stack = [] + node = root + + while node or stack: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + + #do something + print node.val + + node = node.right \ No newline at end of file diff --git a/problems/binary-tree-level-order-traversal-ii.py b/problems/binary-tree-level-order-traversal-ii.py index db49ccd..07084a3 100644 --- a/problems/binary-tree-level-order-traversal-ii.py +++ b/problems/binary-tree-level-order-traversal-ii.py @@ -17,4 +17,51 @@ def levelOrderBottom(self, root): opt.append([node.val]) if node.left: q.append((node.left, depth+1)) if node.right: q.append((node.right, depth+1)) - return reversed(opt) \ No newline at end of file + return reversed(opt) + + +""" +Time: O(N). +Space: O(N). + +Simply using BFS, adding node and the level to the queue. +When popping out append the val to the correct list. +""" +class Solution(object): + def levelOrderBottom(self, root): + if not root: return [] + ans = [] + q = collections.deque([(root, 0)]) + + while q: + node, level = q.popleft() + if len(ans)9 else '0'+str(h) + if all([c in digits for c in hs]): return hs + return '' + + def getSmallestHour(): + for h in xrange(0, 24): + hs = str(h) if h>9 else '0'+str(h) + if all([c in digits for c in hs]): return hs + return '' + + def getNextMinute(): + currentMinute = int(time[3]+time[4]) if time[3]!='0' else int(time[4]) + + for m in xrange(currentMinute+1, 60): + ms = str(m) if m>9 else '0'+str(m) + if all([c in digits for c in ms]): return ms + return '' + + def getSmallestMinute(): + for m in xrange(0, 60): + ms = str(m) if m>9 else '0'+str(m) + if all([c in digits for c in ms]): return ms + return '' + + digits = set([time[0], time[1], time[3], time[4]]) + nextMinute = getNextMinute() + if nextMinute: + return time[:3]+nextMinute + else: + return (getNextHour() or getSmallestHour())+':'+getSmallestMinute() \ No newline at end of file diff --git a/problems/validate-binary-search-tree.py b/problems/validate-binary-search-tree.py index 6331c4b..189b0ff 100644 --- a/problems/validate-binary-search-tree.py +++ b/problems/validate-binary-search-tree.py @@ -9,7 +9,7 @@ your min will be your parent's value your max will be your parent's max, because your parent might be someone's left child. -root have no max and min +node have no max and min 2. for in-order traversal solution @@ -27,19 +27,19 @@ """ class Solution(object): #recursive - def isValidBST(self, root): + def isValidBST(self, node): def helper(node, min_val, max_val): if not node: return True if node.val<=min_val or node.val>=max_val:return False if not helper(node.left, min_val, node.val): return False if not helper(node.right, node.val, max_val): return False return True - return helper(root, float('-inf'), float('inf')) + return helper(node, float('-inf'), float('inf')) #iterative - def isValidBST(self, root): - if root==None: return True - stack = [(root, float('-inf'), float('inf'))] + def isValidBST(self, node): + if node==None: return True + stack = [(node, float('-inf'), float('inf'))] while stack: node, min_val, max_val = stack.pop() if node.val<=min_val or node.val>=max_val: @@ -51,18 +51,47 @@ def isValidBST(self, root): return True #in-order traversal - def isValidBST(self, root): + def isValidBST(self, node): stack = [] last_val = float('-inf') - while root or stack: - while root: - stack.append(root) - root = root.left - root = stack.pop() + while node or stack: + while node: + stack.append(node) + node = node.left + node = stack.pop() - if root.val<=last_val: + if node.val<=last_val: return False - last_val = root.val - root = root.right #if root.right: root = root.right + last_val = node.val + node = node.right #if node.right: node = node.right return True + + + +#2021/9/14 +""" +Time: O(N) +Space: O(N) + +Use in-order traversal to check. If the bst is valid, the node.val should always be larger than the prev. +""" +class Solution(object): + def isValidBST(self, root): + node = root + stack = [] + prev = float('-inf') + + while node or stack: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + + if prev>=node.val: return False + prev = node.val + + node = node.right + + return True \ No newline at end of file From 85a1dea21f9126a6aa89b9aceafb655783c601ba Mon Sep 17 00:00:00 2001 From: wuduhren Date: Wed, 15 Sep 2021 07:54:05 +0800 Subject: [PATCH 116/187] no message --- .../flatten-binary-tree-to-linked-list.py | 47 +++++++++++++++++++ problems/path-sum-ii.py | 24 +++++++++- problems/path-sum.py | 25 +++++++++- 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 problems/flatten-binary-tree-to-linked-list.py diff --git a/problems/flatten-binary-tree-to-linked-list.py b/problems/flatten-binary-tree-to-linked-list.py new file mode 100644 index 0000000..630a144 --- /dev/null +++ b/problems/flatten-binary-tree-to-linked-list.py @@ -0,0 +1,47 @@ +""" +Time: O(N) +Space: O(N) + +Pre-Order Traversal +""" +class Solution(object): + def flatten(self, root): + if not root: return None + + preHead = TreeNode(0) + curr = preHead + stack = [root] + + while stack: + node = stack.pop() + + if node.right: stack.append(node.right) + if node.left: stack.append(node.left) + + node.right = None + node.left = None + curr.right = node + curr = curr.right + + return preHead.right + +""" +Time: O(N) +Space: O(1) + +Morris Traversal +""" +class Solution(object): + def flatten(self, root): + node = root + + while node: + if node.left: + rightmost = node.left + while rightmost.right: rightmost = rightmost.right + rightmost.right = node.right + node.right = node.left + node.left = None + else: + node = node.right + return root \ No newline at end of file diff --git a/problems/path-sum-ii.py b/problems/path-sum-ii.py index a900baa..2bfcda5 100644 --- a/problems/path-sum-ii.py +++ b/problems/path-sum-ii.py @@ -17,4 +17,26 @@ def pathSum(self, root, S): """ Time complexity is O(N), because we traverse all the nodes. Space complexity is O(N^2), because in the worst case, all node could carry all the other nodes in the `path`. -""" \ No newline at end of file +""" + + + +""" +Time complexity is O(N), because we traverse all the nodes. +Space complexity is O(N^2), because in the worst case, all node could carry all the other nodes in the `path`. +""" +class Solution(object): + def pathSum(self, root, targetSum): + if not root: return [] + + ans = [] + stack = [(root, root.val, [root.val])] + + while stack: + node, total, path = stack.pop() + + if not node.left and not node.right and total==targetSum: ans.append(path) + if node.left: stack.append((node.left, total+node.left.val, path+[node.left.val])) + if node.right: stack.append((node.right, total+node.right.val, path+[node.right.val])) + + return ans \ No newline at end of file diff --git a/problems/path-sum.py b/problems/path-sum.py index cd2ae5a..ce50d04 100644 --- a/problems/path-sum.py +++ b/problems/path-sum.py @@ -11,4 +11,27 @@ def hasPathSum(self, root, S): if not node.left and not node.right and s==S: return True if node.left: stack.append((node.left, s)) if node.right: stack.append((node.right, s)) - return False \ No newline at end of file + return False + + +""" +Time: O(N) +Space: O(N) + +DFS +""" +class Solution(object): + def hasPathSum(self, root, targetSum): + if not root: return False + + stack = [(root, root.val)] + + while stack: + node, total = stack.pop() + + if not node.left and not node.right and total==targetSum: return True + if node.left: stack.append((node.left, total+node.left.val)) + if node.right: stack.append((node.right, total+node.right.val)) + + return False + \ No newline at end of file From 2ee868a43a4d3d4a4390a68d5634c927ee04072f Mon Sep 17 00:00:00 2001 From: wuduhren Date: Fri, 17 Sep 2021 08:29:16 +0800 Subject: [PATCH 117/187] no message --- ...ee-from-inorder-and-postorder-traversal.py | 71 +++++++++++++++++++ ...ree-from-preorder-and-inorder-traversal.py | 30 ++++++++ ...vert-sorted-array-to-binary-search-tree.py | 32 ++++++++- 3 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 problems/construct-binary-tree-from-inorder-and-postorder-traversal.py create mode 100644 problems/construct-binary-tree-from-preorder-and-inorder-traversal.py diff --git a/problems/construct-binary-tree-from-inorder-and-postorder-traversal.py b/problems/construct-binary-tree-from-inorder-and-postorder-traversal.py new file mode 100644 index 0000000..1a46912 --- /dev/null +++ b/problems/construct-binary-tree-from-inorder-and-postorder-traversal.py @@ -0,0 +1,71 @@ +""" +inorder: [LEFT]root[RIGHT] +postorder: [LEFT][RIGHT]root + +First thing we know is the value of root, which is the last element of `postorder`. +Find the index of the root in `inorder`. So find out the interval of [LEFT] and [RIGHT] in `inorder`. + +The length of the [LEFT] and [RIGHT] in `inorder` are the same with the length of the [LEFT] and [RIGHT] in `postorder`. +""" +class Solution(object): + def buildTree(self, inorder, postorder): + if not inorder or not postorder: return None + + root = TreeNode(postorder[-1]) + if len(inorder)==1: return root + + r = inorder.index(root.val) + + leftInOrder = inorder[:r] + leftPostOrder = postorder[:r] + rightInOrder = inorder[r+1:] + rightPostOrder = postorder[r:len(postorder)-1] + + root.left = self.buildTree(leftInOrder, leftPostOrder) + root.right = self.buildTree(rightInOrder, rightPostOrder) + + return root +""" +Time: O(NLogN). For each node, we need to do an iteration to its children. To be precise.. +O(N) for constructing root. + +O(N/2) for constructing root.left +O(N/2) for constructing root.right + +O(N/4) for constructing root.left.left +O(N/4) for constructing root.left.right +O(N/4) for constructing root.right.left +O(N/4) for constructing root.right.right +... + +To improve this, we can use a hash table to get the index of `i` below + + +Space: O(NLogN). +For each node, we need to construct inorder/postorder arrays of its children. +We can improve this by using pointers. +""" + +""" +Improved version. +Time: O(N). +Space: O(N). For `index`. +""" +class Solution(object): + def buildTree(self, inorder, postorder): + def helper(i, j, k, l): + if j-i<=0: return None + if l-k<=0: return None + + root = TreeNode(postorder[l-1]) + if j-i==1: return root + + r = index[root.val] + + root.left = helper(i, r, k, k+r-i) + root.right = helper(r+1, j, k+r-i, l-1) + return root + + index = {} #the index of inorder + for i, n in enumerate(inorder): index[n] = i + return helper(0, len(inorder), 0, len(postorder)) \ No newline at end of file diff --git a/problems/construct-binary-tree-from-preorder-and-inorder-traversal.py b/problems/construct-binary-tree-from-preorder-and-inorder-traversal.py new file mode 100644 index 0000000..3f021d7 --- /dev/null +++ b/problems/construct-binary-tree-from-preorder-and-inorder-traversal.py @@ -0,0 +1,30 @@ +""" +Time: O(N) +Space: O(N) + +preorder: root[LEFT][RIGHT] +inorder: [LEFT]root[RIGHT] + +The `helper()` will return the root node from `preorder` and `inorder`. +If they have left or right child, call `helper()` again to get the left or right node. + +Use pointers to represent array, avoiding keep copying `preorder` and `inorder`. +i and j represent the preorder[i:j] +k and l epresent the inorder[k:l] +""" +class Solution(object): + def buildTree(self, preorder, inorder): + def helper(i, j, k, l): + root = TreeNode(preorder[i]) + + r = inorderIndex[root.val] #the index of the root val in inorder + leftLength = r-k + rightLength = l-(r+1) + + if leftLength>0: root.left = helper(i+1, i+1+leftLength, k, k+leftLength) + if rightLength>0: root.right = helper(i+1+leftLength, i+1+leftLength+rightLength, r+1, r+1+rightLength) + return root + + inorderIndex = {} + for i, n in enumerate(inorder): inorderIndex[n] = i + return helper(0, len(preorder), 0, len(inorder)) \ No newline at end of file diff --git a/problems/convert-sorted-array-to-binary-search-tree.py b/problems/convert-sorted-array-to-binary-search-tree.py index d0f2fd8..344d345 100644 --- a/problems/convert-sorted-array-to-binary-search-tree.py +++ b/problems/convert-sorted-array-to-binary-search-tree.py @@ -19,4 +19,34 @@ def sortedArrayToBST(self, nums): Time: O(N). Because there will be N element being construct. Space: O(LogN). There will be LogN level of recursive call. -""" \ No newline at end of file +""" + + + +""" +Time: O(N) +Space: O(LogN) + +To make it height-balanced +We need to make sure that the number of nodes in left substree and right subtree be the same. +Since the `nums` is already sorted, the best nodes to be root is the one in the middle. + +`helper()` will get the root node from the nums[i:j]. +If it has left child, it will recursively call `helper()` to get the child. + +Use pointers i and j as param to avoid keep copying `nums`. +""" +class Solution(object): + def sortedArrayToBST(self, nums): + def helper(i, j): + m = (i+j)/2 + node = TreeNode(nums[m]) + + leftLength = m-i #number of nodes in the left subtree + rightLength = j-(m+1) #number of nodes in the right subtree + + if leftLength>0: node.left = helper(i, m) + if rightLength>0: node.right = helper(m+1, j) + return node + + return helper(0, len(nums)) \ No newline at end of file From 780cc80806930835fe4ca31828d4eb5966cd37e8 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sun, 19 Sep 2021 12:13:35 +0800 Subject: [PATCH 118/187] no message --- README.md | 155 +----------------- ...nvert-sorted-list-to-binary-search-tree.py | 45 +++++ 2 files changed, 50 insertions(+), 150 deletions(-) create mode 100644 problems/convert-sorted-list-to-binary-search-tree.py diff --git a/README.md b/README.md index 88c8aec..fffa095 100644 --- a/README.md +++ b/README.md @@ -2,164 +2,19 @@ 1. This is my Python (2.7) Leetcode solution. As time grows, this also become a guide to prepare for software engineer interview. +2. The solution is at `problems/the-file-name/`. +For example, `merge-sorted-array.py`'s solution is at `https://leetcode.com/problems/merge-sorted-array/`. + 2. I really take time tried to make the best solution and collect the best resource that I found. Because I wanted to help others like me. -If you like my answer, a star on GitHub means a lot to me. -https://github.com/wuduhren/leetcode-python - -3. The solution is at `problems/the-file-name/`. -For example, `merge-sorted-array.py`'s solution is at `https://leetcode.com/problems/merge-sorted-array/`. +You can [BUY ME A COFFEE](https://www.buymeacoffee.com/chriswu) if you want to show support. # Leetcode Problem Lists * https://leetcode.com/list/?selectedList=535ukjh5 (Only 74 problems) * https://www.programcreek.com/2013/08/leetcode-problem-classification/ * https://github.com/wisdompeak/LeetCode -* Below [list](https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO31DBjfeMoA0dlfIA/edit#gid=126913158) is made by **huahua**, I found this on his [youtube](https://www.youtube.com/user/xxfflower/videos). Please visit his [website](https://zxi.mytechroad.com/blog/leetcode-problem-categories/) for more. - -# Similar Problems -I found it makes sense to solve similar problems together, so that we can recognize the problem faster when we encounter a new one. My suggestion is to skip the HARD problems when you first go through these list. - -### Two Pointers -| Id | Name | Difficulty | Comments | -| ---: | --- | :---: | --- | -| 11 | [Container With Most Water](https://leetcode.com/problems/container-with-most-water/ "Container With Most Water") | ★★ | | -| 167 | [Two Sum II - Input array is sorted](https://leetcode.com/problems/two-sum-ii-input-array-is-sorted "Two Sum II - Input array is sorted") | ★★ | | -| 977 | [Squares of a Sorted Array](https://leetcode.com/problems/squares-of-a-sorted-array "Squares of a Sorted Array") | ★★ | merge sort | - -### Recursion -| Id | Name | Difficulty | | | -| ---: | --- | :---: | :---: | --- | -| 726 | [Number of Atoms](https://leetcode.com/problems/number-of-atoms "Number of Atoms") | ★★★ | [736](https://leetcode.com/problems/parse-lisp-expression/ "736") | [394](https://leetcode.com/problems/decode-string/ "394") | -| 856 | [Score of Parentheses](https://leetcode.com/problems/score-of-parentheses/ "Score of Parentheses") | ★★★ | | | - -### Divide and Conquer -| Id | Name | Difficulty | Comments | -| ---: | --- | :---: | --- | -| 169 | [Majority Element](https://leetcode.com/problems/majority-element "Majority Element") | ★★ | | -| 315 | [Count of Smaller Numbers After Self](https://leetcode.com/problems/count-of-smaller-numbers-after-self/ "Count of Smaller Numbers After Self") | ★★★★ | merge sort / BIT | - -### Search -| Id | Name | Difficulty | | | | | | | Comments | -| ---: | --- | :---: | :---: | --- | --- | --- | --- | --- | --- | -| 17 | [Letter Combinations of a Phone Number](https://leetcode.com/problems/letter-combinations-of-a-phone-number "Letter Combinations of a Phone Number") | ★★ | [39](https://leetcode.com/problems/combination-sum/ "39") | [40](https://leetcode.com/problems/combination-sum-ii/ "40") | [77](https://leetcode.com/problems/combinations/ "77") | [78](https://leetcode.com/problems/subsets/ "78") | [90](https://leetcode.com/problems/subsets-ii/ "90") | [216](https://leetcode.com/problems/combination-sum-iii/ "216") | Combination | -| 46 | [Permutations](https://leetcode.com/problems/permutations/ "Permutations") | ★★ | [47](https://leetcode.com/problems/permutations-ii/ "47") | [784](https://leetcode.com/problems/letter-case-permutation/ "784") | [943](https://leetcode.com/problems/find-the-shortest-superstring "943") | [996](https://leetcode.com/problems/number-of-squareful-arrays/ "996") | | | Permutation | -| 22 | [Generate Parentheses](https://leetcode.com/problems/generate-parentheses/ "Generate Parentheses") | ★★★ | [301](https://leetcode.com/problems/remove-invalid-parentheses/ "301") | | | | | | DFS | -| 37 | [Sudoku Solver](https://leetcode.com/problems/sudoku-solver "Sudoku Solver") | ★★★ | [51](https://leetcode.com/problems/n-queens "51") | [52](https://leetcode.com/problems/n-queens-ii "52") | | | | | DFS | -| 79 | [Word Search](https://leetcode.com/problems/word-search/ "Word Search") | ★★★ | [212](https://leetcode.com/problems/word-search-ii/ "212") | | | | | | DFS | -| 127 | [Word Ladder](https://leetcode.com/problems/word-ladder/ "Word Ladder") | ★★★★ | [126](https://leetcode.com/problems/word-ladder-ii/ "126") | [752](https://leetcode.com/problems/open-the-lock/ "752") | | | | | BFS | -| 542 | [01 Matrix](https://leetcode.com/problems/01-matrix/ "01 Matrix") | ★★★ | [675](https://leetcode.com/problems/cut-off-trees-for-golf-event/ "675") | [934](https://leetcode.com/problems/shortest-bridge/ "934") | | | | | BFS | -| 698 | [Partition to K Equal Sum Subsets](https://leetcode.com/problems/partition-to-k-equal-sum-subsets "Partition to K Equal Sum Subsets") | ★★★ | [93](https://leetcode.com/problems/restore-ip-addresses/ "93") | [131](https://leetcode.com/problems/palindrome-partitioning/ "131") | [241](https://leetcode.com/problems/different-ways-to-add-parentheses/ "241") | [282](https://leetcode.com/problems/expression-add-operators/ "282") | [842](https://leetcode.com/problems/split-array-into-fibonacci-sequence/ "842") | | Partition | - -### Hash Table -| Id | Name | Difficulty | | -| ---: | --- | :---: | :---: | -| 1 | [Two Sum](https://leetcode.com/problems/two-sum/ "Two Sum") | ★★ | [560](https://leetcode.com/problems/subarray-sum-equals-k/ "560") | - -### List -| Id | Name | Difficulty | | Comments | -| ---: | --- | :---: | :---: | --- | -| 2 | [Add Two Numbers](https://leetcode.com/problems/add-two-numbers/ "Add Two Numbers") | ★★ | [445](https://leetcode.com/problems/add-two-numbers-ii/ "445") | | -| 24 | [Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs/ "Swap Nodes in Pairs") | ★★ | | | -| 206 | [Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/ "Reverse Linked List") | ★★ | | | -| 141 | [Linked List Cycle](https://leetcode.com/problems/linked-list-cycle/ "Linked List Cycle") | ★★ | [142](https://leetcode.com/problems/linked-list-cycle-ii "142") | fast/slow | -| 23 | [Merge k Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/ "Merge k Sorted Lists") | ★★★ | [21](https://leetcode.com/problems/merge-two-sorted-lists/ "21") | priority_queue | -| 147 | [Insertion Sort List](https://leetcode.com/problems/insertion-sort-list/ "Insertion Sort List") | ★★★ | | insertion sort | -| 148 | [Sort List](https://leetcode.com/problems/sort-list/ "Sort List") | ★★★★ | | merge sort O(1) space | -| 707 | [Design Linked List](https://leetcode.com/problems/design-linked-list "Design Linked List") | ★★★★ | | | - -### Tree -| Id | Name | Difficulty | | | | | | | Comments | -| ---: | --- | :---: | :---: | --- | --- | --- | --- | --- | --- | -| 94 | [Binary Tree Inorder Traversal](https://leetcode.com/problems/binary-tree-inorder-traversal/ "Binary Tree Inorder Traversal") | ★ | [589](https://leetcode.com/problems/n-ary-tree-preorder-traversal "589") | [590](https://leetcode.com/problems/n-ary-tree-postorder-traversal "590") | | | | | traversal | -| 100 | [Same Tree](https://leetcode.com/problems/same-tree/ "Same Tree") | ★★ | [101](https://leetcode.com/problems/symmetric-tree/ "101") | [104](https://leetcode.com/problems/maximum-depth-of-binary-tree/ "104") | [110](https://leetcode.com/problems/balanced-binary-tree/ "110") | [111](https://leetcode.com/problems/minimum-depth-of-binary-tree "111") | [572](https://leetcode.com/problems/subtree-of-another-tree "572") | [965](https://leetcode.com/problems/univalued-binary-tree/ "965") | | -| 102 | [Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/ "Binary Tree Level Order Traversal") | ★★ | [107](https://leetcode.com/problems/binary-tree-level-order-traversal-ii "107") | [429](https://leetcode.com/problems/n-ary-tree-level-order-traversal "429") | [872](https://leetcode.com/problems/leaf-similar-trees/ "872") | [987](https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree "987") | | | collecting nodes | -| 814 | [Binary Tree Pruning](https://leetcode.com/problems/binary-tree-pruning/ "Binary Tree Pruning") | ★★ | [669](https://leetcode.com/problems/trim-a-binary-search-tree/ "669") | | | | | | | -| 112 | [Path Sum](https://leetcode.com/problems/path-sum/ "Path Sum") | ★★★ | [113](https://leetcode.com/problems/path-sum-ii "113") | [437](https://leetcode.com/problems/path-sum-iii "437") | | | | | | -| 124 | [Binary Tree Maximum Path Sum](https://leetcode.com/problems/binary-tree-maximum-path-sum/ "Binary Tree Maximum Path Sum") | ★★★ | [543](https://leetcode.com/problems/diameter-of-binary-tree/ "543") | [687](https://leetcode.com/problems/longest-univalue-path/ "687") | | | | | Use both children, return one | -| 129 | [Sum Root to Leaf Numbers](https://leetcode.com/problems/sum-root-to-leaf-numbers/ "Sum Root to Leaf Numbers") | ★★★ | [257](https://leetcode.com/problems/binary-tree-paths/ "257") | | | | | | | -| 236 | [Lowest Common Ancestor of a Binary Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/ "Lowest Common Ancestor of a Binary Tree") | ★★★ | [235](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree "235") | | | | | | | -| 297 | [Serialize and Deserialize Binary Tree](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/ "Serialize and Deserialize Binary Tree") | ★★★ | [449](https://leetcode.com/problems/serialize-and-deserialize-bst "449") | | | | | | | -| 508 | [Most Frequent Subtree Sum](https://leetcode.com/problems/most-frequent-subtree-sum/ "Most Frequent Subtree Sum") | ★★★ | | | | | | | | -| 968 | [Binary Tree Cameras](https://leetcode.com/problems/binary-tree-cameras/ "Binary Tree Cameras") | ★★★★ | [337](https://leetcode.com/problems/house-robber-iii/ "337") | [979](https://leetcode.com/problems/distribute-coins-in-binary-tree "979") | | | | | | - -### Binary Search -| Id | Name | Difficulty | | | | | | Comments | -| ---: | --- | :---: | :---: | --- | --- | --- | --- | --- | -| 35 | [Search Insert Position](https://leetcode.com/problems/search-insert-position/ "Search Insert Position") | ★★ | [34](https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/ "34") | [704](https://leetcode.com/problems/binary-search/ "704") | [981](https://leetcode.com/problems/time-based-key-value-store "981") | | | upper_bound | -| 33 | [Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array "Search in Rotated Sorted Array") | ★★★ | [81](https://leetcode.com/problems/search-in-rotated-sorted-array-ii/ "81") | [153](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/ "153") | [154](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii "154") | [162](https://leetcode.com/problems/find-peak-element "162") | [852](https://leetcode.com/problems/peak-index-in-a-mountain-array/ "852") | rotated / peak | -| 69 | [Sqrt(x)](https://leetcode.com/problems/sqrtx "Sqrt(x)") | ★★★ | | | | | | upper_bound | -| 74 | [Search a 2D Matrix](https://leetcode.com/problems/search-a-2d-matrix/ "Search a 2D Matrix") | ★★★ | | | | | | treat 2d as 1d | -| 875 | [Koko Eating Bananas](https://leetcode.com/problems/koko-eating-bananas/ "Koko Eating Bananas") | ★★★ | [1011](https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/ "1011") | | | | | guess ans and check | -| 378 | [Kth Smallest Element in a Sorted Matrix](https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/ "Kth Smallest Element in a Sorted Matrix") | ★★★ | [668](https://leetcode.com/problems/kth-smallest-number-in-multiplication-table/ "668") | | | | | kth + matrix | -| 778 | [Swim in Rising Water](https://leetcode.com/problems/swim-in-rising-water/ "Swim in Rising Water") | ★★★ | [174](https://leetcode.com/problems/dungeon-game/ "174") | [875](https://leetcode.com/problems/koko-eating-bananas/ "875") | | | | guess ans and check | -| 4 | [Median of Two Sorted Arrays](https://leetcode.com/problems/median-of-two-sorted-arrays/ "Median of Two Sorted Arrays") | ★★★★ | | | | | | | -| 719 | [Find K-th Smallest Pair Distance](https://leetcode.com/problems/find-k-th-smallest-pair-distance/ "Find K-th Smallest Pair Distance") | ★★★★ | [786](https://leetcode.com/problems/k-th-smallest-prime-fraction/ "786") | | | | | kth + two pointers | - -### Binary Search Tree -| Id | Name | Difficulty | | Comments | -| ---: | --- | :---: | :---: | --- | -| 98 | [Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree/ "Validate Binary Search Tree") | ★★ | [530](https://leetcode.com/problems/minimum-absolute-difference-in-bst "530") | inorder | -| 700 | [Search in a Binary Search Tree](https://leetcode.com/problems/search-in-a-binary-search-tree/ "Search in a Binary Search Tree") | ★★ | [701](https://leetcode.com/problems/insert-into-a-binary-search-tree/ "701") | binary search | -| 230 | [Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst "Kth Smallest Element in a BST") | ★★★ | | inorder | -| 99 | [Recover Binary Search Tree](https://leetcode.com/problems/recover-binary-search-tree/ "Recover Binary Search Tree") | ★★★ | | inorder | -| 108 | [Convert Sorted Array to Binary Search Tree](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/ "Convert Sorted Array to Binary Search Tree") | ★★★ | | | -| 501 | [Find Mode in Binary Search Tree](https://leetcode.com/problems/find-mode-in-binary-search-tree/ "Find Mode in Binary Search Tree") | ★★★ | | inorder | -| 450 | [Delete Node in a BST](https://leetcode.com/problems/delete-node-in-a-bst/ "Delete Node in a BST") | ★★★★ | | binary search | - -### Graph -| Id | Name | Difficulty | | | | | Comments | -| ---: | --- | :---: | :---: | --- | --- | --- | --- | -| 133 | [Clone Graph](https://leetcode.com/problems/clone-graph/ "Clone Graph") | ★★ | [138](https://leetcode.com/problems/copy-list-with-random-pointer/ "138") | | | | queue + hashtable | -| 200 | [Number of Islands](https://leetcode.com/problems/number-of-islands/ "Number of Islands") | ★★ | [547](https://leetcode.com/problems/friend-circles/ "547") | [695](https://leetcode.com/problems/max-area-of-island "695") | [733](https://leetcode.com/problems/flood-fill/ "733") | [827](https://leetcode.com/problems/making-a-large-island/ "827") | grid + connected components | -| 841 | [Keys and Rooms](https://leetcode.com/problems/keys-and-rooms/ "Keys and Rooms") | ★★ | | | | | connected components | -| 207 | [Course Schedule](https://leetcode.com/problems/course-schedule/ "Course Schedule") | ★★★ | [210](https://leetcode.com/problems/course-schedule-ii/ "210") | [802](https://leetcode.com/problems/find-eventual-safe-states "802") | | | topology sorting | -| 399 | [Evaluate Division](https://leetcode.com/problems/evaluate-division "Evaluate Division") | ★★★ | [839](https://leetcode.com/problems/similar-string-groups "839") | [952](https://leetcode.com/problems/largest-component-size-by-common-factor/ "952") | [990](https://leetcode.com/problems/satisfiability-of-equality-equations "990") | [721](https://leetcode.com/problems/accounts-merge/ "721") | union find | -| 785 | [Is Graph Bipartite?](https://leetcode.com/problems/is-graph-bipartite "Is Graph Bipartite?") | ★★★ | | | | | bipartition | -| 684 | [Redundant Connection](https://leetcode.com/problems/redundant-connection "Redundant Connection") | ★★★★ | [685](https://leetcode.com/problems/redundant-connection-ii "685") | [787](https://leetcode.com/problems/cheapest-flights-within-k-stops/ "787") | | | cycle, union find | -| 743 | [Network Delay Time](https://leetcode.com/problems/network-delay-time "Network Delay Time") | ★★★★ | [882](https://leetcode.com/problems/reachable-nodes-in-subdivided-graph/ "882") | | | | shortest path | -| 847 | [Shortest Path Visiting All Nodes](https://leetcode.com/problems/shortest-path-visiting-all-nodes/ "Shortest Path Visiting All Nodes") | ★★★★ | [815](https://leetcode.com/problems/bus-routes/ "815") | [864](https://leetcode.com/problems/shortest-path-to-get-all-keys/ "864") | [924](https://leetcode.com/problems/minimize-malware-spread/ "924") | | BFS | -| 943 | [Find the Shortest Superstring](https://leetcode.com/problems/find-the-shortest-superstring/ "Find the Shortest Superstring") | ★★★★ | [980](https://leetcode.com/problems/unique-paths-iii/ "980") | [996](https://leetcode.com/problems/number-of-squareful-arrays/ "996") | | | Hamiltonian path (DFS / DP) | -| 959 | [Regions Cut By Slashes](https://leetcode.com/problems/regions-cut-by-slashes/ "Regions Cut By Slashes") | ★★★★ | | | | | union find / grid + connected component | -| 332 | [Reconstruct Itinerary](https://leetcode.com/problems/reconstruct-itinerary/ "Reconstruct Itinerary") | ★★★★ | | | | | Eulerian path | -| 1192 | [Critical Connections in a Network](https://leetcode.com/problems/critical-connections-in-a-network/ "Critical Connections in a Network") | ★★★★ | | | | | Tarjan | - - -### Dynamic Programming -| Id | Name | Difficulty | | | | | | | Comments | -| ---: | --- | :---: | :---: | --- | --- | --- | --- | --- | --- | -| 70 | [Climbing Stairs](https://leetcode.com/problems/climbing-stairs "Climbing Stairs") | ★ | [746](https://leetcode.com/problems/min-cost-climbing-stairs "746") | | | | | | I: O(n), S = O(n), T = O(n) | -| 303 | [Range Sum Query - Immutable](https://leetcode.com/problems/range-sum-query-immutable "Range Sum Query - Immutable") | ★ | | | | | | | | -| 53 | [Maximum Subarray](https://leetcode.com/problems/maximum-subarray "Maximum Subarray") | ★★ | [121](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ "121") | | | | | | | -| 198 | [House Robber](https://leetcode.com/problems/house-robber/ "House Robber") | ★★★ | [213](https://leetcode.com/problems/house-robber-ii/ "213") | [309](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/ "309") | [740](https://leetcode.com/problems/delete-and-earn/ "740") | [790](https://leetcode.com/problems/domino-and-tromino-tiling/ "790") | [801](https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/ "801") | | I: O(n), S = O(3n), T = O(3n) | -| 139 | [Word Break](https://leetcode.com/problems/word-break "Word Break") | ★★★ | [140](https://leetcode.com/problems/word-break-ii "140") | [818](https://leetcode.com/problems/race-car/ "818") | | | | | I: O(n), S = O(n), T = O(n^2) | -| 300 | [Longest Increasing Subsequence](https://leetcode.com/problems/longest-increasing-subsequence/ "Longest Increasing Subsequence") | ★★★ | [673](https://leetcode.com/problems/number-of-longest-increasing-subsequence "673") | | | | | | | -| 72 | [Edit Distance](https://leetcode.com/problems/edit-distance "Edit Distance") | ★★★ | [10](https://leetcode.com/problems/regular-expression-matching "10") | [44](https://leetcode.com/problems/wildcard-matching/ "44") | [97](https://leetcode.com/problems/interleaving-string "97") | [115](https://leetcode.com/problems/distinct-subsequences/ "115") | [583](https://leetcode.com/problems/delete-operation-for-two-strings/ "583") | [712](https://leetcode.com/problems/minimum-ascii-delete-sum-for-two-strings "712") | I: O(m+n), S = O(mn), T = O(mn) | -| 322 | [Coin Change](https://leetcode.com/problems/coin-change "Coin Change") | ★★★ | [377](https://leetcode.com/problems/combination-sum-iv/ "377") | [416](https://leetcode.com/problems/partition-equal-subset-sum/ "416") | [494](https://leetcode.com/problems/target-sum "494") | | | | I: O(n) + k, S = O(n), T = O(kn) | -| 813 | [Largest Sum of Averages](https://leetcode.com/problems/largest-sum-of-averages/ "Largest Sum of Averages") | ★★★ | | | | | | | I: O(n) + k, S = O(n), T = O(kn^2) | -| 312 | [Burst Balloons](https://leetcode.com/problems/burst-balloons/ "Burst Balloons") | ★★★★ | [664](https://leetcode.com/problems/strange-printer/ "664") | [1024](https://leetcode.com/problems/video-stitching/ "1024") | [1039](https://leetcode.com/problems/minimum-score-triangulation-of-polygon/ "1039") | | | | I: O(n), S = O(n^2), T = O(n^3) | -| 741 | [Cherry Pickup](https://leetcode.com/problems/cherry-pickup/ "Cherry Pickup") | ★★★★ | | | | | | | I: O(n^2), S = O(n^3), T = O(n^3) | -| 546 | [Remove Boxes](https://leetcode.com/problems/remove-boxes "Remove Boxes") | ★★★★★ | | | | | | | I: O(n), S = O(n^3), T = O(n^4) | -| 943 | [Find the Shortest Superstring](https://leetcode.com/problems/find-the-shortest-superstring/ "Find the Shortest Superstring") | ★★★★ | [980](https://leetcode.com/problems/unique-paths-iii/ "980") | [996](https://leetcode.com/problems/number-of-squareful-arrays/ "996") | | | | | I: O(n), S = O(n*2^n), T = (n^2*2^n) | -| 62 | [Unique Paths](https://leetcode.com/problems/unique-paths "Unique Paths") | ★★ | [63](https://leetcode.com/problems/unique-paths-ii "63") | [64](https://leetcode.com/problems/minimum-path-sum "64") | [120](https://leetcode.com/problems/triangle "120") | [174](https://leetcode.com/problems/dungeon-game "174") | [931](https://leetcode.com/problems/minimum-falling-path-sum/ "931") | | I: O(mn), S = O(mn), T = O(mn) | -| 85 | [Maximal Rectangle](https://leetcode.com/problems/delete-operation-for-two-strings/ "Maximal Rectangle") | ★★★ | [221](https://leetcode.com/problems/maximal-square/ "221") | [304](https://leetcode.com/problems/range-sum-query-2d-immutable "304") | | | | | | -| 688 | [Knight Probability in Chessboard](https://leetcode.com/problems/knight-probability-in-chessboard/ "Knight Probability in Chessboard") | ★★★ | [576](https://leetcode.com/problems/out-of-boundary-paths/ "576") | [935](https://leetcode.com/problems/knight-dialer/ "935") | | | | | I: O(mn) + k, S = O(kmn) T = O(kmn) | -| 322 | [Coin Change](https://leetcode.com/problems/reconstruct-itinerary/ "Coin Change") | ★★★ | [377](https://leetcode.com/problems/combination-sum-iv/ "377") | [416](https://leetcode.com/problems/partition-equal-subset-sum/ "416") | [494](https://leetcode.com/problems/target-sum/ "494") | [1043](https://leetcode.com/problems/partition-array-for-maximum-sum/ "1043") | [1049](https://leetcode.com/problems/last-stone-weight-ii/ "1049") | | I: O(n) + k, S = O(n), T = O(kn) | -| | | | [1220](https://leetcode.com/problems/count-vowels-permutation/ "1220") | [1230](https://leetcode.com/problems/toss-strange-coins/ "1230") | [1262](https://leetcode.com/problems/greatest-sum-divisible-by-three/ "1262") | [1269](https://leetcode.com/problems/number-of-ways-to-stay-in-the-same-place-after-some-steps/ "1269") | | | -| 813 | [Largest Sum of Averages](https://leetcode.com/problems/largest-sum-of-averages/ "Largest Sum of Averages") | ★★★★ | [1278](https://leetcode.com/problems/palindrome-partitioning-iii/ "1278") | [1335](https://leetcode.com/problems/minimum-difficulty-of-a-job-schedule/ "1335") | [410](https://leetcode.com/problems/split-array-largest-sum/ "410") | | | | I: O(n) + k
S = O(n*k), T = O(kn^2) | -| 1223 | [Dice Roll Simulation](https://leetcode.com/problems/dice-roll-simulation/ "Dice Roll Simulation") | ★★★★ | | | | | | | I: O(n) + k + p
S = O(k*p), T = O(n^2kp) | -| 312 | [Burst Balloons](https://leetcode.com/problems/burst-balloons/ "Burst Balloons") | ★★★★ | [664](https://leetcode.com/problems/strange-printer/ "664") | [1024](https://leetcode.com/problems/video-stitching/ "1024") | [1039](https://leetcode.com/problems/minimum-score-triangulation-of-polygon/ "1039") | [1140](https://leetcode.com/problems/stone-game-ii/ "1140") | [1130](https://leetcode.com/problems/minimum-cost-tree-from-leaf-values/ "1130") | | I: O(n), S = O(n^2), T = O(n^3) | -| 741 | [Cherry Pickup](https://leetcode.com/problems/cherry-pickup/ "Cherry Pickup") | ★★★★ | | | | | | | I: O(n^2), S = O(n^3), T = O(n^3) | -| 546 | [Remove Boxes](https://leetcode.com/problems/remove-boxes/ "Remove Boxes") | ★★★★★ | | | | | | | I: O(n), S = O(n^3), T = O(n^4) | -| 943 | [Find the Shortest Superstring](https://leetcode.com/problems/find-the-shortest-superstring/ "Find the Shortest Superstring") | ★★★★★ | [980](https://leetcode.com/problems/unique-paths-iii/ "980") | [996](https://leetcode.com/problems/number-of-squareful-arrays/ "996") | [1125](https://leetcode.com/problems/smallest-sufficient-team/ "1125") | | | | I: O(n)
S = O(n*2^n), T = (n^2*2^n) | - -### Advanced -| Id | Name | Difficulty | | | | | | Comments | -| ---: | --- | :---: | :---: | --- | --- | --- | --- | --- | -| 208 | [Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree "Implement Trie (Prefix Tree)") | ★★★ | [648](https://leetcode.com/problems/replace-words/ "648") | [676](https://leetcode.com/problems/implement-magic-dictionary "676") | [677](https://leetcode.com/problems/map-sum-pairs "677") | [720](https://leetcode.com/problems/longest-word-in-dictionary "720") | [745](https://leetcode.com/problems/prefix-and-suffix-search "745") | Trie | -| 307 | [Range Sum Query - Mutable](https://leetcode.com/problems/range-sum-query-mutable "Range Sum Query - Mutable") | ★★★ | | | | | | BIT/Segment Tree | -| 901 | [Online Stock Span](https://leetcode.com/problems/online-stock-span "Online Stock Span") | ★★★ | [907](https://leetcode.com/problems/sum-of-subarray-minimums "907") | [1019](https://leetcode.com/problems/next-greater-node-in-linked-list/ "1019") | | | | Monotonic Stack | -| 239 | [Sliding Window Maximum](https://leetcode.com/problems/sliding-window-maximum/ "Sliding Window Maximum") | ★★★ | | | | | | Monotonic Queue | +* https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO31DBjfeMoA0dlfIA/edit#gid=126913158 ([huahua](https://www.youtube.com/user/xxfflower/videos)). # Software Engineer Interview diff --git a/problems/convert-sorted-list-to-binary-search-tree.py b/problems/convert-sorted-list-to-binary-search-tree.py new file mode 100644 index 0000000..5b127b7 --- /dev/null +++ b/problems/convert-sorted-list-to-binary-search-tree.py @@ -0,0 +1,45 @@ +""" +Time: O(NLogN), +The root need to traverse N node to get its midNode. + +The root.left need to traverse N/2 node to get its midNode. +The root.right need to traverse N/2 node to get its midNode. + +The root.left.left need to traverse N/4 node to get its midNode. +The root.left.right need to traverse N/4 node to get its midNode. +The root.right.left need to traverse N/4 node to get its midNode. +The root.right.right need to traverse N/4 node to get its midNode. + +... +So total: +N + (N/2+N/2) + (N/4+N/4+N/4+N/4) + ... => N + N + N + ... +There are LogN levels in the tree, so LogN x N => NLogN + +Space: O(LogN) for recursion depth. +""" +class Solution(object): + def sortedListToBST(self, head): + if not head: return None + + midNode = self.getMiddle(head) + root = TreeNode(midNode.val) + + if head.val==midNode.val: return root + + root.left = self.sortedListToBST(head) + root.right = self.sortedListToBST(midNode.next) + + return root + + def getMiddle(self, node): + pre = None + slow = node + fast = node + + while fast and fast.next: + fast = fast.next.next + pre = slow + slow = slow.next + + if pre: pre.next = None + return slow \ No newline at end of file From 4e46d7dd042a0869e7dd13c42506b0bf9ae25a61 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sun, 19 Sep 2021 12:14:22 +0800 Subject: [PATCH 119/187] no message --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fffa095..1c04a74 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ As time grows, this also become a guide to prepare for software engineer intervi For example, `merge-sorted-array.py`'s solution is at `https://leetcode.com/problems/merge-sorted-array/`. 2. I really take time tried to make the best solution and collect the best resource that I found. -Because I wanted to help others like me. -You can [BUY ME A COFFEE](https://www.buymeacoffee.com/chriswu) if you want to show support. +Because I wanted to help others like me. +Please [BUY ME A COFFEE](https://www.buymeacoffee.com/chriswu) if you want to show support. # Leetcode Problem Lists From f15efb21231cd62bc899d7feb4d89f14f1cf06fc Mon Sep 17 00:00:00 2001 From: wuduhren Date: Thu, 23 Sep 2021 08:03:28 +0800 Subject: [PATCH 120/187] no message --- README.md | 4 ++- problems/balanced-binary-tree.py | 23 ++++++++++++++++- problems/minimum-depth-of-binary-tree.py | 25 +++++++++++++++++- problems/symmetric-tree.py | 33 +++++++++++++++++++++++- 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1c04a74..dd42196 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,12 @@ Please [BUY ME A COFFEE](https://www.buymeacoffee.com/chriswu) if you want to sh # Leetcode Problem Lists -* https://leetcode.com/list/?selectedList=535ukjh5 (Only 74 problems) +I found it makes sense to solve similar problems together, so that we can recognize the problem faster when we encounter a new one. My suggestion is to skip the HARD problems when you first go through these list. + * https://www.programcreek.com/2013/08/leetcode-problem-classification/ * https://github.com/wisdompeak/LeetCode * https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO31DBjfeMoA0dlfIA/edit#gid=126913158 ([huahua](https://www.youtube.com/user/xxfflower/videos)). +* https://leetcode.com/list/?selectedList=535ukjh5 (Only 74 problems) # Software Engineer Interview diff --git a/problems/balanced-binary-tree.py b/problems/balanced-binary-tree.py index 3061e57..36232a8 100644 --- a/problems/balanced-binary-tree.py +++ b/problems/balanced-binary-tree.py @@ -24,4 +24,25 @@ def helper(node, depth): return -1 if not root: return True - return helper(root, 0)!=-1 \ No newline at end of file + return helper(root, 0)!=-1 + + +""" +Time: O(N), since we recursively traverse each node once. +Space: O(LogN), for the recursive call. O(N) if the tree is not balanced. +""" +class Solution(object): + def isBalanced(self, root): + + #return (if the node isBalanced, the height of the node) + def helper(node): + if not node: return True, -1 + + isLeftBalanced, leftHeight = helper(node.left) + isRightBalanced, rightHeight = helper(node.right) + + height = max(leftHeight, rightHeight)+1 + + return isLeftBalanced and isRightBalanced and abs(leftHeight-rightHeight)<=1, height + + return helper(root)[0] \ No newline at end of file diff --git a/problems/minimum-depth-of-binary-tree.py b/problems/minimum-depth-of-binary-tree.py index b919ab1..1ea7e27 100644 --- a/problems/minimum-depth-of-binary-tree.py +++ b/problems/minimum-depth-of-binary-tree.py @@ -18,4 +18,27 @@ def minDepth(self, root): if node.left: q.append((node.left, depth+1)) if node.right: - q.append((node.right, depth+1)) \ No newline at end of file + q.append((node.right, depth+1)) + + + +""" +Time: O(N) +Space: O(N) + +Standard BFS on a binary tree. +""" +class Solution(object): + def minDepth(self, root): + if not root: return 0 + q = collections.deque([(root, 1)]) + + while q: + node, depth = q.popleft() + + if not node.left and not node.right: return depth + + if node.left: q.append((node.left, depth+1)) + if node.right: q.append((node.right, depth+1)) + + return 'ERROR' \ No newline at end of file diff --git a/problems/symmetric-tree.py b/problems/symmetric-tree.py index 86330bb..bb5c717 100644 --- a/problems/symmetric-tree.py +++ b/problems/symmetric-tree.py @@ -33,4 +33,35 @@ def isSymmetric(self, root): # if left_node.val!=right_node.val: return False # stack.append((left_node.right, right_node.left)) # stack.append((left_node.left, right_node.right)) -# return True \ No newline at end of file +# return True + +""" +Time: O(N) +Space: O(N) + +Use 2 DFS to traverse the tree at the same time. +s1 will go left first. +s2 will fo right first. +Make sure every element popping out is the same. +""" +class Solution(object): + def isSymmetric(self, root): + s1 = [root] + s2 = [root] + + while s1 and s2: + node1 = s1.pop() + node2 = s2.pop() + + if not node1 and not node2: continue + if not node1 and node2: return False + if node1 and not node2: return False + if node1.val!=node2.val: return False + + s1.append(node1.left) + s1.append(node1.right) + s2.append(node2.right) + s2.append(node2.left) + + if s1 or s2: return False #if there are something left in one of the stack + return True \ No newline at end of file From 2acab52b488daf805ba6d4e4fd5f2e2c51587fe9 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sat, 25 Sep 2021 08:40:02 +0800 Subject: [PATCH 121/187] no message --- problems/binary-search-tree-iterator.py | 50 +++++++++++++++---- problems/binary-tree-right-side-view.py | 26 +++++++++- ...common-ancestor-of-a-binary-search-tree.py | 19 +++++++ ...lowest-common-ancestor-of-a-binary-tree.py | 23 ++++++++- 4 files changed, 105 insertions(+), 13 deletions(-) create mode 100644 problems/lowest-common-ancestor-of-a-binary-search-tree.py diff --git a/problems/binary-search-tree-iterator.py b/problems/binary-search-tree-iterator.py index 2d171bd..65557ce 100644 --- a/problems/binary-search-tree-iterator.py +++ b/problems/binary-search-tree-iterator.py @@ -1,10 +1,3 @@ -# Definition for a binary tree node. -# class TreeNode(object): -# def __init__(self, x): -# self.val = x -# self.left = None -# self.right = None - class BSTIterator(object): def __init__(self, root): @@ -27,10 +20,45 @@ def next(self): def hasNext(self): return len(self.stack)!=0 + +""" +Time: init() O(1). next() O(LogN). hasNext() O(1). +Space: O(N) +""" +class BSTIterator(object): + + def __init__(self, root): + self.node = root + self.stack = [] + + def next(self): + while self.node: + self.stack.append(self.node) + self.node = self.node.left + + node = self.stack.pop() + self.node = node.right + return node.val + def hasNext(self): + return self.stack or self.node -# Your BSTIterator object will be instantiated and called as such: -# obj = BSTIterator(root) -# param_1 = obj.next() -# param_2 = obj.hasNext() \ No newline at end of file +""" +FYI. Template for in-order traverse. +""" +def inOrderTraverse(root): + stack = [] + node = root + + while node or stack: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + + #do something + print node.val + + node = node.right \ No newline at end of file diff --git a/problems/binary-tree-right-side-view.py b/problems/binary-tree-right-side-view.py index ddae3a5..76d807f 100644 --- a/problems/binary-tree-right-side-view.py +++ b/problems/binary-tree-right-side-view.py @@ -28,4 +28,28 @@ def rightSideView(self, root): view.append(node.val) queue.append((node.right, level+1)) queue.append((node.left, level+1)) - return view \ No newline at end of file + return view + +""" +Time: O(N). +Space: O(N). + +Similar solution using DFS. +""" +class Solution(object): + def rightSideView(self, root): + if not root: return [] + + ans = [] + currLevel = -1 + stack = [(root, 0)] + + while stack: + node, level = stack.pop() + if level>currLevel: + ans.append(node.val) + currLevel = level + if node.left: stack.append((node.left, level+1)) + if node.right: stack.append((node.right, level+1)) + + return ans \ No newline at end of file diff --git a/problems/lowest-common-ancestor-of-a-binary-search-tree.py b/problems/lowest-common-ancestor-of-a-binary-search-tree.py new file mode 100644 index 0000000..897d961 --- /dev/null +++ b/problems/lowest-common-ancestor-of-a-binary-search-tree.py @@ -0,0 +1,19 @@ +""" +Time: O(LogN). O(N) if the tree is unbalanced. +Space: O(1) + +If both p and q are both on the left subtree, then search the left subtree. +If both p and q are both on the right subtree, then search the right subtree. +Else the current must be the ans. +""" +class Solution(object): + def lowestCommonAncestor(self, root, p, q): + node = root + + while node: + if node.val>q.val and node.val>p.val: + node = node.left + elif node.val Date: Sun, 26 Sep 2021 14:26:32 +0800 Subject: [PATCH 122/187] no message --- problems/most-frequent-subtree-sum.py | 22 ++++++++++++++++++- ...preorder-serialization-of-a-binary-tree.py | 14 ++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 problems/verify-preorder-serialization-of-a-binary-tree.py diff --git a/problems/most-frequent-subtree-sum.py b/problems/most-frequent-subtree-sum.py index ce457fc..5c1457f 100644 --- a/problems/most-frequent-subtree-sum.py +++ b/problems/most-frequent-subtree-sum.py @@ -17,4 +17,24 @@ def dfs(node): """ Time: O(N) Space: O(N) -""" \ No newline at end of file +""" + +""" +Time: O(N) +Space: O(N) + +Throught the getSubtreeSum(root), we will also count subtreeSum of each node. +""" +class Solution(object): + def findFrequentTreeSum(self, root): + def getSubtreeSum(node): + if not node: return 0 + subtreeSum = node.val+getSubtreeSum(node.left)+getSubtreeSum(node.right) + memo[subtreeSum] += 1 + return subtreeSum + + + memo = collections.Counter() + getSubtreeSum(root) + mostFrequenctCount = max([memo[subtreeSum] for subtreeSum in memo]) + return [subtreeSum for subtreeSum in memo if memo[subtreeSum]==mostFrequenctCount] \ No newline at end of file diff --git a/problems/verify-preorder-serialization-of-a-binary-tree.py b/problems/verify-preorder-serialization-of-a-binary-tree.py new file mode 100644 index 0000000..39930bf --- /dev/null +++ b/problems/verify-preorder-serialization-of-a-binary-tree.py @@ -0,0 +1,14 @@ +""" +Time: O(N) +Space: O(N) for creating the list preorder.split(',') +""" +class Solution(object): + def isValidSerialization(self, preorder): + slot = 1 + + for c in preorder.split(','): + slot -= 1 #each elemet consumes a slot + if slot<0: return False + if c!='#': slot += 2 #each non-null node also create 2 slot + + return slot==0 #all slots should be fill \ No newline at end of file From 9f007062fecc9c7c3c7af3a036b19a38373cad19 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 28 Sep 2021 07:22:58 +0800 Subject: [PATCH 123/187] no message --- ...ing-next-right-pointers-in-each-node-ii.py | 50 +++++++++++++++++ ...lating-next-right-pointers-in-each-node.py | 56 +++++++++++++++++++ problems/unique-binary-search-trees.py | 34 ++++++++++- 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 problems/populating-next-right-pointers-in-each-node-ii.py create mode 100644 problems/populating-next-right-pointers-in-each-node.py diff --git a/problems/populating-next-right-pointers-in-each-node-ii.py b/problems/populating-next-right-pointers-in-each-node-ii.py new file mode 100644 index 0000000..718d84d --- /dev/null +++ b/problems/populating-next-right-pointers-in-each-node-ii.py @@ -0,0 +1,50 @@ +""" +Time: O(N) +Space: O(1) + +View each level as a link list. +Traverse the tree level by level. For each level: +Starting from the leftmost (the head of the link list), we establish the next pointer of the children. + +curr.left.next = curr.right or (curr.next.left or curr.next.right) or (curr.next.next.left or curr.next.next.right) or (...) +curr.right.next = (curr.next.left or curr.next.right) or (curr.next.next.left or curr.next.next.right) or (...) +""" +class Solution(object): + def connect(self, root): + if not root: return root + + leftmost = root + + while leftmost: + curr = leftmost + + while curr: + if curr.left: + if curr.right: + curr.left.next = curr.right + else: + n = curr.next + while n: + curr.left.next = n.left or n.right + if curr.left.next: break + n = n.next + + if curr.right: + n = curr.next + while n: + curr.right.next = n.left or n.right + if curr.right.next: break + n = n.next + + curr = curr.next + + nextLevelLeftmost = None + n = leftmost + while n: + if n.left or n.right: + nextLevelLeftmost = n.left or n.right + break + n = n.next + leftmost = nextLevelLeftmost + + return root \ No newline at end of file diff --git a/problems/populating-next-right-pointers-in-each-node.py b/problems/populating-next-right-pointers-in-each-node.py new file mode 100644 index 0000000..0f01cf2 --- /dev/null +++ b/problems/populating-next-right-pointers-in-each-node.py @@ -0,0 +1,56 @@ +""" +Time: O(N) +Space: O(N) + +Traverse the tree level by level. +For each level connect the node to the "next node". +""" +class Solution(object): + def connect(self, root): + if not root: return root + level = collections.deque([root]) + nextLevel = collections.deque() + + while level: + node = level.popleft() + + if node.left: nextLevel.append(node.left) + if node.right: nextLevel.append(node.right) + + if not level: + if not nextLevel: break + for i, c in enumerate(nextLevel): + if i==len(nextLevel)-1: continue #skip last + c.next = nextLevel[i+1] + level = nextLevel + nextLevel = collections.deque() + + return root + + +""" +Time: O(N) +Space: O(1) + +View each level as a link list. +Traverse the tree level by level. For each level: +Starting from the leftmost (the head of the link list), we establish the next pointer of the children. +curr.left.next = curr.right +curr.right.next = curr.next.left +""" +class Solution(object): + def connect(self, root): + if not root: return root + + leftmost = root + while leftmost: + + curr = leftmost + while curr: + if curr.left: curr.left.next = curr.right + if curr.right and curr.next: curr.right.next = curr.next.left + curr = curr.next + + leftmost = leftmost.left + + return root \ No newline at end of file diff --git a/problems/unique-binary-search-trees.py b/problems/unique-binary-search-trees.py index 65dd64e..37c18a7 100644 --- a/problems/unique-binary-search-trees.py +++ b/problems/unique-binary-search-trees.py @@ -11,4 +11,36 @@ def numTrees(self, n): for root in xrange(1, i+1): dp[i] += dp[root-1]*dp[i-root] - return dp[n] \ No newline at end of file + return dp[n] + +""" +dp[n] := the number of structurally unique BST's which has n nodes with val 1~n +dp[n] = helper(n) + +Form 1~n nodes +If we use 1 as root, the left subtree possible count will be dp[1-1] and right subtree be dp[n-1], the count will be dp[0]*dp[n-1]. +If we use 2 as root, the left subtree possible count will be dp[2-1] and right subtree be dp[n-2], the count will be dp[1]*dp[n-2]. +If we use 3 as root, the left subtree possible count will be dp[3-1] and right subtree be dp[n-3], the count will be dp[2]*dp[n-3]. +... +If we use i as root, the left subtree possible count will be dp[i-1] and right subtree be dp[n-i], the count will be dp[i-1]*dp[n-i]. + +So the number of structurally unique BST's which has n nodes with val 1~n, will be the sum above. + +Time: O(N^2) +Space: O(N) +""" +class Solution(object): + def numTrees(self, N): + def helper(n): + count = 0 + for i in xrange(1, n+1): + count += dp[i-1]*dp[n-i] + return count + + dp = [0]*(N+1) + dp[0] = 1 + dp[1] = 1 + + for n in xrange(2, N+1): + dp[n] = helper(n) + return dp[N] \ No newline at end of file From 511154319991215d22b888a2ec6d5d62a8074b8a Mon Sep 17 00:00:00 2001 From: wuduhren Date: Thu, 30 Sep 2021 09:26:03 +0800 Subject: [PATCH 124/187] no message --- problems/closest-binary-search-tree-value.py | 24 +++++++++++++++++ problems/count-complete-tree-nodes.py | 27 ++++++++++++++++++++ problems/sum-root-to-leaf-numbers.py | 24 +++++++++++++++++ problems/unique-binary-search-trees-ii,py | 23 +++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 problems/closest-binary-search-tree-value.py create mode 100644 problems/count-complete-tree-nodes.py create mode 100644 problems/unique-binary-search-trees-ii,py diff --git a/problems/closest-binary-search-tree-value.py b/problems/closest-binary-search-tree-value.py new file mode 100644 index 0000000..ca3c644 --- /dev/null +++ b/problems/closest-binary-search-tree-value.py @@ -0,0 +1,24 @@ +""" +Time: O(LogN) +Space: O(1) + +Basically we are going to search the target in the BST. +Along the way, we compare it with the `ans`, if the difference is smaller, update it. +""" +class Solution(object): + def closestValue(self, root, target): + node = root + ans = float('inf') + + while node: + if not node: break + + if abs(ans-target)>abs(node.val-target): + ans = node.val + + if target>node.val: + node = node.right + else: + node = node.left + + return ans \ No newline at end of file diff --git a/problems/count-complete-tree-nodes.py b/problems/count-complete-tree-nodes.py new file mode 100644 index 0000000..ab9c7bc --- /dev/null +++ b/problems/count-complete-tree-nodes.py @@ -0,0 +1,27 @@ +""" +Time: O(H^2). The time complexity will countNodes() will be LogH if the tree is perfect. +If not, we will need Log(H-1) + +Space: O(H) +""" +class Solution(object): + def countNodes(self, root): + if not root: return 0 + + node = root + l = 1 #level on the right side + while node.left: + node = node.left + l += 1 + + node = root + r = 1 #level on the left side + while node.right: + node = node.right + r += 1 + + if l==r: + #perfect tree + return (2**r)-1 + else: + return 1+self.countNodes(root.left)+self.countNodes(root.right) \ No newline at end of file diff --git a/problems/sum-root-to-leaf-numbers.py b/problems/sum-root-to-leaf-numbers.py index 2c85693..dcfe56b 100644 --- a/problems/sum-root-to-leaf-numbers.py +++ b/problems/sum-root-to-leaf-numbers.py @@ -43,6 +43,30 @@ def sumNumbers(self, root): """ +""" +Time: O(N) +Space: O(H) + +Use standard DFS to traverse the tree. +""" +class Solution(object): + def sumNumbers(self, root): + ans = 0 + stack = [(root, '')] + + while stack: + node, numString = stack.pop() + + if node.left: + stack.append((node.left, numString+str(node.val))) + if node.right: + stack.append((node.right, numString+str(node.val))) + + if not node.left and not node.right: + ans += int(numString+str(node.val)) + return ans + + diff --git a/problems/unique-binary-search-trees-ii,py b/problems/unique-binary-search-trees-ii,py new file mode 100644 index 0000000..f7ecfc1 --- /dev/null +++ b/problems/unique-binary-search-trees-ii,py @@ -0,0 +1,23 @@ +class Solution(object): + def generateTrees(self, N): + + #generateTrees from s to e + def helper(s, e): + trees = [] + + for i in xrange(s, e+1): + leftTrees = helper(s, i-1) + rightTrees = helper(i+1, e) + + for leftTree in leftTrees: + for rightTree in rightTrees: + + root = TreeNode(i) + root.left = leftTree + root.right = rightTree + trees.append(root) + + return trees if trees else [None] + + #remove None in the output + return [tree for tree in helper(1, N) if tree] \ No newline at end of file From 0637d3a08b8260fb658bd55241f51794027286fb Mon Sep 17 00:00:00 2001 From: wuduhren Date: Fri, 1 Oct 2021 08:16:05 +0800 Subject: [PATCH 125/187] no message --- problems/binary-tree-paths.py | 24 +++++++++ problems/maximum-depth-of-binary-tree.py | 26 ++++++++- problems/recover-binary-search-tree.py | 68 ++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 problems/recover-binary-search-tree.py diff --git a/problems/binary-tree-paths.py b/problems/binary-tree-paths.py index c8bfb99..6dc87cb 100644 --- a/problems/binary-tree-paths.py +++ b/problems/binary-tree-paths.py @@ -15,4 +15,28 @@ def binaryTreePaths(self, root): if node.left: stack.append((node.left, path)) if node.right: stack.append((node.right, path)) + return ans + + +""" +Time: O(N) +Space: O(N) + +Standard BFS. +""" +class Solution(object): + def binaryTreePaths(self, root): + q = collections.deque([(root, '')]) + ans = [] + + while q: + node, path = q.popleft() + + path = (path+'->'+str(node.val)) if path else str(node.val) + + if node.left: q.append((node.left, path)) + if node.right: q.append((node.right, path)) + + if not node.left and not node.right: ans.append(path) + return ans \ No newline at end of file diff --git a/problems/maximum-depth-of-binary-tree.py b/problems/maximum-depth-of-binary-tree.py index 020d153..f114251 100644 --- a/problems/maximum-depth-of-binary-tree.py +++ b/problems/maximum-depth-of-binary-tree.py @@ -18,4 +18,28 @@ def maxDepth(self, root): if node.right: stack.append((node.right, depth+1)) return max_depth - \ No newline at end of file + + +""" +Time: O(N) +Space: O(N) + +Standard BFS. +""" +class Solution(object): + def maxDepth(self, root): + if not root: return 0 + + ans = float('-inf') + q = collections.deque([(root, 1)]) + node = root + + while q: + node, d = q.popleft() + + ans = max(ans, d) + + if node.left: q.append((node.left, d+1)) + if node.right: q.append((node.right, d+1)) + + return ans \ No newline at end of file diff --git a/problems/recover-binary-search-tree.py b/problems/recover-binary-search-tree.py new file mode 100644 index 0000000..eb81e74 --- /dev/null +++ b/problems/recover-binary-search-tree.py @@ -0,0 +1,68 @@ +""" +Time: O(NLogN) +Space: O(N) +""" +class Solution(object): + def recoverTree(self, root): + memo = {} #{node.val:node} + stack = [] + node = root + vals = [] + + #inorder traversal and store the values in `vals` and `memo` + while node or stack: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + + memo[node.val] = node + vals.append(node.val) + + node = node.right + + #find two val that needed to be swapped + diff = [] + sortedVals = sorted(vals) + for i in xrange(len(sortedVals)): + if vals[i]!=sortedVals[i]: diff.append(vals[i]) + if len(diff)>=2: break + + #swap the values + memo[diff[0]].val = diff[1] + memo[diff[1]].val = diff[0] + + return root + + +""" +Time: O(N) +Space: O(N) +""" +class Solution(object): + def recoverTree(self, root): + stack = [] + node = root + prev = TreeNode(float('-inf')) + swap1 = swap2 = None + + #inorder traversal and find the swapped values + while node or stack: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + + if swap1==None and prev.val>node.val: swap1 = prev + if swap1!=None and prev.val>node.val: swap2 = node + + prev = node + + node = node.right + + #swap the values + swap1.val, swap2.val = swap2.val, swap1.val + + return root \ No newline at end of file From 895710d9f65b2c462d448dd2b91dce156e550997 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Mon, 4 Oct 2021 07:32:44 +0800 Subject: [PATCH 126/187] no message --- problems/find-leaves-of-binary-tree.py | 57 +++++++++++++++++++ problems/inorder-successor-in-bst-ii.py | 21 +++++++ problems/inorder-successor-in-bst.py | 52 +++++++++++++++++ problems/same-tree.py | 26 +++++++++ .../serialize-and-deserialize-binary-tree.py | 42 ++++++++++++++ 5 files changed, 198 insertions(+) create mode 100644 problems/find-leaves-of-binary-tree.py create mode 100644 problems/inorder-successor-in-bst-ii.py create mode 100644 problems/inorder-successor-in-bst.py create mode 100644 problems/serialize-and-deserialize-binary-tree.py diff --git a/problems/find-leaves-of-binary-tree.py b/problems/find-leaves-of-binary-tree.py new file mode 100644 index 0000000..8b08b11 --- /dev/null +++ b/problems/find-leaves-of-binary-tree.py @@ -0,0 +1,57 @@ +""" +Time: O(N), each nodes is traversed 2 times. +Space: O(N) for `parents` and `q`, `ans`, `ans2` + +[1] +Through BFS +Store the parent of each node in the `parents`. +Also store the leaf node in the `temp`. + +[2] +Store the `temp` to the ans. +For each node stored to the ans, we need to "detach" it from its parent. +Also check if the parent become a leaf node, if so, store it in the new `temp`. + +[3] +Store the val from node reference in ans to ans2. +""" +class Solution(object): + def findLeaves(self, root): + ans = [] + q = collections.deque([root]) + parents = {} + + #[1] + temp = [] + while q: + node = q.popleft() + + if not node.left and not node.right: + temp.append(node) + + if node.left: + q.append(node.left) + parents[node.left] = node + + if node.right: + q.append(node.right) + parents[node.right] = node + + #[2] + while temp: + ans.append(temp) + temp = [] + + for node in ans[-1]: + if node not in parents: break + p = parents[node] + if p.left==node: p.left = None + if p.right==node: p.right = None + if not p.left and not p.right: temp.append(p) + + #[3] + ans2 = [] + for temp in ans: + ans2.append([node.val for node in temp]) + + return ans2 \ No newline at end of file diff --git a/problems/inorder-successor-in-bst-ii.py b/problems/inorder-successor-in-bst-ii.py new file mode 100644 index 0000000..67440d7 --- /dev/null +++ b/problems/inorder-successor-in-bst-ii.py @@ -0,0 +1,21 @@ +""" +Time: O(H), since we are just moving vertically in the tree. +Space: O(1) + +First, check if the node has right child, if so, continue the traversal. +If the node doesn't have right child, this mean that the node and all its children are visited. +We need to move up. +While moving up a node, if a node itself is a right child, we need to keep moving up, since the node's parent is already vistied. +Keep moving up until the node itself is a left child. Return its parent. +""" +class Solution(object): + def inorderSuccessor(self, node): + if node.right: + node = node.right + while node.left: + node = node.left + return node + + while node.parent and node.parent.right==node: + node = node.parent + return node.parent \ No newline at end of file diff --git a/problems/inorder-successor-in-bst.py b/problems/inorder-successor-in-bst.py new file mode 100644 index 0000000..83ae4d2 --- /dev/null +++ b/problems/inorder-successor-in-bst.py @@ -0,0 +1,52 @@ +""" +Time: O(N) +Space: O(N) + +First, check if the p has right child, if it has a right child, we can continue the inorder traversal from it. +Second, if p does not have right child, we need to do the inorder traversal from the beginning. +During the traversal, do check if the prev is p. +If so, return the current node. +""" +class Solution(object): + def inorderSuccessor(self, root, p): + if p.right: + p = p.right + while p.left: + p = p.left + return p + else: + stack = [] + node = root + prev = None + while node or stack: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + + if prev==p: return node + + prev = node + node = node.right + return None + + +""" +Inorder Traversal Template. +""" +def inOrderTraverse(root): + stack = [] + node = root + + while node or stack: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + + #do something + print node.val + + node = node.right \ No newline at end of file diff --git a/problems/same-tree.py b/problems/same-tree.py index e17c40c..57401db 100644 --- a/problems/same-tree.py +++ b/problems/same-tree.py @@ -21,3 +21,29 @@ def isSameTree(self, p, q): return False return True + +""" +Time: O(N) +Space: O(N) + +Use BFS to traverse the tree and represent the result as a string. +Note that null node still need to be shown in the string. +Because there are the same val in the tree, and different tree may result in the same string. +""" +class Solution(object): + def isSameTree(self, p, q): + def getStr(node): + s = '' + q = collections.deque([node]) + + while q: + node = q.popleft() + if not node: + s += '#' + else: + s += str(node.val) + q.append(node.left) + q.append(node.right) + return s + + return getStr(p)==getStr(q) \ No newline at end of file diff --git a/problems/serialize-and-deserialize-binary-tree.py b/problems/serialize-and-deserialize-binary-tree.py new file mode 100644 index 0000000..9519b74 --- /dev/null +++ b/problems/serialize-and-deserialize-binary-tree.py @@ -0,0 +1,42 @@ +class Codec: + + def serialize(self, root): + if not root: return '' + q = collections.deque([root]) + s = '' + while q: + node = q.popleft() + + if node: + s += str(node.val) + q.append(node.left) + q.append(node.right) + else: + s += '#' + s += ',' + return s[:-1] + + + def deserialize(self, data): + if not data: return None + + data = data.split(',') + root = TreeNode(data[0]) + q = collections.deque([root]) + i = 1 + + while q and i=len(data): continue + if data[i]!='#': + node.right = TreeNode(data[i]) + q.append(node.right) + i += 1 + + return root \ No newline at end of file From c6c84d96df38801efee160773ceeb61aae17a69d Mon Sep 17 00:00:00 2001 From: wuduhren Date: Wed, 6 Oct 2021 07:24:25 +0800 Subject: [PATCH 127/187] no message --- ...earch-tree-to-sorted-doubly-linked-list.py | 60 ++++++++++++++++++- problems/largest-bst-subtree.py | 22 +++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 problems/largest-bst-subtree.py diff --git a/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py b/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py index 36ea609..cfd441f 100644 --- a/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py +++ b/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py @@ -43,4 +43,62 @@ def helper(node, hook_left=True): root.left = right_most right_most.right = root - return root \ No newline at end of file + return root + + + + + +""" +Time: O(N) +Space: O(LogN) if the tree is balanced. + +Do an inorder traversal and link the node.left to the prev and prev.right to node. +""" +class Solution(object): + def treeToDoublyList(self, root): + if not root: return root + + stack = [] + node = root + preHead = Node(-1) + prev = preHead + + while node or stack: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + + prev.right = node + node.left = prev + + prev = node + + node = node.right + + head = preHead.right + head.left = prev + prev.right = head + + return head + +""" +FYI +""" +def inOrderTraverse(root): + stack = [] + node = root + + while node or stack: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + + #do something + print node.val + + node = node.right \ No newline at end of file diff --git a/problems/largest-bst-subtree.py b/problems/largest-bst-subtree.py new file mode 100644 index 0000000..82afb93 --- /dev/null +++ b/problems/largest-bst-subtree.py @@ -0,0 +1,22 @@ +""" +Time: O(N) for recursively traverse each node once. +Space: O(LogN) for recursive stack. +""" +class Solution(object): + def largestBSTSubtree(self, root): + def helper(node, minVal, maxVal): + if not node: return True, 0, float('-inf'), float('inf') + if not node.left and not node.right: return True, 1, node.val, node.val + + isLeftBST, leftSize, leftMin, leftMax = helper(node.left, minVal, node.val) + isRightBST, rightSize, rightMin, rightMax = helper(node.right, node.val, maxVal) + + currMin = min(leftMin, rightMin, node.val) + currMax = max(leftMax, rightMax, node.val) + + if isLeftBST and isRightBST and leftMax Date: Fri, 8 Oct 2021 07:40:02 +0800 Subject: [PATCH 128/187] no message --- ...ign-add-and-search-words-data-structure.py | 35 ++++++++++ problems/implement-trie-prefix-tree.py | 46 +++++++++++++ problems/range-sum-query-mutable.py | 67 +++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 problems/design-add-and-search-words-data-structure.py create mode 100644 problems/implement-trie-prefix-tree.py create mode 100644 problems/range-sum-query-mutable.py diff --git a/problems/design-add-and-search-words-data-structure.py b/problems/design-add-and-search-words-data-structure.py new file mode 100644 index 0000000..4b0d71f --- /dev/null +++ b/problems/design-add-and-search-words-data-structure.py @@ -0,0 +1,35 @@ +class Node(object): + def __init__(self, char): + self.char = char + self.children = {} + +class WordDictionary(object): + + def __init__(self): + self.root = Node('') + self.endSign = ';' + + def addWord(self, word): + word = word + self.endSign + node = self.root + for c in word: + if c not in node.children: + node.children[c] = Node(c) + node = node.children[c] + + def search(self, word): + word = word + self.endSign + return self.searchFromNode(self.root, word) + + def searchFromNode(self, node, word): + if not word: return True + + char = word[0] + if char in node.children: + return self.searchFromNode(node.children[char], word[1:]) + elif char=='.': + for c in node.children: + if self.searchFromNode(node.children[c], word[1:]): + return True + return False + \ No newline at end of file diff --git a/problems/implement-trie-prefix-tree.py b/problems/implement-trie-prefix-tree.py new file mode 100644 index 0000000..fd64dd7 --- /dev/null +++ b/problems/implement-trie-prefix-tree.py @@ -0,0 +1,46 @@ +""" +Time for insert() O(N), search() O(N), startsWith() O(N). N is the number of characters. +Space for insert() O(N), search() O(1), startsWith() O(1). N is the number of characters. + +Use . to represent the end of a string. +""" +class Node(object): + def __init__(self, char): + self.char = char + self.children = {} + +class Trie(object): + + def __init__(self): + self.period = '.' + self.root = Node('') + + + def insert(self, word): + word = word + self.period + node = self.root + + for c in word: + if c not in node.children: + node.children[c] = Node(c) + node = node.children[c] + + + def search(self, word): + word = word + self.period + node = self.root + + for c in word: + if c not in node.children: + return False + node = node.children[c] + return True + + + def startsWith(self, prefix): + node = self.root + for c in prefix: + if c not in node.children: + return False + node = node.children[c] + return True \ No newline at end of file diff --git a/problems/range-sum-query-mutable.py b/problems/range-sum-query-mutable.py new file mode 100644 index 0000000..2502a15 --- /dev/null +++ b/problems/range-sum-query-mutable.py @@ -0,0 +1,67 @@ +""" +Time: O(LogN) for all operations. +Space: O(N) for the segment tree. + +Build a segment tree from the array `nums`. Each node store the info of the segment in nums (from `node.start` to `node.end`) +And `node.val` is equal to sum from nums[start] to nums[end] +""" +class NumArray(object): + + def __init__(self, nums): + def buildSegmentTree(start, end): + if start>end: return None + node = Node(start, end) + + if start==end: + node.val = nums[end] + else: + node.left = buildSegmentTree(start, node.mid) + node.right = buildSegmentTree(node.mid+1, end) + node.val = (node.left.val if node.left else 0) + (node.right.val if node.right else 0) + + return node + + self.root = buildSegmentTree(0, len(nums)-1) + + + def update(self, i, val): + def helper(node, i, val): + if node.start==node.end==i: + node.val = val + return + + if node.mid Date: Wed, 13 Oct 2021 07:30:34 +0800 Subject: [PATCH 129/187] no message --- problems/partition-to-k-equal-sum-subsets.py | 23 ++++++++++++++++++++ problems/permutations.py | 21 ++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/problems/partition-to-k-equal-sum-subsets.py b/problems/partition-to-k-equal-sum-subsets.py index 5d98491..13c2411 100644 --- a/problems/partition-to-k-equal-sum-subsets.py +++ b/problems/partition-to-k-equal-sum-subsets.py @@ -16,3 +16,26 @@ def search(subs): target = sum(nums)/k nums.sort() return search([0]*k) + + + +class Solution(object): + def canPartitionKSubsets(self, nums, k): + def dfs(currSum, k, s=0): + if k==0: return True + if currSum==target: return dfs(0, k-1) + + for i in xrange(s, N): + num = nums[i] + if not visited[i] and num+currSum<=target: + visited[i] = True + if dfs(currSum+num, k, i+1): return True + visited[i] = False + return False + + target, remain = divmod(sum(nums), k) + if remain>0: return False + + N = len(nums) + visited = [False]*N + return dfs(target, k) \ No newline at end of file diff --git a/problems/permutations.py b/problems/permutations.py index 6659d57..de065a4 100644 --- a/problems/permutations.py +++ b/problems/permutations.py @@ -27,3 +27,24 @@ def dfs(path, options): opt = [] dfs([], nums) return opt + + + + +""" +Time complexity: O(N!). Since in this example our choices is N at the beginning, then N-1, then N-2, then N-3... then 1. +Space complexity: O(N!). The recursion takes N level of recursion. + +For each `dfs()` we put the `n` in `remains` to the `path`, if there is no `remains`, add the `path` to the `ans`. +""" +class Solution(object): + def permute(self, nums): + def dfs(remains, path): + if not remains: ans.append(path) + + for i, n in enumerate(remains): + dfs(remains[:i]+remains[i+1:], path+[n]) + + ans = [] + dfs(nums, []) + return ans \ No newline at end of file From b744b8798d9ae91edbceff5e14c68dfe8964ba97 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Mon, 22 Nov 2021 10:24:12 +0800 Subject: [PATCH 130/187] no message --- .../all-nodes-distance-k-in-binary-tree.py | 40 +++++++++++++ .../analyze-user-website-visit-pattern.py | 44 +++++++++++++++ problems/combination-sum-ii.py | 24 ++++++++ problems/combination-sum-iii.py | 37 ++++++++++++ problems/combination-sum-iv.py | 44 ++++++++++++++- problems/combination-sum.py | 23 ++++++++ .../connecting-cities-with-minimum-cost.py | 38 +++++++++++++ problems/course-schedule-ii.py | 38 +++++++++++-- problems/design-tic-tac-toe.py | 52 +++++++++++++++++ .../flip-string-to-monotone-increasing.py | 20 +++++++ problems/generate-parentheses.py | 17 ++++++ problems/k-closest-points-to-origin.py | 15 +++++ ...ber-of-unique-integers-after-k-removals.py | 20 +++++++ ...m-number-of-events-that-can-be-attended.py | 25 +++++++++ problems/meeting-rooms-ii.py | 30 +++++++++- problems/minimum-cost-to-connect-sticks.py | 15 +++++ ...ected-components-in-an-undirected-graph.py | 28 ++++++++++ problems/number-of-provinces.py | 24 ++++++++ problems/number-of-squareful-arrays.py | 36 ++++++++++++ ...gs-with-total-durations-divisible-by-60.py | 10 ++++ problems/permutations-ii.py | 29 ++++++++++ problems/permutations.py | 26 +++++++++ problems/robot-bounded-in-circle.py | 28 ++++++++++ problems/search-suggestions-system.py | 40 +++++++++++++ .../sell-diminishing-valued-colored-balls.py | 25 +++++++++ problems/sum-of-subarray-minimums.py | 51 +++++++++++++++++ problems/the-kth-factor-of-n.py | 32 +++++++++++ problems/umber-of-islands-ii.py | 56 +++++++++++++++++++ 28 files changed, 859 insertions(+), 8 deletions(-) create mode 100644 problems/all-nodes-distance-k-in-binary-tree.py create mode 100644 problems/analyze-user-website-visit-pattern.py create mode 100644 problems/connecting-cities-with-minimum-cost.py create mode 100644 problems/design-tic-tac-toe.py create mode 100644 problems/flip-string-to-monotone-increasing.py create mode 100644 problems/k-closest-points-to-origin.py create mode 100644 problems/least-number-of-unique-integers-after-k-removals.py create mode 100644 problems/maximum-number-of-events-that-can-be-attended.py create mode 100644 problems/minimum-cost-to-connect-sticks.py create mode 100644 problems/number-of-connected-components-in-an-undirected-graph.py create mode 100644 problems/number-of-provinces.py create mode 100644 problems/number-of-squareful-arrays.py create mode 100644 problems/pairs-of-songs-with-total-durations-divisible-by-60.py create mode 100644 problems/robot-bounded-in-circle.py create mode 100644 problems/search-suggestions-system.py create mode 100644 problems/sell-diminishing-valued-colored-balls.py create mode 100644 problems/sum-of-subarray-minimums.py create mode 100644 problems/the-kth-factor-of-n.py create mode 100644 problems/umber-of-islands-ii.py diff --git a/problems/all-nodes-distance-k-in-binary-tree.py b/problems/all-nodes-distance-k-in-binary-tree.py new file mode 100644 index 0000000..77152e3 --- /dev/null +++ b/problems/all-nodes-distance-k-in-binary-tree.py @@ -0,0 +1,40 @@ +class Solution(object): + def distanceK(self, root, target, k): + graph = collections.defaultdict(list) + q = collections.deque([root]) #for traverse binary tree + q2 = collections.deque([(target, k)]) #for bfs the graph + visited = set() #for bfs the graph + ans = [] + + #build graph + while q: + node = q.popleft() + + if node.left: + graph[node].append(node.left) + graph[node.left].append(node) + q.append(node.left) + + if node.right: + graph[node].append(node.right) + graph[node.right].append(node) + q.append(node.right) + + + #bfs graph + while q2: + node, distance = q2.popleft() + if node.val in visited: continue + visited.add(node.val) + if distance==0: ans.append(node.val) + if distance<0 or distance>k: continue + + for nei in graph[node]: + q2.append((nei, distance-1)) + + return ans + + + + + \ No newline at end of file diff --git a/problems/analyze-user-website-visit-pattern.py b/problems/analyze-user-website-visit-pattern.py new file mode 100644 index 0000000..9ad4787 --- /dev/null +++ b/problems/analyze-user-website-visit-pattern.py @@ -0,0 +1,44 @@ +class Solution(object): + def mostVisitedPattern(self, usernames, timestamps, websites): + + data = [] + history = collections.defaultdict(list) + counter = collections.Counter() + maxCount = 0 + + for i in xrange(len(usernames)): + username = usernames[i] + timestamp = timestamps[i] + website = websites[i] + data.append((timestamp, website, username)) + + data = sorted(data) + + for _, website, username in data: + history[username].append(website) + + for username in history: + for comb in self.getCombination(history[username]): + counter[comb] += 1 + maxCount = max(maxCount, counter[comb]) + + for comb in sorted(counter.keys()): + if counter[comb]==maxCount: return comb + + def getCombination(self, websites): + def helper(comb, i): + if len(comb)==3: + combs.add(tuple(comb[:])) + elif len(comb)>3 or i>=len(websites): + return + else: + helper(comb+[websites[i]], i+1) + helper(comb[:], i+1) + + combs = set() + helper([], 0) + return combs + + + + \ No newline at end of file diff --git a/problems/combination-sum-ii.py b/problems/combination-sum-ii.py index 68f7f48..dd62374 100644 --- a/problems/combination-sum-ii.py +++ b/problems/combination-sum-ii.py @@ -54,3 +54,27 @@ def dfs(index, target, path): candidates.sort() dfs(0, T, []) return opt + + +class Solution(object): + def combinationSum2(self, candidates, target): + def helper(remain, comb, start): + if remain==0: + ans.append(comb[:]) + elif remain<0: + return + else: + for i in xrange(start, len(candidates)): + if i>start and candidates[i]==candidates[i-1]: continue + candidate = candidates[i] + comb.append(candidate) + helper(remain-candidate, comb, i+1) + comb.pop() + + ans = [] + candidates.sort() + helper(target, [], 0) + return ans + + + \ No newline at end of file diff --git a/problems/combination-sum-iii.py b/problems/combination-sum-iii.py index c5fa010..d5fccc1 100644 --- a/problems/combination-sum-iii.py +++ b/problems/combination-sum-iii.py @@ -38,3 +38,40 @@ def dfs(path, min_num): dfs([], 1) return opt + + +""" +Use a helper to check the remain. +comb is the combination to sum up to remain. +k is the max length of comb. +start is the starting index of "nums", since we already explore the all the possible comb from previous index. + +Time: O(9!/(9-k)! * k), 9*8*7... for k times. And each ans takes O(k) to copy the comb list. +Space: O(k) +""" +class Solution(object): + def combinationSum3(self, k, n): + def helper(remain, comb, k, start): + if remain==0 and len(comb)==k: + ans.append(comb[:]) + elif remain<0 or len(comb)>k: + return + else: + for i in xrange(start, len(nums)): + used = nums[i] + num = i+1 + + if used: continue + + comb.append(num) + nums[i] = True + + helper(remain-num, comb, k, i+1) + + comb.pop() + nums[i] = False + + nums = [False]*9 + ans = [] + helper(n, [], k, 0) + return ans \ No newline at end of file diff --git a/problems/combination-sum-iv.py b/problems/combination-sum-iv.py index 9aa59b3..88bc853 100644 --- a/problems/combination-sum-iv.py +++ b/problems/combination-sum-iv.py @@ -21,4 +21,46 @@ def helper(t): """ Time: O(TN), T is the value of target and N is the count of nums. Space: O(T) -""" \ No newline at end of file +""" + + +""" +dp[n] := number of combs sums up to n + +For example, lets say target is 32 and nums is [4,2,1]. +dp[32] = dp[28]+dp[30]+dp[31] +Since the combs of dp[28] adds 4 will all equals to 32. +Since the combs of dp[30] adds 2 will all equals to 32. +Since the combs of dp[31] adds 1 will all equals to 32. + +... + +dp[28] = dp[24]+dp[26]+dp[27] +Since the combs of dp[28] adds 4 will all equals to 24. +Since the combs of dp[28] adds 2 will all equals to 26. +Since the combs of dp[28] adds 1 will all equals to 27. + +... + + + +Time: O(TN), T is the value of target and N is the count of nums. +Space: O(T) +""" +class Solution(object): + def combinationSum4(self, nums, target): + dp = [0]*(target+1) + dp[0] = 1 + + t = 1 + + while t<=target: + combs = 0 + for num in nums: + if t-num<0: continue + combs += dp[t-num] + + dp[t] = combs + t += 1 + + return dp[target] \ No newline at end of file diff --git a/problems/combination-sum.py b/problems/combination-sum.py index 423f3c1..c76cc6a 100644 --- a/problems/combination-sum.py +++ b/problems/combination-sum.py @@ -118,3 +118,26 @@ def dfs(index, target, path): candidates.sort() dfs(0, T, []) return opt + + +""" +Time: O(N^(T/M)), N is the number of candidates. T is target. M is min(candidates). +Space: O(T/M) +""" +class Solution(object): + def combinationSum(self, candidates, target): + def helper(remain, comb, start=0): + if remain==0: + ans.append(comb[:]) + elif remain<0: + return + elif remain>0: + for i in xrange(start, len(candidates)): + candidate = candidates[i] + comb.append(candidate) + helper(remain-candidate, comb, i) + comb.pop() + + ans = [] + helper(target, []) + return ans \ No newline at end of file diff --git a/problems/connecting-cities-with-minimum-cost.py b/problems/connecting-cities-with-minimum-cost.py new file mode 100644 index 0000000..50a04e5 --- /dev/null +++ b/problems/connecting-cities-with-minimum-cost.py @@ -0,0 +1,38 @@ +class Solution(object): + def minimumCost(self, N, connections): + def union(n1, n2): + p1 = find(n1) + p2 = find(n2) + + if p1==p2: return False + + if ranks[p1]>ranks[p2]: + parents[p2] = p1 + ranks[p1] += 1 + else: + parents[p1] = p2 + ranks[p2] += 1 + return True + + def find(n): + p = parents[n] + while p!=parents[p]: p = find(p) + parents[n] = p + return p + + if not connections: return 0 + + parents = [n for n in xrange(N+1)] + ranks = [0]*(N+1) + totalCost = 0 + count = N # the count of nodes not yet union + + # sort by cost, union the ones with less cost first + sortedConnections = sorted([(cost, x, y) for x, y, cost in connections]) + + for cost, x, y in sortedConnections: + if union(x, y): + totalCost += cost + count -= 1 + + return totalCost if count==1 else -1 \ No newline at end of file diff --git a/problems/course-schedule-ii.py b/problems/course-schedule-ii.py index 9715692..a7c139f 100644 --- a/problems/course-schedule-ii.py +++ b/problems/course-schedule-ii.py @@ -35,16 +35,42 @@ def findOrder(self, numCourses, prerequisites): We can use it to know which node comes after which or detect cycles. The algorithm is easy to understand. First, we build the adjacent list (`graph`) and count all the inbound of the node. -Then we start from the node whose inbound count is 0, adding it in to the `q`. -For every node we pop out from `q` +Then we start from the node whose inbound count is 0, adding it in to the `pq` (priority queue). +For every node we pop out from `pq` * We remove the node's outbound by decrease 1 on all its neighbor's inbound. - * Put the node's neighbor to `q` if it has no inbound - * Put the node into the `order` + * Put the node's neighbor to `pq` if it has no inbound + * Put the node into the `sortedNodes` Repeat the process until there is no more node. -The order in the `order` is the order we are going to encounter when we run through the directed graph. +The order in the `sortedNodes` is the order we are going to encounter when we run through the directed graph. If we cannot sort all the nodes in the graph, it means that there are some nodes we couldn't find its starting point, in other words, there are cycles in the graph. Time: O(E+2V) ~= O(E+V) we used O(E) to build the graph #[1], O(V) to find the starting point #[2], then traverse all the nodes again #[3]. Space: O(E+3V) ~= O(E+V), O(E+V) for the adjacent list. O(V) for the `q`, O(V) for the `q_next`. -""" \ No newline at end of file +""" +class Solution(object): + def findOrder(self, numCourses, prerequisites): + graph = collections.defaultdict(list) + inbounds = collections.defaultdict(int) + pq = collections.deque() + sortedNodes = [] + + for c1, c2 in prerequisites: + graph[c2].append(c1) + inbounds[c1]+=1 + + for node in xrange(numCourses): + if inbounds[node]==0: + pq.append(node) + + while pq: + node = pq.popleft() + + for nei in graph[node]: + inbounds[nei] -= 1 + if inbounds[nei]==0: + pq.append(nei) + sortedNodes.append(node) + + return sortedNodes if len(sortedNodes)==numCourses else [] + \ No newline at end of file diff --git a/problems/design-tic-tac-toe.py b/problems/design-tic-tac-toe.py new file mode 100644 index 0000000..5e72cda --- /dev/null +++ b/problems/design-tic-tac-toe.py @@ -0,0 +1,52 @@ +""" +Time: O(1) for move(). +Space: O(N). + +We need to find a way to quikly check if the player wins after the move. +Checking the whole map row by row or column by column will take a lots of time. +What we do instead is to record the count of the placement for each row and colomn. Also the count of topright-bottomleft, topleft-bottomright placement. +So if any of the count adds up to n, the player wins. + +self.records[0] stores player1's record. +self.records[1] stores player2's record. + +For player1's record (self.records[0]), +record[0][row] stores the placement count of the row for player1. +record[1][col] stores the placement count of the col for player1. +record[2] stores the topright-bottomleft placement count for player1. +record[3] stores the topleft-bottomright placement count for player1. + +For player2's record (self.records[1]), +record[0][row] stores the placement count of the row for player2. +record[1][col] stores the placement count of the col for player2. +record[2] stores the topright-bottomleft placement count for player2. +record[3] stores the topleft-bottomright placement count for player2. + +Note that, when checkRecord() we only need to check the (row, col) we just placed. +So we can achieve O(1) in time. +""" +class TicTacToe(object): + + def __init__(self, n): + self.records = [[[0]*n, [0]*n, 0, 0], [[0]*n, [0]*n, 0, 0]] + self.n = n + + + def move(self, row, col, player): + record = self.records[player-1] + record[0][row] += 1 + record[1][col] += 1 + if row==col: record[2] += 1 + if row+col==self.n-1: record[3] += 1 + + if self.checkRecord(record, row, col): return player + + return 0 + + def checkRecord(self, record, row, col): + if record[0][row]==self.n: return True + if record[1][col]==self.n: return True + if record[2]==self.n: return True + if record[3]==self.n: return True + + return False \ No newline at end of file diff --git a/problems/flip-string-to-monotone-increasing.py b/problems/flip-string-to-monotone-increasing.py new file mode 100644 index 0000000..ec2b0df --- /dev/null +++ b/problems/flip-string-to-monotone-increasing.py @@ -0,0 +1,20 @@ +""" +dp[i][0] := min number of flips to form monotone string that ends s[:i] at 0 +dp[i][1] := min number of flips to form monotone string that ends s[:i] at 1 + +Time: O(N) +Space: O(N), can further deduce to O(1) +""" +class Solution(object): + def minFlipsMonoIncr(self, s): + dp = [[0, 0] for _ in xrange(len(s)+1)] + + for i, c in enumerate(s): + if c=='0': + dp[i+1][0] = dp[i][0] + dp[i+1][1] = min(dp[i][0], dp[i][1]) + 1 + elif c=='1': + dp[i+1][0] = dp[i][0] + 1 + dp[i+1][1] = min(dp[i][0], dp[i][1]) + + return min(dp[-1]) \ No newline at end of file diff --git a/problems/generate-parentheses.py b/problems/generate-parentheses.py index b2d5b70..cadbe96 100644 --- a/problems/generate-parentheses.py +++ b/problems/generate-parentheses.py @@ -34,3 +34,20 @@ def helper(open_remain, close_remain, s): ans = [] helper(N, N, '') return ans + +""" +Time: O(2^N) +Space: O(N) +""" +class Solution(object): + def generateParenthesis(self, n): + def helper(curr, openCount, left, right): + if left==0 and right==0: ans.append(curr) + if left>0: + helper(curr+'(', openCount+1, left-1, right) + if right>0 and openCount>0: + helper(curr+')', openCount-1, left, right-1) + + ans = [] + helper('', 0, n, n) + return ans \ No newline at end of file diff --git a/problems/k-closest-points-to-origin.py b/problems/k-closest-points-to-origin.py new file mode 100644 index 0000000..8af9889 --- /dev/null +++ b/problems/k-closest-points-to-origin.py @@ -0,0 +1,15 @@ +class Solution(object): + def kClosest(self, points, k): + h = [] + + for x, y in points: + d = (x**2+y**2)**0.5 + if len(h)>=k and -h[0][0]>d: + heapq.heappop(h) + heapq.heappush(h, (-d, x, y)) + elif len(h)>=k and -h[0][0]<=d: + pass + else: + heapq.heappush(h, (-d, x, y)) + + return [(x, y) for _, x, y in h] \ No newline at end of file diff --git a/problems/least-number-of-unique-integers-after-k-removals.py b/problems/least-number-of-unique-integers-after-k-removals.py new file mode 100644 index 0000000..ec69576 --- /dev/null +++ b/problems/least-number-of-unique-integers-after-k-removals.py @@ -0,0 +1,20 @@ +""" +Time: Build counter takes O(N). Build heap takes O(NLogN). Last operation takes O(KLogN). +Since N>k, O(N+NLogN+KLogN) ~= O(NLogN) + +Space: O(N) +""" +class Solution(object): + def findLeastNumOfUniqueInts(self, nums, k): + counter = collections.Counter(nums) + h = [] + + for num in counter: + heapq.heappush(h, (counter[num], num)) + + for _ in xrange(k): + count, num = heapq.heappop(h) + count -= 1 + if count>0: heapq.heappush(h, (count, num)) + + return len(h) \ No newline at end of file diff --git a/problems/maximum-number-of-events-that-can-be-attended.py b/problems/maximum-number-of-events-that-can-be-attended.py new file mode 100644 index 0000000..087489d --- /dev/null +++ b/problems/maximum-number-of-events-that-can-be-attended.py @@ -0,0 +1,25 @@ +""" +Time: O(NLogN). Sort the event takes O(NLogN). Each event will get push in and pop out the heap: O(NLogN) +Space: O(N) +""" +class Solution(object): + def maxEvents(self, A): + d = 0 + count = 0 + h = [] #a heap. store the started event + A.sort(reverse=True) + + #for each day, attend the event with smallest endtime, so we can have the most free time in the future. + while A or h: + if not h: d = A[-1][0] + + while A and A[-1][0]<=d: + heapq.heappush(h, A.pop()[1]) + + heapq.heappop(h) #attend the event with smallest endtime + count += 1 + d += 1 + + while h and h[0]=e0: heapq.heappop(h) + heapq.heappush(h, (e, s)) + ans = max(ans, len(h)) + + return ans \ No newline at end of file diff --git a/problems/minimum-cost-to-connect-sticks.py b/problems/minimum-cost-to-connect-sticks.py new file mode 100644 index 0000000..81cd617 --- /dev/null +++ b/problems/minimum-cost-to-connect-sticks.py @@ -0,0 +1,15 @@ +class Solution(object): + def connectSticks(self, sticks): + if not sticks or len(sticks)==1: return 0 + h = [] + + for n in sticks: + heapq.heappush(h, n) + + cost = 0 + while len(h)>1: + currSum = heapq.heappop(h)+heapq.heappop(h) + cost += currSum + heapq.heappush(h, currSum) + + return cost \ No newline at end of file diff --git a/problems/number-of-connected-components-in-an-undirected-graph.py b/problems/number-of-connected-components-in-an-undirected-graph.py new file mode 100644 index 0000000..872a62a --- /dev/null +++ b/problems/number-of-connected-components-in-an-undirected-graph.py @@ -0,0 +1,28 @@ +class Solution(object): + def countComponents(self, N, edges): + def dfs(start): + stack = [start] + + while stack: + node = stack.pop() + if node in visited: continue + visited.add(node) + + for nei in g[node]: + stack.append(nei) + + g = collections.defaultdict(list) + visited = set() + count = 0 + + for n1, n2 in edges: + g[n1].append(n2) + g[n2].append(n1) + + for n in xrange(N): + # print visited + if n in visited: continue + dfs(n) + count += 1 + + return count \ No newline at end of file diff --git a/problems/number-of-provinces.py b/problems/number-of-provinces.py new file mode 100644 index 0000000..a0edfd7 --- /dev/null +++ b/problems/number-of-provinces.py @@ -0,0 +1,24 @@ +class Solution(object): + def findCircleNum(self, isConnected): + def bfs(startNode): + q = collections.deque([startNode]) + + while q: + node = q.popleft() + if node in visited: continue + visited.add(node) + + for nei in xrange(N): + if nei!=node and isConnected[node][nei]==1: + q.append(nei) + + N = len(isConnected) + visited = set() + ans = 0 + + for node in xrange(N): + if node in visited: continue + bfs(node) #put all the nodes in the same province to visited + ans += 1 + + return ans \ No newline at end of file diff --git a/problems/number-of-squareful-arrays.py b/problems/number-of-squareful-arrays.py new file mode 100644 index 0000000..b27fdd6 --- /dev/null +++ b/problems/number-of-squareful-arrays.py @@ -0,0 +1,36 @@ +""" +Time: O(N!) +Space: O(N!) + +Create a helper function: +If there is no remains, ans += 1 +Check the last num in the permutaion, last +For each num in remains see if it and the last sum to a square number +If true, call helper + +Also, if the number is the same as the previous one, skip it, since we already explore the number. +""" + +class Solution(object): + def __init__(self): + self.ans = 0 + + def numSquarefulPerms(self, nums): + def isSquare(num): + return int(math.sqrt(num))**2==num + + def helper(per, remains): + if not remains: self.ans += 1 + last = per[-1] + + for i, n in enumerate(remains): + if i>0 and n==remains[i-1]: continue + if isSquare(last+n): + helper(per+[n], remains[:i]+remains[i+1:]) + + nums.sort() + for i, n in enumerate(nums): + if i>0 and n==nums[i-1]: continue + helper([nums[i]], nums[:i]+nums[i+1:]) + + return self.ans \ No newline at end of file diff --git a/problems/pairs-of-songs-with-total-durations-divisible-by-60.py b/problems/pairs-of-songs-with-total-durations-divisible-by-60.py new file mode 100644 index 0000000..d4d7fa6 --- /dev/null +++ b/problems/pairs-of-songs-with-total-durations-divisible-by-60.py @@ -0,0 +1,10 @@ +class Solution(object): + def numPairsDivisibleBy60(self, times): + counter = collections.Counter() + ans = 0 + + for time in times: + time = time%60 + ans += counter[60-time if time!=0 else 0] + counter[time] += 1 + return ans \ No newline at end of file diff --git a/problems/permutations-ii.py b/problems/permutations-ii.py index 89ba9ee..e4aa3c2 100644 --- a/problems/permutations-ii.py +++ b/problems/permutations-ii.py @@ -24,3 +24,32 @@ def dfs(path, options): nums.sort() dfs([], nums) return opt + + +""" +Time: O(N!) +Space: O(N!) + +Since we are iterating the key of the counter, we will only place "each kind of number" at the first place once. +For example, [1,1,2], it will not happend that +We place the first "1" at index 0, and keep exploring... +And place the second "1" at index 0, and keep exploring... +""" +class Solution(object): + def permuteUnique(self, nums): + def helper(path): + if len(path)==len(nums): ans.append(path[:]) + + for num in counter: + if counter[num]>0: + path.append(num) + counter[num] -= 1 + + helper(path) + + path.pop() + counter[num] += 1 + ans = [] + counter = collections.Counter(nums) + helper([]) + return ans diff --git a/problems/permutations.py b/problems/permutations.py index de065a4..bc27184 100644 --- a/problems/permutations.py +++ b/problems/permutations.py @@ -47,4 +47,30 @@ def dfs(remains, path): ans = [] dfs(nums, []) + return ans + + +""" +Time: O(N!) +Space: O(N!) + +helper(0) will set index 0 to all number. +helper(1) will set index 1 to all number remains. +helper(2) will set index 2 to all number remains. +helper(3) will set index 3 to all number remains. +... +""" +class Solution(object): + def permute(self, nums): + def helper(i): + if i>=N: ans.append(nums[:]) + + for j in xrange(i, N): + nums[i], nums[j] = nums[j], nums[i] + helper(i+1) + nums[i], nums[j] = nums[j], nums[i] + + N = len(nums) + ans = [] + helper(0) return ans \ No newline at end of file diff --git a/problems/robot-bounded-in-circle.py b/problems/robot-bounded-in-circle.py new file mode 100644 index 0000000..3eaa106 --- /dev/null +++ b/problems/robot-bounded-in-circle.py @@ -0,0 +1,28 @@ +class Solution(object): + def isRobotBounded(self, instructions): + direction = 0 + x = y = 0 + + for i in instructions: + if i=='L': + direction -= 1 + direction = direction%4 + elif i=='R': + direction += 1 + direction = direction%4 + elif i=='G': + if direction==0: + y+=1 + elif direction==1: + x+=1 + elif direction==2: + y-=1 + elif direction==3: + x-=1 + + moved = (x, y) != (0, 0) + rotated = direction!=0 + + if not moved: return True + if moved and rotated: return True + if moved and not rotated: return False \ No newline at end of file diff --git a/problems/search-suggestions-system.py b/problems/search-suggestions-system.py new file mode 100644 index 0000000..aa58bcf --- /dev/null +++ b/problems/search-suggestions-system.py @@ -0,0 +1,40 @@ +class Node(object): + def __init__(self, c): + self.c = c + self.nexts = {} + +class Solution(object): + def suggestedProducts(self, products, searchWord): + ans = [] + root = Node('') + + #build trie + for product in products: + curr = root + for c in product+'.': + if c not in curr.nexts: + curr.nexts[c] = Node(c) + curr = curr.nexts[c] + + # search top3 for each prefix + curr = root + for i, c in enumerate(searchWord): + if c not in curr.nexts: break + curr = curr.nexts[c] + ans.append(self.getTop3(searchWord[:i+1], curr)) + + ans += [[] for _ in xrange(len(searchWord)-len(ans))] + return ans + + def getTop3(self, prefix, node): + def helper(prefix, node): + if len(top3)>=3: return + if '.' in node.nexts: top3.append(prefix) + + for c in 'abcdefghijklmnopqrstuvwxyz': + if c in node.nexts: + helper(prefix+c, node.nexts[c]) + + top3 = [] + helper(prefix, node) + return top3 \ No newline at end of file diff --git a/problems/sell-diminishing-valued-colored-balls.py b/problems/sell-diminishing-valued-colored-balls.py new file mode 100644 index 0000000..e871597 --- /dev/null +++ b/problems/sell-diminishing-valued-colored-balls.py @@ -0,0 +1,25 @@ +class Solution(object): + def maxProfit(self, I, orders): + I.sort(reverse=True) + I.append(0) + + profit = 0 + w = 1 + + for i in xrange(len(I)-1): + if orders==0: break + if I[i]>I[i+1]: + if w*(I[i]-I[i+1])=0 and uf.isLand((x-1)*n+y)): connected.append((x-1)*n+y) + if (x+1=0 and uf.isLand(x*n+y-1)): connected.append(x*n+y-1) + if (y+1=0 + + def setLand(self, i): + self.parents[i] = i + self.count += 1 + + def find(self, i): + if self.parents[i]!=i: self.parents[i] = self.find(self.parents[i]) + return self.parents[i] + + def union(self, i1, i2): + parent1 = self.find(i1) + parent2 = self.find(i2) + + if parent1!=parent2: + if self.ranks[parent1]>self.ranks[parent2]: + self.parents[parent2] = parent1 + elif self.ranks[parent1] Date: Sun, 28 Nov 2021 14:21:11 +0800 Subject: [PATCH 131/187] no message --- ...-stones-removed-with-same-row-or-column.py | 49 ++++++++++++++++++ problems/network-delay-time.py | 49 ++++++++++++++++++ ...ected-components-in-an-undirected-graph.py | 24 ++++++++- problems/number-of-islands-ii.py | 50 +++++++++++++++++++ 4 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 problems/most-stones-removed-with-same-row-or-column.py create mode 100644 problems/number-of-islands-ii.py diff --git a/problems/most-stones-removed-with-same-row-or-column.py b/problems/most-stones-removed-with-same-row-or-column.py new file mode 100644 index 0000000..b10b373 --- /dev/null +++ b/problems/most-stones-removed-with-same-row-or-column.py @@ -0,0 +1,49 @@ +""" +Max stones can be remove = number of stones - number of groups +The stone in the same group has the same row or col with any stone in the group. +Since finding stones in the same group will take O(N^2) +Instead, we union the row or col itself. + +So initially each col (c1, c2...) and row (r1, r2...)'s parent is itself. +We iterate through the stones and union the col and row. +For example, the stone (1, 2) will union r2 and c1. +the stone (0, 3) will union r3 and c0. +... + +This way, we can also get the number of groups. + +See better explanation in https://www.youtube.com/watch?v=beOCN7G4h-M + +Time: O(N). +Space: O(N) +""" +class Solution(object): + def removeStones(self, stones): + def union(x, y): + row = 'r'+str(x) + col = 'c'+str(y) + p1 = find(row) + p2 = find(col) + if p1==p2: return False + parents[p2] = p1 + return True + + def find(c): + p = parents[c] + while p!=parents[p]: + p = find(p) + parents[c] = p + return p + + parents = {} + for x, y in stones: + row = 'r'+str(x) + col = 'c'+str(y) + parents[row] = row + parents[col] = col + + groupCount = len(parents) + for x, y in stones: + if union(x, y): groupCount -= 1 + + return len(stones)-groupCount \ No newline at end of file diff --git a/problems/network-delay-time.py b/problems/network-delay-time.py index 89d9195..8098a31 100644 --- a/problems/network-delay-time.py +++ b/problems/network-delay-time.py @@ -78,3 +78,52 @@ def networkDelayTime(self, times, N, K): return -1 + + + + + + +class Solution(object): + def networkDelayTime(self, times, n, k): + G = collections.defaultdict(list) #adjacency list + D = [float('inf')]*(n+1) #D[n] store the distance between n and k + D[k] = 0 + h = [(0, k)] + visited = set() + + #form the djacency list + for u, v, w in times: + G[u].append((v, w)) + + #dijkstra + while h: + d1, node = heapq.heappop(h) + if node in visited: continue + visited.add(node) + + for nei, d2 in G[node]: + if d1+d2 Date: Wed, 1 Dec 2021 09:47:31 +0800 Subject: [PATCH 132/187] no message --- problems/cheapest-flights-within-k-stops.py | 33 +++++++++++++++++++ problems/maximum-average-subtree.py | 25 ++++++++++++++ .../minimum-swaps-to-group-all-1s-together.py | 30 +++++++++++++++++ problems/shortest-path-to-get-food.py | 29 ++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 problems/maximum-average-subtree.py create mode 100644 problems/minimum-swaps-to-group-all-1s-together.py create mode 100644 problems/shortest-path-to-get-food.py diff --git a/problems/cheapest-flights-within-k-stops.py b/problems/cheapest-flights-within-k-stops.py index f5e8f0c..a5733f3 100644 --- a/problems/cheapest-flights-within-k-stops.py +++ b/problems/cheapest-flights-within-k-stops.py @@ -66,3 +66,36 @@ def findCheapestPrice(self, n, flights, src, dst, K): return min_price if min_price!=float('inf') else -1 + +""" +Standard Dijkstra, except this time instead of only explore the ones with least price +We also need to explore the ones with less steps. So add stepFromSrc to check. + +Time: O(ELogE), since there will be at most E edges that get pushed into the heap. +Space: O(E) +""" +class Solution(object): + def findCheapestPrice(self, n, flights, src, dst, K): + priceFromSrc = {} + stepFromSrc = {} + h = [(0, 0, src)] + G = collections.defaultdict(list) + + #build graph + for s, d, p in flights: + G[s].append((d, p)) + + #dijkstra + while h: + price, k, node = heapq.heappop(h) + + if node==dst: return price + if k>K: continue + + for nei, price2 in G[node]: + if nei not in priceFromSrc or price+price2<=priceFromSrc[nei] or k=len(data): break + if data[j]==1: count += 1 + if data[i-1]==1: count -= 1 + maxCount = max(maxCount, count) + + return L-maxCount \ No newline at end of file diff --git a/problems/shortest-path-to-get-food.py b/problems/shortest-path-to-get-food.py new file mode 100644 index 0000000..d4ba792 --- /dev/null +++ b/problems/shortest-path-to-get-food.py @@ -0,0 +1,29 @@ +class Solution(object): + def getFood(self, grid): + q = collections.deque() + visited = set() + + for i in xrange(len(grid)): + for j in xrange(len(grid[0])): + if grid[i][j]=='*': + q.append((i, j, 0)) + break + while q: + i, j, steps = q.popleft() + + if not 0<=i Date: Mon, 6 Dec 2021 09:03:36 +0800 Subject: [PATCH 133/187] no message --- problems/cheapest-flights-within-k-stops.py | 1 + problems/consecutive-numbers-sum.py | 43 +++++++++++++++++++ problems/integer-to-english-words.py | 28 ++++++++++++ .../minimum-swaps-to-group-all-1s-together.py | 5 ++- 4 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 problems/consecutive-numbers-sum.py create mode 100644 problems/integer-to-english-words.py diff --git a/problems/cheapest-flights-within-k-stops.py b/problems/cheapest-flights-within-k-stops.py index a5733f3..28b2927 100644 --- a/problems/cheapest-flights-within-k-stops.py +++ b/problems/cheapest-flights-within-k-stops.py @@ -93,6 +93,7 @@ def findCheapestPrice(self, n, flights, src, dst, K): if k>K: continue for nei, price2 in G[node]: + #explore next destination with less price or less steps if nei not in priceFromSrc or price+price2<=priceFromSrc[nei] or kN: + s -= i + i += 1 + else: + s += j + j += 1 + return ans + + +#Math +class Solution(object): + def consecutiveNumbersSum(self, N): + ans = 0 + upperLimit = int((2 * N + 0.25)**0.5 - 0.5) + 2 + + for x in xrange(1, upperLimit): + if x%2==0: + if float(N)/x-N/x==0.5: + upper = N/x + x/2 + lower = N/x - x/2 + 1 + if 1<=lower and upper<=N: + ans += 1 + else: + if N%x==0: + upper = N/x + (x-1)/2 + lower = N/x - (x-1)/2 + if 1<=lower and upper<=N: + ans += 1 + return ans \ No newline at end of file diff --git a/problems/integer-to-english-words.py b/problems/integer-to-english-words.py new file mode 100644 index 0000000..a4e8d88 --- /dev/null +++ b/problems/integer-to-english-words.py @@ -0,0 +1,28 @@ +class Solution(object): + def numberToWords(self, num): + underTwenty = ['', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine', 'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen', ] + tens = ['', '', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety'] + + def toWords(n): + if n==0: + return [] + elif n<20: + return [underTwenty[n]] + elif n<100: + c, r = n/10, n%10 + return [tens[c]] + toWords(r) + elif n<1000: + c, r = n/100, n%100 + return toWords(c) + ['Hundred'] + toWords(r) + else: + if n>=1000000000: + c, r = n/1000000000, n%1000000000 + return toWords(c) + ['Billion'] + toWords(r) + elif n>=1000000: + c, r = n/1000000, n%1000000 + return toWords(c) + ['Million'] + toWords(r) + elif n>=1000: + c, r = n/1000, n%1000 + return toWords(c) + ['Thousand'] + toWords(r) + + return ' '.join(toWords(num)) or 'Zero' \ No newline at end of file diff --git a/problems/minimum-swaps-to-group-all-1s-together.py b/problems/minimum-swaps-to-group-all-1s-together.py index 714b457..0f44bc6 100644 --- a/problems/minimum-swaps-to-group-all-1s-together.py +++ b/problems/minimum-swaps-to-group-all-1s-together.py @@ -2,6 +2,9 @@ We know that, after swapping, the length of the continuous 1 will be equal to number of 1 in the data. Let's call it `L`. So what we need to do is sliding window with length L and see what is the max 1 count within the window. The window with max 1 count will need to do minimal swap. + +Time: O(N) +Space: O(1) """ class Solution(object): def minSwaps(self, data): @@ -10,7 +13,6 @@ def minSwaps(self, data): for num in data: if num==1: L += 1 - count = 0 #count of 1 within the sliding window maxCount = 0 #max count of 1 within the sliding window @@ -21,6 +23,7 @@ def minSwaps(self, data): #slide the window for i in xrange(1, len(data)): + #i: start index of the sliding window j = i+L-1 #end index of the sliding window if j>=len(data): break if data[j]==1: count += 1 From a20b61a56f8e6d7eb092ea1ba831e1d8f55a6e68 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sat, 11 Dec 2021 19:51:31 +0800 Subject: [PATCH 134/187] no message --- ...vert-sorted-array-to-binary-search-tree.py | 16 ++++- problems/design-in-memory-file-system.py | 46 +++++++++++++ problems/find-mode-in-binary-search-tree.py | 65 +++++++++++++------ problems/insert-into-a-binary-search-tree.py | 28 +++++++- 4 files changed, 130 insertions(+), 25 deletions(-) create mode 100644 problems/design-in-memory-file-system.py diff --git a/problems/convert-sorted-array-to-binary-search-tree.py b/problems/convert-sorted-array-to-binary-search-tree.py index 344d345..32bc6bf 100644 --- a/problems/convert-sorted-array-to-binary-search-tree.py +++ b/problems/convert-sorted-array-to-binary-search-tree.py @@ -49,4 +49,18 @@ def helper(i, j): if rightLength>0: node.right = helper(m+1, j) return node - return helper(0, len(nums)) \ No newline at end of file + return helper(0, len(nums)) + + + + +class Solution(object): + def sortedArrayToBST(self, nums): + def helper(s, e): + if s>e: return None + m = (s+e)/2 + node = TreeNode(nums[m]) + node.left = helper(s, m-1) + node.right = helper(m+1, e) + return node + return helper(0, len(nums)-1) \ No newline at end of file diff --git a/problems/design-in-memory-file-system.py b/problems/design-in-memory-file-system.py new file mode 100644 index 0000000..3e9d808 --- /dev/null +++ b/problems/design-in-memory-file-system.py @@ -0,0 +1,46 @@ +""" +self.dirs is a nested hashmap to store the file structure. +self.files is a hashmap, mainly used to determine if the path is a "file", also used to store the content of the file. + +Time: +ls O(K) +mkdir O(K) +addContentToFile O(K) +readContentFromFile O(1) +K is the path count, for example /a/b/c/d, K=4. + +Space: +O(N), N is the dir counts. +""" +class FileSystem(object): + + def __init__(self): + self.files = {} + self.dirs = {} + + def ls(self, path): + if path in self.files: + return [path.split('/')[-1]] + else: + if path=='/': return sorted(self.dirs.keys()) + curr = self.dirs + for d in path.split('/')[1:]: + curr = curr[d] + return sorted(curr.keys()) + + def mkdir(self, path): + curr = self.dirs + for d in path.split('/')[1:]: + if d not in curr: + curr[d] = {} + curr = curr[d] + + def addContentToFile(self, filePath, content): + if filePath not in self.files: + self.mkdir(filePath) + self.files[filePath] = content + else: + self.files[filePath] += content + + def readContentFromFile(self, filePath): + return self.files[filePath] \ No newline at end of file diff --git a/problems/find-mode-in-binary-search-tree.py b/problems/find-mode-in-binary-search-tree.py index 4705a77..b4d3aff 100644 --- a/problems/find-mode-in-binary-search-tree.py +++ b/problems/find-mode-in-binary-search-tree.py @@ -1,3 +1,8 @@ +""" +Time: O(N). For we traverse every node recursively. +Space: O(N). Becuase we store all element's val and count in `counter`. +Note that, we do not use the feature of BST. +""" from collections import Counter class Solution(object): def findMode(self, root): @@ -14,11 +19,21 @@ def count(node): return [val for val, count in counter.items() if count==max_count] """ -Time: O(N). For we traverse every node recursively. -Space: O(N). Becuase we store all element's val and count in `counter`. -Note that, we do not use the feature of BST. -""" +To use the feature of BST, we are going to inorder traverse the BST. +So it will be like we are iterating a sorted array. + +[1] +While iterating, we can put only the element count that is greater or equal than `max_count` to `ans`. +If we encounter a new element with larger `curr_count`, we reset the `ans`. +[0] +With the help of `prev_val` we can know that `curr_node` is the same to the previous or not. +If not, its a new element, we need to reset the `curr_count`. + +Time: O(N). Space: O(LogN) + +For better understanding, below is a template for inorder traverse. +""" class Solution(object): def findMode(self, root): if not root: return [] @@ -54,23 +69,6 @@ def findMode(self, root): return ans -""" -To use the feature of BST, we are going to inorder traverse the BST. -So it will be like we are iterating a sorted array. - -[1] -While iterating, we can put only the element count that is greater or equal than `max_count` to `ans`. -If we encounter a new element with larger `curr_count`, we reset the `ans`. - -[0] -With the help of `prev_val` we can know that `curr_node` is the same to the previous or not. -If not, its a new element, we need to reset the `curr_count`. - -Time: O(N). Space: O(LogN) - -For better understanding, below is a template for inorder traverse. -""" - #inorder traversal of BST def inorder_traverse(root): curr = root @@ -85,3 +83,28 @@ def inorder_traverse(root): print curr.val curr = curr.right + + + + +""" +Time: O(N) +Space: O(N) +""" +class Solution(object): + def findMode(self, root): + def helper(node): + if not node: return + counter[node.val] += 1 + counter['maxCount'] = max(counter['maxCount'], counter[node.val]) + helper(node.left) + helper(node.right) + + ans = [] + counter = collections.Counter() + helper(root) + for v in counter: + if v!='maxCount' and counter[v]==counter['maxCount']: + ans.append(v) + + return ans \ No newline at end of file diff --git a/problems/insert-into-a-binary-search-tree.py b/problems/insert-into-a-binary-search-tree.py index 2670175..9b3da5a 100644 --- a/problems/insert-into-a-binary-search-tree.py +++ b/problems/insert-into-a-binary-search-tree.py @@ -1,3 +1,7 @@ +""" +Time complexity: O(LogN) +Space complexity: O(1) +""" class Solution(object): def insertIntoBST(self, root, val): if not root: return TreeNode(val) @@ -19,8 +23,26 @@ def insertIntoBST(self, root, val): return None - """ Time complexity: O(LogN) -Space complexity: O(1) -""" \ No newline at end of file +Space complexity: O(LogN) +""" +class Solution(object): + def insertIntoBST(self, root, val): + def helper(node, val): + if not node: return + if val Date: Sat, 11 Dec 2021 20:42:50 +0800 Subject: [PATCH 135/187] no message --- problems/delete-node-in-a-bst.py | 68 +++++++++++++++---- .../minimum-absolute-difference-in-bst.py | 45 +++++++++++- problems/search-in-a-binary-search-tree.py | 18 ++++- 3 files changed, 112 insertions(+), 19 deletions(-) diff --git a/problems/delete-node-in-a-bst.py b/problems/delete-node-in-a-bst.py index de1101a..f1e0fe2 100644 --- a/problems/delete-node-in-a-bst.py +++ b/problems/delete-node-in-a-bst.py @@ -1,3 +1,23 @@ +""" +Find the parant and the node to be deleted. [0] +Deleting the node means replacing its reference by something else. [1] + +For the node to be deleted, if it only has no child, just remove it from the parent. Return None. [2] + +If it has one child, return the child. So its parent will directly connect to its child. [3] + +If it has both child. Update the node's val to the minimum value in the right subtree. Remove the minimum value node in the right subtree. [4] +This is equivalent to replacing the node by the minimum value node in the right subtree. +Another option is to replace the node by the maximum value node in the left subtree. + +Find the minimum value in the left subtree is easy. The leftest node value in the tree is the smallest. [5] + +Time Complexity: O(LogN). O(LogN) for finding the node to be deleted. +The recursive call in `remove()` will be apply to a much smaller subtree. And much smaller subtree... +So can be ignored. +Space complexity is O(LogN). Because the recursive call will at most be called LogN times. +N is the number of nodes. And LogN can be consider the height of the tree. +""" class Solution(object): def deleteNode(self, root, key): def find_min(root): @@ -39,23 +59,41 @@ def remove(node): return root -""" -Find the parant and the node to be deleted. [0] -Deleting the node means replacing its reference by something else. [1] -For the node to be deleted, if it only has no child, just remove it from the parent. Return None. [2] -If it has one child, return the child. So its parent will directly connect to its child. [3] -If it has both child. Update the node's val to the minimum value in the right subtree. Remove the minimum value node in the right subtree. [4] -This is equivalent to replacing the node by the minimum value node in the right subtree. -Another option is to replace the node by the maximum value node in the left subtree. +class Solution(object): + def deleteNode(self, node, key): + if not node: + return node + elif keynode.val: + node.right = self.deleteNode(node.right, key) + return node + elif key==node.val: + if not node.left and not node.right: + return None + elif not node.left: + return node.right + elif not node.right: + return node.left + else: + node.val = self.findMin(node.right) #min value in the right subtree + node.right = self.deleteNode(node.right, node.val) + return node + + def findMin(self, root): + ans = float('inf') + stack = [root] + + while stack: + node = stack.pop() + ans = min(ans, node.val) + if node.left: stack.append(node.left) + if node.right: stack.append(node.right) + return ans + -Find the minimum value in the left subtree is easy. The leftest node value in the tree is the smallest. [5] -Time Complexity: O(LogN). O(LogN) for finding the node to be deleted. -The recursive call in `remove()` will be apply to a much smaller subtree. And much smaller subtree... -So can be ignored. -Space complexity is O(LogN). Because the recursive call will at most be called LogN times. -N is the number of nodes. And LogN can be consider the height of the tree. -""" \ No newline at end of file diff --git a/problems/minimum-absolute-difference-in-bst.py b/problems/minimum-absolute-difference-in-bst.py index 4ab828c..2fe5f5b 100644 --- a/problems/minimum-absolute-difference-in-bst.py +++ b/problems/minimum-absolute-difference-in-bst.py @@ -43,4 +43,47 @@ def traverse(node): """ Time complexity: O(N) Space complexity: O(N) -""" \ No newline at end of file +""" + + +""" +Inorder traverse the BST and update the diff. +Time complexity: O(N) +Space complexity: O(N) +""" +class Solution(object): + def getMinimumDifference(self, root): + ans = float('inf') + + stack = [] + curr = root + prevVal = float('-inf') + + while stack or curr: + while curr: + stack.append(curr) + curr = curr.left + + curr = stack.pop() + ans = min(ans, curr.val-prevVal) + prevVal = curr.val + + curr = curr.right + return ans + + +def inorderTraversal(self, root): + stack = [] + curr = root + + while stack or curr: + while curr: + stack.append(curr) + curr = curr.left + + curr = stack.pop() + + # do something + print curr.val + + curr = curr.right \ No newline at end of file diff --git a/problems/search-in-a-binary-search-tree.py b/problems/search-in-a-binary-search-tree.py index 6fc233e..08f05d2 100644 --- a/problems/search-in-a-binary-search-tree.py +++ b/problems/search-in-a-binary-search-tree.py @@ -1,3 +1,7 @@ +""" +Time complexity: O(LogN) +Space complexity: O(1) +""" class Solution(object): def searchBST(self, root, val): node = root @@ -12,8 +16,16 @@ def searchBST(self, root, val): return None - """ Time complexity: O(LogN) -Space complexity: O(1) -""" \ No newline at end of file +Space complexity: O(LogN) +""" +class Solution(object): + def searchBST(self, node, val): + if not node: return None + if node.val==val: + return node + elif node.valval: + return self.searchBST(node.left, val) \ No newline at end of file From eca05c7091490f92b1b64e3dca97a8e031b5c016 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Wed, 22 Dec 2021 14:21:29 +0800 Subject: [PATCH 136/187] no message --- problems/alien-dictionary.py | 37 +++++++++++++++++ problems/remove-nth-node-from-end-of-list.py | 25 ++++++++++++ problems/rotate-image.py | 16 ++++++++ problems/spiral-matrix.py | 42 ++++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 problems/alien-dictionary.py create mode 100644 problems/remove-nth-node-from-end-of-list.py create mode 100644 problems/rotate-image.py create mode 100644 problems/spiral-matrix.py diff --git a/problems/alien-dictionary.py b/problems/alien-dictionary.py new file mode 100644 index 0000000..5c27918 --- /dev/null +++ b/problems/alien-dictionary.py @@ -0,0 +1,37 @@ +""" +Topological Sort +""" +class Solution(object): + def alienOrder(self, words): + #return true if cycles are detected. + def dfs(c): + if c in path: return True + if c in visited: return False + path.add(c) + for nei in adj[c]: + if dfs(nei): return True + res.append(c) + path.remove(c) + visited.add(c) + return False + + #build adjacency list + adj = {c: set() for word in words for c in word} + for i in xrange(len(words)-1): + w1, w2 = words[i], words[i+1] + minLen = min(len(w1), len(w2)) + if w1[:minLen]==w2[:minLen] and len(w1)>len(w2): return "" + + for j in xrange(minLen): + if w1[j]!=w2[j]: + adj[w1[j]].add(w2[j]) + break + + #topological sort + path = set() #path currently being reversed + visited = set() #done processing + res = [] + for c in adj: + if dfs(c): return "" + + return "".join(reversed(res)) \ No newline at end of file diff --git a/problems/remove-nth-node-from-end-of-list.py b/problems/remove-nth-node-from-end-of-list.py new file mode 100644 index 0000000..d92ddd7 --- /dev/null +++ b/problems/remove-nth-node-from-end-of-list.py @@ -0,0 +1,25 @@ +class Solution(object): + def removeNthFromEnd(self, head, n): + def getCount(node0): + curr = node0 + count = 0 + while curr: + curr = curr.next + count += 1 + return count + + def removeNext(node0): + nextNode = node0.next + if not nextNode: return + node0.next = nextNode.next + + k = getCount(head)-n-1 #need to "curr = curr.next" k times to reach the node that we can call removeNext(curr) + if k==-1: return head.next #remove head + + curr = head + while k>0: + k -= 1 + curr = curr.next + + removeNext(curr) + return head \ No newline at end of file diff --git a/problems/rotate-image.py b/problems/rotate-image.py new file mode 100644 index 0000000..59ce93c --- /dev/null +++ b/problems/rotate-image.py @@ -0,0 +1,16 @@ +class Solution(object): + def rotate(self, matrix): + N = len(matrix) + + #transpose + for i in xrange(N): + for j in xrange(N): + if j<=i: continue + matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] + + #reflect + for i in xrange(N): + for j in xrange(N/2): + matrix[i][j], matrix[i][N-1-j] = matrix[i][N-1-j], matrix[i][j] + + return matrix \ No newline at end of file diff --git a/problems/spiral-matrix.py b/problems/spiral-matrix.py new file mode 100644 index 0000000..96965d2 --- /dev/null +++ b/problems/spiral-matrix.py @@ -0,0 +1,42 @@ +class Solution(object): + def spiralOrder(self, matrix): + ans = [] + i, j = 0, 0 + direction = 'right' + count = 0 + + while count<=len(matrix)*len(matrix[0]): + iNext, jNext = i, j + + if direction=='right': + if j+1=0 and matrix[i][j-1]!='v': + jNext = j-1 + else: + direction = 'up' + elif direction=='up': + if i-1>=0 and matrix[i-1][j]!='v': + iNext = i-1 + else: + direction = 'right' + + if (iNext, jNext)!=(i, j) or count>=len(matrix)*len(matrix[0])-1: + ans.append(matrix[i][j]) + matrix[i][j] = 'v' #visited + count += 1 + i = iNext + j = jNext + + return ans[:-1] + + + \ No newline at end of file From 133c9bcefa5f6dc215307cd95afecf6bb487f468 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sun, 2 Jan 2022 11:01:00 +0800 Subject: [PATCH 137/187] no message --- ...ers-of-all-substrings-of-a-given-string.py | 18 ++++++ problems/decode-ways.py | 19 ++++++ ...longest-repeating-character-replacement.py | 23 +++++++ problems/maximum-product-subarray.py | 57 +++++++++++++++++ problems/maximum-units-on-a-truck.py | 17 ++++++ problems/pacific-atlantic-water-flow.py | 30 +++++++++ problems/palindromic-substrings.py | 61 +++++++++++++++++++ problems/search-suggestions-system.py | 61 ++++++++++++++++++- problems/set-matrix-zeroes.py | 35 +++++++++++ problems/unique-paths.py | 9 +++ problems/word-search-ii.py | 46 ++++++++++++++ 11 files changed, 375 insertions(+), 1 deletion(-) create mode 100644 problems/count-unique-characters-of-all-substrings-of-a-given-string.py create mode 100644 problems/decode-ways.py create mode 100644 problems/longest-repeating-character-replacement.py create mode 100644 problems/maximum-product-subarray.py create mode 100644 problems/maximum-units-on-a-truck.py create mode 100644 problems/pacific-atlantic-water-flow.py create mode 100644 problems/palindromic-substrings.py create mode 100644 problems/set-matrix-zeroes.py create mode 100644 problems/unique-paths.py diff --git a/problems/count-unique-characters-of-all-substrings-of-a-given-string.py b/problems/count-unique-characters-of-all-substrings-of-a-given-string.py new file mode 100644 index 0000000..fe58877 --- /dev/null +++ b/problems/count-unique-characters-of-all-substrings-of-a-given-string.py @@ -0,0 +1,18 @@ +class Solution(object): + def uniqueLetterString(self, s): + index = {} + ans = 0 + for c in 'abcdefghijklmnopqrstuvwxyz': + index[c.upper()] = [-1, -1] + + # count the substring that s[j] is the unique letter + for k, c in enumerate(s): + i, j = index[c] + ans += (j-i) * (k-j) + index[c] = [j, k] + + # count the substring that s[j] is the unique letter, because last iteration did not count the last letter + for c in index: + i, j = index[c] + ans += (j-i) * (len(s)-j) + return ans \ No newline at end of file diff --git a/problems/decode-ways.py b/problems/decode-ways.py new file mode 100644 index 0000000..82f4682 --- /dev/null +++ b/problems/decode-ways.py @@ -0,0 +1,19 @@ +""" +Time: O(N), due to the "memo", the time can reduce from O(2^N) to O(N). +Space: O(N) +""" +class Solution(object): + def numDecodings(self, s): + def helper(s, i): + if (s, i) in memo: return memo[(s, i)] + if i>=len(s): return 1 + if s[i]=='0': return 0 + + count = 0 + count += helper(s, i+1) + if len(s)-i>=2 and int(s[i:i+2])<=26: count += helper(s, i+2) + memo[(s, i)] = count + return count + + memo = {} + return helper(s, 0) \ No newline at end of file diff --git a/problems/longest-repeating-character-replacement.py b/problems/longest-repeating-character-replacement.py new file mode 100644 index 0000000..9546fb9 --- /dev/null +++ b/problems/longest-repeating-character-replacement.py @@ -0,0 +1,23 @@ +""" +Use the sliding window to iterate over the sub-strings. At the same time use a counter to track the count. +The operation needed is the (length of the window) - (count of the max count char in the counter) +Since there are at most 26 char in the counter, `max(counter.values())` can be view as a O(1) operation. + +Time: O(N) +Space: O(N) +""" +class Solution(object): + def characterReplacement(self, s, k): + counter = collections.Counter() + ans = 0 + + l = 0 + for r in xrange(len(s)): + counter[s[r]] += 1 + + while r-l+1-max(counter.values())>k: + counter[s[l]] -= 1 + l += 1 + + ans = max(ans, r-l+1) + return ans \ No newline at end of file diff --git a/problems/maximum-product-subarray.py b/problems/maximum-product-subarray.py new file mode 100644 index 0000000..b48bf12 --- /dev/null +++ b/problems/maximum-product-subarray.py @@ -0,0 +1,57 @@ +""" +Time: O(N) +Space: O(N) + +dp[i][0] := the maximum subarray product that includes nums[i] +dp[i][1] := the minimum subarray product that includes nums[i] +""" +class Solution(object): + def maxProduct(self, nums): + if not nums: return 0 + dp = [[float('-inf'), float('inf')] for _ in xrange(len(nums))] + + dp[0] = [nums[0], nums[0]] + ans = nums[0] + + for i in xrange(1, len(nums)): + if nums[i]==0: + dp[i][0] = 0 + dp[i][1] = 0 + elif nums[i]>0: + dp[i][0] = dp[i-1][0]*nums[i] if dp[i-1][0]>0 else nums[i] + dp[i][1] = dp[i-1][1]*nums[i] if dp[i-1][1]<=0 else nums[i] + else: + dp[i][0] = dp[i-1][1]*nums[i] if dp[i-1][1]<=0 else nums[i] + dp[i][1] = dp[i-1][0]*nums[i] if dp[i-1][0]>0 else nums[i] + + ans = max(ans, dp[i][0]) + + return ans + +""" +The above solution can further reduce the space complexity to O(1). +""" +class Solution(object): + def maxProduct(self, nums): + if not nums: return 0 + + maxLast = nums[0] + minLast = nums[0] + ans = nums[0] + + for i in xrange(1, len(nums)): + if nums[i]==0: + newMax = 0 + newMin = 0 + elif nums[i]>0: + newMax = maxLast*nums[i] if maxLast>0 else nums[i] + newMin = minLast*nums[i] if minLast<=0 else nums[i] + else: + newMax = minLast*nums[i] if minLast<=0 else nums[i] + newMin = maxLast*nums[i] if maxLast>0 else nums[i] + + maxLast = newMax + minLast = newMin + ans = max(ans, maxLast) + + return ans \ No newline at end of file diff --git a/problems/maximum-units-on-a-truck.py b/problems/maximum-units-on-a-truck.py new file mode 100644 index 0000000..4e0ce10 --- /dev/null +++ b/problems/maximum-units-on-a-truck.py @@ -0,0 +1,17 @@ +class Solution(object): + def maximumUnits(self, boxTypes, truckSize): + sortedBox = [] + ans = 0 + + for count, units in boxTypes: + sortedBox.append((units, count)) + + sortedBox.sort() + + while sortedBox and truckSize>0: + units, count = sortedBox.pop() + d = min(count, truckSize) + truckSize -= d + ans += d*units + + return ans \ No newline at end of file diff --git a/problems/pacific-atlantic-water-flow.py b/problems/pacific-atlantic-water-flow.py new file mode 100644 index 0000000..15186ff --- /dev/null +++ b/problems/pacific-atlantic-water-flow.py @@ -0,0 +1,30 @@ +class Solution(object): + def pacificAtlantic(self, heights): + def bfs(q, ocian): + while q: + i0, j0 = q.popleft() + if (i0, j0) in ocian: continue + ocian.add((i0, j0)) + + for i, j in [(i0+1, j0), (i0-1, j0), (i0, j0+1), (i0, j0-1)]: + if i>=len(heights) or i<0 or j>=len(heights[0]) or j<0: continue + if heights[i][j]>=heights[i0][j0]: q.append((i, j)) + + pacific = set() + altalantic = set() + q1 = collections.deque() + q2 = collections.deque() + + #add top, left to pacific + for j in xrange(len(heights[0])): q1.append((0, j)) + for i in xrange(len(heights)): q1.append((i, 0)) + + #add right, bottom to atalantic + for j in xrange(len(heights[0])): q2.append((len(heights)-1, j)) + for i in xrange(len(heights)): q2.append((i, len(heights[0])-1)) + + bfs(q1, pacific) + bfs(q2, altalantic) + + return pacific.intersection(altalantic) + \ No newline at end of file diff --git a/problems/palindromic-substrings.py b/problems/palindromic-substrings.py new file mode 100644 index 0000000..a375af6 --- /dev/null +++ b/problems/palindromic-substrings.py @@ -0,0 +1,61 @@ +""" +dp[i][j] := if s[i:j+1] is palindrome. +1. all length==1 string is palindrome. +2. all length==2 string is palindrome if two are the same. +3. all length>=3 string is palindrome if the outer most two char is the same and have an palindrome string inside. + +Time: O(N^2) +Space: 0(N^2) +""" +class Solution(object): + def countSubstrings(self, s): + N = len(s) + dp = [[False]*N for _ in xrange(N)] + ans = 0 + + #1 + for i in xrange(N): + dp[i][i] = True + ans += 1 + + #2 + for i in xrange(N-1): + if s[i]==s[i+1]: + dp[i][i+1] = True + ans += 1 + + #3 + for l in xrange(3, N+1): + for i in xrange(N): + j = i+l-1 + if j>=N: continue + if dp[i+1][j-1] and s[i]==s[j]: + dp[i][j] = True + ans += 1 + return ans + +""" +Iterate through the string, expand around each character. +Like this solution more since it is more intuitive. + +Time: O(N^2) +Space: O(1) +""" +class Solution(object): + def countSubstrings(self, s): + def count(l, r, N): + count = 0 + + while l>=0 and rword: + r = m-1 + else: + l = m+1 + + return [] + + def getTop3(products, word, i): + suggestion = [] + + while i-1>=0 and products[i-1].startswith(word): + i -= 1 + + for j in xrange(i, min(len(products), i+3)): + if not products[j].startswith(word): break + suggestion.append(products[j]) + return suggestion + + + ans = [] + products.sort() + + currSearchWord = '' + for c in searchWord: + currSearchWord += c + ans.append(search(products, currSearchWord)) + + return ans + + + +""" +Time: O(M) + O(S^2) ~= O(M). M is the number of char in products. S is number of char of a searchWord. +O(M) to build trie. O(len(prefix)) (~= O(S/2)) to get to the prefix node, and it will perform S time. O(1) to get top 3. +Space: O(M) + +Use Trie to store the relation and search it. +""" class Node(object): def __init__(self, c): self.c = c self.nexts = {} + class Solution(object): def suggestedProducts(self, products, searchWord): ans = [] @@ -37,4 +95,5 @@ def helper(prefix, node): top3 = [] helper(prefix, node) - return top3 \ No newline at end of file + return top3 + diff --git a/problems/set-matrix-zeroes.py b/problems/set-matrix-zeroes.py new file mode 100644 index 0000000..94e512d --- /dev/null +++ b/problems/set-matrix-zeroes.py @@ -0,0 +1,35 @@ +""" +Space: O(1) +Time: O(N^2) + +Mark matrix[i][0] as string if all matrix[i][?] needs to be set to 0. +Mark matrix[0][j] as string if all matrix[?][j] needs to be set to 0. +There is an edje case where matrix[0][0] cannot represent for row and col at the same time. +So we need an additional variable, firstRowToZero. + +Explanation: https://www.youtube.com/watch?v=T41rL0L3Pnw +""" +class Solution(object): + def setZeroes(self, matrix): + firstRowToZero = False + + for i in xrange(len(matrix)): + for j in xrange(len(matrix[0])): + if matrix[i][j]==0: + if i!=0: + matrix[i][0] = str(matrix[i][0]) + else: + firstRowToZero = True + matrix[0][j] = str(matrix[0][j]) + + + for i in xrange(1, len(matrix)): + if type(matrix[i][0])!=type(''): continue + for j in xrange(len(matrix[0])): matrix[i][j] = 0 + + for j in xrange(len(matrix[0])): + if type(matrix[0][j])!=type(''): continue + for i in xrange(len(matrix)): matrix[i][j] = 0 + + if firstRowToZero: + for j in xrange(len(matrix[0])): matrix[0][j] = 0 \ No newline at end of file diff --git a/problems/unique-paths.py b/problems/unique-paths.py new file mode 100644 index 0000000..f7f5c5b --- /dev/null +++ b/problems/unique-paths.py @@ -0,0 +1,9 @@ +class Solution(object): + def uniquePaths(self, m, n): + def factorial(n): + ans = 1 + for i in xrange(1, n+1): + ans *= i + return ans + + return factorial((m-1)+(n-1))/(factorial(n-1)*factorial(m-1)) \ No newline at end of file diff --git a/problems/word-search-ii.py b/problems/word-search-ii.py index e7d7b91..e62eba3 100644 --- a/problems/word-search-ii.py +++ b/problems/word-search-ii.py @@ -48,3 +48,49 @@ def dfs(i, j, l, word): words = ["oath","pea","eat","rain"] print Solution().findWords(board, words) + + + + +class Solution(object): + def findWords(self, board, words): + def dfs(i, j, parent): + c = board[i][j] + node = parent[c] + + if '.' in node: ans.append(node.pop('.')) + + board[i][j] = '#' + + for (rowOffset, colOffset) in [(-1, 0), (0, 1), (1, 0), (0, -1)]: + newRow, newCol = i + rowOffset, j + colOffset + if newRow<0 or newRow>=len(board) or newCol<0 or newCol>=len(board[0]): continue + if not board[newRow][newCol] in node: continue + dfs(newRow, newCol, node) + + board[i][j] = c + if not node: parent.pop(c) + + trie = {} + ans = [] + + #build trie + for word in words: + node = trie + for c in word: + if c not in node: + node[c] = {} + node = node[c] + node['.'] = word + print trie + + for i in xrange(len(board)): + for j in xrange(len(board[0])): + if board[i][j] in trie: dfs(i, j, trie) + + + return ans + + + + \ No newline at end of file From fd5bc7c537ecea127018aee3cbc7406ddafff80b Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 11 Jan 2022 11:57:12 +0800 Subject: [PATCH 138/187] no message --- problems/count-binary-substrings.py | 21 +++++++ problems/guess-the-word.py | 32 ++++++++++ .../maximum-number-of-points-with-cost.py | 63 +++++++++++++++++++ .../maximum-subarray-sum-with-one-deletion.py | 2 +- ...th-in-a-grid-with-obstacles-elimination.py | 25 ++++++++ problems/snapshot-array.py | 19 ++++++ 6 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 problems/count-binary-substrings.py create mode 100644 problems/guess-the-word.py create mode 100644 problems/maximum-number-of-points-with-cost.py create mode 100644 problems/shortest-path-in-a-grid-with-obstacles-elimination.py create mode 100644 problems/snapshot-array.py diff --git a/problems/count-binary-substrings.py b/problems/count-binary-substrings.py new file mode 100644 index 0000000..5a2520e --- /dev/null +++ b/problems/count-binary-substrings.py @@ -0,0 +1,21 @@ +class Solution(object): + def countBinarySubstrings(self, s): + groups = [] + count = 0 + last = s[0] + ans = 0 + + for bit in s: + if bit==last: + count += 1 + else: + groups.append(count) + count = 1 + last = bit + + groups.append(count) + + for i in xrange(1, len(groups)): + ans += min(groups[i], groups[i-1]) + + return ans \ No newline at end of file diff --git a/problems/guess-the-word.py b/problems/guess-the-word.py new file mode 100644 index 0000000..278a659 --- /dev/null +++ b/problems/guess-the-word.py @@ -0,0 +1,32 @@ +# """ +# This is Master's API interface. +# You should not implement it, or speculate about its implementation +# """ +#class Master(object): +# def guess(self, word): +# """ +# :type word: str +# :rtype int +# """ + +class Solution(object): + def findSecretWord(self, wordlist, master): + def similarity(w1, w2): + count = 0 + for i in xrange(6): + if w1[i]==w2[i]: count += 1 + return count + + for _ in xrange(10): + + temp = [] + + word = random.choice(wordlist) + k = master.guess(word) + if k==6: return + + for otherWord in wordlist: + if otherWord==word: continue + if similarity(word, otherWord)==k: temp.append(otherWord) + + wordlist = temp \ No newline at end of file diff --git a/problems/maximum-number-of-points-with-cost.py b/problems/maximum-number-of-points-with-cost.py new file mode 100644 index 0000000..c365817 --- /dev/null +++ b/problems/maximum-number-of-points-with-cost.py @@ -0,0 +1,63 @@ +""" +dp[i][j] := considering from points[0]~points[i], the max points if choosing points[i][j] +""" +class Solution(object): + def maxPoints(self, points): + N = len(points) + M = len(points[0]) + dp = [[0]*M for _ in xrange(N)] + + for i in xrange(N): + for j in xrange(M): + if i==0: + dp[i][j] = points[i][j] + else: + dp[i][j] = points[i][j]+max([dp[i-1][k] - abs(k-j) for k in xrange(M)]) + return max(dp[N-1]) + + +""" +The above solution will take O(NM^2) in time. +The bottle neck is for each j we need to traverse the whole last row. +Let us see a little bit closer on `dp[i][j]` + +dp[i][j] = points[i][j]+max([dp[i-1][k] - abs(k-j) for k in xrange(M)]) + +So, if j>=k (Part 1) +points[i][j]+max([dp[i-1][k] - (j-k) for k in xrange(M)]) +points[i][j] - j + max([dp[i-1][k] + k) for k in xrange(M)]) + +if k>=j (Part 2) +points[i][j] + max([dp[i-1][k] - (k-j) for k in xrange(M)]) +points[i][j] + j + max([dp[i-1][k] - k) for k in xrange(M)]) + +Since we cannot do a full scan +why not we update the value from left to right for Part 1 and +right to left for part 2 +With a variable call rollingMax to store the max. + +That way dp[i][j] will be updated as if we do a full scan. + +The time complexity will become O(NM) +""" +class Solution(object): + def maxPoints(self, points): + N = len(points) + M = len(points[0]) + dp = [[0]*M for _ in xrange(N)] + + for j in xrange(M): + dp[0][j] = points[0][j] + + for i in xrange(1, N): + rollingMax = float('-inf') + for j in xrange(M): + rollingMax = max(rollingMax, dp[i-1][j] - j) + dp[i][j] = max(dp[i][j], points[i][j] + j + rollingMax)) + + rollingMax = float('-inf') + for j in xrange(M, -1, -1): + rollingMax = max(rollingMax, dp[i-1][j] + j) + dp[i][j] = max(dp[i][j], points[i][j] - j + rollingMax)) + + return max(dp[N-1]) \ No newline at end of file diff --git a/problems/maximum-subarray-sum-with-one-deletion.py b/problems/maximum-subarray-sum-with-one-deletion.py index d713751..a7b34f2 100644 --- a/problems/maximum-subarray-sum-with-one-deletion.py +++ b/problems/maximum-subarray-sum-with-one-deletion.py @@ -23,7 +23,7 @@ def maximumSum(self, arr): dp[i][1] = arr[i] else: dp[i][0] = max(dp[i-1][0]+arr[i], arr[i]) - dp[i][1] = max(dp[i-1][0], dp[i-1][1]+arr[i], arr[i]) + dp[i][1] = max(dp[i-1][0], dp[i-1][1]+arr[i]) subarrayMaxSum = max(subarrayMaxSum, dp[i][0], dp[i][1]) return subarrayMaxSum \ No newline at end of file diff --git a/problems/shortest-path-in-a-grid-with-obstacles-elimination.py b/problems/shortest-path-in-a-grid-with-obstacles-elimination.py new file mode 100644 index 0000000..9c94c8a --- /dev/null +++ b/problems/shortest-path-in-a-grid-with-obstacles-elimination.py @@ -0,0 +1,25 @@ +class Solution(object): + def shortestPath(self, grid, K): + N = len(grid) + M = len(grid[0]) + + q = collections.deque([(0, 0, 0, K)]) + qNext = collections.deque() + visited = set() + + while q: + step, i0, j0, k0 = q.popleft() + if (i0, j0, k0) in visited: continue + visited.add((i0, j0, k0)) + + if i0==N-1 and j0==M-1: return step + + for i, j in [(i0+1, j0), (i0-1, j0), (i0, j0+1), (i0, j0-1)]: + if i>=N or i<0 or j>=M or j<0: continue + if grid[i][j]==1 and k0>0: + qNext.append((step+1, i, j, k0-1)) + elif grid[i][j]==0: + qNext.append((step+1, i, j, k0)) + if not q: q = qNext + + return -1 \ No newline at end of file diff --git a/problems/snapshot-array.py b/problems/snapshot-array.py new file mode 100644 index 0000000..baa9f15 --- /dev/null +++ b/problems/snapshot-array.py @@ -0,0 +1,19 @@ +class SnapshotArray(object): + + def __init__(self, length): + self.data = [[(-1, 0)] for _ in xrange(length)] + self.snapId = 0 + + + def set(self, index, val): + self.data[index].append((self.snapId, val)) + + + def snap(self): + self.snapId += 1 + return self.snapId - 1 + + + def get(self, index, snapId): + j = bisect.bisect_right(self.data[index], (snapId, float('inf'))) - 1 + return self.data[index][j][1] \ No newline at end of file From 98a3a80101ebd2c2f2c9a08f193b9773ec5fa898 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Thu, 13 Jan 2022 17:10:45 +0800 Subject: [PATCH 139/187] no message --- problems/text-justification.py | 68 ++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 problems/text-justification.py diff --git a/problems/text-justification.py b/problems/text-justification.py new file mode 100644 index 0000000..98eb0be --- /dev/null +++ b/problems/text-justification.py @@ -0,0 +1,68 @@ +""" +The description of this problem is unclear. +"Extra spaces between words should be distributed as evenly as possible." Should be "Extra spaces between words IN EACH LINE should be distributed as evenly as possible." +So the problem in short is: +1. Every line should have as many as word as possible. But they should be separate by space or spaces. +2. Mid align all the line. Except the last line and the lines with one word. +3. For mid align, distribute space evenly, if there are extra spaces, it should be located left. For example 5 spaces distribute to 2 places, it should be 3 2, not 2 3. 7 spaces distribute to 3 places, it should be 3 2 2, not 2 3 2, not 2 2 3. + +Time: O(N), N is the number of words. +Space: O(W), W is maxWidth for keeping strings in currLine. Can further reduce to O(1) using only index. +""" +class Solution(object): + def fullJustify(self, words, maxWidth): + def canAddToCurrLine(word, currLineStringLength): + currWidth = len(currLine)-1 + currLineStringLength # space+currLineStringLength + return currWidth+len(word)+1<=maxWidth + + def leftAlign(currLine): + line = '' + + for word in currLine: + line += word + ' ' + line = line[:-1] #remove last space + + line += ' '*(maxWidth-len(line)) + return line + + def midAlign(currLine, currLineStringLength): + line = '' + + totalSpaceCount = maxWidth-currLineStringLength + extraSpaceCount = totalSpaceCount%(len(currLine)-1) + spaceCount = totalSpaceCount-extraSpaceCount + spaces = ' '*(totalSpaceCount/(len(currLine)-1)) + + for word in currLine: + line += word + if spaceCount>0: + line += spaces + spaceCount -= len(spaces) + + if extraSpaceCount>0: + line += ' ' + extraSpaceCount -= 1 + + return line + + currLineStringLength = 0 + currLine = [] + ans = [] + + i = 0 + while i Date: Fri, 14 Jan 2022 14:36:13 +0800 Subject: [PATCH 140/187] no message --- .../find-original-array-from-doubled-array,py | 26 +++++++++++++++++++ problems/logger-rate-limiter.py | 10 +++++++ 2 files changed, 36 insertions(+) create mode 100644 problems/find-original-array-from-doubled-array,py create mode 100644 problems/logger-rate-limiter.py diff --git a/problems/find-original-array-from-doubled-array,py b/problems/find-original-array-from-doubled-array,py new file mode 100644 index 0000000..e9e2726 --- /dev/null +++ b/problems/find-original-array-from-doubled-array,py @@ -0,0 +1,26 @@ +""" +Time: O(NLogN) +Space: O(N) +""" +class Solution(object): + def findOriginalArray(self, changed): + if len(changed)%2!=0: return [] + + ans = [] + counter = collections.Counter() #store the count of the doubled number + count = 0 #sum of count in counter + + changed.sort() #need to be sorted, otherwise we cannot identify which number is orginal or it is doubled. + + for num in changed: + if counter[num]>0: + #num is a doubled num + counter[num] -= 1 + count -= 1 + ans.append(num/2) + else: + #num is an original num + counter[num*2] += 1 + count += 1 + + return ans if count==0 else [] \ No newline at end of file diff --git a/problems/logger-rate-limiter.py b/problems/logger-rate-limiter.py new file mode 100644 index 0000000..2a1a7e6 --- /dev/null +++ b/problems/logger-rate-limiter.py @@ -0,0 +1,10 @@ +class Logger(object): + def __init__(self): + self.log = collections.Counter() #store the latest timestamp + + def shouldPrintMessage(self, timestamp, message): + if message not in self.log or self.log[message]+10<=timestamp: + self.log[message] = timestamp + return True + else: + return False \ No newline at end of file From 82cd50e998d96342483b9d0f872c0e2149bed0e2 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Fri, 21 Jan 2022 11:04:21 +0800 Subject: [PATCH 141/187] no message --- .../delete-duplicate-folders-in-system.py | 43 +++++++++++++++ problems/find-and-replace-in-string.py | 28 ++++++++++ problems/longest-string-chain.py | 39 ++++++++++++++ problems/maximum-number-of-visible-points.py | 54 +++++++++++++++++++ problems/number-of-matching-subsequences.py | 25 +++++++++ ...move-all-ones-with-row-and-column-flips.py | 28 ++++++++++ problems/stock-price-fluctuation.py | 37 +++++++++++++ problems/student-attendance-record-ii.py | 28 ++++++++++ 8 files changed, 282 insertions(+) create mode 100644 problems/delete-duplicate-folders-in-system.py create mode 100644 problems/maximum-number-of-visible-points.py create mode 100644 problems/number-of-matching-subsequences.py create mode 100644 problems/remove-all-ones-with-row-and-column-flips.py create mode 100644 problems/stock-price-fluctuation.py create mode 100644 problems/student-attendance-record-ii.py diff --git a/problems/delete-duplicate-folders-in-system.py b/problems/delete-duplicate-folders-in-system.py new file mode 100644 index 0000000..721a8b1 --- /dev/null +++ b/problems/delete-duplicate-folders-in-system.py @@ -0,0 +1,43 @@ +from sortedcontainers import SortedDict + +class Node(object): + def __init__(self, val): + self.val = val + self.key = None + self.children = SortedDict() + + +class Solution(object): + def deleteDuplicateFolder(self, paths): + def setKey(node): + if not node.children: + node.key = node.val + else: + node.key = '' + for c in node.children: + setKey(node.children[c]) + node.key += node.children[c].val + '|' + node.children[c].key + '|' + + keyCount[node.key] += 1 + + def addPath(node, path): + if node.children and keyCount[node.key]>1: return + ans.append(path+[node.val]) + for c in node.children: + addPath(node.children[c], path+[node.val]) + + + ans = [] + root = Node('/') + keyCount = collections.Counter() + + #build the tree + for path in paths: + node = root + for c in path: + if c not in node.children: node.children[c] = Node(c) + node = node.children[c] + + setKey(root) + for c in root.children: addPath(root.children[c], []) + return ans \ No newline at end of file diff --git a/problems/find-and-replace-in-string.py b/problems/find-and-replace-in-string.py index ed407d1..4d74203 100644 --- a/problems/find-and-replace-in-string.py +++ b/problems/find-and-replace-in-string.py @@ -20,4 +20,32 @@ def findReplaceString(self, s, indices, sources, targets): ans += s[i] p = i + return ans + +""" +Time: O(N). N is the length of `s`. The replacement won't be more than the length of the string, Let's assume it is N. +Space: O(N). +""" +class Solution(object): + def findReplaceString(self, s, indices, sources, targets): + ans = '' + + replacement = {} + for i in xrange(len(indices)): + index = indices[i] + source = sources[i] + target = targets[i] + + if s[index:index+len(source)]!=source: continue + replacement[index] = (source, target) + + i = 0 + while i0 and y==0: + return 0 + elif x==0 and y>0: + return 90 + elif x<0 and y==0: + return 180 + elif x==0 and y<0: + return 270 + + #4 quadrant + if x>0 and y>0: + return math.degrees(math.atan2(abs(y), abs(x))) + elif x<0 and y>0: + return 180-math.degrees(math.atan2(abs(y), abs(x))) + elif x<0 and y<0: + return 180+math.degrees(math.atan2(abs(y), abs(x))) + else: + return 360-math.degrees(math.atan2(abs(y), abs(x))) + + ans = 0 + onLocation = 0 + angles = [] + + for x, y in points: + if x==location[0] and y==location[1]: + onLocation += 1 + else: + a = getAngle(x-location[0], y-location[1]) + angles.append(a) + if a<=angle: angles.append(360+a) #[1] + + angles.sort() + + i = 0 + for j in xrange(len(angles)): + while angles[j]-angles[i]>angle: + i += 1 + ans = max(ans, j-i+1) + + return ans+onLocation \ No newline at end of file diff --git a/problems/number-of-matching-subsequences.py b/problems/number-of-matching-subsequences.py new file mode 100644 index 0000000..fd97676 --- /dev/null +++ b/problems/number-of-matching-subsequences.py @@ -0,0 +1,25 @@ +""" +Time: O(WL x LogS), W is the length of words, L is the length of word. +LogS is the time for binary search and S should be the count of repetitive words, we can assume it is Log(S/26) ~= LogS. + +Space: O(S) +""" +class Solution(object): + def numMatchingSubseq(self, s, words): + def match(position, word): + prev = -1 + for c in word: + if c not in position: return False + i = bisect.bisect_left(position[c], prev+1) + if i==len(position[c]): return False + prev = position[c][i] + return True + + position = collections.defaultdict(list) + count = 0 + for i, c in enumerate(s): + position[c].append(i) + + for word in words: + if match(position, word): count += 1 + return count \ No newline at end of file diff --git a/problems/remove-all-ones-with-row-and-column-flips.py b/problems/remove-all-ones-with-row-and-column-flips.py new file mode 100644 index 0000000..69093cc --- /dev/null +++ b/problems/remove-all-ones-with-row-and-column-flips.py @@ -0,0 +1,28 @@ +""" +Not sure how to scientifically prove this. +In order to turn all the 1 to 0, every row need to have "the same pattern". Or it is imposible. +This same pattern is means they are 1. identical 2. entirely different. +For example 101 and 101, 101 and 010. +110011 and 110011. 110011 and 001100. + +Time: O(N), N is the number of element in the grid. +Space: O(N) +""" +class Solution(object): + def removeOnes(self, grid): + if not grid: return True + rowStrings = set() + + for row in grid: + rowStrings.add(''.join((str(e) for e in row))) + + if len(rowStrings)>2: return False + if len(rowStrings)==1: return True + + s1 = rowStrings.pop() + s2 = rowStrings.pop() + + for i in xrange(len(s1)): + if (s1[i]=='0' and s2[i]=='1') or (s1[i]=='1' and s2[i]=='0'): continue + return False + return True \ No newline at end of file diff --git a/problems/stock-price-fluctuation.py b/problems/stock-price-fluctuation.py new file mode 100644 index 0000000..e75beb2 --- /dev/null +++ b/problems/stock-price-fluctuation.py @@ -0,0 +1,37 @@ +""" +[0] priceToTime tracks price to timestamps, but since for each timestamp the price might be overridden, the price in priceToTime might not be exsit. So we need to check if the price still have any valid timestamps. +[1] SortedDict is a BST like structure. + +Time: O(LogN) +Space: O(N) +""" +from sortedcontainers import SortedDict #[1] + +class StockPrice(object): + + def __init__(self): + self.timeToPrice = SortedDict() #time will be sorted + self.priceToTime = SortedDict() #the price will be sorted + + + def update(self, timestamp, price): + if timestamp in self.timeToPrice: + prevPrice = self.timeToPrice[timestamp] + self.priceToTime[prevPrice].remove(timestamp) + if len(self.priceToTime[prevPrice])==0: self.priceToTime.pop(prevPrice) #[0] + + if price not in self.priceToTime: self.priceToTime[price] = set() #initialized + self.priceToTime[price].add(timestamp) + self.timeToPrice[timestamp] = price + + + def current(self): + return self.timeToPrice.peekitem(-1)[1] + + + def maximum(self): + return self.priceToTime.peekitem(-1)[0] + + + def minimum(self): + return self.priceToTime.peekitem(0)[0] \ No newline at end of file diff --git a/problems/student-attendance-record-ii.py b/problems/student-attendance-record-ii.py new file mode 100644 index 0000000..ed55473 --- /dev/null +++ b/problems/student-attendance-record-ii.py @@ -0,0 +1,28 @@ +class Solution(object): + def checkRecord(self, n): + """ + dp[l] := number of eligible combination of a length l record without A + """ + + ans = 0 + M = 1000000007 + + dp = [0]*max(n+1, 4) + dp[0] = 1 + dp[1] = 2 + dp[2] = 4 + dp[3] = 7 + + for i in xrange(4, n+1): + dp[i] += dp[i-1]%M #ends at P + dp[i] += (dp[i-1]%M - dp[i-4]%M) #ends at L. All posiblity but the end cannot be PLL + + + ans += dp[n] + + for i in xrange(n): + ans += dp[i] * dp[n-i-1] + ans %= M + + return ans + \ No newline at end of file From 5e28daff0c37856e5d7299d958f5907d0d74bd0d Mon Sep 17 00:00:00 2001 From: wuduhren Date: Fri, 21 Jan 2022 11:08:15 +0800 Subject: [PATCH 142/187] no message --- problems/delete-duplicate-folders-in-system.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/problems/delete-duplicate-folders-in-system.py b/problems/delete-duplicate-folders-in-system.py index 721a8b1..763eefd 100644 --- a/problems/delete-duplicate-folders-in-system.py +++ b/problems/delete-duplicate-folders-in-system.py @@ -21,7 +21,7 @@ def setKey(node): keyCount[node.key] += 1 def addPath(node, path): - if node.children and keyCount[node.key]>1: return + if node.children and keyCount[node.key]>1: return #leaf node does not apply to this rule ans.append(path+[node.val]) for c in node.children: addPath(node.children[c], path+[node.val]) @@ -38,6 +38,11 @@ def addPath(node, path): if c not in node.children: node.children[c] = Node(c) node = node.children[c] + #set all nodes key recursively setKey(root) - for c in root.children: addPath(root.children[c], []) + + #build ans + for c in root.children: + addPath(root.children[c], []) + return ans \ No newline at end of file From a2551c9a3bcff6de96c328b6a8d1b901cd42f49a Mon Sep 17 00:00:00 2001 From: wuduhren Date: Fri, 21 Jan 2022 11:31:10 +0800 Subject: [PATCH 143/187] no message --- problems/delete-duplicate-folders-in-system.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/problems/delete-duplicate-folders-in-system.py b/problems/delete-duplicate-folders-in-system.py index 763eefd..f05d4ff 100644 --- a/problems/delete-duplicate-folders-in-system.py +++ b/problems/delete-duplicate-folders-in-system.py @@ -1,12 +1,10 @@ -from sortedcontainers import SortedDict - class Node(object): def __init__(self, val): self.val = val self.key = None - self.children = SortedDict() - - + self.children = {} + + class Solution(object): def deleteDuplicateFolder(self, paths): def setKey(node): @@ -14,7 +12,7 @@ def setKey(node): node.key = node.val else: node.key = '' - for c in node.children: + for c in sorted(node.children.keys()): setKey(node.children[c]) node.key += node.children[c].val + '|' + node.children[c].key + '|' From 803fb76e20fc2e469f3a7d7d4521b2d799ab632c Mon Sep 17 00:00:00 2001 From: wuduhren Date: Mon, 24 Jan 2022 11:45:02 +0800 Subject: [PATCH 144/187] no message --- problems/binary-subarrays-with-sum.py | 19 ++++++++ problems/coloring-a-border.py | 43 +++++++++++++++++++ problems/count-number-of-nice-subarrays.py | 19 ++++++++ .../delete-duplicate-folders-in-system.py | 12 ++---- problems/fruit-into-baskets.py | 23 ++++++++++ problems/max-consecutive-ones-iii.py | 15 +++++++ problems/minimum-knight-moves.py | 30 +++++++++++++ ...umber-of-substrings-containing-all-thre.py | 22 ++++++++++ ...place-the-substring-for-balanced-string.py | 15 +++++++ .../subarrays-with-k-different-integers.py | 25 +++++++++++ 10 files changed, 215 insertions(+), 8 deletions(-) create mode 100644 problems/binary-subarrays-with-sum.py create mode 100644 problems/coloring-a-border.py create mode 100644 problems/count-number-of-nice-subarrays.py create mode 100644 problems/max-consecutive-ones-iii.py create mode 100644 problems/minimum-knight-moves.py create mode 100644 problems/number-of-substrings-containing-all-thre.py create mode 100644 problems/replace-the-substring-for-balanced-string.py create mode 100644 problems/subarrays-with-k-different-integers.py diff --git a/problems/binary-subarrays-with-sum.py b/problems/binary-subarrays-with-sum.py new file mode 100644 index 0000000..dafb077 --- /dev/null +++ b/problems/binary-subarrays-with-sum.py @@ -0,0 +1,19 @@ +class Solution(object): + def numSubarraysWithSum(self, nums, goal): + #number of subarrays with sum at most "goal" + def atMost(goal): + ans = 0 + total = 0 + i = 0 + + for j, num in enumerate(nums): + if num==1: total += 1 + + while igoal: + if nums[i]==1: total -= 1 + i += 1 + + ans += j-i+1 #number of subarrays that can generate from nums[i~j] + return ans + + return atMost(goal)-atMost(goal-1) if goal>0 else atMost(goal) \ No newline at end of file diff --git a/problems/coloring-a-border.py b/problems/coloring-a-border.py new file mode 100644 index 0000000..0b1ecc9 --- /dev/null +++ b/problems/coloring-a-border.py @@ -0,0 +1,43 @@ +""" +A node is on the "border" if +1. It is on the actual border of the grid. +Or +2. Any of its neighbor has different color. + +BFS the grid starting from (row, col), if the node "isBorder" add it to nodesToColor. +Color the nodes in the nodesToColor. + +Time: O(N) +Space: O(N) +""" +class Solution(object): + def colorBorder(self, grid, row, col, color): + def isValid(i, j): + return i>=0 and j>=0 and ik: + if nums[i]%2!=0: oddCount -= 1 + i += 1 + + ans += j-i+1 + + return ans + + return atMost(K)-atMost(K-1) \ No newline at end of file diff --git a/problems/delete-duplicate-folders-in-system.py b/problems/delete-duplicate-folders-in-system.py index f05d4ff..512cd1a 100644 --- a/problems/delete-duplicate-folders-in-system.py +++ b/problems/delete-duplicate-folders-in-system.py @@ -4,17 +4,13 @@ def __init__(self, val): self.key = None self.children = {} - class Solution(object): def deleteDuplicateFolder(self, paths): def setKey(node): - if not node.children: - node.key = node.val - else: - node.key = '' - for c in sorted(node.children.keys()): - setKey(node.children[c]) - node.key += node.children[c].val + '|' + node.children[c].key + '|' + node.key = '' + for c in sorted(node.children.keys()): #need to be sorted. so when child structs are the same, we won't generate different key from different iteration order. + setKey(node.children[c]) + node.key += node.children[c].val + '|' + node.children[c].key + '|' #generate a key for each node. only considering its children structure. (see the "identical" definition, it does not consider the val of the node itself.) keyCount[node.key] += 1 diff --git a/problems/fruit-into-baskets.py b/problems/fruit-into-baskets.py index 29bb77c..8645ae0 100644 --- a/problems/fruit-into-baskets.py +++ b/problems/fruit-into-baskets.py @@ -44,3 +44,26 @@ def totalFruit(self, tree): counter = max(counter, i-start+1) mark[t] = i return counter + + +""" +Find the length of longest subarray that at most has 2 unique number. +""" +class Solution(object): + def totalFruit(self, fruits): + ans = 0 + uniqueFruits = 0 + i = 0 + counter = collections.Counter() + + for j, fruit in enumerate(fruits): + counter[fruit] += 1 + if counter[fruit]==1: uniqueFruits += 1 + + while uniqueFruits>2: + counter[fruits[i]] -= 1 + if counter[fruits[i]]==0: uniqueFruits -= 1 + i += 1 + + ans = max(ans, j-i+1) + return ans \ No newline at end of file diff --git a/problems/max-consecutive-ones-iii.py b/problems/max-consecutive-ones-iii.py new file mode 100644 index 0000000..2ebd05c --- /dev/null +++ b/problems/max-consecutive-ones-iii.py @@ -0,0 +1,15 @@ +class Solution(object): + def longestOnes(self, nums, k): + ans = 0 + zeroCount = 0 + i = 0 + + for j, num in enumerate(nums): + if num==0: zeroCount += 1 + + while zeroCount>k: + if nums[i]==0: zeroCount -= 1 + i += 1 + ans = max(ans, j-i+1) + + return ans \ No newline at end of file diff --git a/problems/minimum-knight-moves.py b/problems/minimum-knight-moves.py new file mode 100644 index 0000000..84cb400 --- /dev/null +++ b/problems/minimum-knight-moves.py @@ -0,0 +1,30 @@ +# Bidirectional BFS +class Solution(object): + def minKnightMoves(self, x, y): + offsets = [(1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1), (-2, 1), (-1, 2)] + q1 = collections.deque([(0, 0)]) + q2 = collections.deque([(x, y)]) + steps1 = {(0, 0): 0} #steps needed starting from (0, 0) + steps2 = {(x, y): 0} #steps needed starting from (x,y) + + while q1 and q2: + i1, j1 = q1.popleft() + if (i1, j1) in steps2: return steps1[(i1, j1)]+steps2[(i1, j1)] + + i2, j2 = q2.popleft() + if (i2, j2) in steps1: return steps1[(i2, j2)]+steps2[(i2, j2)] + + for ox, oy in offsets: + nextI1 = i1+ox + nextJ1 = j1+oy + if (nextI1, nextJ1) not in steps1: + q1.append((nextI1, nextJ1)) + steps1[(nextI1, nextJ1)] = steps1[(i1, j1)]+1 + + nextI2 = i2+ox + nextJ2 = j2+oy + if (nextI2, nextJ2) not in steps2: + q2.append((nextI2, nextJ2)) + steps2[(nextI2, nextJ2)] = steps2[(i2, j2)]+1 + + return float('inf') \ No newline at end of file diff --git a/problems/number-of-substrings-containing-all-thre.py b/problems/number-of-substrings-containing-all-thre.py new file mode 100644 index 0000000..66d43cc --- /dev/null +++ b/problems/number-of-substrings-containing-all-thre.py @@ -0,0 +1,22 @@ +class Solution(object): + def numberOfSubstrings(self, s): + #number of subarrays that at most have k unique char + def atMost(k): + counter = collections.Counter() + uniqueCount = 0 + ans = 0 + i = 0 + + for j, c in enumerate(s): + counter[c] += 1 + if counter[c]==1: uniqueCount += 1 + + while uniqueCount>k: + counter[s[i]] -= 1 + if counter[s[i]]==0: uniqueCount-= 1 + i += 1 + ans += j-i+1 + return ans + + n = len(s) + return atMost(3) - atMost(2) \ No newline at end of file diff --git a/problems/replace-the-substring-for-balanced-string.py b/problems/replace-the-substring-for-balanced-string.py new file mode 100644 index 0000000..0ce1250 --- /dev/null +++ b/problems/replace-the-substring-for-balanced-string.py @@ -0,0 +1,15 @@ +class Solution(object): + def balancedString(self, s): + n = len(s) + counter = collections.Counter(s) + i = 0 + ans = n + + for j, c in enumerate(s): + counter[c] -= 1 + + while ik: + counter[nums[i]] -= 1 + if counter[nums[i]]==0: uniqueCount -= 1 + i += 1 + + # the logest subarray that ends at j is nums[i:j+1] + # nums[i:j+1] can produce j-i+1 subarrays that at most has k different number. + ans += j-i+1 + + return ans + + return atMost(K)-atMost(K-1) \ No newline at end of file From 5dda17bb500798a3e70f1ac1cf79eab59083b8e2 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Thu, 3 Feb 2022 12:22:33 +0800 Subject: [PATCH 145/187] no message --- problems/backspace-string-compare.py | 22 +++++++- problems/balance-a-binary-search-tree.py | 36 ++++++++++++ problems/binary-search-tree-iterator.py | 26 ++++++++- .../binary-tree-vertical-order-traversal.py | 25 ++++++++- ...earch-tree-to-sorted-doubly-linked-list.py | 4 +- problems/copy-list-with-random-pointer.py | 37 +++++++++++- problems/diameter-of-binary-tree.py | 20 +++++++ problems/find-distance-in-a-binary-tree.py | 28 ++++++++++ problems/find-duplicate-subtrees.py | 16 ++++++ problems/find-k-closest-elements.py | 20 +++++++ ...sert-into-a-sorted-circular-linked-list.py | 42 ++++++++++++++ ...est-common-ancestor-of-a-binary-tree-ii.py | 17 ++++++ ...st-common-ancestor-of-a-binary-tree-iii.py | 56 +++++++++++++++++++ ...est-common-ancestor-of-a-binary-tree-iv.py | 18 ++++++ ...owest-common-ancestor-of-deepest-leaves.py | 41 ++++++++++++++ problems/maximal-square.py | 22 +++++++- problems/random-pick-with-weight.py | 29 ++++++++++ problems/range-sum-of-bst.py | 11 ++++ .../serialize-and-deserialize-binary-tree.py | 23 +++++++- ...ions-from-a-binary-tree-node-to-another.py | 36 ++++++++++++ problems/subarray-sum-equals-k.py | 2 +- problems/top-k-frequent-elements.py | 19 +++++++ problems/two-out-of-three.py | 17 ++++++ 23 files changed, 558 insertions(+), 9 deletions(-) create mode 100644 problems/balance-a-binary-search-tree.py create mode 100644 problems/find-distance-in-a-binary-tree.py create mode 100644 problems/find-duplicate-subtrees.py create mode 100644 problems/find-k-closest-elements.py create mode 100644 problems/insert-into-a-sorted-circular-linked-list.py create mode 100644 problems/lowest-common-ancestor-of-a-binary-tree-ii.py create mode 100644 problems/lowest-common-ancestor-of-a-binary-tree-iii.py create mode 100644 problems/lowest-common-ancestor-of-a-binary-tree-iv.py create mode 100644 problems/lowest-common-ancestor-of-deepest-leaves.py create mode 100644 problems/random-pick-with-weight.py create mode 100644 problems/range-sum-of-bst.py create mode 100644 problems/step-by-step-directions-from-a-binary-tree-node-to-another.py create mode 100644 problems/two-out-of-three.py diff --git a/problems/backspace-string-compare.py b/problems/backspace-string-compare.py index f3df6d2..cec9e8a 100644 --- a/problems/backspace-string-compare.py +++ b/problems/backspace-string-compare.py @@ -82,4 +82,24 @@ def backspaceCompare(self, s1, s2): j -= 1 return True - \ No newline at end of file + + +class Solution(object): + def backspaceCompare(self, s, t): + def helper(S): + ans = '' + i = len(S)-1 + backspaceCount = 0 + + while i>=0: + if S[i]=='#': + backspaceCount += 1 + else: + if backspaceCount>0: + backspaceCount -= 1 + else: + ans += S[i] + i -= 1 + return ans + + return helper(s)==helper(t) \ No newline at end of file diff --git a/problems/balance-a-binary-search-tree.py b/problems/balance-a-binary-search-tree.py new file mode 100644 index 0000000..015934d --- /dev/null +++ b/problems/balance-a-binary-search-tree.py @@ -0,0 +1,36 @@ +""" +Imagine a list of sorted nodes, if we wanted to use the nodes to form a balanced BST, which root should we use? +Yes, the one in the middle, since it can evenly spread two groups of nodes. This is what `getRoot()` does. +And we do the same for the left half and right half. And so on. And so on... + +Time: O(N), N is the number of nodes. +Space: O(N) +""" +class Solution(object): + def balanceBST(self, root): + def getInorderNodes(root): + nodes = [] + stack = [] + node = root + + while node or stack: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + nodes.append(node) + node = node.right + + return nodes + + def getRoot(l, r): + if l>r: return None + m = (l+r)/2 + root = inorderNodes[m] + root.left = getRoot(l, m-1) + root.right = getRoot(m+1, r) + return root + + inorderNodes = getInorderNodes(root) + return getRoot(0, len(inorderNodes)-1) \ No newline at end of file diff --git a/problems/binary-search-tree-iterator.py b/problems/binary-search-tree-iterator.py index 65557ce..48d1458 100644 --- a/problems/binary-search-tree-iterator.py +++ b/problems/binary-search-tree-iterator.py @@ -61,4 +61,28 @@ def inOrderTraverse(root): #do something print node.val - node = node.right \ No newline at end of file + node = node.right + + + +class BSTIterator(object): + + def __init__(self, root): + self.stack = [] + self.node = root + + + + def next(self): + while self.node: + self.stack.append(self.node) + self.node = self.node.left + self.node = self.stack.pop() + returnVal = self.node.val + self.node = self.node.right + return returnVal + + + + def hasNext(self): + return self.node or self.stack \ No newline at end of file diff --git a/problems/binary-tree-vertical-order-traversal.py b/problems/binary-tree-vertical-order-traversal.py index ac0f3c6..1510ac0 100644 --- a/problems/binary-tree-vertical-order-traversal.py +++ b/problems/binary-tree-vertical-order-traversal.py @@ -24,4 +24,27 @@ def verticalOrder(self, root): if node.left: q.append((node.left, x-1)) if node.right: q.append((node.right, x+1)) - return [ans[x] for x in xrange(minX, maxX+1)] \ No newline at end of file + return [ans[x] for x in xrange(minX, maxX+1)] + + +class Solution(object): + def verticalOrder(self, root): + if not root: return [] + ans = [] + minX = float('inf') + maxX = float('-inf') + locations = collections.defaultdict(list) + q = collections.deque([(root, 0)]) + + while q: + node, x = q.popleft() + locations[x].append(node.val) + minX = min(minX, x) + maxX = max(maxX, x) + if node.left: q.append((node.left, x-1)) + if node.right: q.append((node.right, x+1)) + + for x in xrange(minX, maxX+1): + if locations[x]: ans.append(locations[x]) + + return ans \ No newline at end of file diff --git a/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py b/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py index cfd441f..a9cd2bf 100644 --- a/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py +++ b/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py @@ -101,4 +101,6 @@ def inOrderTraverse(root): #do something print node.val - node = node.right \ No newline at end of file + node = node.right + + \ No newline at end of file diff --git a/problems/copy-list-with-random-pointer.py b/problems/copy-list-with-random-pointer.py index 0790e26..ddf901e 100644 --- a/problems/copy-list-with-random-pointer.py +++ b/problems/copy-list-with-random-pointer.py @@ -55,5 +55,38 @@ def copyRandomList(self, head): """ Time: O(N). Two iteration. First iteration make a the clones. Second iteration setup the links. -Space: O(1). No extra space except the cloned node. -""" \ No newline at end of file +Space: O(N). +""" + + +""" +Time: O(N) +Space: O(1) +""" +class Solution(object): + def copyRandomList(self, head): + if not head: return head + curr = head + while curr: + nextCurr = curr.next + copy = Node(curr.val) + curr.next = copy + copy.next = nextCurr + curr = nextCurr + + copyHead = head.next + + curr = head + while curr: + if curr.random: curr.next.random = curr.random.next + curr = curr.next.next + + curr = head + while curr: + nextCurr = curr.next.next + if nextCurr: + curr.next.next = nextCurr.next + curr.next = nextCurr + curr = nextCurr + + return copyHead \ No newline at end of file diff --git a/problems/diameter-of-binary-tree.py b/problems/diameter-of-binary-tree.py index f30ea33..8af4f9b 100644 --- a/problems/diameter-of-binary-tree.py +++ b/problems/diameter-of-binary-tree.py @@ -83,3 +83,23 @@ def getMaxDepth(node): # return ans + +""" +For each route in the binary tree, we can view it from the highest node in the route. +So the length will be helper(node.left) + 1 + helper(node.right). +""" +class Solution(object): + def __init__(self): + self.ans = 0 #number of nodes in the longest route + + def diameterOfBinaryTree(self, root): + #return the longest length to the leaf including itself + #also update self.ans + def helper(node): + r = helper(node.right) if node.right else 0 + l = helper(node.left) if node.left else 0 + self.ans = max(self.ans, l+1+r) + return max(l+1, r+1) + + helper(root) + return self.ans-1 \ No newline at end of file diff --git a/problems/find-distance-in-a-binary-tree.py b/problems/find-distance-in-a-binary-tree.py new file mode 100644 index 0000000..b87dd1b --- /dev/null +++ b/problems/find-distance-in-a-binary-tree.py @@ -0,0 +1,28 @@ +class Solution(object): + def __init__(self): + self.lca = None + self.pHeight = 0 + self.qHeight = 0 + + def findDistance(self, root, p, q): + #find the count of p or q in node's subtree, set the first node we found that has count>=2 as lca. + def findCount(node): + if not node: return 0 + count = 0 + if node.val==p or node.val==q: count += 1 + count += findPQCount(node.left) + count += findPQCount(node.right) + if count>=2 and not self.lca: self.lca = node + return count + + def findHeight(node, h): + if not node: return + if node.val==p: self.pHeight = h + if node.val==q: self.qHeight = h + if self.pHeight and self.qHeight: return + findHeight(node.left, h+1) + findHeight(node.right, h+1) + + findCount(root) + findHeight(self.lca, 0) + return self.qHeight + self.pHeight \ No newline at end of file diff --git a/problems/find-duplicate-subtrees.py b/problems/find-duplicate-subtrees.py new file mode 100644 index 0000000..5729e8e --- /dev/null +++ b/problems/find-duplicate-subtrees.py @@ -0,0 +1,16 @@ +class Solution(object): + def findDuplicateSubtrees(self, root): + def dfs(node): + if not node: return '#' + string = str(node.val) + ',' + dfs(node.left) + ',' + dfs(node.right) + data[string].append(node) + return string + + data = collections.defaultdict(list) + ans = [] + + dfs(root) + + for s in data: + if len(data[s])>=2: ans.append(data[s][0]) + return ans \ No newline at end of file diff --git a/problems/find-k-closest-elements.py b/problems/find-k-closest-elements.py new file mode 100644 index 0000000..802279f --- /dev/null +++ b/problems/find-k-closest-elements.py @@ -0,0 +1,20 @@ +class Solution(object): + def findClosestElements(self, arr, K, X): + def isCloserThan(n1, n2, x): + return abs(x-n1)=len(arr) or (l>=0 and isCloserThan(arr[l], arr[r], X)): + output1.append(arr[l]) + l -= 1 + else: + output2.append(arr[r]) + r += 1 + + return output1[::-1]+output2 diff --git a/problems/insert-into-a-sorted-circular-linked-list.py b/problems/insert-into-a-sorted-circular-linked-list.py new file mode 100644 index 0000000..9a4a067 --- /dev/null +++ b/problems/insert-into-a-sorted-circular-linked-list.py @@ -0,0 +1,42 @@ +class Solution(object): + def insert(self, random, insertVal): + def allValSame(node): + curr = node.next + while curr!=node: + if curr.val!=node.val: return False + curr = curr.next + return True + + newNode = Node(insertVal) + + #handle null linked list + if not random: + newNode.next = newNode + return newNode + + #handle linked list with val all the same + if allValSame(random): + temp = random.next + random.next = newNode + newNode.next = temp + return random + + #find head and tail, head is the min val node, tail is the max val node. + curr = random + while curr.val<=curr.next.val: + curr = curr.next + tail = curr + head = curr.next + + #insert new node + if insertVal>=tail.val or insertVal<=head.val: + tail.next = newNode + newNode.next = head + else: + curr = head + while not curr.val<=insertVal<=curr.next.val: curr = curr.next + temp = curr.next + curr.next = newNode + newNode.next = temp + + return random \ No newline at end of file diff --git a/problems/lowest-common-ancestor-of-a-binary-tree-ii.py b/problems/lowest-common-ancestor-of-a-binary-tree-ii.py new file mode 100644 index 0000000..8f07177 --- /dev/null +++ b/problems/lowest-common-ancestor-of-a-binary-tree-ii.py @@ -0,0 +1,17 @@ +class Solution(object): + def __init__(self): + self.ans = None + + def lowestCommonAncestor(self, root, p, q): + def dfs(node): + if not node: return 0 + + count = 0 + if node is p or node is q: count += 1 + count += dfs(node.left) + count += dfs(node.right) + if count>=2 and not self.ans: self.ans = node + return count + + dfs(root) + return self.ans diff --git a/problems/lowest-common-ancestor-of-a-binary-tree-iii.py b/problems/lowest-common-ancestor-of-a-binary-tree-iii.py new file mode 100644 index 0000000..cfd14f7 --- /dev/null +++ b/problems/lowest-common-ancestor-of-a-binary-tree-iii.py @@ -0,0 +1,56 @@ +""" +Time: O(H), H is the height of the tree. +Space: O(1) +""" +class Solution(object): + def lowestCommonAncestor(self, p, q): + ancestorP = set() + ancestorQ = set() + + temp = p + while temp: + ancestorP.add(temp) + temp = temp.parent + + temp = q + while temp: + ancestorQ.add(temp) + temp = temp.parent + + commonAncestor = ancestorQ.intersection(ancestorP) + temp = q + while temp: + if temp in commonAncestor: return temp + temp = temp.parent + return None + + +""" +Time: O(LogN) +Space: O(LogN) + +Looking from backward, parents1 and parents2 will be the same at first, since they must have a common ancestor. +Find the last the same parents. +""" +class Solution(object): + def lowestCommonAncestor(self, p, q): + parents1 = [] + parents2 = [] + + curr = p + while curr: + parents1.append(curr) + curr = curr.parent + + curr = q + while curr: + parents2.append(curr) + curr = curr.parent + + i = len(parents1)-1 + j = len(parents2)-1 + while i>=0 and j>=0 and parents1[i]==parents2[j]: + i -= 1 + j -= 1 + return parents1[i+1] + diff --git a/problems/lowest-common-ancestor-of-a-binary-tree-iv.py b/problems/lowest-common-ancestor-of-a-binary-tree-iv.py new file mode 100644 index 0000000..f7458a3 --- /dev/null +++ b/problems/lowest-common-ancestor-of-a-binary-tree-iv.py @@ -0,0 +1,18 @@ +class Solution(object): + def __init__(self): + self.ans = None + + def lowestCommonAncestor(self, root, nodes): + def dfs(node): + if not node: return 0 + + count = 0 + if node in nodes: count += 1 + count += dfs(node.left) + count += dfs(node.right) + if count>=len(nodes) and not self.ans: self.ans = node + return count + + nodes = set(nodes) + dfs(root) + return self.ans \ No newline at end of file diff --git a/problems/lowest-common-ancestor-of-deepest-leaves.py b/problems/lowest-common-ancestor-of-deepest-leaves.py new file mode 100644 index 0000000..cffade3 --- /dev/null +++ b/problems/lowest-common-ancestor-of-deepest-leaves.py @@ -0,0 +1,41 @@ +class Solution(object): + def __init__(self): + self.ans = None + + def lcaDeepestLeaves(self, root): + def checkCount(node, deepestNode): + if not node: + count = 0 + if count==len(deepestNode) and not self.ans: self.ans = node + return 0 + + if node in deepestNode: + count = 1 + if count==len(deepestNode) and not self.ans: self.ans = node + return count + + leftCount = checkCount(node.left, deepestNode) + rightCount = checkCount(node.right, deepestNode) + + if leftCount+rightCount==len(deepestNode) and not self.ans: self.ans = node + return leftCount+rightCount + + q = collections.deque([(root, 0)]) + q2 = collections.deque() + deepestNode = set([node for node, h in q]) + + while q: + node, d = q.popleft() + if node.left: q2.append((node.left, d+1)) + if node.right: q2.append((node.right, d+1)) + if not q: + q = q2 + if q: deepestNode = set([node for node, h in q]) + q2 = collections.deque() + + checkCount(root, deepestNode) + return self.ans + + + + \ No newline at end of file diff --git a/problems/maximal-square.py b/problems/maximal-square.py index 4ba17d6..9e6711b 100644 --- a/problems/maximal-square.py +++ b/problems/maximal-square.py @@ -10,4 +10,24 @@ def maximalSquare(self, grid): if grid[i][j]=='1': dp[i+1][j+1] = min(dp[i][j], dp[i][j+1], dp[i+1][j])+1 ans = max(ans, dp[i+1][j+1]) - return ans**2 \ No newline at end of file + return ans**2 + + + +class Solution(object): + def maximalSquare(self, matrix): + """ + dp[i][j] := maximal square length with matrix[i-1][j-1] at the bottom right corner in the square + """ + ans = 0 + N = len(matrix) + M = len(matrix[0]) + + dp = [[0 for _ in xrange(M+1)] for _ in xrange(N+1)] + + for i in xrange(1, N+1): + for j in xrange(1, M+1): + if matrix[i-1][j-1]=='1': + dp[i][j] = min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1])+1 + ans = max(ans, dp[i][j]**2) + return ans \ No newline at end of file diff --git a/problems/random-pick-with-weight.py b/problems/random-pick-with-weight.py new file mode 100644 index 0000000..9c88bd0 --- /dev/null +++ b/problems/random-pick-with-weight.py @@ -0,0 +1,29 @@ +""" +For W = [1,3,2,4] (total 10, 1+2+3+4) +Think of a line _,___,__,____ ([1,4,6,10]) +Now we randomly throw a ball on the line the probability to land on the first section will be 1/10. +the second section, 3/10. +the third section, 2/10. +the forth section, 4/10. + +Above is equivilant to we randomly pick a number [0~10) and see which section it is in. +And since the cumulative probability in the "line" is strictly increasing, we can use binary search. + +Time: O(LogN), N is the number of W. +Space: O(N). +""" +from random import randrange + +class Solution(object): + + def __init__(self, W): + self.line = [] #cumulative probability distribution + self.total = 0 + + for w in W: + self.total += w + self.line.append(self.total) + + def pickIndex(self): + rand = random.randrange(self.total) + return bisect.bisect(self.line, rand) \ No newline at end of file diff --git a/problems/range-sum-of-bst.py b/problems/range-sum-of-bst.py new file mode 100644 index 0000000..0ca07ed --- /dev/null +++ b/problems/range-sum-of-bst.py @@ -0,0 +1,11 @@ +class Solution(object): + def rangeSumBST(self, root, low, high): + def helper(node, low, high): + total = 0 + if not node: return total + if low<=node.val<=high: total += node.val + if node.val<=high: total += helper(node.right, low, high) + if node.val>=low: total += helper(node.left, low, high) + return total + + return helper(root, low, high) \ No newline at end of file diff --git a/problems/serialize-and-deserialize-binary-tree.py b/problems/serialize-and-deserialize-binary-tree.py index 9519b74..e48f9d2 100644 --- a/problems/serialize-and-deserialize-binary-tree.py +++ b/problems/serialize-and-deserialize-binary-tree.py @@ -39,4 +39,25 @@ def deserialize(self, data): q.append(node.right) i += 1 - return root \ No newline at end of file + return root + + + +#Preorder traversal +class Codec: + def serialize(self, root): + if not root: return '#,' + return str(root.val) + ',' + self.serialize(root.left) + self.serialize(root.right) + + def deserialize(self, data): + data = data.split(',')[::-1] + return self.getNode(data) + + def getNode(self, data): + if not data: return None + val = data.pop() + if val=='#': return None + node = TreeNode(val) + node.left = self.getNode(data) + node.right = self.getNode(data) + return node \ No newline at end of file diff --git a/problems/step-by-step-directions-from-a-binary-tree-node-to-another.py b/problems/step-by-step-directions-from-a-binary-tree-node-to-another.py new file mode 100644 index 0000000..a9177d4 --- /dev/null +++ b/problems/step-by-step-directions-from-a-binary-tree-node-to-another.py @@ -0,0 +1,36 @@ +class Solution(object): + def __init__(self): + self.lca = None + + def getDirections(self, root, startValue, destValue): + def findPath(node, path, val): + if not node: return False + if node.val==val: return True + + path.append('L') + if findPath(node.left, path, val): return True + path.pop() + + path.append('R') + if findPath(node.right, path, val): return True + path.pop() + + return False + + def findCount(node, startValue, destValue): + if not node: return 0 + count = 0 + if node.val==startValue or node.val==destValue: count += 1 + count += findCount(node.left, startValue, destValue) + count += findCount(node.right, startValue, destValue) + if count>=2 and not self.lca: self.lca = node + return count + + findCount(root, startValue, destValue) + + path1 = [] + findPath(self.lca, path1, startValue) + path2 = [] + findPath(self.lca, path2, destValue) + + return 'U'*len(path1) + ''.join(path2) \ No newline at end of file diff --git a/problems/subarray-sum-equals-k.py b/problems/subarray-sum-equals-k.py index 3220cff..3ed67dc 100644 --- a/problems/subarray-sum-equals-k.py +++ b/problems/subarray-sum-equals-k.py @@ -52,4 +52,4 @@ def subarraySum(self, nums, k): ans += prefixSumCount[I] #there are "prefixSumCount[I]" combinations of J-I that equals to k. prefixSumCount[J] += 1 - return ans \ No newline at end of file + return ans diff --git a/problems/top-k-frequent-elements.py b/problems/top-k-frequent-elements.py index fbb68a6..d2cb1a5 100644 --- a/problems/top-k-frequent-elements.py +++ b/problems/top-k-frequent-elements.py @@ -88,4 +88,23 @@ def topKFrequent(self, nums, k): ans.append(num) k -= 1 + return ans + +""" +Bucket sort for counts. +Space/Time: O(N) +""" +class Solution(object): + def topKFrequent(self, nums, k): + counter = collections.Counter(nums) + count2Nums = [[] for _ in xrange(len(nums)+1)] #count2Nums[i] := elements with count i + + for num in counter: + count2Nums[counter[num]].append(num) + + ans = [] + for i in xrange(len(count2Nums)-1, -1, -1): + ans += count2Nums[i] + if len(ans)>=k: break + return ans \ No newline at end of file diff --git a/problems/two-out-of-three.py b/problems/two-out-of-three.py new file mode 100644 index 0000000..8518903 --- /dev/null +++ b/problems/two-out-of-three.py @@ -0,0 +1,17 @@ +class Solution(object): + def twoOutOfThree(self, nums1, nums2, nums3): + ans = [] + + counter = collections.Counter() + + for num in list(set(nums1)): + counter[num] += 1 + for num in list(set(nums2)): + counter[num] += 1 + for num in list(set(nums3)): + counter[num] += 1 + + for num in counter: + if counter[num]>=2: ans.append(num) + + return ans \ No newline at end of file From 13fbec9603dbb4dbab725cb38842f9e0008a5bfb Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 15 Feb 2022 17:38:32 +0800 Subject: [PATCH 146/187] no message --- problems/campus-bikes-ii.py | 35 ++++++++ ...ee-from-inorder-and-postorder-traversal.py | 33 ++++++- ...binary-tree-to-match-preorder-traversal.py | 23 +++++ problems/kth-largest-element-in-an-array.py | 32 ++++++- problems/maximum-compatibility-score-sum.py | 44 +++++++++ ...-make-at-least-one-valid-path-in-a-grid.py | 32 +++++++ problems/minimum-xor-sum-of-two-arrays.py | 24 +++++ problems/network-delay-time.py | 90 ++++++++++++++++++- ...number-of-ways-to-arrive-at-destination.py | 33 +++++++ problems/path-with-maximum-probability.py | 24 +++++ problems/reverse-linked-list.py | 16 ++++ problems/the-maze-ii.py | 45 ++++++++++ problems/top-k-frequent-elements.py | 39 ++++++++ problems/trapping-rain-water-ii.py | 28 ++++++ 14 files changed, 493 insertions(+), 5 deletions(-) create mode 100644 problems/campus-bikes-ii.py create mode 100644 problems/flip-binary-tree-to-match-preorder-traversal.py create mode 100644 problems/maximum-compatibility-score-sum.py create mode 100644 problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py create mode 100644 problems/minimum-xor-sum-of-two-arrays.py create mode 100644 problems/number-of-ways-to-arrive-at-destination.py create mode 100644 problems/path-with-maximum-probability.py create mode 100644 problems/the-maze-ii.py create mode 100644 problems/trapping-rain-water-ii.py diff --git a/problems/campus-bikes-ii.py b/problems/campus-bikes-ii.py new file mode 100644 index 0000000..a292d91 --- /dev/null +++ b/problems/campus-bikes-ii.py @@ -0,0 +1,35 @@ +""" +state[i] := ith bike has been selected. +For example, there are M bikes, 0000, 0100, 0110, 1111..... + +Time: O(ELogE) +Space: O(E) +""" +class Solution(object): + def assignBikes(self, workers, bikes): + M = len(bikes) + N = len(workers) + costs = [[0]*N for _ in xrange(M)] + + for i in xrange(M): + for j in xrange(N): + costs[i][j] = abs(workers[j][0]-bikes[i][0])+abs(workers[j][1]-bikes[i][1]) + + pq = [(0, '0'*M)] + visited = set() + while pq: + cost, state = heapq.heappop(pq) + if state in visited: continue + visited.add(state) + + j = state.count('1') #j users have selected bikes + if j>=N: return cost + + for i in xrange(M): + if state[i]=='1': continue + + nextState = state[:i] + '1' + state[i+1:] + if nextState in visited: continue + heapq.heappush(pq, (cost+costs[i][j], nextState)) + + return float('inf') \ No newline at end of file diff --git a/problems/construct-binary-tree-from-inorder-and-postorder-traversal.py b/problems/construct-binary-tree-from-inorder-and-postorder-traversal.py index 1a46912..f8304fc 100644 --- a/problems/construct-binary-tree-from-inorder-and-postorder-traversal.py +++ b/problems/construct-binary-tree-from-inorder-and-postorder-traversal.py @@ -68,4 +68,35 @@ def helper(i, j, k, l): index = {} #the index of inorder for i, n in enumerate(inorder): index[n] = i - return helper(0, len(inorder), 0, len(postorder)) \ No newline at end of file + return helper(0, len(inorder), 0, len(postorder)) + + + + + +""" +Inorder: [LEFT]root[RIGHT] +Postorder: [LEFT][RIGHT]root +As you can see, rootVal is the last val in postorder. + +i and j is the range of the inorder +k and l is the range of the postorder +Get the root +Also recursively use the same method to get the left and right node, but this time we change the inorder and postorder. +""" +class Solution(object): + def buildTree(self, inorder, postorder): + def helper(i, j, k, l): + if i>j or k>l: return None + rootVal = postorder[l] + root = TreeNode(rootVal) + r = inorderIndex[rootVal] + leftLength = r-i + rightLength = j-r + root.left = helper(i, r-1, k, k+leftLength-1) + root.right = helper(r+1, j, k+leftLength, k+leftLength+rightLength-1) + return root + + inorderIndex = {} + for i, n in enumerate(inorder): inorderIndex[n] = i + return helper(0, len(inorder)-1, 0, len(postorder)-1) diff --git a/problems/flip-binary-tree-to-match-preorder-traversal.py b/problems/flip-binary-tree-to-match-preorder-traversal.py new file mode 100644 index 0000000..8727e28 --- /dev/null +++ b/problems/flip-binary-tree-to-match-preorder-traversal.py @@ -0,0 +1,23 @@ +class Solution(object): + def flipMatchVoyage(self, root, voyage): + def helper(node): + if not node: return + if node.val!=voyage[self.i]: + self.valid = False + return + + self.i += 1 + if node.left and node.left.val!=voyage[self.i]: + self.ans.append(node.val) + helper(node.right) + helper(node.left) + + else: + helper(node.left) + helper(node.right) + + self.ans = [] + self.i = 0 + self.valid = True + helper(root) + return self.ans if self.valid else [-1] \ No newline at end of file diff --git a/problems/kth-largest-element-in-an-array.py b/problems/kth-largest-element-in-an-array.py index d12f59c..27c4b72 100644 --- a/problems/kth-largest-element-in-an-array.py +++ b/problems/kth-largest-element-in-an-array.py @@ -63,4 +63,34 @@ def partition(A, l, r, p): k = len(nums)-k #redefine the problem to find the kth nums when sorted sortRange(nums, 0, len(nums)-1) - return nums[k] \ No newline at end of file + return nums[k] + + +#Quick Select +class Solution(object): + def findKthLargest(self, nums, K): + def quickSelect(A, s, e, K): + pivot = A[(s+e)/2] + i = s + t = s + j = e + + while t<=j: + if A[t]=K: + return quickSelect(A, j+1, e, K) + elif e-i+1>=K: + return pivot + else: + return quickSelect(A, s, i-1, K-(e-(i-1))) + + return quickSelect(nums, 0, len(nums)-1, K) \ No newline at end of file diff --git a/problems/maximum-compatibility-score-sum.py b/problems/maximum-compatibility-score-sum.py new file mode 100644 index 0000000..a0f744c --- /dev/null +++ b/problems/maximum-compatibility-score-sum.py @@ -0,0 +1,44 @@ +""" +Time: O(ELogE), E is the edge of the graph. +Note that state[i] means if the ith student is matched or not. (for example M=4, 0000, 0010, 0111, 1111...) +2^M is the number of states. So in this case E will be 2^M x M. + +Space: O(2^M) +""" +class Solution(object): + def maxCompatibilitySum(self, students, mentors): + M = len(students) + N = len(students[0]) + + #initialize reverseScores + reverseScores = [[0]*M for _ in xrange(M)] + for i in xrange(M): + for j in xrange(M): + reverseScore = 0 + for k in xrange(N): + if students[i][k]!=mentors[j][k]: + reverseScore += 1 + reverseScores[i][j] = reverseScore + + #Dijkstra + startState = '0'*M + endState = '1'*M + visited = set() + pq = [(0, startState)] + + while pq: + cost, state = heapq.heappop(pq) + if state in visited: continue + visited.add(state) + + if state==endState: return M*N-cost + + j = state.count('1') + for i in xrange(M): + if state[i]=='1': continue + + nextState = state[:i]+'1'+state[i+1:] + if nextState in visited: continue + heapq.heappush(pq, (cost+reverseScores[i][j], nextState)) + + return -1 \ No newline at end of file diff --git a/problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py b/problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py new file mode 100644 index 0000000..2188f4a --- /dev/null +++ b/problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py @@ -0,0 +1,32 @@ +class Solution(object): + def minCost(self, grid): + pq = [(0, False, 0, 0, 0)] + visited = set() + M = len(grid) + N = len(grid[0]) + + while pq: + cost, modified, direction, x, y = heapq.heappop(pq) + if x<0 or x>=M or y<0 or y>=N: continue + if (direction, x, y) in visited: continue + visited.add((direction, x, y)) + + if x==M-1 and y==N-1: return cost + + if direction==0: direction = grid[x][y] + + if direction==1: + heapq.heappush(pq, (cost, False, 0, x, y+1)) + elif direction==2: + heapq.heappush(pq, (cost, False, 0, x, y-1)) + elif direction==3: + heapq.heappush(pq, (cost, False, 0, x+1, y)) + elif direction==4: + heapq.heappush(pq, (cost, False, 0, x-1, y)) + + if not modified: + for d in [1,2,3,4]: + if d==grid[x][y]: continue + heapq.heappush(pq, (cost+1, True, d, x, y)) + + return float('inf') \ No newline at end of file diff --git a/problems/minimum-xor-sum-of-two-arrays.py b/problems/minimum-xor-sum-of-two-arrays.py new file mode 100644 index 0000000..7c3a195 --- /dev/null +++ b/problems/minimum-xor-sum-of-two-arrays.py @@ -0,0 +1,24 @@ +""" +state[i] := nums1[i] has been matched. +""" +class Solution(object): + def minimumXORSum(self, nums1, nums2): + N = len(nums1) + + pq = [(0, '0'*N)] + visited = set() + while pq: + s, state = heapq.heappop(pq) + if state in visited: continue + visited.add(state) + + j = state.count('1') + if j==N: return s + + for i in xrange(N): + if state[i]=='1': continue + nextState = state[:i]+'1'+state[i+1:] + if nextState in visited: continue + heapq.heappush(pq, ((s+(nums1[i]^nums2[j-1]), nextState))) + + return float('inf') \ No newline at end of file diff --git a/problems/network-delay-time.py b/problems/network-delay-time.py index 8098a31..aa67bb0 100644 --- a/problems/network-delay-time.py +++ b/problems/network-delay-time.py @@ -118,12 +118,96 @@ def networkDelayTime(self, times, n, k): +""" +Dijkstra BFS+Priority Queue Implementation +Time: O(ELogE), E is the edges count in the graph. +""" +class Solution(object): + def networkDelayTime(self, times, N, K): + ans = -1 #max time from K to any + visited = set() + pq = [(0, K)] #[(node's distance to K, node)] + + #construct adjacency list + adj = collections.defaultdict(list) + for u, v, w in times: + adj[u].append((w, v)) + + while pq: + dis, node = heapq.heappop(pq) + if node in visited: continue + visited.add(node) + + ans = max(ans, dis) + + for d2, nei in adj[node]: + heapq.heappush(pq, (d2+dis, nei)) + + return ans if len(visited)==N else -1 +""" +Dijkstra Normal Implementation +Time: O(N^2), N is the nodes count in the graph. +""" +class Solution(object): + def networkDelayTime(self, times, N, K): + #construct dis. dis[n] := node n distance to K + dis = {} + for n in xrange(1, N+1): + dis[n] = float('inf') + dis[K] = 0 + + visited = set() + + #construct adjacency list + adj = collections.defaultdict(list) + for u, v, w in times: + adj[u].append((w, v)) + + while len(visited)=N or j<0 or j>=M: continue + if maze[i][j]==1: continue + + if i==destination[0] and j==destination[1] and direction=='stop': return dis + + if direction=='stop': + heapq.heappush(pq, (dis+1, i-1, j, 'left')) + heapq.heappush(pq, (dis+1, i+1, j, 'right')) + heapq.heappush(pq, (dis+1, i, j-1, 'down')) + heapq.heappush(pq, (dis+1, i, j+1, 'up')) + elif direction=='left': + if i-1<0 or i-1>=N or j<0 or j>=M or maze[i-1][j]==1: + heapq.heappush(pq, (dis, i, j, 'stop')) + else: + heapq.heappush(pq, (dis+1, i-1, j, direction)) + elif direction=='right': + if i+1<0 or i+1>=N or j<0 or j>=M or maze[i+1][j]==1: + heapq.heappush(pq, (dis, i, j, 'stop')) + else: + heapq.heappush(pq, (dis+1, i+1, j, direction)) + elif direction=='down': + if i<0 or i>=N or j-1<0 or j-1>=M or maze[i][j-1]==1: + heapq.heappush(pq, (dis, i, j, 'stop')) + else: + heapq.heappush(pq, (dis+1, i, j-1, direction)) + elif direction=='up': + if i<0 or i>=N or j+1<0 or j+1>=M or maze[i][j+1]==1: + heapq.heappush(pq, (dis, i, j, 'stop')) + else: + heapq.heappush(pq, (dis+1, i, j+1, direction)) + + return -1 \ No newline at end of file diff --git a/problems/top-k-frequent-elements.py b/problems/top-k-frequent-elements.py index d2cb1a5..e1dea8c 100644 --- a/problems/top-k-frequent-elements.py +++ b/problems/top-k-frequent-elements.py @@ -107,4 +107,43 @@ def topKFrequent(self, nums, k): ans += count2Nums[i] if len(ans)>=k: break + return ans + + +# Quick Select +class Solution(object): + def topKFrequent(self, nums, K): + def quickselect(A, s, e, K): + i = s + t = s + j = e + + pivot = A[(s+e)/2][0] + while t<=j: + if A[t][0]=K: + return quickselect(A, j+1, e, K) + elif e-(i-1)>=K: + return pivot + else: + return quickselect(A, s, i-1, K-(e-i+1)) + + ans = [] + counter = collections.Counter(nums) + freqs = [(counter[num], num) for num in counter] + + KthLargestFreq = quickselect(freqs, 0, len(freqs)-1, K) + + for freq, num in freqs: + if freq>=KthLargestFreq: ans.append(num) + return ans \ No newline at end of file diff --git a/problems/trapping-rain-water-ii.py b/problems/trapping-rain-water-ii.py new file mode 100644 index 0000000..dd14bc7 --- /dev/null +++ b/problems/trapping-rain-water-ii.py @@ -0,0 +1,28 @@ +class Solution(object): + def trapRainWater(self, heightMap): + pq = [] + N = len(heightMap) + M = len(heightMap[0]) + visited = set() + ans = 0 + curr = float('-inf') + + for i in xrange(N): + for j in xrange(M): + if i==0 or i==N-1 or j==0 or j==M-1: + heapq.heappush(pq, (heightMap[i][j], i, j)) + + while pq: + h, i, j = heapq.heappop(pq) + if (i, j) in visited: continue + visited.add((i, j)) + + if h>curr: curr = h + ans += (curr-h) + + for iNext, jNext in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)]: + if iNext<0 or iNext>=N or jNext<0 or jNext>=M: continue + if (iNext, jNext) in visited: continue + heapq.heappush(pq, (heightMap[iNext][jNext], iNext, jNext)) + + return ans \ No newline at end of file From 0de2fcff4588bec862c266b090d52b8b24f39b83 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sun, 20 Feb 2022 17:41:52 +0800 Subject: [PATCH 147/187] no message --- problems/combinations.py | 15 ++++++ ...ount-all-valid-pickup-and-delivery-opti.py | 5 ++ problems/logger-rate-limiter.py | 22 +++++++++ ...nimum-cost-to-reach-city-with-discounts.py | 25 ++++++++++ ...to-convert-binary-matrix-to-zero-matrix.py | 46 +++++++++++++++++++ problems/permutation-sequence.py | 14 ++++++ problems/permutations-ii.py | 25 ++++++++++ problems/permutations.py | 26 ++++++++++- problems/profitable-schemes.py | 28 ++++++++++- problems/single-threaded-cpu.py | 22 +++++++++ problems/target-sum.py | 21 ++++++++- 11 files changed, 246 insertions(+), 3 deletions(-) create mode 100644 problems/count-all-valid-pickup-and-delivery-opti.py create mode 100644 problems/minimum-cost-to-reach-city-with-discounts.py create mode 100644 problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py create mode 100644 problems/permutation-sequence.py create mode 100644 problems/single-threaded-cpu.py diff --git a/problems/combinations.py b/problems/combinations.py index 49f7ebf..f3a0937 100644 --- a/problems/combinations.py +++ b/problems/combinations.py @@ -83,6 +83,21 @@ def dfs(n_min, path): +class Solution(object): + def combine(self, N, K): + def dfs(comb, start, N, K): + if len(comb)==K: ans.append(comb[:]) + + for n in xrange(start, N+1): + comb.append(n) + dfs(comb, n+1, N, K) + comb.pop() + + ans = [] + dfs([], 1, N, K) + return ans + + diff --git a/problems/count-all-valid-pickup-and-delivery-opti.py b/problems/count-all-valid-pickup-and-delivery-opti.py new file mode 100644 index 0000000..8bfe82a --- /dev/null +++ b/problems/count-all-valid-pickup-and-delivery-opti.py @@ -0,0 +1,5 @@ +class Solution(object): + def countOrders(self, n): + d = 1 + for i in xrange(1, 2*n, 2): d*=i + return math.factorial(n)*d % (10**9 + 7) \ No newline at end of file diff --git a/problems/logger-rate-limiter.py b/problems/logger-rate-limiter.py index 2a1a7e6..0f5f7ad 100644 --- a/problems/logger-rate-limiter.py +++ b/problems/logger-rate-limiter.py @@ -6,5 +6,27 @@ def shouldPrintMessage(self, timestamp, message): if message not in self.log or self.log[message]+10<=timestamp: self.log[message] = timestamp return True + else: + return False + + + +class Logger(object): + + def __init__(self): + #stores the messages within 10 seconds + self.q = collections.deque() + self.set = set() + + + def shouldPrintMessage(self, timestamp, message): + while self.q and timestamp-self.q[0][0]>=10: + time, msg = self.q.popleft() + self.set.remove(msg) + + if message not in self.set: + self.q.append((timestamp, message)) + self.set.add(message) + return True else: return False \ No newline at end of file diff --git a/problems/minimum-cost-to-reach-city-with-discounts.py b/problems/minimum-cost-to-reach-city-with-discounts.py new file mode 100644 index 0000000..93205f3 --- /dev/null +++ b/problems/minimum-cost-to-reach-city-with-discounts.py @@ -0,0 +1,25 @@ +class Solution(object): + def minimumCost(self, n, highways, discounts): + pq = [(0, discounts, 0)] + visited = set() + + adj = collections.defaultdict(list) + for city1, city2, toll in highways: + adj[city1].append((city2, toll)) + adj[city2].append((city1, toll)) + + + while pq: + toll, d, city = heapq.heappop(pq) + if (d, city) in visited: continue + visited.add((d, city)) + + if city==n-1: return toll + + for nei, toll2 in adj[city]: + if (d, nei) not in visited: + heapq.heappush(pq, (toll+toll2, d, nei)) + if d>0 and (d-1, nei) not in visited: + heapq.heappush(pq, (toll+toll2/2, d-1, nei)) + + return -1 \ No newline at end of file diff --git a/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py b/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py new file mode 100644 index 0000000..2c07805 --- /dev/null +++ b/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py @@ -0,0 +1,46 @@ +class Solution(object): + def minFlips(self, mat): + def flip(mat, m, n): + mat[m][n] = 0 if mat[m][n]==1 else 1 + if m+1=0: mat[m-1][n] = 0 if mat[m-1][n]==1 else 1 + if n-1>=0: mat[m][n-1] = 0 if mat[m][n-1]==1 else 1 + + def check(mat, state): + for i, b in enumerate(state): + if b=='1': + m = i/len(mat[0]) + n = i%len(mat[0]) + flip(mat, m, n) + + for i in xrange(len(mat)): + for j in xrange(len(mat[0])): + if mat[i][j]==1: return False + + return True + + + M = len(mat) + N = len(mat[0]) + q = collections.deque(['0'*(M*N)]) + visited = set() + + while q: + state = q.popleft() + if state in visited: continue + visited.add(state) + + if check([row[:] for row in mat], state): return state.count('1') + + for i in xrange(len(state)): + if state[i]=='1': continue + nextState = state[:i] + '1' +state[i+1:] + q.append(nextState) + + return -1 + + + + + \ No newline at end of file diff --git a/problems/permutation-sequence.py b/problems/permutation-sequence.py new file mode 100644 index 0000000..f7e5be2 --- /dev/null +++ b/problems/permutation-sequence.py @@ -0,0 +1,14 @@ +class Solution(object): + def getPermutation(self, N, K): + K = K-1 #make it 0-index + nums = range(1, N+1) + ans = '' + + while N>0: + a = K/math.factorial(N-1) + ans += str(nums[a]) + nums.pop(a) + + K -= math.factorial(N-1)*(a+1) + N -= 1 + return ans \ No newline at end of file diff --git a/problems/permutations-ii.py b/problems/permutations-ii.py index e4aa3c2..a6c9ff7 100644 --- a/problems/permutations-ii.py +++ b/problems/permutations-ii.py @@ -53,3 +53,28 @@ def helper(path): counter = collections.Counter(nums) helper([]) return ans + + +""" +差板法 +""" +class Solution(object): + def permuteUnique(self, nums): + if not nums: return [] + + permutations = collections.deque([[nums[0]]]) + + for i in xrange(1, len(nums)): + num = nums[i] + l = len(permutations) + + while l: + permutation = permutations.popleft() + for j in xrange(len(permutation)+1): + if 0=0 and n-group[i-1]>=0 else 0) + dp[i-1][n][p] if i==len(profit) and p>=minProfit and n<=maxMember: count += dp[i][n][p] return count - \ No newline at end of file + + + +""" +dp[i][g][p] := consider only crime[:i] the scheme that can generate profit p using man power g. +""" +class Solution(object): + def profitableSchemes(self, n, minProfit, group, profit): + N = len(profit) + + dp = [[[0]*(n+2) for _ in xrange(minProfit+1)] for _ in xrange(N+1)] + dp[0][0][0] = 1 + + for i in xrange(1, N+1): + for p in xrange(minProfit+1): + for g in xrange(n+1): + pi = profit[i-1] + gi = group[i-1] + + #considerting last round using p and g + dp[i][p][g] += dp[i-1][p][g] + dp[i][min(pi+p, minProfit)][min(gi+g, n+1)] += dp[i-1][p][g] + + ans = 0 + for g in xrange(n+1): + ans += dp[N][minProfit][g] + return ans % (10**9 + 7) \ No newline at end of file diff --git a/problems/single-threaded-cpu.py b/problems/single-threaded-cpu.py new file mode 100644 index 0000000..fe30e21 --- /dev/null +++ b/problems/single-threaded-cpu.py @@ -0,0 +1,22 @@ +class Solution(object): + def getOrder(self, tasks): + ans = [] + tasks = sorted([(task[0], task[1], i) for i, task in enumerate(tasks)], reverse=True) + pq = [] #tasks available + now = 0 + + + while tasks or pq: + #check if the task is availiable, if yes, add to pq + while tasks and tasks[-1][0]<=now: + startTime, processTime, i = tasks.pop() + heapq.heappush(pq, (processTime, i)) + + if pq: + processTime, i = heapq.heappop(pq) + ans.append(i) + now += processTime + else: + now = tasks[-1][0] + + return ans \ No newline at end of file diff --git a/problems/target-sum.py b/problems/target-sum.py index 75d9abe..c216522 100644 --- a/problems/target-sum.py +++ b/problems/target-sum.py @@ -55,4 +55,23 @@ def findTargetSumWays(self, nums, target): for t in xrange(minTarget, maxTarget+1): dp[i][t] = (dp[i-1][t-nums[i-1]] if t-nums[i-1]>=minTarget else 0) + (dp[i-1][t+nums[i-1]] if t+nums[i-1]<=maxTarget else 0) - return dp[N][target] \ No newline at end of file + return dp[N][target] + + +""" +dp[i][s] := considerting nums[:i] how many expressions can sum up to s. +dp[0][0] = 1 +""" +class Solution(object): + def findTargetSumWays(self, nums, target): + S = sum(nums) + if not -S<=target<=S: return 0 + + dp = [{s:0 for s in xrange(-S, S+1)} for _ in xrange(len(nums)+1)] + dp[0][0] = 1 + + for i in xrange(1, len(nums)+1): + for s in xrange(-S, S+1): + dp[i][s] = (dp[i-1][s+nums[i-1]] if s+nums[i-1]<=S else 0) + (dp[i-1][s-nums[i-1]] if s-nums[i-1]>=-S else 0) + + return dp[-1][target] \ No newline at end of file From 2191a5373def2d31ee450db15032179ecc43f11c Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 1 Mar 2022 17:01:54 +0800 Subject: [PATCH 148/187] no message --- .../amount-of-new-area-painted-each-day.py | 40 ++++++ problems/basic-calculator-ii.py | 31 +++++ problems/buildings-with-an-ocean-view.py | 16 +++ ...earch-tree-to-sorted-doubly-linked-list.py | 26 +++- problems/custom-sort-string.py | 20 +++ problems/dot-product-of-two-sparse-vectors.py | 16 +++ ...ll-possible-recipes-from-given-supplies.py | 33 +++++ problems/k-closest-points-to-origin.py | 118 +++++++++++++++++- .../longest-increasing-path-in-a-matrix.py | 31 +++++ problems/making-a-large-island.py | 44 +++++++ ...to-convert-binary-matrix-to-zero-matrix.py | 4 - problems/minimum-time-difference.py | 32 +++++ problems/next-permutation.py | 31 ++++- problems/powx-n.py | 12 ++ problems/simplify-path.py | 18 +++ problems/student-attendance-record-ii.py | 1 - problems/swap-adjacent-in-lr-string.py | 18 +++ problems/valid-number.py | 44 +++++++ problems/valid-palindrome-ii.py | 29 +++++ problems/valid-word-abbreviation.py | 30 +++++ ...rtical-order-traversal-of-a-binary-tree.py | 41 +++++- 21 files changed, 626 insertions(+), 9 deletions(-) create mode 100644 problems/amount-of-new-area-painted-each-day.py create mode 100644 problems/basic-calculator-ii.py create mode 100644 problems/buildings-with-an-ocean-view.py create mode 100644 problems/custom-sort-string.py create mode 100644 problems/dot-product-of-two-sparse-vectors.py create mode 100644 problems/find-all-possible-recipes-from-given-supplies.py create mode 100644 problems/longest-increasing-path-in-a-matrix.py create mode 100644 problems/making-a-large-island.py create mode 100644 problems/minimum-time-difference.py create mode 100644 problems/powx-n.py create mode 100644 problems/simplify-path.py create mode 100644 problems/swap-adjacent-in-lr-string.py create mode 100644 problems/valid-number.py create mode 100644 problems/valid-palindrome-ii.py create mode 100644 problems/valid-word-abbreviation.py diff --git a/problems/amount-of-new-area-painted-each-day.py b/problems/amount-of-new-area-painted-each-day.py new file mode 100644 index 0000000..a5504d5 --- /dev/null +++ b/problems/amount-of-new-area-painted-each-day.py @@ -0,0 +1,40 @@ +""" +1. Build sorted records = [(position, index, isStart)...] +2. Iterate through all positions and maintain a box with all the "index" of the records its position is in start ~ end +3. The smallest index in the box is the actual one that is paiting. + +Time: O(NLogN+P), N is the count of paint. Sorting the records takes NLogN. P is the max position. +Although there is a while loop when iterate through P, each record is only being iterated once. +O(NLogN + P + NLogN) ~= O(NLogN + P) +Space: O(N) +""" +from sortedcontainers import SortedList + +class Solution(object): + def amountPainted(self, paint): + ans = [0]*len(paint) + box = SortedList() + records = [] + maxPos = float('-inf') + + #[1] + for i, (start, end) in enumerate(paint): + records.append((start, i, -1)) + records.append((end, i, 1)) + maxPos = max(maxPos, end) + + records.sort() + + #[2] + i = 0 + for pos in xrange(maxPos+1): + while icurrMaxHeight: ans.append(i) + currMaxHeight = max(currMaxHeight, h) + + return reversed(ans) \ No newline at end of file diff --git a/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py b/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py index a9cd2bf..f813a37 100644 --- a/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py +++ b/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py @@ -103,4 +103,28 @@ def inOrderTraverse(root): node = node.right - \ No newline at end of file +""" +Time: O(N) +Space: O(LogN) +""" +class Solution(object): + def treeToDoublyList(self, root): + def helper(node): + ll = rr = node + if node.left: + ll, lr = helper(node.left) + node.left = lr + lr.right = node + + if node.right: + rl, rr = helper(node.right) + node.right = rl + rl.left = node + + return ll, rr + + if not root: return root + left, right = helper(root) + right.right = left + left.left = right + return left \ No newline at end of file diff --git a/problems/custom-sort-string.py b/problems/custom-sort-string.py new file mode 100644 index 0000000..2e63523 --- /dev/null +++ b/problems/custom-sort-string.py @@ -0,0 +1,20 @@ +""" +Take a look at the char in s. +For the char that is in the order, rearrange them to sortedChars with respect to the "order". +For the char that is in not the order, put them in postString. +""" +class Solution(object): + def customSortString(self, order, s): + sortedChars = '' + counter = collections.Counter(s) + for c in order: + if c in order: + sortedChars += c*counter[c] + + orderSet = set(order) + postString = '' + for c in s: + if c not in orderSet: + postString += c + + return sortedChars+postString \ No newline at end of file diff --git a/problems/dot-product-of-two-sparse-vectors.py b/problems/dot-product-of-two-sparse-vectors.py new file mode 100644 index 0000000..be69714 --- /dev/null +++ b/problems/dot-product-of-two-sparse-vectors.py @@ -0,0 +1,16 @@ +class SparseVector: + def __init__(self, nums): + self.indices = set() + self.values = {} + + for i, n in enumerate(nums): + if n!=0: + self.indices.add(i) + self.values[i] = n + + def dotProduct(self, vec): + products = 0 + indices = self.indices.intersection(vec.indices) + for i in indices: + products += self.values[i]*vec.values[i] + return products \ No newline at end of file diff --git a/problems/find-all-possible-recipes-from-given-supplies.py b/problems/find-all-possible-recipes-from-given-supplies.py new file mode 100644 index 0000000..13772ac --- /dev/null +++ b/problems/find-all-possible-recipes-from-given-supplies.py @@ -0,0 +1,33 @@ +""" +Use Topological Sort +1. Build an adj list and inbound. +2. Starts from supplies topologically traverse the map. +3. For each node popping up, if it is in recipes, add it to ans. + +Time: O(N), N is the number of "nodes" (ingredients+recipes) +Space: O(N). +""" +class Solution(object): + def findAllRecipes(self, recipes, ingredients, supplies): + N = len(recipes) + adj = collections.defaultdict(list) + inbounds = collections.Counter() + q = collections.deque(supplies) + recipeSet = set(recipes) + ans = [] + + for i, recipe in enumerate(recipes): + for ingredient in ingredients[i]: + adj[ingredient].append(recipe) + inbounds[recipe] += 1 + + while q: + node = q.popleft() + + if node in recipeSet: ans.append(node) + + for nei in adj[node]: + inbounds[nei] -= 1 + if inbounds[nei]==0: q.append(nei) + + return ans \ No newline at end of file diff --git a/problems/k-closest-points-to-origin.py b/problems/k-closest-points-to-origin.py index 8af9889..1f536c1 100644 --- a/problems/k-closest-points-to-origin.py +++ b/problems/k-closest-points-to-origin.py @@ -12,4 +12,120 @@ def kClosest(self, points, k): else: heapq.heappush(h, (-d, x, y)) - return [(x, y) for _, x, y in h] \ No newline at end of file + return [(x, y) for _, x, y in h] + + +""" +1. Process `points` into `distances`. + +2. Binary search the "distance". For every distance: +Split the elements in `distances` by distance +Put the ones smaller to smaller. +Put the ones larger to larger. +If len(smaller)<=k, then all the elements in the smaller must belong to the `ans`, do the same thing to the larger. +Else we ignore the larger and do the same thing to the smaller again. + +Time: O(N) +The binary search range in average is N, N/2, N/4... = 2N +Space: O(N) +""" +class Solution(object): + def kClosest(self, points, K): + #[1] + maxD = float('-inf') + minD = float('inf') + distances = [] + for x, y in points: + distance = ((x**2+y**2)**0.5) + distances.append((distance, x, y)) + maxD = max(maxD, distance) + minD = min(minD, distance) + + #[2] + ans = [] + smaller = [] + larger = [] + while K>0: + #split distances into smaller and larger + distance = (maxD+minD)/2 + for d, x, y in distances: + if d<=distance: + smaller.append((d, x, y)) + else: + larger.append((d, x, y)) + + if len(smaller)<=K: + ans += smaller + K -= len(smaller) + distances = larger + minD = distance + larger = [] + smaller = [] + else: + distances = smaller + maxD = distance + larger = [] + smaller = [] + + return [(x, y) for _, x, y in ans] + + + +""" +Quick Select +Time: O(N) +Space: O(N), can be optimize to O(1). +""" +class Solution(object): + def kClosest(self, points, K): + """ + Start State: + i = s #next element after "SSS"s + t = s #unprocessed elements + j = e #next element after "LLLL"s + + SSSPP?????LLL + i t j + + End State: + SSSPPPPPLLLLL + i jt + """ + def quickSelect(distances, s, e, k): + + pivot = distances[(s+e)/2][0] + i = s + j = e + t = s + + while t<=j: + if pivotdistances[t][0]: + distances[t], distances[i] = distances[i], distances[t] + i += 1 + t += 1 + else: + t += 1 + + if i-s>=k: + return quickSelect(distances, s, i, k) + elif j-s+1>=k: + return pivot + else: + return quickSelect(distances, t, e, k-(t-s)) + + distances = [] + for x, y in points: + distance = ((x**2+y**2)**0.5) + distances.append((distance, x, y)) + + kthSmallestDistance = quickSelect(distances, 0, len(distances)-1, K) + + ans = [] + for d, x, y in distances: + if len(ans)==K: break + if d<=kthSmallestDistance: ans.append((x, y)) + + return ans \ No newline at end of file diff --git a/problems/longest-increasing-path-in-a-matrix.py b/problems/longest-increasing-path-in-a-matrix.py new file mode 100644 index 0000000..cd446d9 --- /dev/null +++ b/problems/longest-increasing-path-in-a-matrix.py @@ -0,0 +1,31 @@ +class Solution(object): + def longestIncreasingPath(self, matrix): + def getLongest(i, j): + if (i, j) in longest: return longest[(i, j)] + l = 1 + + #call getLongest to the neighbors that are larger than itself. + if i+1=0 and matrix[i][j]=0 and matrix[i][j]1: + neiGroupId.add(grid[iNext][jNext]) + + for groupId in list(neiGroupId): + neiSize += groupIdToSize[groupId] + + ans = max(ans, 1+neiSize) + + return ans \ No newline at end of file diff --git a/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py b/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py index 2c07805..5559c80 100644 --- a/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py +++ b/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py @@ -39,8 +39,4 @@ def check(mat, state): q.append(nextState) return -1 - - - - \ No newline at end of file diff --git a/problems/minimum-time-difference.py b/problems/minimum-time-difference.py new file mode 100644 index 0000000..1645692 --- /dev/null +++ b/problems/minimum-time-difference.py @@ -0,0 +1,32 @@ +""" +Time: O(1440) +Space: O(1440) +""" +class Solution(object): + def findMinDifference(self, timeStrings): + def timeStringToMinutes(timeString): + time = timeString.split(':') + h = int(time[0]) + m = int(time[1]) + return h*60+m + + ans = float('inf') + minTime = float('inf') + maxTime = float('-inf') + timeSet = set() + for timeString in timeStrings: + t = timeStringToMinutes(timeString) + if t in timeSet: return 0 + minTime = min(minTime, t) + maxTime = max(maxTime, t) + timeSet.add(t) + + + prev = None + for t in xrange(minTime, maxTime+1): + if t not in timeSet: continue + if prev!=None: ans = min(ans, t-prev) + prev = t + + ans = min(ans, 1440+minTime-maxTime) #compare minTime and maxTime + return ans \ No newline at end of file diff --git a/problems/next-permutation.py b/problems/next-permutation.py index f228cc4..0a816ee 100644 --- a/problems/next-permutation.py +++ b/problems/next-permutation.py @@ -29,4 +29,33 @@ def swap(i, j): swap(i, j) reverse(i+1) - return nums \ No newline at end of file + return nums + +""" +Next Permutation means find the next (slightly) larger number using nums. + +1. Iterate from right, find the first num that is smaller. That's the one we are going to swap. => nums[i] +2. From the nums right to nums[i], find the smallest num that is larger than nums[i] => nums[j] +Since the right of the i must be an increasing sequence (looking from right), the first one that larger than nums[i] is the smallest one that is larger than nums[i] +3. Swap nums[i] and nums[j] +4. sort nums[i+1:] it will be the smallest permutaion. +5. Note that when an list is in increasing order looking from right, we can use `reverse` to sort it. +""" +class Solution(object): + def nextPermutation(self, nums): + def reverse(nums, l, r): + while l<=r: + nums[l], nums[r] = nums[r], nums[l] + l += 1 + r -= 1 + + i = len(nums)-2 + while i>=0 and nums[i]>=nums[i+1]: i -= 1 #[1] + + if i==-1: + return reverse(nums, 0, len(nums)-1) #nums is the largest permutation, sort nums + else: + j = len(nums)-1 + while j>i and nums[j]<=nums[i]: j -= 1 #[2] + nums[i], nums[j] = nums[j], nums[i] #[3] + reverse(nums, i+1, len(nums)-1) #[4] \ No newline at end of file diff --git a/problems/powx-n.py b/problems/powx-n.py new file mode 100644 index 0000000..d0fac2b --- /dev/null +++ b/problems/powx-n.py @@ -0,0 +1,12 @@ +class Solution(object): + def myPow(self, x, n): + if n==0: + return 1 + elif n<0: + return 1/self.myPow(x, -n) + elif n%2>0: + half = self.myPow(x, n-1) + return x*half + elif n%2==0: + half = self.myPow(x, n/2) + return half*half \ No newline at end of file diff --git a/problems/simplify-path.py b/problems/simplify-path.py new file mode 100644 index 0000000..46589cf --- /dev/null +++ b/problems/simplify-path.py @@ -0,0 +1,18 @@ +class Solution(object): + def simplifyPath(self, path): + ans = '' + skip = 0 + + for directory in reversed(path.split('/')): + if directory=='' or directory=='.': + continue + elif directory=='..': + skip += 1 + else: + if skip>0: + skip -= 1 + continue + else: + ans = '/'+directory+ans + + return ans if ans!='' else '/' \ No newline at end of file diff --git a/problems/student-attendance-record-ii.py b/problems/student-attendance-record-ii.py index ed55473..efc2923 100644 --- a/problems/student-attendance-record-ii.py +++ b/problems/student-attendance-record-ii.py @@ -17,7 +17,6 @@ def checkRecord(self, n): dp[i] += dp[i-1]%M #ends at P dp[i] += (dp[i-1]%M - dp[i-4]%M) #ends at L. All posiblity but the end cannot be PLL - ans += dp[n] for i in xrange(n): diff --git a/problems/swap-adjacent-in-lr-string.py b/problems/swap-adjacent-in-lr-string.py new file mode 100644 index 0000000..a8acf65 --- /dev/null +++ b/problems/swap-adjacent-in-lr-string.py @@ -0,0 +1,18 @@ +class Solution(object): + def canTransform(self, start, end): + if len(start)!=len(end): return False + if start.replace('X', '')!=end.replace('X', ''): return False + + startLIndex = [i for i, c in enumerate(start) if c=='L'] + endLIndex = [i for i, c in enumerate(end) if c=='L'] + for i in xrange(len(startLIndex)): + if startLIndex[i]endRIndex[i]: + return False + + return True \ No newline at end of file diff --git a/problems/valid-number.py b/problems/valid-number.py new file mode 100644 index 0000000..81a71b3 --- /dev/null +++ b/problems/valid-number.py @@ -0,0 +1,44 @@ +class Solution(object): + def isNumber(self, s): + def isOK(s, maxDots): + if not s: return False + + #check and remove +/- + for i, c in enumerate(s): + if (c=='+' or c=='-') and i!=0: + return False + if s[0]=='+' or s[0]=='-': s = s[1:] + + #check dot and if there is digit + dotCount = 0 + dotPos = 0 + digitCount = 0 + for i, c in enumerate(s): + if c=='.': + dotCount += 1 + dotPos = i + elif c.isdigit(): + digitCount += 1 + + if dotCount>maxDots: return False + if digitCount==0: return False + + return True + + #get e's position. Also check if all char is in validChar + validChar = set(['1','2', '3', '4', '5', '6', '7', '8', '9', '0', 'e', 'E', '.', '+', '-']) + eCount = 0 + ePos = 0 + for i, c in enumerate(s): + if c not in validChar: + return False + if c=='e' or c=='E': + eCount += 1 + ePos = i + + if eCount>1: + return False + elif eCount==1: + return isOK(s[:ePos], 1) and isOK(s[ePos+1:], 0) + else: + return isOK(s, 1) \ No newline at end of file diff --git a/problems/valid-palindrome-ii.py b/problems/valid-palindrome-ii.py new file mode 100644 index 0000000..84bce52 --- /dev/null +++ b/problems/valid-palindrome-ii.py @@ -0,0 +1,29 @@ +""" +When seeing the first different chars in the string. +Check if anyone of the string is palindrome if we remove one of them. + +Time: O(N) +Space: O(1) +""" +class Solution(object): + def validPalindrome(self, s): + def isPalindrome(s): + i = 0 + j = len(s)-1 + while i1: + temp += sorted(data[(x, y)]) + else: + temp.append(data[(x, y)][0]) + ans.append(temp) + return ans \ No newline at end of file From a9671e8430d8449d39aa611995b6808c6fb7ff95 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Wed, 2 Mar 2022 18:28:53 +0800 Subject: [PATCH 149/187] no message --- README.md | 2 +- problems/accounts-merge.py | 116 +++++++++++++++++++++++++----- problems/diagonal-traverse.py | 25 +++++++ problems/group-shifted-strings.py | 20 ++++++ problems/making-a-large-island.py | 7 ++ problems/maximum-swap.py | 23 ++++++ problems/valid-number.py | 2 +- 7 files changed, 176 insertions(+), 19 deletions(-) create mode 100644 problems/diagonal-traverse.py create mode 100644 problems/group-shifted-strings.py create mode 100644 problems/maximum-swap.py diff --git a/README.md b/README.md index dd42196..f076d25 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ I found it makes sense to solve similar problems together, so that we can recogn 3. [What should I know from the CLRS 3rd edition book if my aim is to get into Google?](https://www.quora.com/What-should-I-know-from-the-CLRS-3rd-edition-book-if-my-aim-is-to-get-into-Google/answer/Jimmy-Saade) ## Data Structures and Algorithms for beginners -If you are new or know nothing about data structures and algorithms, I recommend [this course](). This course is taught in Python and design to help you find job and do well in the interview. +If you are new or know nothing about data structures and algorithms, I recommend [this course](). This course is taught in Python and design to help you find job and do well in the interview. # System Design diff --git a/problems/accounts-merge.py b/problems/accounts-merge.py index 30e4787..91e03ef 100644 --- a/problems/accounts-merge.py +++ b/problems/accounts-merge.py @@ -1,3 +1,22 @@ +""" +Treat each email as a node. +Build an adjacency graph. [0] + +For every account's data +First, lets check if the first email is already merged. [1] +If the first email is already merged to other groups, then other emails will be in another group as well. +So don't need to check. + +Second, do a DFS starting from the first email. Put all the connected nodes into visited. [2] +And append the sorted(visited) to the ans with name. [3] + +Let N be the total number of emails. M be the total number of final groups. +Build the graph takes O(N). +For each final groups, we make a DFS to all nodes, taking O(MN). +Sort the group takes O((N/M)*Log(N/M)) -> O((N/M)*(logN-LogM)) +Time: O(MN) +Space: O(N) +""" from collections import defaultdict class Solution(object): @@ -31,22 +50,85 @@ def accountsMerge(self, accounts): return ans -""" -Treat each email as a node. -Build an adjacency graph. [0] - -For every account's data -First, lets check if the first email is already merged. [1] -If the first email is already merged to other groups, then other emails will be in another group as well. -So don't need to check. -Second, do a DFS starting from the first email. Put all the connected nodes into visited. [2] -And append the sorted(visited) to the ans with name. [3] +#Union Find +class Solution(object): + def accountsMerge(self, accounts): + def find(x): + p = parents[x] + while p!=parents[p]: + p = find(p) + parents[x] = p + return p + + def union(x, y): + p1, p2 = find(x), find(y) + if p1==p2: return + parents[p2] = p1 + + parents = {} + mailToName = {} + + for account in accounts: + name = account[0] + root = account[1] + if root not in parents: parents[root] = root + root = find(root) + mailToName[root] = name + + for i in xrange(2, len(account)): + email = account[i] + if email in parents: + union(parents[email], root) + root = find(root) + parents[email] = root + + rootToMails = collections.defaultdict(list) + for email in parents: + rootToMails[find(email)].append(email) + + ans = [] + for root in rootToMails: + name = mailToName[root] + mails = rootToMails[root] + ans.append([name]+sorted(mails)) + + return ans -Let N be the total number of emails. M be the total number of final groups. -Build the graph takes O(N). -For each final groups, we make a DFS to all nodes, taking O(MN). -Sort the group takes O((N/M)*Log(N/M)) -> O((N/M)*(logN-LogM)) -Time: O(MN) -Space: O(N) -""" \ No newline at end of file +#DFS +class Solution(object): + def accountsMerge(self, accounts): + + #build adjacency list + adj = collections.defaultdict(list) + for account in accounts: + name = account[0] + email0 = account[1] + for i in xrange(2, len(account)): + email = account[i] + adj[email0].append(email) + adj[email].append(email0) + + #iterate accounts and dfs each email group + ans = [] + visited = set() #store all the visited email + for account in accounts: + name = account[0] + email0 = account[1] + if email0 in visited: continue + + #dfs + group = set() #store the email group related to email0 + stack = [email0] + while stack: + email = stack.pop() + if email in group or email in visited: continue + group.add(email) + visited.add(email) + for nei in adj[email]: + stack.append(nei) + + ans.append([name]+sorted(list(group))) + + return ans + \ No newline at end of file diff --git a/problems/diagonal-traverse.py b/problems/diagonal-traverse.py new file mode 100644 index 0000000..0510201 --- /dev/null +++ b/problems/diagonal-traverse.py @@ -0,0 +1,25 @@ +class Solution(object): + def findDiagonalOrder(self, mat): + def helper(i, j, reverse): + output = [] + while 0<=i=0 else 26+(getNumByChar(c)+offset)) + return h + + def getNumByChar(letter): + return ord(letter) - 97 + + def getCharByNum(pos): + return chr(pos + 97) + + groups = collections.defaultdict(list) + for string in strings: + h = getHash(string) + groups[h].append(string) + return groups.values() \ No newline at end of file diff --git a/problems/making-a-large-island.py b/problems/making-a-large-island.py index 0df3ac0..215aa2a 100644 --- a/problems/making-a-large-island.py +++ b/problems/making-a-large-island.py @@ -1,3 +1,10 @@ +""" +For each "island" asign them a group id. Also calculate the group's size. +Iterate all the zeros, update the ans. + +Time:O(MN) +Space: O(MN) in the worst case. +""" class Solution(object): def largestIsland(self, grid): def isValid(i, j, M, N): diff --git a/problems/maximum-swap.py b/problems/maximum-swap.py new file mode 100644 index 0000000..ffca66a --- /dev/null +++ b/problems/maximum-swap.py @@ -0,0 +1,23 @@ +""" +1. Generate positions. Storing the mapping between number to indices. +2. Iterate from left, for each n1, find the largest number larger than n1 (searching from 9, 8, 7 to n1+1). +3. Since we need to find the max output. There might be multiple the same number, we need to find the index of the rightest number. +4. Remove n1 when it is done. Because right of the n1 should not consider it anymore. +""" +class Solution(object): + def maximumSwap(self, num): + numList = [int(n) for n in str(num)] + positions = collections.defaultdict(list) + for i, n in enumerate(numList): positions[n].append(i) #[1] + + i = 0 + for i, n1 in enumerate(numList): #[2] + n1 = numList[i] + for n2 in xrange(9, n1, -1): + if n2 in positions and len(positions[n2])>0: + j = positions[n2][-1] #[3] + numList[i], numList[j] = numList[j], numList[i] + return int(''.join([str(n) for n in numList])) + positions[n1].pop(0) #[4] + + return num \ No newline at end of file diff --git a/problems/valid-number.py b/problems/valid-number.py index 81a71b3..9d0793a 100644 --- a/problems/valid-number.py +++ b/problems/valid-number.py @@ -41,4 +41,4 @@ def isOK(s, maxDots): elif eCount==1: return isOK(s[:ePos], 1) and isOK(s[ePos+1:], 0) else: - return isOK(s, 1) \ No newline at end of file + return isOK(s, 1) From 6f00d183b5ec1bf4888eb20ab164c5e1ec32ef5f Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sat, 5 Mar 2022 09:49:07 +0800 Subject: [PATCH 150/187] no message --- problems/add-strings.py | 34 ++++++++++++++++ problems/cheapest-flights-within-k-stops.py | 3 ++ problems/continuous-subarray-sum.py | 35 +++++++++++++++++ problems/cutting-ribbons.py | 13 +++++++ problems/exclusive-time-of-functions.py | 24 ++++++++++++ problems/expression-add-operators.py | 23 +++++++++++ problems/find-peak-element.py | 21 +++++++++- ...emove-all-adjacent-duplicates-in-string.py | 12 ++++++ problems/remove-invalid-parentheses.py | 38 ++++++++++++++++++ .../shortest-distance-from-all-buildings.py | 39 +++++++++++++++++++ problems/shortest-path-in-binary-matrix.py | 17 ++++++++ problems/subarray-sum-equals-k.py | 1 - problems/toeplitz-matrix.py | 22 +++++++++++ 13 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 problems/add-strings.py create mode 100644 problems/continuous-subarray-sum.py create mode 100644 problems/cutting-ribbons.py create mode 100644 problems/exclusive-time-of-functions.py create mode 100644 problems/expression-add-operators.py create mode 100644 problems/remove-all-adjacent-duplicates-in-string.py create mode 100644 problems/remove-invalid-parentheses.py create mode 100644 problems/shortest-distance-from-all-buildings.py create mode 100644 problems/shortest-path-in-binary-matrix.py create mode 100644 problems/toeplitz-matrix.py diff --git a/problems/add-strings.py b/problems/add-strings.py new file mode 100644 index 0000000..9cdd7f9 --- /dev/null +++ b/problems/add-strings.py @@ -0,0 +1,34 @@ +class Solution(object): + def addStrings(self, nums1, nums2): + ans = '' + i = len(nums1)-1 + j = len(nums2)-1 + + carry = 0 + while 0<=i and 0<=j: + n1 = int(nums1[i]) + n2 = int(nums2[j]) + total = n1+n2+carry + n = total%10 + carry = 1 if total>=10 else 0 + ans = str(n)+ans + i -= 1 + j -= 1 + + while 0<=i: + total = int(nums1[i])+carry + n = total%10 + carry = 1 if total>=10 else 0 + ans = str(n)+ans + i -= 1 + + while 0<=j: + total = int(nums2[j])+carry + n = total%10 + carry = 1 if total>=10 else 0 + ans = str(n)+ans + j -= 1 + + if carry: ans = str(carry)+ans + + return ans \ No newline at end of file diff --git a/problems/cheapest-flights-within-k-stops.py b/problems/cheapest-flights-within-k-stops.py index 28b2927..eb785b3 100644 --- a/problems/cheapest-flights-within-k-stops.py +++ b/problems/cheapest-flights-within-k-stops.py @@ -23,16 +23,19 @@ class Solution1(object): def findCheapestPrice(self, n, flights, src, dst, K): graph = collections.defaultdict(list) pq = [] + visited = set() for u, v, w in flights: graph[u].append((w, v)) heapq.heappush(pq, (0, K+1, src)) while pq: price, stops, city = heapq.heappop(pq) + visited.add(city) if city is dst: return price if stops>0: for price_to_nei, nei in graph[city]: + if nei in visited: continue heapq.heappush(pq, (price+price_to_nei, stops-1, nei)) return -1 diff --git a/problems/continuous-subarray-sum.py b/problems/continuous-subarray-sum.py new file mode 100644 index 0000000..75dd08b --- /dev/null +++ b/problems/continuous-subarray-sum.py @@ -0,0 +1,35 @@ +class Solution(object): + def checkSubarraySum(self, nums, k): + prefixSumEndings = collections.defaultdict(list) + prefixSumEndings[0].append(-1) + + prefixSum = 0 + for i, n in enumerate(nums): + prefixSum += n + + x = prefixSum/k + while x>=0: + p2 = prefixSum-k*x + if len(prefixSumEndings[p2])>0 and prefixSumEndings[p2][0]=1: return True + if len(prefixSumKRemain[remain])>0 and prefixSumKRemain[remain][0]=k: + minLen = l + else: + maxLen = l-1 + return maxLen \ No newline at end of file diff --git a/problems/exclusive-time-of-functions.py b/problems/exclusive-time-of-functions.py new file mode 100644 index 0000000..0f4fc4d --- /dev/null +++ b/problems/exclusive-time-of-functions.py @@ -0,0 +1,24 @@ +class Solution(object): + def exclusiveTime(self, n, logs): + ans = [0]*n + data = [] + for log in logs: + fid, action, t = log.split(':') + data.append([int(t), -1 if action=='start' else 1, int(fid)]) + + data.sort() + + stack = [] + for t, action, fid in data: + if action==-1: + if stack: + prevT, _, prevFid = stack[-1] + ans[prevFid] += t-prevT + elif action==1: + prevT, _, prevFid = stack.pop() + ans[fid] += t+1-prevT + if stack: stack[-1][0] = t+1 + + if action==-1: stack.append([t, action, fid]) + + return ans \ No newline at end of file diff --git a/problems/expression-add-operators.py b/problems/expression-add-operators.py new file mode 100644 index 0000000..64421a7 --- /dev/null +++ b/problems/expression-add-operators.py @@ -0,0 +1,23 @@ +class Solution(object): + def addOperators(self, num, target): + def dfs(num, curr, i): + if i==len(num): + if eval(curr[1:])==target: ans.append(curr[1:]) + return + + if curr and curr[-1] in operators: + dfs(num, curr+num[i], i+1) + elif curr and curr[-1]=='0': + dfs(num, curr+'+', i) + dfs(num, curr+'-', i) + dfs(num, curr+'*', i) + else: + dfs(num, curr+'+', i) + dfs(num, curr+'-', i) + dfs(num, curr+'*', i) + dfs(num, curr+num[i], i+1) + + operators = set(['+', '-', '*']) + ans = [] + dfs(num, '+', 0) + return ans \ No newline at end of file diff --git a/problems/find-peak-element.py b/problems/find-peak-element.py index 5b9a8b3..aeb4726 100644 --- a/problems/find-peak-element.py +++ b/problems/find-peak-element.py @@ -54,5 +54,24 @@ def findPeakElement(self, nums): return l - + +""" +[l, r] is the possible range. +Keep decreasing the range unsing binary search until l==r. +Pay attention to +m = l+(r-l+1)/2 +Sometimes you need m = l+(r-l)/2 to avoid infinite loop. +""" +class Solution(object): + def findPeakElement(self, nums): + l = 0 + r = len(nums)-1 + + while lself.maxLen: return + + if i>=len(s): + if len(curr)==self.maxLen and count==0: + self.ans.append(curr) + return + + if s[i]!='(' and s[i]!=')': + dfs(s, curr+s[i], i+1, count) + elif not curr or s[i]!=curr[-1]: + dfs(s, curr+s[i], i+1, count + (1 if s[i]=='(' else -1)) + dfs(s, curr, i+1, count) + elif s[i]==curr[-1]: + dfs(s, curr+s[i], i+1, count + (1 if s[i]=='(' else -1)) + + def getMaxLen(s): + openCount = removeCount = 0 + for c in s: + if c=='(': + openCount += 1 + elif c==')': + openCount -= 1 + + if openCount<0: + removeCount += abs(openCount) + openCount = 0 + removeCount += openCount + return len(s)-removeCount + + self.ans = [] + self.maxLen = getMaxLen(s) + + dfs(s, "", 0, 0) + return self.ans \ No newline at end of file diff --git a/problems/shortest-distance-from-all-buildings.py b/problems/shortest-distance-from-all-buildings.py new file mode 100644 index 0000000..490e6a2 --- /dev/null +++ b/problems/shortest-distance-from-all-buildings.py @@ -0,0 +1,39 @@ +class Solution(object): + def shortestDistance(self, grid): + def bfs(i0, j0): + q = collections.deque([(i0, j0, 0)]) + visited = set() + while q: + i, j, dis = q.popleft() + if (i, j) in visited: continue + visited.add((i, j)) + + reach[i][j] += 1 + distances[i][j] += dis + + for iNext, jNext in ((i+1, j), (i-1, j), (i, j+1), (i, j-1)): + if not (0<=iNext Date: Mon, 25 Apr 2022 18:49:04 +0800 Subject: [PATCH 151/187] no message --- README.md | 6 +++--- problems/{ => python}/01-matrix.py | 0 problems/{ => python}/3sum-closest.py | 0 problems/{ => python}/3sum.py | 0 problems/{ => python}/4sum.py | 0 problems/{ => python}/accounts-merge.py | 0 problems/{ => python}/add-binary.py | 0 problems/{ => python}/add-digits.py | 0 problems/{ => python}/add-strings.py | 0 problems/{ => python}/add-two-numbers-ii.py | 0 problems/{ => python}/add-two-numbers.py | 0 problems/{ => python}/alien-dictionary.py | 0 .../{ => python}/all-nodes-distance-k-in-binary-tree.py | 0 .../{ => python}/amount-of-new-area-painted-each-day.py | 0 problems/{ => python}/analyze-user-website-visit-pattern.py | 0 problems/{ => python}/backspace-string-compare.py | 0 problems/{ => python}/balance-a-binary-search-tree.py | 0 problems/{ => python}/balanced-binary-tree.py | 0 problems/{ => python}/basic-calculator-ii.py | 0 problems/{ => python}/best-time-to-buy-an-stock.py | 0 .../{ => python}/best-time-to-buy-and-sell-stock-iii.py | 0 .../best-time-to-buy-and-sell-stock-with-cooldown.py | 0 problems/{ => python}/best-time-to-buy-and-sell-stock.py | 0 problems/{ => python}/big-countries.sql | 0 problems/{ => python}/binary-search-tree-iterator.py | 0 problems/{ => python}/binary-search.py | 0 problems/{ => python}/binary-subarrays-with-sum.py | 0 problems/{ => python}/binary-tree-inorder-traversal.py | 0 .../{ => python}/binary-tree-level-order-traversal-ii.py | 0 problems/{ => python}/binary-tree-level-order-traversal.py | 0 .../binary-tree-longest-consecutive-sequence.py | 0 problems/{ => python}/binary-tree-maximum-path-sum.py | 0 problems/{ => python}/binary-tree-paths.py | 0 problems/{ => python}/binary-tree-pruning.py | 0 problems/{ => python}/binary-tree-right-side-view.py | 0 .../{ => python}/binary-tree-vertical-order-traversal.py | 0 problems/{ => python}/binary-watch.py | 0 problems/{ => python}/buildings-with-an-ocean-view.py | 0 problems/{ => python}/burst-balloons.py | 0 problems/{ => python}/campus-bikes-ii.py | 0 problems/{ => python}/candy.py | 0 .../{ => python}/capacity-to-ship-packages-within-d-days.py | 0 problems/{ => python}/cheapest-flights-within-k-stops.py | 0 problems/{ => python}/climbing-stairs.py | 0 problems/{ => python}/clone-graph.py | 0 problems/{ => python}/closest-binary-search-tree-value.py | 0 problems/{ => python}/coin-change.py | 0 problems/{ => python}/coloring-a-border.py | 0 problems/{ => python}/combination-sum-ii.py | 0 problems/{ => python}/combination-sum-iii.py | 0 problems/{ => python}/combination-sum-iv.py | 0 problems/{ => python}/combination-sum.py | 0 problems/{ => python}/combinations.py | 0 problems/{ => python}/combine-two-tables.sql | 0 problems/{ => python}/compare-version-numbers.py | 0 .../{ => python}/connecting-cities-with-minimum-cost.py | 0 problems/{ => python}/consecutive-numbers-sum.py | 0 ...ruct-binary-tree-from-inorder-and-postorder-traversal.py | 0 ...truct-binary-tree-from-preorder-and-inorder-traversal.py | 0 problems/{ => python}/container-with-most-water.py | 0 problems/{ => python}/contains-duplicate-ii.py | 0 problems/{ => python}/contains-duplicate-iii.py | 0 problems/{ => python}/contains-duplicate.py | 0 problems/{ => python}/continuous-subarray-sum.py | 0 ...nvert-binary-search-tree-to-sorted-doubly-linked-list.py | 0 .../convert-sorted-array-to-binary-search-tree.py | 0 .../convert-sorted-list-to-binary-search-tree.py | 0 problems/{ => python}/copy-list-with-random-pointer.py | 0 .../count-all-valid-pickup-and-delivery-opti.py | 0 problems/{ => python}/count-binary-substrings.py | 0 problems/{ => python}/count-complete-tree-nodes.py | 0 problems/{ => python}/count-number-of-nice-subarrays.py | 0 ...unique-characters-of-all-substrings-of-a-given-string.py | 0 problems/{ => python}/course-schedule-ii.py | 0 problems/{ => python}/course-schedule.py | 0 problems/{ => python}/custom-sort-string.py | 0 problems/{ => python}/cutting-ribbons.py | 0 problems/{ => python}/data-stream-as-disjoint-intervals.py | 0 problems/{ => python}/decode-string.py | 0 problems/{ => python}/decode-ways.py | 0 problems/{ => python}/delete-and-earn.py | 0 problems/{ => python}/delete-duplicate-folders-in-system.py | 0 problems/{ => python}/delete-node-in-a-bst.py | 0 problems/{ => python}/delete-operation-for-two-strings.py | 0 .../design-add-and-search-words-data-structure.py | 0 problems/{ => python}/design-in-memory-file-system.py | 0 problems/{ => python}/design-linked-list.py | 0 problems/{ => python}/design-tic-tac-toe.py | 0 problems/{ => python}/diagonal-traverse.py | 0 problems/{ => python}/diameter-of-binary-tree.py | 0 problems/{ => python}/different-ways-to-add-parentheses.py | 0 problems/{ => python}/distinct-subsequences.py | 0 problems/{ => python}/distribute-coins-in-binary-tree.py | 0 problems/{ => python}/domino-and-tromino-tiling.py | 0 problems/{ => python}/dot-product-of-two-sparse-vectors.py | 0 problems/{ => python}/dungeon-game.py | 0 problems/{ => python}/edit-distance.py | 0 problems/{ => python}/egions-cut-by-slashes.py | 0 problems/{ => python}/evaluate-division.py | 0 problems/{ => python}/evaluate-reverse-polish-notation.py | 0 problems/{ => python}/exclusive-time-of-functions.py | 0 problems/{ => python}/expression-add-operators.py | 0 problems/{ => python}/filling-bookcase-shelves.py | 0 .../find-all-possible-recipes-from-given-supplies.py | 0 problems/{ => python}/find-and-replace-in-string.py | 0 problems/{ => python}/find-distance-in-a-binary-tree.py | 0 problems/{ => python}/find-duplicate-subtrees.py | 0 problems/{ => python}/find-eventual-safe-states.py | 0 ...nd-first-and-last-position-of-element-in-sorted-array.py | 0 problems/{ => python}/find-k-closest-elements.py | 0 problems/{ => python}/find-k-pairs-with-smallest-sums.py | 0 problems/{ => python}/find-leaves-of-binary-tree.py | 0 problems/{ => python}/find-median-from-data-stream.py | 0 .../{ => python}/find-minimum-in-rotated-sorted-array-ii.py | 0 .../{ => python}/find-minimum-in-rotated-sorted-array.py | 0 problems/{ => python}/find-mode-in-binary-search-tree.py | 0 .../{ => python}/find-original-array-from-doubled-array,py | 0 problems/{ => python}/find-peak-element.py | 0 problems/{ => python}/find-the-duplicate-number.py | 0 problems/{ => python}/first-bad-version.py | 0 problems/{ => python}/first-missing-positive.py | 0 problems/{ => python}/first-unique-character-in-a-string.py | 0 problems/{ => python}/fizz-buzz.py | 0 problems/{ => python}/flatten-binary-tree-to-linked-list.py | 0 .../flip-binary-tree-to-match-preorder-traversal.py | 0 problems/{ => python}/flip-string-to-monotone-increasing.py | 0 problems/{ => python}/flood-fill.py | 0 problems/{ => python}/friend-circles.py | 0 problems/{ => python}/fruit-into-baskets.py | 0 problems/{ => python}/game-of-life.py | 0 problems/{ => python}/generate-parentheses.py | 0 problems/{ => python}/graph-valid-tree.py | 0 problems/{ => python}/greatest-sum-divisible-by-three.py | 0 problems/{ => python}/group-anagrams.py | 0 problems/{ => python}/group-shifted-strings.py | 0 problems/{ => python}/guess-number-higher-or-lower-ii.py | 0 problems/{ => python}/guess-number-higher-or-lower.py | 0 problems/{ => python}/guess-the-word.py | 0 problems/{ => python}/h-index-ii.py | 0 problems/{ => python}/h-index.py | 0 problems/{ => python}/hamming-distance.py | 0 problems/{ => python}/house-robber-ii.py | 0 problems/{ => python}/house-robber-iii.py | 0 problems/{ => python}/house-robber.py | 0 problems/{ => python}/implement-trie-prefix-tree.py | 0 problems/{ => python}/increasing-triplet-subsequence.py | 0 problems/{ => python}/inorder-successor-in-bst-ii.py | 0 problems/{ => python}/inorder-successor-in-bst.py | 0 problems/{ => python}/insert-interval.py | 0 problems/{ => python}/insert-into-a-binary-search-tree.py | 0 .../insert-into-a-sorted-circular-linked-list.py | 0 problems/{ => python}/insertion-sort-list.py | 0 problems/{ => python}/integer-to-english-words.py | 0 problems/{ => python}/interleaving-string.py | 0 problems/{ => python}/intersection-of-two-arrays-ii.py | 0 problems/{ => python}/intersection-of-two-arrays.py | 0 problems/{ => python}/invert-binary-tree.py | 0 problems/{ => python}/is-graph-bipartite.py | 0 problems/{ => python}/is-subsequence.py | 0 problems/{ => python}/isomorphic-strings.py | 0 problems/{ => python}/jewels-and-stones.py | 0 problems/{ => python}/jump-game.py | 0 problems/{ => python}/k-closest-points-to-origin.py | 0 problems/{ => python}/k-empty-slots.py | 0 problems/{ => python}/keys-and-rooms.py | 0 problems/{ => python}/knight-dialer.py | 0 problems/{ => python}/knight-probability-in-chessboard.py | 0 problems/{ => python}/koko-eating-bananas.py | 0 problems/{ => python}/kth-largest-element-in-an-array.py | 0 problems/{ => python}/kth-smallest-element-in-a-bst.py | 0 .../{ => python}/kth-smallest-element-in-a-sorted-matrix.py | 0 problems/{ => python}/largest-1-bordered-square.py | 0 problems/{ => python}/largest-bst-subtree.py | 0 problems/{ => python}/largest-sum-of-averages.py | 0 problems/{ => python}/last-stone-weight-ii.py | 0 problems/{ => python}/last-stone-weight.py | 0 .../least-number-of-unique-integers-after-k-removals.py | 0 problems/{ => python}/letter-case-permutation.py | 0 .../{ => python}/letter-combinations-of-a-phone-number.py | 0 problems/{ => python}/license-key-formatting.py | 0 problems/{ => python}/linked-list-cycle-ii.py | 0 problems/{ => python}/linked-list-cycle.py | 0 problems/{ => python}/linked-list-random-node.py | 0 problems/{ => python}/logger-rate-limiter.py | 0 problems/{ => python}/longest-common-prefix.py | 0 problems/{ => python}/longest-common-subsequence.py | 0 problems/{ => python}/longest-consecutive-sequence.py | 0 .../{ => python}/longest-increasing-path-in-a-matrix.py | 0 problems/{ => python}/longest-increasing-subsequence.py | 0 problems/{ => python}/longest-palindromic-subsequence.py | 0 problems/{ => python}/longest-palindromic-substring.py | 0 .../{ => python}/longest-repeating-character-replacement.py | 0 problems/{ => python}/longest-string-chain.py | 0 ...ongest-substring-with-at-least-k-repeating-characters.py | 0 .../longest-substring-without-repeating-characters.py | 0 problems/{ => python}/longest-univalue-path.py | 0 .../lowest-common-ancestor-of-a-binary-search-tree.py | 0 .../lowest-common-ancestor-of-a-binary-search.py | 0 .../lowest-common-ancestor-of-a-binary-tree-ii.py | 0 .../lowest-common-ancestor-of-a-binary-tree-iii.py | 0 .../lowest-common-ancestor-of-a-binary-tree-iv.py | 0 .../{ => python}/lowest-common-ancestor-of-a-binary-tree.py | 0 .../lowest-common-ancestor-of-deepest-leaves.py | 0 problems/{ => python}/lru-cache.py | 0 problems/{ => python}/majority-element-ii.py | 0 problems/{ => python}/majority-element.py | 0 problems/{ => python}/making-a-large-island.py | 0 problems/{ => python}/max-area-of-island.py | 0 problems/{ => python}/max-consecutive-ones-iii.py | 0 problems/{ => python}/max-stack.py | 0 .../{ => python}/max-sum-of-rectangle-no-larger-than-k.py | 0 problems/{ => python}/maximal-square.py | 0 problems/{ => python}/maximum-average-subtree.py | 0 problems/{ => python}/maximum-compatibility-score-sum.py | 0 problems/{ => python}/maximum-depth-of-binary-tree.py | 0 problems/{ => python}/maximum-gap.py | 0 .../{ => python}/maximum-length-of-repeated-subarray.py | 0 .../maximum-number-of-events-that-can-be-attended.py | 0 problems/{ => python}/maximum-number-of-points-with-cost.py | 0 problems/{ => python}/maximum-number-of-visible-points.py | 0 problems/{ => python}/maximum-product-of-three-numbers.py | 0 problems/{ => python}/maximum-product-subarray.py | 0 .../{ => python}/maximum-subarray-sum-with-one-deletion.py | 0 problems/{ => python}/maximum-subarray.py | 0 problems/{ => python}/maximum-swap.py | 0 problems/{ => python}/maximum-units-on-a-truck.py | 0 problems/{ => python}/median-of-two-sorted-arrays.py | 0 problems/{ => python}/meeting-rooms-ii.py | 0 problems/{ => python}/meeting-rooms.py | 0 problems/{ => python}/merge-intervals.py | 0 problems/{ => python}/merge-k-sorted-lists.py | 0 problems/{ => python}/merge-sorted-array.py | 0 problems/{ => python}/merge-two-sorted-lists.py | 0 problems/{ => python}/min-cost-climbing-stairs.py | 0 problems/{ => python}/min-stack.py | 0 problems/{ => python}/minimize-malware-spread.py | 0 problems/{ => python}/minimum-absolute-difference-in-bst.py | 0 .../minimum-ascii-delete-sum-for-two-strings.py | 0 problems/{ => python}/minimum-cost-to-connect-sticks.py | 0 problems/{ => python}/minimum-cost-to-hire-k-workers.py | 0 ...inimum-cost-to-make-at-least-one-valid-path-in-a-grid.py | 0 .../minimum-cost-to-reach-city-with-discounts.py | 0 problems/{ => python}/minimum-depth-of-binary-tree.py | 0 .../{ => python}/minimum-difficulty-of-a-job-schedule.py | 0 problems/{ => python}/minimum-falling-path-sum-ii.py | 0 problems/{ => python}/minimum-knight-moves.py | 0 ...mber-of-flips-to-convert-binary-matrix-to-zero-matrix.py | 0 problems/{ => python}/minimum-path-sum.py | 0 .../{ => python}/minimum-score-triangulation-of-polygon.py | 0 problems/{ => python}/minimum-size-subarray-sum.py | 0 .../{ => python}/minimum-swaps-to-group-all-1s-together.py | 0 .../minimum-swaps-to-make-sequences-increasing.py | 0 problems/{ => python}/minimum-time-difference.py | 0 problems/{ => python}/minimum-window-substring.py | 0 problems/{ => python}/minimum-xor-sum-of-two-arrays.py | 0 problems/{ => python}/missing-number.py | 0 problems/{ => python}/most-frequent-subtree-sum.py | 0 .../most-stones-removed-with-same-row-or-column.py | 0 problems/{ => python}/move-zeroes.py | 0 problems/{ => python}/moving-average-from-data-stream.py | 0 problems/{ => python}/my-calendar-ii.py | 0 problems/{ => python}/n-ary-tree-level-order-traversal.py | 0 problems/{ => python}/n-ary-tree-postorder-traversal.py | 0 problems/{ => python}/n-ary-tree-preorder-traversal.py | 0 problems/{ => python}/nested-list-weight-sum.py | 0 problems/{ => python}/network-delay-time.py | 0 problems/{ => python}/next-closest-time.py | 0 problems/{ => python}/next-permutation.py | 0 problems/{ => python}/number-complement.py | 0 ...number-of-connected-components-in-an-undirected-graph.py | 0 problems/{ => python}/number-of-islands-ii.py | 0 problems/{ => python}/number-of-islands.py | 0 .../number-of-longest-increasing-subsequence.py | 0 problems/{ => python}/number-of-matching-subsequences.py | 0 problems/{ => python}/number-of-provinces.py | 0 problems/{ => python}/number-of-recent-calls.py | 0 problems/{ => python}/number-of-squareful-arrays.py | 0 .../number-of-substrings-containing-all-thre.py | 0 .../{ => python}/number-of-ways-to-arrive-at-destination.py | 0 problems/{ => python}/odd-even-jump.py | 0 problems/{ => python}/ones-and-zeroes.py | 0 problems/{ => python}/open-the-lock.py | 0 problems/{ => python}/out-of-boundary-paths.py | 0 problems/{ => python}/pacific-atlantic-water-flow.py | 0 .../pairs-of-songs-with-total-durations-divisible-by-60.py | 0 problems/{ => python}/palindrome-number.py | 0 problems/{ => python}/palindrome-pairs.py | 0 problems/{ => python}/palindrome-partitioning-iii.py | 0 problems/{ => python}/palindrome-partitioning.py | 0 problems/{ => python}/palindromic-substrings.py | 0 problems/{ => python}/partition-array-for-maximum-sum.py | 0 problems/{ => python}/partition-labels.py | 0 problems/{ => python}/partition-to-k-equal-sum-subsets.py | 0 problems/{ => python}/path-sum-ii.py | 0 problems/{ => python}/path-sum-iii.py | 0 problems/{ => python}/path-sum.py | 0 problems/{ => python}/path-with-maximum-probability.py | 0 .../peak-index-in-a-mountain-array.py} | 0 problems/{ => python}/perfect-squares.py | 0 problems/{ => python}/permutation-in-string.py | 0 problems/{ => python}/permutation-sequence.py | 0 problems/{ => python}/permutations-ii.py | 0 problems/{ => python}/permutations.py | 0 .../populating-next-right-pointers-in-each-node-ii.py | 0 .../populating-next-right-pointers-in-each-node.py | 0 problems/{ => python}/powx-n.py | 0 problems/{ => python}/product-of-array-except-self.py | 0 problems/{ => python}/profitable-schemes.py | 0 problems/{ => python}/queue-reconstruction-by-height.py | 0 problems/{ => python}/random-pick-with-weight.py | 0 problems/{ => python}/range-addition.py | 0 problems/{ => python}/range-sum-of-bst.py | 0 problems/{ => python}/range-sum-query-immutable.py | 0 problems/{ => python}/range-sum-query-mutable.py | 0 problems/{ => python}/rearrange-string-k-distance-apart.py | 0 problems/{ => python}/reconstruct-itinerary.py | 0 problems/{ => python}/recover-binary-search-tree.py | 0 problems/{ => python}/redundant-connection.py | 0 .../remove-all-adjacent-duplicates-in-string.py | 0 .../remove-all-ones-with-row-and-column-flips.py | 0 .../{ => python}/remove-duplicates-from-sorted-array-ii.py | 0 .../{ => python}/remove-duplicates-from-sorted-array.py | 0 problems/{ => python}/remove-duplicates-from-sorted-list.py | 0 problems/{ => python}/remove-element.py | 0 problems/{ => python}/remove-invalid-parentheses.py | 0 problems/{ => python}/remove-linked-list-elements.py | 0 problems/{ => python}/remove-nth-node-from-end-of-list.py | 0 problems/{ => python}/reorder-list.py | 0 problems/{ => python}/repeated-string-match.py | 0 .../replace-the-substring-for-balanced-string.py | 0 problems/{ => python}/restore-ip-addresses.py | 0 problems/{ => python}/reverse-integer.py | 0 problems/{ => python}/reverse-linked-list.py | 0 problems/{ => python}/reverse-string.py | 0 problems/{ => python}/reverse-vowels-of-a-string.py | 0 problems/{ => python}/reverse-words-in-a-string.py | 0 problems/{ => python}/robot-bounded-in-circle.py | 0 problems/{ => python}/roman-to-integer.py | 0 problems/{ => python}/rotate-array.py | 0 problems/{ => python}/rotate-image.py | 0 problems/{ => python}/russian-doll-envelopes.py | 0 problems/{ => python}/same-tree.py | 0 .../{ => python}/satisfiability-of-equality-equations.py | 0 problems/{ => python}/score-of-parentheses.py | 0 problems/{ => python}/search-a-2d-matrix.py | 0 problems/{ => python}/search-in-a-binary-search-tree.py | 0 problems/{ => python}/search-in-rotated-sorted-array-ii.py | 0 problems/{ => python}/search-in-rotated-sorted-array.py | 0 problems/{ => python}/search-insert-position.py | 0 problems/{ => python}/search-suggestions-system.py | 0 problems/{ => python}/second-highest-salary.sql | 0 .../{ => python}/sell-diminishing-valued-colored-balls.py | 0 .../{ => python}/serialize-and-deserialize-binary-tree.py | 0 problems/{ => python}/serialize-and-deserialize-bst.py | 0 problems/{ => python}/set-matrix-zeroes.py | 0 problems/{ => python}/shortest-bridge.py | 0 problems/{ => python}/shortest-common-supersequence.py | 0 .../{ => python}/shortest-distance-from-all-buildings.py | 0 .../shortest-path-in-a-grid-with-obstacles-elimination.py | 0 problems/{ => python}/shortest-path-in-binary-matrix.py | 0 problems/{ => python}/shortest-path-to-get-food.py | 0 problems/{ => python}/shuffle-an-array.py | 0 problems/{ => python}/simplify-path.py | 0 problems/{ => python}/single-threaded-cpu.py | 0 problems/{ => python}/sliding-window-maximum.py | 0 problems/{ => python}/snapshot-array.py | 0 problems/{ => python}/sort-colors.py | 0 problems/{ => python}/sort-list.py | 0 problems/{ => python}/spiral-matrix.py | 0 .../{ => python}/split-array-into-fibonacci-sequence.py | 0 problems/{ => python}/split-array-largest-sum.py | 0 problems/{ => python}/sqrtx.py | 0 problems/{ => python}/squares-of-a-sorted-array.py | 0 ...by-step-directions-from-a-binary-tree-node-to-another.py | 0 problems/{ => python}/stock-price-fluctuation.py | 0 problems/{ => python}/stone-game-ii.py | 0 problems/{ => python}/student-attendance-record-ii.py | 0 problems/{ => python}/subarray-sum-equals-k.py | 0 .../{ => python}/subarrays-with-k-different-integers.py | 0 problems/{ => python}/subdomain-visit-count.py | 0 problems/{ => python}/subsets-ii.py | 0 problems/{ => python}/subsets.py | 0 .../substring-with-concatenation-of-all-words.py | 0 problems/{ => python}/subtree-of-another-tree.py | 0 problems/{ => python}/sum-of-subarray-minimums.py | 0 problems/{ => python}/sum-root-to-leaf-numbers.py | 0 problems/{ => python}/summary-ranges.py | 0 problems/{ => python}/super-ugly-number.py | 0 problems/{ => python}/swap-adjacent-in-lr-string.py | 0 problems/{ => python}/swap-nodes-in-pairs.py | 0 problems/{ => python}/swim-in-rising-water.py | 0 problems/{ => python}/symmetric-tree.py | 0 problems/{ => python}/tallest-billboard.py | 0 problems/{ => python}/target-sum.py | 0 problems/{ => python}/task-scheduler.py | 0 problems/{ => python}/text-justification.py | 0 problems/{ => python}/the-kth-factor-of-n.py | 0 problems/{ => python}/the-maze-ii.py | 0 problems/{ => python}/time-based-key-value-store.py | 0 problems/{ => python}/to-lower-case.py | 0 problems/{ => python}/toeplitz-matrix.py | 0 problems/{ => python}/top-k-frequent-elements.py | 0 problems/{ => python}/trapping-rain-water-ii.py | 0 problems/{ => python}/trapping-rain-water.py | 0 problems/{ => python}/trim-a-binary-search-tree.py | 0 problems/{ => python}/two-out-of-three.py | 0 problems/{ => python}/two-sum-ii-input-array-is-sorted.py | 0 problems/{ => python}/two-sum.py | 0 problems/{ => python}/ugly-number-ii.py | 0 problems/{ => python}/ugly-number.py | 0 problems/{ => python}/umber-of-islands-ii.py | 0 problems/{ => python}/unique-binary-search-trees-ii,py | 0 problems/{ => python}/unique-binary-search-trees.py | 0 problems/{ => python}/unique-email-addres.py | 0 problems/{ => python}/unique-paths.py | 0 problems/{ => python}/univalued-binary-tree.py | 0 problems/{ => python}/valid-anagram.py | 0 problems/{ => python}/valid-number.py | 0 problems/{ => python}/valid-palindrome-ii.py | 0 problems/{ => python}/valid-palindrome.py | 0 problems/{ => python}/valid-parentheses.py | 0 problems/{ => python}/valid-word-abbreviation.py | 0 problems/{ => python}/validate-binary-search-tree.py | 0 .../verify-preorder-serialization-of-a-binary-tree.py | 0 .../vertical-order-traversal-of-a-binary-tree.py | 0 problems/{ => python}/wiggle-subsequence.py | 0 problems/{ => python}/word-break.py | 0 problems/{ => python}/word-ladder-ii.py | 0 problems/{ => python}/word-ladder.py | 0 problems/{ => python}/word-search-ii.py | 0 problems/{ => python}/word-search.py | 0 431 files changed, 3 insertions(+), 3 deletions(-) rename problems/{ => python}/01-matrix.py (100%) rename problems/{ => python}/3sum-closest.py (100%) rename problems/{ => python}/3sum.py (100%) rename problems/{ => python}/4sum.py (100%) rename problems/{ => python}/accounts-merge.py (100%) rename problems/{ => python}/add-binary.py (100%) rename problems/{ => python}/add-digits.py (100%) rename problems/{ => python}/add-strings.py (100%) rename problems/{ => python}/add-two-numbers-ii.py (100%) rename problems/{ => python}/add-two-numbers.py (100%) rename problems/{ => python}/alien-dictionary.py (100%) rename problems/{ => python}/all-nodes-distance-k-in-binary-tree.py (100%) rename problems/{ => python}/amount-of-new-area-painted-each-day.py (100%) rename problems/{ => python}/analyze-user-website-visit-pattern.py (100%) rename problems/{ => python}/backspace-string-compare.py (100%) rename problems/{ => python}/balance-a-binary-search-tree.py (100%) rename problems/{ => python}/balanced-binary-tree.py (100%) rename problems/{ => python}/basic-calculator-ii.py (100%) rename problems/{ => python}/best-time-to-buy-an-stock.py (100%) rename problems/{ => python}/best-time-to-buy-and-sell-stock-iii.py (100%) rename problems/{ => python}/best-time-to-buy-and-sell-stock-with-cooldown.py (100%) rename problems/{ => python}/best-time-to-buy-and-sell-stock.py (100%) rename problems/{ => python}/big-countries.sql (100%) rename problems/{ => python}/binary-search-tree-iterator.py (100%) rename problems/{ => python}/binary-search.py (100%) rename problems/{ => python}/binary-subarrays-with-sum.py (100%) rename problems/{ => python}/binary-tree-inorder-traversal.py (100%) rename problems/{ => python}/binary-tree-level-order-traversal-ii.py (100%) rename problems/{ => python}/binary-tree-level-order-traversal.py (100%) rename problems/{ => python}/binary-tree-longest-consecutive-sequence.py (100%) rename problems/{ => python}/binary-tree-maximum-path-sum.py (100%) rename problems/{ => python}/binary-tree-paths.py (100%) rename problems/{ => python}/binary-tree-pruning.py (100%) rename problems/{ => python}/binary-tree-right-side-view.py (100%) rename problems/{ => python}/binary-tree-vertical-order-traversal.py (100%) rename problems/{ => python}/binary-watch.py (100%) rename problems/{ => python}/buildings-with-an-ocean-view.py (100%) rename problems/{ => python}/burst-balloons.py (100%) rename problems/{ => python}/campus-bikes-ii.py (100%) rename problems/{ => python}/candy.py (100%) rename problems/{ => python}/capacity-to-ship-packages-within-d-days.py (100%) rename problems/{ => python}/cheapest-flights-within-k-stops.py (100%) rename problems/{ => python}/climbing-stairs.py (100%) rename problems/{ => python}/clone-graph.py (100%) rename problems/{ => python}/closest-binary-search-tree-value.py (100%) rename problems/{ => python}/coin-change.py (100%) rename problems/{ => python}/coloring-a-border.py (100%) rename problems/{ => python}/combination-sum-ii.py (100%) rename problems/{ => python}/combination-sum-iii.py (100%) rename problems/{ => python}/combination-sum-iv.py (100%) rename problems/{ => python}/combination-sum.py (100%) rename problems/{ => python}/combinations.py (100%) rename problems/{ => python}/combine-two-tables.sql (100%) rename problems/{ => python}/compare-version-numbers.py (100%) rename problems/{ => python}/connecting-cities-with-minimum-cost.py (100%) rename problems/{ => python}/consecutive-numbers-sum.py (100%) rename problems/{ => python}/construct-binary-tree-from-inorder-and-postorder-traversal.py (100%) rename problems/{ => python}/construct-binary-tree-from-preorder-and-inorder-traversal.py (100%) rename problems/{ => python}/container-with-most-water.py (100%) rename problems/{ => python}/contains-duplicate-ii.py (100%) rename problems/{ => python}/contains-duplicate-iii.py (100%) rename problems/{ => python}/contains-duplicate.py (100%) rename problems/{ => python}/continuous-subarray-sum.py (100%) rename problems/{ => python}/convert-binary-search-tree-to-sorted-doubly-linked-list.py (100%) rename problems/{ => python}/convert-sorted-array-to-binary-search-tree.py (100%) rename problems/{ => python}/convert-sorted-list-to-binary-search-tree.py (100%) rename problems/{ => python}/copy-list-with-random-pointer.py (100%) rename problems/{ => python}/count-all-valid-pickup-and-delivery-opti.py (100%) rename problems/{ => python}/count-binary-substrings.py (100%) rename problems/{ => python}/count-complete-tree-nodes.py (100%) rename problems/{ => python}/count-number-of-nice-subarrays.py (100%) rename problems/{ => python}/count-unique-characters-of-all-substrings-of-a-given-string.py (100%) rename problems/{ => python}/course-schedule-ii.py (100%) rename problems/{ => python}/course-schedule.py (100%) rename problems/{ => python}/custom-sort-string.py (100%) rename problems/{ => python}/cutting-ribbons.py (100%) rename problems/{ => python}/data-stream-as-disjoint-intervals.py (100%) rename problems/{ => python}/decode-string.py (100%) rename problems/{ => python}/decode-ways.py (100%) rename problems/{ => python}/delete-and-earn.py (100%) rename problems/{ => python}/delete-duplicate-folders-in-system.py (100%) rename problems/{ => python}/delete-node-in-a-bst.py (100%) rename problems/{ => python}/delete-operation-for-two-strings.py (100%) rename problems/{ => python}/design-add-and-search-words-data-structure.py (100%) rename problems/{ => python}/design-in-memory-file-system.py (100%) rename problems/{ => python}/design-linked-list.py (100%) rename problems/{ => python}/design-tic-tac-toe.py (100%) rename problems/{ => python}/diagonal-traverse.py (100%) rename problems/{ => python}/diameter-of-binary-tree.py (100%) rename problems/{ => python}/different-ways-to-add-parentheses.py (100%) rename problems/{ => python}/distinct-subsequences.py (100%) rename problems/{ => python}/distribute-coins-in-binary-tree.py (100%) rename problems/{ => python}/domino-and-tromino-tiling.py (100%) rename problems/{ => python}/dot-product-of-two-sparse-vectors.py (100%) rename problems/{ => python}/dungeon-game.py (100%) rename problems/{ => python}/edit-distance.py (100%) rename problems/{ => python}/egions-cut-by-slashes.py (100%) rename problems/{ => python}/evaluate-division.py (100%) rename problems/{ => python}/evaluate-reverse-polish-notation.py (100%) rename problems/{ => python}/exclusive-time-of-functions.py (100%) rename problems/{ => python}/expression-add-operators.py (100%) rename problems/{ => python}/filling-bookcase-shelves.py (100%) rename problems/{ => python}/find-all-possible-recipes-from-given-supplies.py (100%) rename problems/{ => python}/find-and-replace-in-string.py (100%) rename problems/{ => python}/find-distance-in-a-binary-tree.py (100%) rename problems/{ => python}/find-duplicate-subtrees.py (100%) rename problems/{ => python}/find-eventual-safe-states.py (100%) rename problems/{ => python}/find-first-and-last-position-of-element-in-sorted-array.py (100%) rename problems/{ => python}/find-k-closest-elements.py (100%) rename problems/{ => python}/find-k-pairs-with-smallest-sums.py (100%) rename problems/{ => python}/find-leaves-of-binary-tree.py (100%) rename problems/{ => python}/find-median-from-data-stream.py (100%) rename problems/{ => python}/find-minimum-in-rotated-sorted-array-ii.py (100%) rename problems/{ => python}/find-minimum-in-rotated-sorted-array.py (100%) rename problems/{ => python}/find-mode-in-binary-search-tree.py (100%) rename problems/{ => python}/find-original-array-from-doubled-array,py (100%) rename problems/{ => python}/find-peak-element.py (100%) rename problems/{ => python}/find-the-duplicate-number.py (100%) rename problems/{ => python}/first-bad-version.py (100%) rename problems/{ => python}/first-missing-positive.py (100%) rename problems/{ => python}/first-unique-character-in-a-string.py (100%) rename problems/{ => python}/fizz-buzz.py (100%) rename problems/{ => python}/flatten-binary-tree-to-linked-list.py (100%) rename problems/{ => python}/flip-binary-tree-to-match-preorder-traversal.py (100%) rename problems/{ => python}/flip-string-to-monotone-increasing.py (100%) rename problems/{ => python}/flood-fill.py (100%) rename problems/{ => python}/friend-circles.py (100%) rename problems/{ => python}/fruit-into-baskets.py (100%) rename problems/{ => python}/game-of-life.py (100%) rename problems/{ => python}/generate-parentheses.py (100%) rename problems/{ => python}/graph-valid-tree.py (100%) rename problems/{ => python}/greatest-sum-divisible-by-three.py (100%) rename problems/{ => python}/group-anagrams.py (100%) rename problems/{ => python}/group-shifted-strings.py (100%) rename problems/{ => python}/guess-number-higher-or-lower-ii.py (100%) rename problems/{ => python}/guess-number-higher-or-lower.py (100%) rename problems/{ => python}/guess-the-word.py (100%) rename problems/{ => python}/h-index-ii.py (100%) rename problems/{ => python}/h-index.py (100%) rename problems/{ => python}/hamming-distance.py (100%) rename problems/{ => python}/house-robber-ii.py (100%) rename problems/{ => python}/house-robber-iii.py (100%) rename problems/{ => python}/house-robber.py (100%) rename problems/{ => python}/implement-trie-prefix-tree.py (100%) rename problems/{ => python}/increasing-triplet-subsequence.py (100%) rename problems/{ => python}/inorder-successor-in-bst-ii.py (100%) rename problems/{ => python}/inorder-successor-in-bst.py (100%) rename problems/{ => python}/insert-interval.py (100%) rename problems/{ => python}/insert-into-a-binary-search-tree.py (100%) rename problems/{ => python}/insert-into-a-sorted-circular-linked-list.py (100%) rename problems/{ => python}/insertion-sort-list.py (100%) rename problems/{ => python}/integer-to-english-words.py (100%) rename problems/{ => python}/interleaving-string.py (100%) rename problems/{ => python}/intersection-of-two-arrays-ii.py (100%) rename problems/{ => python}/intersection-of-two-arrays.py (100%) rename problems/{ => python}/invert-binary-tree.py (100%) rename problems/{ => python}/is-graph-bipartite.py (100%) rename problems/{ => python}/is-subsequence.py (100%) rename problems/{ => python}/isomorphic-strings.py (100%) rename problems/{ => python}/jewels-and-stones.py (100%) rename problems/{ => python}/jump-game.py (100%) rename problems/{ => python}/k-closest-points-to-origin.py (100%) rename problems/{ => python}/k-empty-slots.py (100%) rename problems/{ => python}/keys-and-rooms.py (100%) rename problems/{ => python}/knight-dialer.py (100%) rename problems/{ => python}/knight-probability-in-chessboard.py (100%) rename problems/{ => python}/koko-eating-bananas.py (100%) rename problems/{ => python}/kth-largest-element-in-an-array.py (100%) rename problems/{ => python}/kth-smallest-element-in-a-bst.py (100%) rename problems/{ => python}/kth-smallest-element-in-a-sorted-matrix.py (100%) rename problems/{ => python}/largest-1-bordered-square.py (100%) rename problems/{ => python}/largest-bst-subtree.py (100%) rename problems/{ => python}/largest-sum-of-averages.py (100%) rename problems/{ => python}/last-stone-weight-ii.py (100%) rename problems/{ => python}/last-stone-weight.py (100%) rename problems/{ => python}/least-number-of-unique-integers-after-k-removals.py (100%) rename problems/{ => python}/letter-case-permutation.py (100%) rename problems/{ => python}/letter-combinations-of-a-phone-number.py (100%) rename problems/{ => python}/license-key-formatting.py (100%) rename problems/{ => python}/linked-list-cycle-ii.py (100%) rename problems/{ => python}/linked-list-cycle.py (100%) rename problems/{ => python}/linked-list-random-node.py (100%) rename problems/{ => python}/logger-rate-limiter.py (100%) rename problems/{ => python}/longest-common-prefix.py (100%) rename problems/{ => python}/longest-common-subsequence.py (100%) rename problems/{ => python}/longest-consecutive-sequence.py (100%) rename problems/{ => python}/longest-increasing-path-in-a-matrix.py (100%) rename problems/{ => python}/longest-increasing-subsequence.py (100%) rename problems/{ => python}/longest-palindromic-subsequence.py (100%) rename problems/{ => python}/longest-palindromic-substring.py (100%) rename problems/{ => python}/longest-repeating-character-replacement.py (100%) rename problems/{ => python}/longest-string-chain.py (100%) rename problems/{ => python}/longest-substring-with-at-least-k-repeating-characters.py (100%) rename problems/{ => python}/longest-substring-without-repeating-characters.py (100%) rename problems/{ => python}/longest-univalue-path.py (100%) rename problems/{ => python}/lowest-common-ancestor-of-a-binary-search-tree.py (100%) rename problems/{ => python}/lowest-common-ancestor-of-a-binary-search.py (100%) rename problems/{ => python}/lowest-common-ancestor-of-a-binary-tree-ii.py (100%) rename problems/{ => python}/lowest-common-ancestor-of-a-binary-tree-iii.py (100%) rename problems/{ => python}/lowest-common-ancestor-of-a-binary-tree-iv.py (100%) rename problems/{ => python}/lowest-common-ancestor-of-a-binary-tree.py (100%) rename problems/{ => python}/lowest-common-ancestor-of-deepest-leaves.py (100%) rename problems/{ => python}/lru-cache.py (100%) rename problems/{ => python}/majority-element-ii.py (100%) rename problems/{ => python}/majority-element.py (100%) rename problems/{ => python}/making-a-large-island.py (100%) rename problems/{ => python}/max-area-of-island.py (100%) rename problems/{ => python}/max-consecutive-ones-iii.py (100%) rename problems/{ => python}/max-stack.py (100%) rename problems/{ => python}/max-sum-of-rectangle-no-larger-than-k.py (100%) rename problems/{ => python}/maximal-square.py (100%) rename problems/{ => python}/maximum-average-subtree.py (100%) rename problems/{ => python}/maximum-compatibility-score-sum.py (100%) rename problems/{ => python}/maximum-depth-of-binary-tree.py (100%) rename problems/{ => python}/maximum-gap.py (100%) rename problems/{ => python}/maximum-length-of-repeated-subarray.py (100%) rename problems/{ => python}/maximum-number-of-events-that-can-be-attended.py (100%) rename problems/{ => python}/maximum-number-of-points-with-cost.py (100%) rename problems/{ => python}/maximum-number-of-visible-points.py (100%) rename problems/{ => python}/maximum-product-of-three-numbers.py (100%) rename problems/{ => python}/maximum-product-subarray.py (100%) rename problems/{ => python}/maximum-subarray-sum-with-one-deletion.py (100%) rename problems/{ => python}/maximum-subarray.py (100%) rename problems/{ => python}/maximum-swap.py (100%) rename problems/{ => python}/maximum-units-on-a-truck.py (100%) rename problems/{ => python}/median-of-two-sorted-arrays.py (100%) rename problems/{ => python}/meeting-rooms-ii.py (100%) rename problems/{ => python}/meeting-rooms.py (100%) rename problems/{ => python}/merge-intervals.py (100%) rename problems/{ => python}/merge-k-sorted-lists.py (100%) rename problems/{ => python}/merge-sorted-array.py (100%) rename problems/{ => python}/merge-two-sorted-lists.py (100%) rename problems/{ => python}/min-cost-climbing-stairs.py (100%) rename problems/{ => python}/min-stack.py (100%) rename problems/{ => python}/minimize-malware-spread.py (100%) rename problems/{ => python}/minimum-absolute-difference-in-bst.py (100%) rename problems/{ => python}/minimum-ascii-delete-sum-for-two-strings.py (100%) rename problems/{ => python}/minimum-cost-to-connect-sticks.py (100%) rename problems/{ => python}/minimum-cost-to-hire-k-workers.py (100%) rename problems/{ => python}/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py (100%) rename problems/{ => python}/minimum-cost-to-reach-city-with-discounts.py (100%) rename problems/{ => python}/minimum-depth-of-binary-tree.py (100%) rename problems/{ => python}/minimum-difficulty-of-a-job-schedule.py (100%) rename problems/{ => python}/minimum-falling-path-sum-ii.py (100%) rename problems/{ => python}/minimum-knight-moves.py (100%) rename problems/{ => python}/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py (100%) rename problems/{ => python}/minimum-path-sum.py (100%) rename problems/{ => python}/minimum-score-triangulation-of-polygon.py (100%) rename problems/{ => python}/minimum-size-subarray-sum.py (100%) rename problems/{ => python}/minimum-swaps-to-group-all-1s-together.py (100%) rename problems/{ => python}/minimum-swaps-to-make-sequences-increasing.py (100%) rename problems/{ => python}/minimum-time-difference.py (100%) rename problems/{ => python}/minimum-window-substring.py (100%) rename problems/{ => python}/minimum-xor-sum-of-two-arrays.py (100%) rename problems/{ => python}/missing-number.py (100%) rename problems/{ => python}/most-frequent-subtree-sum.py (100%) rename problems/{ => python}/most-stones-removed-with-same-row-or-column.py (100%) rename problems/{ => python}/move-zeroes.py (100%) rename problems/{ => python}/moving-average-from-data-stream.py (100%) rename problems/{ => python}/my-calendar-ii.py (100%) rename problems/{ => python}/n-ary-tree-level-order-traversal.py (100%) rename problems/{ => python}/n-ary-tree-postorder-traversal.py (100%) rename problems/{ => python}/n-ary-tree-preorder-traversal.py (100%) rename problems/{ => python}/nested-list-weight-sum.py (100%) rename problems/{ => python}/network-delay-time.py (100%) rename problems/{ => python}/next-closest-time.py (100%) rename problems/{ => python}/next-permutation.py (100%) rename problems/{ => python}/number-complement.py (100%) rename problems/{ => python}/number-of-connected-components-in-an-undirected-graph.py (100%) rename problems/{ => python}/number-of-islands-ii.py (100%) rename problems/{ => python}/number-of-islands.py (100%) rename problems/{ => python}/number-of-longest-increasing-subsequence.py (100%) rename problems/{ => python}/number-of-matching-subsequences.py (100%) rename problems/{ => python}/number-of-provinces.py (100%) rename problems/{ => python}/number-of-recent-calls.py (100%) rename problems/{ => python}/number-of-squareful-arrays.py (100%) rename problems/{ => python}/number-of-substrings-containing-all-thre.py (100%) rename problems/{ => python}/number-of-ways-to-arrive-at-destination.py (100%) rename problems/{ => python}/odd-even-jump.py (100%) rename problems/{ => python}/ones-and-zeroes.py (100%) rename problems/{ => python}/open-the-lock.py (100%) rename problems/{ => python}/out-of-boundary-paths.py (100%) rename problems/{ => python}/pacific-atlantic-water-flow.py (100%) rename problems/{ => python}/pairs-of-songs-with-total-durations-divisible-by-60.py (100%) rename problems/{ => python}/palindrome-number.py (100%) rename problems/{ => python}/palindrome-pairs.py (100%) rename problems/{ => python}/palindrome-partitioning-iii.py (100%) rename problems/{ => python}/palindrome-partitioning.py (100%) rename problems/{ => python}/palindromic-substrings.py (100%) rename problems/{ => python}/partition-array-for-maximum-sum.py (100%) rename problems/{ => python}/partition-labels.py (100%) rename problems/{ => python}/partition-to-k-equal-sum-subsets.py (100%) rename problems/{ => python}/path-sum-ii.py (100%) rename problems/{ => python}/path-sum-iii.py (100%) rename problems/{ => python}/path-sum.py (100%) rename problems/{ => python}/path-with-maximum-probability.py (100%) rename problems/{peak-index-in-a-mountain-array.PY => python/peak-index-in-a-mountain-array.py} (100%) rename problems/{ => python}/perfect-squares.py (100%) rename problems/{ => python}/permutation-in-string.py (100%) rename problems/{ => python}/permutation-sequence.py (100%) rename problems/{ => python}/permutations-ii.py (100%) rename problems/{ => python}/permutations.py (100%) rename problems/{ => python}/populating-next-right-pointers-in-each-node-ii.py (100%) rename problems/{ => python}/populating-next-right-pointers-in-each-node.py (100%) rename problems/{ => python}/powx-n.py (100%) rename problems/{ => python}/product-of-array-except-self.py (100%) rename problems/{ => python}/profitable-schemes.py (100%) rename problems/{ => python}/queue-reconstruction-by-height.py (100%) rename problems/{ => python}/random-pick-with-weight.py (100%) rename problems/{ => python}/range-addition.py (100%) rename problems/{ => python}/range-sum-of-bst.py (100%) rename problems/{ => python}/range-sum-query-immutable.py (100%) rename problems/{ => python}/range-sum-query-mutable.py (100%) rename problems/{ => python}/rearrange-string-k-distance-apart.py (100%) rename problems/{ => python}/reconstruct-itinerary.py (100%) rename problems/{ => python}/recover-binary-search-tree.py (100%) rename problems/{ => python}/redundant-connection.py (100%) rename problems/{ => python}/remove-all-adjacent-duplicates-in-string.py (100%) rename problems/{ => python}/remove-all-ones-with-row-and-column-flips.py (100%) rename problems/{ => python}/remove-duplicates-from-sorted-array-ii.py (100%) rename problems/{ => python}/remove-duplicates-from-sorted-array.py (100%) rename problems/{ => python}/remove-duplicates-from-sorted-list.py (100%) rename problems/{ => python}/remove-element.py (100%) rename problems/{ => python}/remove-invalid-parentheses.py (100%) rename problems/{ => python}/remove-linked-list-elements.py (100%) rename problems/{ => python}/remove-nth-node-from-end-of-list.py (100%) rename problems/{ => python}/reorder-list.py (100%) rename problems/{ => python}/repeated-string-match.py (100%) rename problems/{ => python}/replace-the-substring-for-balanced-string.py (100%) rename problems/{ => python}/restore-ip-addresses.py (100%) rename problems/{ => python}/reverse-integer.py (100%) rename problems/{ => python}/reverse-linked-list.py (100%) rename problems/{ => python}/reverse-string.py (100%) rename problems/{ => python}/reverse-vowels-of-a-string.py (100%) rename problems/{ => python}/reverse-words-in-a-string.py (100%) rename problems/{ => python}/robot-bounded-in-circle.py (100%) rename problems/{ => python}/roman-to-integer.py (100%) rename problems/{ => python}/rotate-array.py (100%) rename problems/{ => python}/rotate-image.py (100%) rename problems/{ => python}/russian-doll-envelopes.py (100%) rename problems/{ => python}/same-tree.py (100%) rename problems/{ => python}/satisfiability-of-equality-equations.py (100%) rename problems/{ => python}/score-of-parentheses.py (100%) rename problems/{ => python}/search-a-2d-matrix.py (100%) rename problems/{ => python}/search-in-a-binary-search-tree.py (100%) rename problems/{ => python}/search-in-rotated-sorted-array-ii.py (100%) rename problems/{ => python}/search-in-rotated-sorted-array.py (100%) rename problems/{ => python}/search-insert-position.py (100%) rename problems/{ => python}/search-suggestions-system.py (100%) rename problems/{ => python}/second-highest-salary.sql (100%) rename problems/{ => python}/sell-diminishing-valued-colored-balls.py (100%) rename problems/{ => python}/serialize-and-deserialize-binary-tree.py (100%) rename problems/{ => python}/serialize-and-deserialize-bst.py (100%) rename problems/{ => python}/set-matrix-zeroes.py (100%) rename problems/{ => python}/shortest-bridge.py (100%) rename problems/{ => python}/shortest-common-supersequence.py (100%) rename problems/{ => python}/shortest-distance-from-all-buildings.py (100%) rename problems/{ => python}/shortest-path-in-a-grid-with-obstacles-elimination.py (100%) rename problems/{ => python}/shortest-path-in-binary-matrix.py (100%) rename problems/{ => python}/shortest-path-to-get-food.py (100%) rename problems/{ => python}/shuffle-an-array.py (100%) rename problems/{ => python}/simplify-path.py (100%) rename problems/{ => python}/single-threaded-cpu.py (100%) rename problems/{ => python}/sliding-window-maximum.py (100%) rename problems/{ => python}/snapshot-array.py (100%) rename problems/{ => python}/sort-colors.py (100%) rename problems/{ => python}/sort-list.py (100%) rename problems/{ => python}/spiral-matrix.py (100%) rename problems/{ => python}/split-array-into-fibonacci-sequence.py (100%) rename problems/{ => python}/split-array-largest-sum.py (100%) rename problems/{ => python}/sqrtx.py (100%) rename problems/{ => python}/squares-of-a-sorted-array.py (100%) rename problems/{ => python}/step-by-step-directions-from-a-binary-tree-node-to-another.py (100%) rename problems/{ => python}/stock-price-fluctuation.py (100%) rename problems/{ => python}/stone-game-ii.py (100%) rename problems/{ => python}/student-attendance-record-ii.py (100%) rename problems/{ => python}/subarray-sum-equals-k.py (100%) rename problems/{ => python}/subarrays-with-k-different-integers.py (100%) rename problems/{ => python}/subdomain-visit-count.py (100%) rename problems/{ => python}/subsets-ii.py (100%) rename problems/{ => python}/subsets.py (100%) rename problems/{ => python}/substring-with-concatenation-of-all-words.py (100%) rename problems/{ => python}/subtree-of-another-tree.py (100%) rename problems/{ => python}/sum-of-subarray-minimums.py (100%) rename problems/{ => python}/sum-root-to-leaf-numbers.py (100%) rename problems/{ => python}/summary-ranges.py (100%) rename problems/{ => python}/super-ugly-number.py (100%) rename problems/{ => python}/swap-adjacent-in-lr-string.py (100%) rename problems/{ => python}/swap-nodes-in-pairs.py (100%) rename problems/{ => python}/swim-in-rising-water.py (100%) rename problems/{ => python}/symmetric-tree.py (100%) rename problems/{ => python}/tallest-billboard.py (100%) rename problems/{ => python}/target-sum.py (100%) rename problems/{ => python}/task-scheduler.py (100%) rename problems/{ => python}/text-justification.py (100%) rename problems/{ => python}/the-kth-factor-of-n.py (100%) rename problems/{ => python}/the-maze-ii.py (100%) rename problems/{ => python}/time-based-key-value-store.py (100%) rename problems/{ => python}/to-lower-case.py (100%) rename problems/{ => python}/toeplitz-matrix.py (100%) rename problems/{ => python}/top-k-frequent-elements.py (100%) rename problems/{ => python}/trapping-rain-water-ii.py (100%) rename problems/{ => python}/trapping-rain-water.py (100%) rename problems/{ => python}/trim-a-binary-search-tree.py (100%) rename problems/{ => python}/two-out-of-three.py (100%) rename problems/{ => python}/two-sum-ii-input-array-is-sorted.py (100%) rename problems/{ => python}/two-sum.py (100%) rename problems/{ => python}/ugly-number-ii.py (100%) rename problems/{ => python}/ugly-number.py (100%) rename problems/{ => python}/umber-of-islands-ii.py (100%) rename problems/{ => python}/unique-binary-search-trees-ii,py (100%) rename problems/{ => python}/unique-binary-search-trees.py (100%) rename problems/{ => python}/unique-email-addres.py (100%) rename problems/{ => python}/unique-paths.py (100%) rename problems/{ => python}/univalued-binary-tree.py (100%) rename problems/{ => python}/valid-anagram.py (100%) rename problems/{ => python}/valid-number.py (100%) rename problems/{ => python}/valid-palindrome-ii.py (100%) rename problems/{ => python}/valid-palindrome.py (100%) rename problems/{ => python}/valid-parentheses.py (100%) rename problems/{ => python}/valid-word-abbreviation.py (100%) rename problems/{ => python}/validate-binary-search-tree.py (100%) rename problems/{ => python}/verify-preorder-serialization-of-a-binary-tree.py (100%) rename problems/{ => python}/vertical-order-traversal-of-a-binary-tree.py (100%) rename problems/{ => python}/wiggle-subsequence.py (100%) rename problems/{ => python}/word-break.py (100%) rename problems/{ => python}/word-ladder-ii.py (100%) rename problems/{ => python}/word-ladder.py (100%) rename problems/{ => python}/word-search-ii.py (100%) rename problems/{ => python}/word-search.py (100%) diff --git a/README.md b/README.md index f076d25..8e05de7 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Overview -1. This is my Python (2.7) Leetcode solution. +1. This is my Python Leetcode solution. As time grows, this also become a guide to prepare for software engineer interview. -2. The solution is at `problems/the-file-name/`. -For example, `merge-sorted-array.py`'s solution is at `https://leetcode.com/problems/merge-sorted-array/`. +1. The solution is at `problems/python/` or `problems/python3/`. +For example, `merge-sorted-array.py`'s solution is at `https://leetcode.com/problems/python/merge-sorted-array/`. 2. I really take time tried to make the best solution and collect the best resource that I found. Because I wanted to help others like me. diff --git a/problems/01-matrix.py b/problems/python/01-matrix.py similarity index 100% rename from problems/01-matrix.py rename to problems/python/01-matrix.py diff --git a/problems/3sum-closest.py b/problems/python/3sum-closest.py similarity index 100% rename from problems/3sum-closest.py rename to problems/python/3sum-closest.py diff --git a/problems/3sum.py b/problems/python/3sum.py similarity index 100% rename from problems/3sum.py rename to problems/python/3sum.py diff --git a/problems/4sum.py b/problems/python/4sum.py similarity index 100% rename from problems/4sum.py rename to problems/python/4sum.py diff --git a/problems/accounts-merge.py b/problems/python/accounts-merge.py similarity index 100% rename from problems/accounts-merge.py rename to problems/python/accounts-merge.py diff --git a/problems/add-binary.py b/problems/python/add-binary.py similarity index 100% rename from problems/add-binary.py rename to problems/python/add-binary.py diff --git a/problems/add-digits.py b/problems/python/add-digits.py similarity index 100% rename from problems/add-digits.py rename to problems/python/add-digits.py diff --git a/problems/add-strings.py b/problems/python/add-strings.py similarity index 100% rename from problems/add-strings.py rename to problems/python/add-strings.py diff --git a/problems/add-two-numbers-ii.py b/problems/python/add-two-numbers-ii.py similarity index 100% rename from problems/add-two-numbers-ii.py rename to problems/python/add-two-numbers-ii.py diff --git a/problems/add-two-numbers.py b/problems/python/add-two-numbers.py similarity index 100% rename from problems/add-two-numbers.py rename to problems/python/add-two-numbers.py diff --git a/problems/alien-dictionary.py b/problems/python/alien-dictionary.py similarity index 100% rename from problems/alien-dictionary.py rename to problems/python/alien-dictionary.py diff --git a/problems/all-nodes-distance-k-in-binary-tree.py b/problems/python/all-nodes-distance-k-in-binary-tree.py similarity index 100% rename from problems/all-nodes-distance-k-in-binary-tree.py rename to problems/python/all-nodes-distance-k-in-binary-tree.py diff --git a/problems/amount-of-new-area-painted-each-day.py b/problems/python/amount-of-new-area-painted-each-day.py similarity index 100% rename from problems/amount-of-new-area-painted-each-day.py rename to problems/python/amount-of-new-area-painted-each-day.py diff --git a/problems/analyze-user-website-visit-pattern.py b/problems/python/analyze-user-website-visit-pattern.py similarity index 100% rename from problems/analyze-user-website-visit-pattern.py rename to problems/python/analyze-user-website-visit-pattern.py diff --git a/problems/backspace-string-compare.py b/problems/python/backspace-string-compare.py similarity index 100% rename from problems/backspace-string-compare.py rename to problems/python/backspace-string-compare.py diff --git a/problems/balance-a-binary-search-tree.py b/problems/python/balance-a-binary-search-tree.py similarity index 100% rename from problems/balance-a-binary-search-tree.py rename to problems/python/balance-a-binary-search-tree.py diff --git a/problems/balanced-binary-tree.py b/problems/python/balanced-binary-tree.py similarity index 100% rename from problems/balanced-binary-tree.py rename to problems/python/balanced-binary-tree.py diff --git a/problems/basic-calculator-ii.py b/problems/python/basic-calculator-ii.py similarity index 100% rename from problems/basic-calculator-ii.py rename to problems/python/basic-calculator-ii.py diff --git a/problems/best-time-to-buy-an-stock.py b/problems/python/best-time-to-buy-an-stock.py similarity index 100% rename from problems/best-time-to-buy-an-stock.py rename to problems/python/best-time-to-buy-an-stock.py diff --git a/problems/best-time-to-buy-and-sell-stock-iii.py b/problems/python/best-time-to-buy-and-sell-stock-iii.py similarity index 100% rename from problems/best-time-to-buy-and-sell-stock-iii.py rename to problems/python/best-time-to-buy-and-sell-stock-iii.py diff --git a/problems/best-time-to-buy-and-sell-stock-with-cooldown.py b/problems/python/best-time-to-buy-and-sell-stock-with-cooldown.py similarity index 100% rename from problems/best-time-to-buy-and-sell-stock-with-cooldown.py rename to problems/python/best-time-to-buy-and-sell-stock-with-cooldown.py diff --git a/problems/best-time-to-buy-and-sell-stock.py b/problems/python/best-time-to-buy-and-sell-stock.py similarity index 100% rename from problems/best-time-to-buy-and-sell-stock.py rename to problems/python/best-time-to-buy-and-sell-stock.py diff --git a/problems/big-countries.sql b/problems/python/big-countries.sql similarity index 100% rename from problems/big-countries.sql rename to problems/python/big-countries.sql diff --git a/problems/binary-search-tree-iterator.py b/problems/python/binary-search-tree-iterator.py similarity index 100% rename from problems/binary-search-tree-iterator.py rename to problems/python/binary-search-tree-iterator.py diff --git a/problems/binary-search.py b/problems/python/binary-search.py similarity index 100% rename from problems/binary-search.py rename to problems/python/binary-search.py diff --git a/problems/binary-subarrays-with-sum.py b/problems/python/binary-subarrays-with-sum.py similarity index 100% rename from problems/binary-subarrays-with-sum.py rename to problems/python/binary-subarrays-with-sum.py diff --git a/problems/binary-tree-inorder-traversal.py b/problems/python/binary-tree-inorder-traversal.py similarity index 100% rename from problems/binary-tree-inorder-traversal.py rename to problems/python/binary-tree-inorder-traversal.py diff --git a/problems/binary-tree-level-order-traversal-ii.py b/problems/python/binary-tree-level-order-traversal-ii.py similarity index 100% rename from problems/binary-tree-level-order-traversal-ii.py rename to problems/python/binary-tree-level-order-traversal-ii.py diff --git a/problems/binary-tree-level-order-traversal.py b/problems/python/binary-tree-level-order-traversal.py similarity index 100% rename from problems/binary-tree-level-order-traversal.py rename to problems/python/binary-tree-level-order-traversal.py diff --git a/problems/binary-tree-longest-consecutive-sequence.py b/problems/python/binary-tree-longest-consecutive-sequence.py similarity index 100% rename from problems/binary-tree-longest-consecutive-sequence.py rename to problems/python/binary-tree-longest-consecutive-sequence.py diff --git a/problems/binary-tree-maximum-path-sum.py b/problems/python/binary-tree-maximum-path-sum.py similarity index 100% rename from problems/binary-tree-maximum-path-sum.py rename to problems/python/binary-tree-maximum-path-sum.py diff --git a/problems/binary-tree-paths.py b/problems/python/binary-tree-paths.py similarity index 100% rename from problems/binary-tree-paths.py rename to problems/python/binary-tree-paths.py diff --git a/problems/binary-tree-pruning.py b/problems/python/binary-tree-pruning.py similarity index 100% rename from problems/binary-tree-pruning.py rename to problems/python/binary-tree-pruning.py diff --git a/problems/binary-tree-right-side-view.py b/problems/python/binary-tree-right-side-view.py similarity index 100% rename from problems/binary-tree-right-side-view.py rename to problems/python/binary-tree-right-side-view.py diff --git a/problems/binary-tree-vertical-order-traversal.py b/problems/python/binary-tree-vertical-order-traversal.py similarity index 100% rename from problems/binary-tree-vertical-order-traversal.py rename to problems/python/binary-tree-vertical-order-traversal.py diff --git a/problems/binary-watch.py b/problems/python/binary-watch.py similarity index 100% rename from problems/binary-watch.py rename to problems/python/binary-watch.py diff --git a/problems/buildings-with-an-ocean-view.py b/problems/python/buildings-with-an-ocean-view.py similarity index 100% rename from problems/buildings-with-an-ocean-view.py rename to problems/python/buildings-with-an-ocean-view.py diff --git a/problems/burst-balloons.py b/problems/python/burst-balloons.py similarity index 100% rename from problems/burst-balloons.py rename to problems/python/burst-balloons.py diff --git a/problems/campus-bikes-ii.py b/problems/python/campus-bikes-ii.py similarity index 100% rename from problems/campus-bikes-ii.py rename to problems/python/campus-bikes-ii.py diff --git a/problems/candy.py b/problems/python/candy.py similarity index 100% rename from problems/candy.py rename to problems/python/candy.py diff --git a/problems/capacity-to-ship-packages-within-d-days.py b/problems/python/capacity-to-ship-packages-within-d-days.py similarity index 100% rename from problems/capacity-to-ship-packages-within-d-days.py rename to problems/python/capacity-to-ship-packages-within-d-days.py diff --git a/problems/cheapest-flights-within-k-stops.py b/problems/python/cheapest-flights-within-k-stops.py similarity index 100% rename from problems/cheapest-flights-within-k-stops.py rename to problems/python/cheapest-flights-within-k-stops.py diff --git a/problems/climbing-stairs.py b/problems/python/climbing-stairs.py similarity index 100% rename from problems/climbing-stairs.py rename to problems/python/climbing-stairs.py diff --git a/problems/clone-graph.py b/problems/python/clone-graph.py similarity index 100% rename from problems/clone-graph.py rename to problems/python/clone-graph.py diff --git a/problems/closest-binary-search-tree-value.py b/problems/python/closest-binary-search-tree-value.py similarity index 100% rename from problems/closest-binary-search-tree-value.py rename to problems/python/closest-binary-search-tree-value.py diff --git a/problems/coin-change.py b/problems/python/coin-change.py similarity index 100% rename from problems/coin-change.py rename to problems/python/coin-change.py diff --git a/problems/coloring-a-border.py b/problems/python/coloring-a-border.py similarity index 100% rename from problems/coloring-a-border.py rename to problems/python/coloring-a-border.py diff --git a/problems/combination-sum-ii.py b/problems/python/combination-sum-ii.py similarity index 100% rename from problems/combination-sum-ii.py rename to problems/python/combination-sum-ii.py diff --git a/problems/combination-sum-iii.py b/problems/python/combination-sum-iii.py similarity index 100% rename from problems/combination-sum-iii.py rename to problems/python/combination-sum-iii.py diff --git a/problems/combination-sum-iv.py b/problems/python/combination-sum-iv.py similarity index 100% rename from problems/combination-sum-iv.py rename to problems/python/combination-sum-iv.py diff --git a/problems/combination-sum.py b/problems/python/combination-sum.py similarity index 100% rename from problems/combination-sum.py rename to problems/python/combination-sum.py diff --git a/problems/combinations.py b/problems/python/combinations.py similarity index 100% rename from problems/combinations.py rename to problems/python/combinations.py diff --git a/problems/combine-two-tables.sql b/problems/python/combine-two-tables.sql similarity index 100% rename from problems/combine-two-tables.sql rename to problems/python/combine-two-tables.sql diff --git a/problems/compare-version-numbers.py b/problems/python/compare-version-numbers.py similarity index 100% rename from problems/compare-version-numbers.py rename to problems/python/compare-version-numbers.py diff --git a/problems/connecting-cities-with-minimum-cost.py b/problems/python/connecting-cities-with-minimum-cost.py similarity index 100% rename from problems/connecting-cities-with-minimum-cost.py rename to problems/python/connecting-cities-with-minimum-cost.py diff --git a/problems/consecutive-numbers-sum.py b/problems/python/consecutive-numbers-sum.py similarity index 100% rename from problems/consecutive-numbers-sum.py rename to problems/python/consecutive-numbers-sum.py diff --git a/problems/construct-binary-tree-from-inorder-and-postorder-traversal.py b/problems/python/construct-binary-tree-from-inorder-and-postorder-traversal.py similarity index 100% rename from problems/construct-binary-tree-from-inorder-and-postorder-traversal.py rename to problems/python/construct-binary-tree-from-inorder-and-postorder-traversal.py diff --git a/problems/construct-binary-tree-from-preorder-and-inorder-traversal.py b/problems/python/construct-binary-tree-from-preorder-and-inorder-traversal.py similarity index 100% rename from problems/construct-binary-tree-from-preorder-and-inorder-traversal.py rename to problems/python/construct-binary-tree-from-preorder-and-inorder-traversal.py diff --git a/problems/container-with-most-water.py b/problems/python/container-with-most-water.py similarity index 100% rename from problems/container-with-most-water.py rename to problems/python/container-with-most-water.py diff --git a/problems/contains-duplicate-ii.py b/problems/python/contains-duplicate-ii.py similarity index 100% rename from problems/contains-duplicate-ii.py rename to problems/python/contains-duplicate-ii.py diff --git a/problems/contains-duplicate-iii.py b/problems/python/contains-duplicate-iii.py similarity index 100% rename from problems/contains-duplicate-iii.py rename to problems/python/contains-duplicate-iii.py diff --git a/problems/contains-duplicate.py b/problems/python/contains-duplicate.py similarity index 100% rename from problems/contains-duplicate.py rename to problems/python/contains-duplicate.py diff --git a/problems/continuous-subarray-sum.py b/problems/python/continuous-subarray-sum.py similarity index 100% rename from problems/continuous-subarray-sum.py rename to problems/python/continuous-subarray-sum.py diff --git a/problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py b/problems/python/convert-binary-search-tree-to-sorted-doubly-linked-list.py similarity index 100% rename from problems/convert-binary-search-tree-to-sorted-doubly-linked-list.py rename to problems/python/convert-binary-search-tree-to-sorted-doubly-linked-list.py diff --git a/problems/convert-sorted-array-to-binary-search-tree.py b/problems/python/convert-sorted-array-to-binary-search-tree.py similarity index 100% rename from problems/convert-sorted-array-to-binary-search-tree.py rename to problems/python/convert-sorted-array-to-binary-search-tree.py diff --git a/problems/convert-sorted-list-to-binary-search-tree.py b/problems/python/convert-sorted-list-to-binary-search-tree.py similarity index 100% rename from problems/convert-sorted-list-to-binary-search-tree.py rename to problems/python/convert-sorted-list-to-binary-search-tree.py diff --git a/problems/copy-list-with-random-pointer.py b/problems/python/copy-list-with-random-pointer.py similarity index 100% rename from problems/copy-list-with-random-pointer.py rename to problems/python/copy-list-with-random-pointer.py diff --git a/problems/count-all-valid-pickup-and-delivery-opti.py b/problems/python/count-all-valid-pickup-and-delivery-opti.py similarity index 100% rename from problems/count-all-valid-pickup-and-delivery-opti.py rename to problems/python/count-all-valid-pickup-and-delivery-opti.py diff --git a/problems/count-binary-substrings.py b/problems/python/count-binary-substrings.py similarity index 100% rename from problems/count-binary-substrings.py rename to problems/python/count-binary-substrings.py diff --git a/problems/count-complete-tree-nodes.py b/problems/python/count-complete-tree-nodes.py similarity index 100% rename from problems/count-complete-tree-nodes.py rename to problems/python/count-complete-tree-nodes.py diff --git a/problems/count-number-of-nice-subarrays.py b/problems/python/count-number-of-nice-subarrays.py similarity index 100% rename from problems/count-number-of-nice-subarrays.py rename to problems/python/count-number-of-nice-subarrays.py diff --git a/problems/count-unique-characters-of-all-substrings-of-a-given-string.py b/problems/python/count-unique-characters-of-all-substrings-of-a-given-string.py similarity index 100% rename from problems/count-unique-characters-of-all-substrings-of-a-given-string.py rename to problems/python/count-unique-characters-of-all-substrings-of-a-given-string.py diff --git a/problems/course-schedule-ii.py b/problems/python/course-schedule-ii.py similarity index 100% rename from problems/course-schedule-ii.py rename to problems/python/course-schedule-ii.py diff --git a/problems/course-schedule.py b/problems/python/course-schedule.py similarity index 100% rename from problems/course-schedule.py rename to problems/python/course-schedule.py diff --git a/problems/custom-sort-string.py b/problems/python/custom-sort-string.py similarity index 100% rename from problems/custom-sort-string.py rename to problems/python/custom-sort-string.py diff --git a/problems/cutting-ribbons.py b/problems/python/cutting-ribbons.py similarity index 100% rename from problems/cutting-ribbons.py rename to problems/python/cutting-ribbons.py diff --git a/problems/data-stream-as-disjoint-intervals.py b/problems/python/data-stream-as-disjoint-intervals.py similarity index 100% rename from problems/data-stream-as-disjoint-intervals.py rename to problems/python/data-stream-as-disjoint-intervals.py diff --git a/problems/decode-string.py b/problems/python/decode-string.py similarity index 100% rename from problems/decode-string.py rename to problems/python/decode-string.py diff --git a/problems/decode-ways.py b/problems/python/decode-ways.py similarity index 100% rename from problems/decode-ways.py rename to problems/python/decode-ways.py diff --git a/problems/delete-and-earn.py b/problems/python/delete-and-earn.py similarity index 100% rename from problems/delete-and-earn.py rename to problems/python/delete-and-earn.py diff --git a/problems/delete-duplicate-folders-in-system.py b/problems/python/delete-duplicate-folders-in-system.py similarity index 100% rename from problems/delete-duplicate-folders-in-system.py rename to problems/python/delete-duplicate-folders-in-system.py diff --git a/problems/delete-node-in-a-bst.py b/problems/python/delete-node-in-a-bst.py similarity index 100% rename from problems/delete-node-in-a-bst.py rename to problems/python/delete-node-in-a-bst.py diff --git a/problems/delete-operation-for-two-strings.py b/problems/python/delete-operation-for-two-strings.py similarity index 100% rename from problems/delete-operation-for-two-strings.py rename to problems/python/delete-operation-for-two-strings.py diff --git a/problems/design-add-and-search-words-data-structure.py b/problems/python/design-add-and-search-words-data-structure.py similarity index 100% rename from problems/design-add-and-search-words-data-structure.py rename to problems/python/design-add-and-search-words-data-structure.py diff --git a/problems/design-in-memory-file-system.py b/problems/python/design-in-memory-file-system.py similarity index 100% rename from problems/design-in-memory-file-system.py rename to problems/python/design-in-memory-file-system.py diff --git a/problems/design-linked-list.py b/problems/python/design-linked-list.py similarity index 100% rename from problems/design-linked-list.py rename to problems/python/design-linked-list.py diff --git a/problems/design-tic-tac-toe.py b/problems/python/design-tic-tac-toe.py similarity index 100% rename from problems/design-tic-tac-toe.py rename to problems/python/design-tic-tac-toe.py diff --git a/problems/diagonal-traverse.py b/problems/python/diagonal-traverse.py similarity index 100% rename from problems/diagonal-traverse.py rename to problems/python/diagonal-traverse.py diff --git a/problems/diameter-of-binary-tree.py b/problems/python/diameter-of-binary-tree.py similarity index 100% rename from problems/diameter-of-binary-tree.py rename to problems/python/diameter-of-binary-tree.py diff --git a/problems/different-ways-to-add-parentheses.py b/problems/python/different-ways-to-add-parentheses.py similarity index 100% rename from problems/different-ways-to-add-parentheses.py rename to problems/python/different-ways-to-add-parentheses.py diff --git a/problems/distinct-subsequences.py b/problems/python/distinct-subsequences.py similarity index 100% rename from problems/distinct-subsequences.py rename to problems/python/distinct-subsequences.py diff --git a/problems/distribute-coins-in-binary-tree.py b/problems/python/distribute-coins-in-binary-tree.py similarity index 100% rename from problems/distribute-coins-in-binary-tree.py rename to problems/python/distribute-coins-in-binary-tree.py diff --git a/problems/domino-and-tromino-tiling.py b/problems/python/domino-and-tromino-tiling.py similarity index 100% rename from problems/domino-and-tromino-tiling.py rename to problems/python/domino-and-tromino-tiling.py diff --git a/problems/dot-product-of-two-sparse-vectors.py b/problems/python/dot-product-of-two-sparse-vectors.py similarity index 100% rename from problems/dot-product-of-two-sparse-vectors.py rename to problems/python/dot-product-of-two-sparse-vectors.py diff --git a/problems/dungeon-game.py b/problems/python/dungeon-game.py similarity index 100% rename from problems/dungeon-game.py rename to problems/python/dungeon-game.py diff --git a/problems/edit-distance.py b/problems/python/edit-distance.py similarity index 100% rename from problems/edit-distance.py rename to problems/python/edit-distance.py diff --git a/problems/egions-cut-by-slashes.py b/problems/python/egions-cut-by-slashes.py similarity index 100% rename from problems/egions-cut-by-slashes.py rename to problems/python/egions-cut-by-slashes.py diff --git a/problems/evaluate-division.py b/problems/python/evaluate-division.py similarity index 100% rename from problems/evaluate-division.py rename to problems/python/evaluate-division.py diff --git a/problems/evaluate-reverse-polish-notation.py b/problems/python/evaluate-reverse-polish-notation.py similarity index 100% rename from problems/evaluate-reverse-polish-notation.py rename to problems/python/evaluate-reverse-polish-notation.py diff --git a/problems/exclusive-time-of-functions.py b/problems/python/exclusive-time-of-functions.py similarity index 100% rename from problems/exclusive-time-of-functions.py rename to problems/python/exclusive-time-of-functions.py diff --git a/problems/expression-add-operators.py b/problems/python/expression-add-operators.py similarity index 100% rename from problems/expression-add-operators.py rename to problems/python/expression-add-operators.py diff --git a/problems/filling-bookcase-shelves.py b/problems/python/filling-bookcase-shelves.py similarity index 100% rename from problems/filling-bookcase-shelves.py rename to problems/python/filling-bookcase-shelves.py diff --git a/problems/find-all-possible-recipes-from-given-supplies.py b/problems/python/find-all-possible-recipes-from-given-supplies.py similarity index 100% rename from problems/find-all-possible-recipes-from-given-supplies.py rename to problems/python/find-all-possible-recipes-from-given-supplies.py diff --git a/problems/find-and-replace-in-string.py b/problems/python/find-and-replace-in-string.py similarity index 100% rename from problems/find-and-replace-in-string.py rename to problems/python/find-and-replace-in-string.py diff --git a/problems/find-distance-in-a-binary-tree.py b/problems/python/find-distance-in-a-binary-tree.py similarity index 100% rename from problems/find-distance-in-a-binary-tree.py rename to problems/python/find-distance-in-a-binary-tree.py diff --git a/problems/find-duplicate-subtrees.py b/problems/python/find-duplicate-subtrees.py similarity index 100% rename from problems/find-duplicate-subtrees.py rename to problems/python/find-duplicate-subtrees.py diff --git a/problems/find-eventual-safe-states.py b/problems/python/find-eventual-safe-states.py similarity index 100% rename from problems/find-eventual-safe-states.py rename to problems/python/find-eventual-safe-states.py diff --git a/problems/find-first-and-last-position-of-element-in-sorted-array.py b/problems/python/find-first-and-last-position-of-element-in-sorted-array.py similarity index 100% rename from problems/find-first-and-last-position-of-element-in-sorted-array.py rename to problems/python/find-first-and-last-position-of-element-in-sorted-array.py diff --git a/problems/find-k-closest-elements.py b/problems/python/find-k-closest-elements.py similarity index 100% rename from problems/find-k-closest-elements.py rename to problems/python/find-k-closest-elements.py diff --git a/problems/find-k-pairs-with-smallest-sums.py b/problems/python/find-k-pairs-with-smallest-sums.py similarity index 100% rename from problems/find-k-pairs-with-smallest-sums.py rename to problems/python/find-k-pairs-with-smallest-sums.py diff --git a/problems/find-leaves-of-binary-tree.py b/problems/python/find-leaves-of-binary-tree.py similarity index 100% rename from problems/find-leaves-of-binary-tree.py rename to problems/python/find-leaves-of-binary-tree.py diff --git a/problems/find-median-from-data-stream.py b/problems/python/find-median-from-data-stream.py similarity index 100% rename from problems/find-median-from-data-stream.py rename to problems/python/find-median-from-data-stream.py diff --git a/problems/find-minimum-in-rotated-sorted-array-ii.py b/problems/python/find-minimum-in-rotated-sorted-array-ii.py similarity index 100% rename from problems/find-minimum-in-rotated-sorted-array-ii.py rename to problems/python/find-minimum-in-rotated-sorted-array-ii.py diff --git a/problems/find-minimum-in-rotated-sorted-array.py b/problems/python/find-minimum-in-rotated-sorted-array.py similarity index 100% rename from problems/find-minimum-in-rotated-sorted-array.py rename to problems/python/find-minimum-in-rotated-sorted-array.py diff --git a/problems/find-mode-in-binary-search-tree.py b/problems/python/find-mode-in-binary-search-tree.py similarity index 100% rename from problems/find-mode-in-binary-search-tree.py rename to problems/python/find-mode-in-binary-search-tree.py diff --git a/problems/find-original-array-from-doubled-array,py b/problems/python/find-original-array-from-doubled-array,py similarity index 100% rename from problems/find-original-array-from-doubled-array,py rename to problems/python/find-original-array-from-doubled-array,py diff --git a/problems/find-peak-element.py b/problems/python/find-peak-element.py similarity index 100% rename from problems/find-peak-element.py rename to problems/python/find-peak-element.py diff --git a/problems/find-the-duplicate-number.py b/problems/python/find-the-duplicate-number.py similarity index 100% rename from problems/find-the-duplicate-number.py rename to problems/python/find-the-duplicate-number.py diff --git a/problems/first-bad-version.py b/problems/python/first-bad-version.py similarity index 100% rename from problems/first-bad-version.py rename to problems/python/first-bad-version.py diff --git a/problems/first-missing-positive.py b/problems/python/first-missing-positive.py similarity index 100% rename from problems/first-missing-positive.py rename to problems/python/first-missing-positive.py diff --git a/problems/first-unique-character-in-a-string.py b/problems/python/first-unique-character-in-a-string.py similarity index 100% rename from problems/first-unique-character-in-a-string.py rename to problems/python/first-unique-character-in-a-string.py diff --git a/problems/fizz-buzz.py b/problems/python/fizz-buzz.py similarity index 100% rename from problems/fizz-buzz.py rename to problems/python/fizz-buzz.py diff --git a/problems/flatten-binary-tree-to-linked-list.py b/problems/python/flatten-binary-tree-to-linked-list.py similarity index 100% rename from problems/flatten-binary-tree-to-linked-list.py rename to problems/python/flatten-binary-tree-to-linked-list.py diff --git a/problems/flip-binary-tree-to-match-preorder-traversal.py b/problems/python/flip-binary-tree-to-match-preorder-traversal.py similarity index 100% rename from problems/flip-binary-tree-to-match-preorder-traversal.py rename to problems/python/flip-binary-tree-to-match-preorder-traversal.py diff --git a/problems/flip-string-to-monotone-increasing.py b/problems/python/flip-string-to-monotone-increasing.py similarity index 100% rename from problems/flip-string-to-monotone-increasing.py rename to problems/python/flip-string-to-monotone-increasing.py diff --git a/problems/flood-fill.py b/problems/python/flood-fill.py similarity index 100% rename from problems/flood-fill.py rename to problems/python/flood-fill.py diff --git a/problems/friend-circles.py b/problems/python/friend-circles.py similarity index 100% rename from problems/friend-circles.py rename to problems/python/friend-circles.py diff --git a/problems/fruit-into-baskets.py b/problems/python/fruit-into-baskets.py similarity index 100% rename from problems/fruit-into-baskets.py rename to problems/python/fruit-into-baskets.py diff --git a/problems/game-of-life.py b/problems/python/game-of-life.py similarity index 100% rename from problems/game-of-life.py rename to problems/python/game-of-life.py diff --git a/problems/generate-parentheses.py b/problems/python/generate-parentheses.py similarity index 100% rename from problems/generate-parentheses.py rename to problems/python/generate-parentheses.py diff --git a/problems/graph-valid-tree.py b/problems/python/graph-valid-tree.py similarity index 100% rename from problems/graph-valid-tree.py rename to problems/python/graph-valid-tree.py diff --git a/problems/greatest-sum-divisible-by-three.py b/problems/python/greatest-sum-divisible-by-three.py similarity index 100% rename from problems/greatest-sum-divisible-by-three.py rename to problems/python/greatest-sum-divisible-by-three.py diff --git a/problems/group-anagrams.py b/problems/python/group-anagrams.py similarity index 100% rename from problems/group-anagrams.py rename to problems/python/group-anagrams.py diff --git a/problems/group-shifted-strings.py b/problems/python/group-shifted-strings.py similarity index 100% rename from problems/group-shifted-strings.py rename to problems/python/group-shifted-strings.py diff --git a/problems/guess-number-higher-or-lower-ii.py b/problems/python/guess-number-higher-or-lower-ii.py similarity index 100% rename from problems/guess-number-higher-or-lower-ii.py rename to problems/python/guess-number-higher-or-lower-ii.py diff --git a/problems/guess-number-higher-or-lower.py b/problems/python/guess-number-higher-or-lower.py similarity index 100% rename from problems/guess-number-higher-or-lower.py rename to problems/python/guess-number-higher-or-lower.py diff --git a/problems/guess-the-word.py b/problems/python/guess-the-word.py similarity index 100% rename from problems/guess-the-word.py rename to problems/python/guess-the-word.py diff --git a/problems/h-index-ii.py b/problems/python/h-index-ii.py similarity index 100% rename from problems/h-index-ii.py rename to problems/python/h-index-ii.py diff --git a/problems/h-index.py b/problems/python/h-index.py similarity index 100% rename from problems/h-index.py rename to problems/python/h-index.py diff --git a/problems/hamming-distance.py b/problems/python/hamming-distance.py similarity index 100% rename from problems/hamming-distance.py rename to problems/python/hamming-distance.py diff --git a/problems/house-robber-ii.py b/problems/python/house-robber-ii.py similarity index 100% rename from problems/house-robber-ii.py rename to problems/python/house-robber-ii.py diff --git a/problems/house-robber-iii.py b/problems/python/house-robber-iii.py similarity index 100% rename from problems/house-robber-iii.py rename to problems/python/house-robber-iii.py diff --git a/problems/house-robber.py b/problems/python/house-robber.py similarity index 100% rename from problems/house-robber.py rename to problems/python/house-robber.py diff --git a/problems/implement-trie-prefix-tree.py b/problems/python/implement-trie-prefix-tree.py similarity index 100% rename from problems/implement-trie-prefix-tree.py rename to problems/python/implement-trie-prefix-tree.py diff --git a/problems/increasing-triplet-subsequence.py b/problems/python/increasing-triplet-subsequence.py similarity index 100% rename from problems/increasing-triplet-subsequence.py rename to problems/python/increasing-triplet-subsequence.py diff --git a/problems/inorder-successor-in-bst-ii.py b/problems/python/inorder-successor-in-bst-ii.py similarity index 100% rename from problems/inorder-successor-in-bst-ii.py rename to problems/python/inorder-successor-in-bst-ii.py diff --git a/problems/inorder-successor-in-bst.py b/problems/python/inorder-successor-in-bst.py similarity index 100% rename from problems/inorder-successor-in-bst.py rename to problems/python/inorder-successor-in-bst.py diff --git a/problems/insert-interval.py b/problems/python/insert-interval.py similarity index 100% rename from problems/insert-interval.py rename to problems/python/insert-interval.py diff --git a/problems/insert-into-a-binary-search-tree.py b/problems/python/insert-into-a-binary-search-tree.py similarity index 100% rename from problems/insert-into-a-binary-search-tree.py rename to problems/python/insert-into-a-binary-search-tree.py diff --git a/problems/insert-into-a-sorted-circular-linked-list.py b/problems/python/insert-into-a-sorted-circular-linked-list.py similarity index 100% rename from problems/insert-into-a-sorted-circular-linked-list.py rename to problems/python/insert-into-a-sorted-circular-linked-list.py diff --git a/problems/insertion-sort-list.py b/problems/python/insertion-sort-list.py similarity index 100% rename from problems/insertion-sort-list.py rename to problems/python/insertion-sort-list.py diff --git a/problems/integer-to-english-words.py b/problems/python/integer-to-english-words.py similarity index 100% rename from problems/integer-to-english-words.py rename to problems/python/integer-to-english-words.py diff --git a/problems/interleaving-string.py b/problems/python/interleaving-string.py similarity index 100% rename from problems/interleaving-string.py rename to problems/python/interleaving-string.py diff --git a/problems/intersection-of-two-arrays-ii.py b/problems/python/intersection-of-two-arrays-ii.py similarity index 100% rename from problems/intersection-of-two-arrays-ii.py rename to problems/python/intersection-of-two-arrays-ii.py diff --git a/problems/intersection-of-two-arrays.py b/problems/python/intersection-of-two-arrays.py similarity index 100% rename from problems/intersection-of-two-arrays.py rename to problems/python/intersection-of-two-arrays.py diff --git a/problems/invert-binary-tree.py b/problems/python/invert-binary-tree.py similarity index 100% rename from problems/invert-binary-tree.py rename to problems/python/invert-binary-tree.py diff --git a/problems/is-graph-bipartite.py b/problems/python/is-graph-bipartite.py similarity index 100% rename from problems/is-graph-bipartite.py rename to problems/python/is-graph-bipartite.py diff --git a/problems/is-subsequence.py b/problems/python/is-subsequence.py similarity index 100% rename from problems/is-subsequence.py rename to problems/python/is-subsequence.py diff --git a/problems/isomorphic-strings.py b/problems/python/isomorphic-strings.py similarity index 100% rename from problems/isomorphic-strings.py rename to problems/python/isomorphic-strings.py diff --git a/problems/jewels-and-stones.py b/problems/python/jewels-and-stones.py similarity index 100% rename from problems/jewels-and-stones.py rename to problems/python/jewels-and-stones.py diff --git a/problems/jump-game.py b/problems/python/jump-game.py similarity index 100% rename from problems/jump-game.py rename to problems/python/jump-game.py diff --git a/problems/k-closest-points-to-origin.py b/problems/python/k-closest-points-to-origin.py similarity index 100% rename from problems/k-closest-points-to-origin.py rename to problems/python/k-closest-points-to-origin.py diff --git a/problems/k-empty-slots.py b/problems/python/k-empty-slots.py similarity index 100% rename from problems/k-empty-slots.py rename to problems/python/k-empty-slots.py diff --git a/problems/keys-and-rooms.py b/problems/python/keys-and-rooms.py similarity index 100% rename from problems/keys-and-rooms.py rename to problems/python/keys-and-rooms.py diff --git a/problems/knight-dialer.py b/problems/python/knight-dialer.py similarity index 100% rename from problems/knight-dialer.py rename to problems/python/knight-dialer.py diff --git a/problems/knight-probability-in-chessboard.py b/problems/python/knight-probability-in-chessboard.py similarity index 100% rename from problems/knight-probability-in-chessboard.py rename to problems/python/knight-probability-in-chessboard.py diff --git a/problems/koko-eating-bananas.py b/problems/python/koko-eating-bananas.py similarity index 100% rename from problems/koko-eating-bananas.py rename to problems/python/koko-eating-bananas.py diff --git a/problems/kth-largest-element-in-an-array.py b/problems/python/kth-largest-element-in-an-array.py similarity index 100% rename from problems/kth-largest-element-in-an-array.py rename to problems/python/kth-largest-element-in-an-array.py diff --git a/problems/kth-smallest-element-in-a-bst.py b/problems/python/kth-smallest-element-in-a-bst.py similarity index 100% rename from problems/kth-smallest-element-in-a-bst.py rename to problems/python/kth-smallest-element-in-a-bst.py diff --git a/problems/kth-smallest-element-in-a-sorted-matrix.py b/problems/python/kth-smallest-element-in-a-sorted-matrix.py similarity index 100% rename from problems/kth-smallest-element-in-a-sorted-matrix.py rename to problems/python/kth-smallest-element-in-a-sorted-matrix.py diff --git a/problems/largest-1-bordered-square.py b/problems/python/largest-1-bordered-square.py similarity index 100% rename from problems/largest-1-bordered-square.py rename to problems/python/largest-1-bordered-square.py diff --git a/problems/largest-bst-subtree.py b/problems/python/largest-bst-subtree.py similarity index 100% rename from problems/largest-bst-subtree.py rename to problems/python/largest-bst-subtree.py diff --git a/problems/largest-sum-of-averages.py b/problems/python/largest-sum-of-averages.py similarity index 100% rename from problems/largest-sum-of-averages.py rename to problems/python/largest-sum-of-averages.py diff --git a/problems/last-stone-weight-ii.py b/problems/python/last-stone-weight-ii.py similarity index 100% rename from problems/last-stone-weight-ii.py rename to problems/python/last-stone-weight-ii.py diff --git a/problems/last-stone-weight.py b/problems/python/last-stone-weight.py similarity index 100% rename from problems/last-stone-weight.py rename to problems/python/last-stone-weight.py diff --git a/problems/least-number-of-unique-integers-after-k-removals.py b/problems/python/least-number-of-unique-integers-after-k-removals.py similarity index 100% rename from problems/least-number-of-unique-integers-after-k-removals.py rename to problems/python/least-number-of-unique-integers-after-k-removals.py diff --git a/problems/letter-case-permutation.py b/problems/python/letter-case-permutation.py similarity index 100% rename from problems/letter-case-permutation.py rename to problems/python/letter-case-permutation.py diff --git a/problems/letter-combinations-of-a-phone-number.py b/problems/python/letter-combinations-of-a-phone-number.py similarity index 100% rename from problems/letter-combinations-of-a-phone-number.py rename to problems/python/letter-combinations-of-a-phone-number.py diff --git a/problems/license-key-formatting.py b/problems/python/license-key-formatting.py similarity index 100% rename from problems/license-key-formatting.py rename to problems/python/license-key-formatting.py diff --git a/problems/linked-list-cycle-ii.py b/problems/python/linked-list-cycle-ii.py similarity index 100% rename from problems/linked-list-cycle-ii.py rename to problems/python/linked-list-cycle-ii.py diff --git a/problems/linked-list-cycle.py b/problems/python/linked-list-cycle.py similarity index 100% rename from problems/linked-list-cycle.py rename to problems/python/linked-list-cycle.py diff --git a/problems/linked-list-random-node.py b/problems/python/linked-list-random-node.py similarity index 100% rename from problems/linked-list-random-node.py rename to problems/python/linked-list-random-node.py diff --git a/problems/logger-rate-limiter.py b/problems/python/logger-rate-limiter.py similarity index 100% rename from problems/logger-rate-limiter.py rename to problems/python/logger-rate-limiter.py diff --git a/problems/longest-common-prefix.py b/problems/python/longest-common-prefix.py similarity index 100% rename from problems/longest-common-prefix.py rename to problems/python/longest-common-prefix.py diff --git a/problems/longest-common-subsequence.py b/problems/python/longest-common-subsequence.py similarity index 100% rename from problems/longest-common-subsequence.py rename to problems/python/longest-common-subsequence.py diff --git a/problems/longest-consecutive-sequence.py b/problems/python/longest-consecutive-sequence.py similarity index 100% rename from problems/longest-consecutive-sequence.py rename to problems/python/longest-consecutive-sequence.py diff --git a/problems/longest-increasing-path-in-a-matrix.py b/problems/python/longest-increasing-path-in-a-matrix.py similarity index 100% rename from problems/longest-increasing-path-in-a-matrix.py rename to problems/python/longest-increasing-path-in-a-matrix.py diff --git a/problems/longest-increasing-subsequence.py b/problems/python/longest-increasing-subsequence.py similarity index 100% rename from problems/longest-increasing-subsequence.py rename to problems/python/longest-increasing-subsequence.py diff --git a/problems/longest-palindromic-subsequence.py b/problems/python/longest-palindromic-subsequence.py similarity index 100% rename from problems/longest-palindromic-subsequence.py rename to problems/python/longest-palindromic-subsequence.py diff --git a/problems/longest-palindromic-substring.py b/problems/python/longest-palindromic-substring.py similarity index 100% rename from problems/longest-palindromic-substring.py rename to problems/python/longest-palindromic-substring.py diff --git a/problems/longest-repeating-character-replacement.py b/problems/python/longest-repeating-character-replacement.py similarity index 100% rename from problems/longest-repeating-character-replacement.py rename to problems/python/longest-repeating-character-replacement.py diff --git a/problems/longest-string-chain.py b/problems/python/longest-string-chain.py similarity index 100% rename from problems/longest-string-chain.py rename to problems/python/longest-string-chain.py diff --git a/problems/longest-substring-with-at-least-k-repeating-characters.py b/problems/python/longest-substring-with-at-least-k-repeating-characters.py similarity index 100% rename from problems/longest-substring-with-at-least-k-repeating-characters.py rename to problems/python/longest-substring-with-at-least-k-repeating-characters.py diff --git a/problems/longest-substring-without-repeating-characters.py b/problems/python/longest-substring-without-repeating-characters.py similarity index 100% rename from problems/longest-substring-without-repeating-characters.py rename to problems/python/longest-substring-without-repeating-characters.py diff --git a/problems/longest-univalue-path.py b/problems/python/longest-univalue-path.py similarity index 100% rename from problems/longest-univalue-path.py rename to problems/python/longest-univalue-path.py diff --git a/problems/lowest-common-ancestor-of-a-binary-search-tree.py b/problems/python/lowest-common-ancestor-of-a-binary-search-tree.py similarity index 100% rename from problems/lowest-common-ancestor-of-a-binary-search-tree.py rename to problems/python/lowest-common-ancestor-of-a-binary-search-tree.py diff --git a/problems/lowest-common-ancestor-of-a-binary-search.py b/problems/python/lowest-common-ancestor-of-a-binary-search.py similarity index 100% rename from problems/lowest-common-ancestor-of-a-binary-search.py rename to problems/python/lowest-common-ancestor-of-a-binary-search.py diff --git a/problems/lowest-common-ancestor-of-a-binary-tree-ii.py b/problems/python/lowest-common-ancestor-of-a-binary-tree-ii.py similarity index 100% rename from problems/lowest-common-ancestor-of-a-binary-tree-ii.py rename to problems/python/lowest-common-ancestor-of-a-binary-tree-ii.py diff --git a/problems/lowest-common-ancestor-of-a-binary-tree-iii.py b/problems/python/lowest-common-ancestor-of-a-binary-tree-iii.py similarity index 100% rename from problems/lowest-common-ancestor-of-a-binary-tree-iii.py rename to problems/python/lowest-common-ancestor-of-a-binary-tree-iii.py diff --git a/problems/lowest-common-ancestor-of-a-binary-tree-iv.py b/problems/python/lowest-common-ancestor-of-a-binary-tree-iv.py similarity index 100% rename from problems/lowest-common-ancestor-of-a-binary-tree-iv.py rename to problems/python/lowest-common-ancestor-of-a-binary-tree-iv.py diff --git a/problems/lowest-common-ancestor-of-a-binary-tree.py b/problems/python/lowest-common-ancestor-of-a-binary-tree.py similarity index 100% rename from problems/lowest-common-ancestor-of-a-binary-tree.py rename to problems/python/lowest-common-ancestor-of-a-binary-tree.py diff --git a/problems/lowest-common-ancestor-of-deepest-leaves.py b/problems/python/lowest-common-ancestor-of-deepest-leaves.py similarity index 100% rename from problems/lowest-common-ancestor-of-deepest-leaves.py rename to problems/python/lowest-common-ancestor-of-deepest-leaves.py diff --git a/problems/lru-cache.py b/problems/python/lru-cache.py similarity index 100% rename from problems/lru-cache.py rename to problems/python/lru-cache.py diff --git a/problems/majority-element-ii.py b/problems/python/majority-element-ii.py similarity index 100% rename from problems/majority-element-ii.py rename to problems/python/majority-element-ii.py diff --git a/problems/majority-element.py b/problems/python/majority-element.py similarity index 100% rename from problems/majority-element.py rename to problems/python/majority-element.py diff --git a/problems/making-a-large-island.py b/problems/python/making-a-large-island.py similarity index 100% rename from problems/making-a-large-island.py rename to problems/python/making-a-large-island.py diff --git a/problems/max-area-of-island.py b/problems/python/max-area-of-island.py similarity index 100% rename from problems/max-area-of-island.py rename to problems/python/max-area-of-island.py diff --git a/problems/max-consecutive-ones-iii.py b/problems/python/max-consecutive-ones-iii.py similarity index 100% rename from problems/max-consecutive-ones-iii.py rename to problems/python/max-consecutive-ones-iii.py diff --git a/problems/max-stack.py b/problems/python/max-stack.py similarity index 100% rename from problems/max-stack.py rename to problems/python/max-stack.py diff --git a/problems/max-sum-of-rectangle-no-larger-than-k.py b/problems/python/max-sum-of-rectangle-no-larger-than-k.py similarity index 100% rename from problems/max-sum-of-rectangle-no-larger-than-k.py rename to problems/python/max-sum-of-rectangle-no-larger-than-k.py diff --git a/problems/maximal-square.py b/problems/python/maximal-square.py similarity index 100% rename from problems/maximal-square.py rename to problems/python/maximal-square.py diff --git a/problems/maximum-average-subtree.py b/problems/python/maximum-average-subtree.py similarity index 100% rename from problems/maximum-average-subtree.py rename to problems/python/maximum-average-subtree.py diff --git a/problems/maximum-compatibility-score-sum.py b/problems/python/maximum-compatibility-score-sum.py similarity index 100% rename from problems/maximum-compatibility-score-sum.py rename to problems/python/maximum-compatibility-score-sum.py diff --git a/problems/maximum-depth-of-binary-tree.py b/problems/python/maximum-depth-of-binary-tree.py similarity index 100% rename from problems/maximum-depth-of-binary-tree.py rename to problems/python/maximum-depth-of-binary-tree.py diff --git a/problems/maximum-gap.py b/problems/python/maximum-gap.py similarity index 100% rename from problems/maximum-gap.py rename to problems/python/maximum-gap.py diff --git a/problems/maximum-length-of-repeated-subarray.py b/problems/python/maximum-length-of-repeated-subarray.py similarity index 100% rename from problems/maximum-length-of-repeated-subarray.py rename to problems/python/maximum-length-of-repeated-subarray.py diff --git a/problems/maximum-number-of-events-that-can-be-attended.py b/problems/python/maximum-number-of-events-that-can-be-attended.py similarity index 100% rename from problems/maximum-number-of-events-that-can-be-attended.py rename to problems/python/maximum-number-of-events-that-can-be-attended.py diff --git a/problems/maximum-number-of-points-with-cost.py b/problems/python/maximum-number-of-points-with-cost.py similarity index 100% rename from problems/maximum-number-of-points-with-cost.py rename to problems/python/maximum-number-of-points-with-cost.py diff --git a/problems/maximum-number-of-visible-points.py b/problems/python/maximum-number-of-visible-points.py similarity index 100% rename from problems/maximum-number-of-visible-points.py rename to problems/python/maximum-number-of-visible-points.py diff --git a/problems/maximum-product-of-three-numbers.py b/problems/python/maximum-product-of-three-numbers.py similarity index 100% rename from problems/maximum-product-of-three-numbers.py rename to problems/python/maximum-product-of-three-numbers.py diff --git a/problems/maximum-product-subarray.py b/problems/python/maximum-product-subarray.py similarity index 100% rename from problems/maximum-product-subarray.py rename to problems/python/maximum-product-subarray.py diff --git a/problems/maximum-subarray-sum-with-one-deletion.py b/problems/python/maximum-subarray-sum-with-one-deletion.py similarity index 100% rename from problems/maximum-subarray-sum-with-one-deletion.py rename to problems/python/maximum-subarray-sum-with-one-deletion.py diff --git a/problems/maximum-subarray.py b/problems/python/maximum-subarray.py similarity index 100% rename from problems/maximum-subarray.py rename to problems/python/maximum-subarray.py diff --git a/problems/maximum-swap.py b/problems/python/maximum-swap.py similarity index 100% rename from problems/maximum-swap.py rename to problems/python/maximum-swap.py diff --git a/problems/maximum-units-on-a-truck.py b/problems/python/maximum-units-on-a-truck.py similarity index 100% rename from problems/maximum-units-on-a-truck.py rename to problems/python/maximum-units-on-a-truck.py diff --git a/problems/median-of-two-sorted-arrays.py b/problems/python/median-of-two-sorted-arrays.py similarity index 100% rename from problems/median-of-two-sorted-arrays.py rename to problems/python/median-of-two-sorted-arrays.py diff --git a/problems/meeting-rooms-ii.py b/problems/python/meeting-rooms-ii.py similarity index 100% rename from problems/meeting-rooms-ii.py rename to problems/python/meeting-rooms-ii.py diff --git a/problems/meeting-rooms.py b/problems/python/meeting-rooms.py similarity index 100% rename from problems/meeting-rooms.py rename to problems/python/meeting-rooms.py diff --git a/problems/merge-intervals.py b/problems/python/merge-intervals.py similarity index 100% rename from problems/merge-intervals.py rename to problems/python/merge-intervals.py diff --git a/problems/merge-k-sorted-lists.py b/problems/python/merge-k-sorted-lists.py similarity index 100% rename from problems/merge-k-sorted-lists.py rename to problems/python/merge-k-sorted-lists.py diff --git a/problems/merge-sorted-array.py b/problems/python/merge-sorted-array.py similarity index 100% rename from problems/merge-sorted-array.py rename to problems/python/merge-sorted-array.py diff --git a/problems/merge-two-sorted-lists.py b/problems/python/merge-two-sorted-lists.py similarity index 100% rename from problems/merge-two-sorted-lists.py rename to problems/python/merge-two-sorted-lists.py diff --git a/problems/min-cost-climbing-stairs.py b/problems/python/min-cost-climbing-stairs.py similarity index 100% rename from problems/min-cost-climbing-stairs.py rename to problems/python/min-cost-climbing-stairs.py diff --git a/problems/min-stack.py b/problems/python/min-stack.py similarity index 100% rename from problems/min-stack.py rename to problems/python/min-stack.py diff --git a/problems/minimize-malware-spread.py b/problems/python/minimize-malware-spread.py similarity index 100% rename from problems/minimize-malware-spread.py rename to problems/python/minimize-malware-spread.py diff --git a/problems/minimum-absolute-difference-in-bst.py b/problems/python/minimum-absolute-difference-in-bst.py similarity index 100% rename from problems/minimum-absolute-difference-in-bst.py rename to problems/python/minimum-absolute-difference-in-bst.py diff --git a/problems/minimum-ascii-delete-sum-for-two-strings.py b/problems/python/minimum-ascii-delete-sum-for-two-strings.py similarity index 100% rename from problems/minimum-ascii-delete-sum-for-two-strings.py rename to problems/python/minimum-ascii-delete-sum-for-two-strings.py diff --git a/problems/minimum-cost-to-connect-sticks.py b/problems/python/minimum-cost-to-connect-sticks.py similarity index 100% rename from problems/minimum-cost-to-connect-sticks.py rename to problems/python/minimum-cost-to-connect-sticks.py diff --git a/problems/minimum-cost-to-hire-k-workers.py b/problems/python/minimum-cost-to-hire-k-workers.py similarity index 100% rename from problems/minimum-cost-to-hire-k-workers.py rename to problems/python/minimum-cost-to-hire-k-workers.py diff --git a/problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py b/problems/python/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py similarity index 100% rename from problems/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py rename to problems/python/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py diff --git a/problems/minimum-cost-to-reach-city-with-discounts.py b/problems/python/minimum-cost-to-reach-city-with-discounts.py similarity index 100% rename from problems/minimum-cost-to-reach-city-with-discounts.py rename to problems/python/minimum-cost-to-reach-city-with-discounts.py diff --git a/problems/minimum-depth-of-binary-tree.py b/problems/python/minimum-depth-of-binary-tree.py similarity index 100% rename from problems/minimum-depth-of-binary-tree.py rename to problems/python/minimum-depth-of-binary-tree.py diff --git a/problems/minimum-difficulty-of-a-job-schedule.py b/problems/python/minimum-difficulty-of-a-job-schedule.py similarity index 100% rename from problems/minimum-difficulty-of-a-job-schedule.py rename to problems/python/minimum-difficulty-of-a-job-schedule.py diff --git a/problems/minimum-falling-path-sum-ii.py b/problems/python/minimum-falling-path-sum-ii.py similarity index 100% rename from problems/minimum-falling-path-sum-ii.py rename to problems/python/minimum-falling-path-sum-ii.py diff --git a/problems/minimum-knight-moves.py b/problems/python/minimum-knight-moves.py similarity index 100% rename from problems/minimum-knight-moves.py rename to problems/python/minimum-knight-moves.py diff --git a/problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py b/problems/python/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py similarity index 100% rename from problems/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py rename to problems/python/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py diff --git a/problems/minimum-path-sum.py b/problems/python/minimum-path-sum.py similarity index 100% rename from problems/minimum-path-sum.py rename to problems/python/minimum-path-sum.py diff --git a/problems/minimum-score-triangulation-of-polygon.py b/problems/python/minimum-score-triangulation-of-polygon.py similarity index 100% rename from problems/minimum-score-triangulation-of-polygon.py rename to problems/python/minimum-score-triangulation-of-polygon.py diff --git a/problems/minimum-size-subarray-sum.py b/problems/python/minimum-size-subarray-sum.py similarity index 100% rename from problems/minimum-size-subarray-sum.py rename to problems/python/minimum-size-subarray-sum.py diff --git a/problems/minimum-swaps-to-group-all-1s-together.py b/problems/python/minimum-swaps-to-group-all-1s-together.py similarity index 100% rename from problems/minimum-swaps-to-group-all-1s-together.py rename to problems/python/minimum-swaps-to-group-all-1s-together.py diff --git a/problems/minimum-swaps-to-make-sequences-increasing.py b/problems/python/minimum-swaps-to-make-sequences-increasing.py similarity index 100% rename from problems/minimum-swaps-to-make-sequences-increasing.py rename to problems/python/minimum-swaps-to-make-sequences-increasing.py diff --git a/problems/minimum-time-difference.py b/problems/python/minimum-time-difference.py similarity index 100% rename from problems/minimum-time-difference.py rename to problems/python/minimum-time-difference.py diff --git a/problems/minimum-window-substring.py b/problems/python/minimum-window-substring.py similarity index 100% rename from problems/minimum-window-substring.py rename to problems/python/minimum-window-substring.py diff --git a/problems/minimum-xor-sum-of-two-arrays.py b/problems/python/minimum-xor-sum-of-two-arrays.py similarity index 100% rename from problems/minimum-xor-sum-of-two-arrays.py rename to problems/python/minimum-xor-sum-of-two-arrays.py diff --git a/problems/missing-number.py b/problems/python/missing-number.py similarity index 100% rename from problems/missing-number.py rename to problems/python/missing-number.py diff --git a/problems/most-frequent-subtree-sum.py b/problems/python/most-frequent-subtree-sum.py similarity index 100% rename from problems/most-frequent-subtree-sum.py rename to problems/python/most-frequent-subtree-sum.py diff --git a/problems/most-stones-removed-with-same-row-or-column.py b/problems/python/most-stones-removed-with-same-row-or-column.py similarity index 100% rename from problems/most-stones-removed-with-same-row-or-column.py rename to problems/python/most-stones-removed-with-same-row-or-column.py diff --git a/problems/move-zeroes.py b/problems/python/move-zeroes.py similarity index 100% rename from problems/move-zeroes.py rename to problems/python/move-zeroes.py diff --git a/problems/moving-average-from-data-stream.py b/problems/python/moving-average-from-data-stream.py similarity index 100% rename from problems/moving-average-from-data-stream.py rename to problems/python/moving-average-from-data-stream.py diff --git a/problems/my-calendar-ii.py b/problems/python/my-calendar-ii.py similarity index 100% rename from problems/my-calendar-ii.py rename to problems/python/my-calendar-ii.py diff --git a/problems/n-ary-tree-level-order-traversal.py b/problems/python/n-ary-tree-level-order-traversal.py similarity index 100% rename from problems/n-ary-tree-level-order-traversal.py rename to problems/python/n-ary-tree-level-order-traversal.py diff --git a/problems/n-ary-tree-postorder-traversal.py b/problems/python/n-ary-tree-postorder-traversal.py similarity index 100% rename from problems/n-ary-tree-postorder-traversal.py rename to problems/python/n-ary-tree-postorder-traversal.py diff --git a/problems/n-ary-tree-preorder-traversal.py b/problems/python/n-ary-tree-preorder-traversal.py similarity index 100% rename from problems/n-ary-tree-preorder-traversal.py rename to problems/python/n-ary-tree-preorder-traversal.py diff --git a/problems/nested-list-weight-sum.py b/problems/python/nested-list-weight-sum.py similarity index 100% rename from problems/nested-list-weight-sum.py rename to problems/python/nested-list-weight-sum.py diff --git a/problems/network-delay-time.py b/problems/python/network-delay-time.py similarity index 100% rename from problems/network-delay-time.py rename to problems/python/network-delay-time.py diff --git a/problems/next-closest-time.py b/problems/python/next-closest-time.py similarity index 100% rename from problems/next-closest-time.py rename to problems/python/next-closest-time.py diff --git a/problems/next-permutation.py b/problems/python/next-permutation.py similarity index 100% rename from problems/next-permutation.py rename to problems/python/next-permutation.py diff --git a/problems/number-complement.py b/problems/python/number-complement.py similarity index 100% rename from problems/number-complement.py rename to problems/python/number-complement.py diff --git a/problems/number-of-connected-components-in-an-undirected-graph.py b/problems/python/number-of-connected-components-in-an-undirected-graph.py similarity index 100% rename from problems/number-of-connected-components-in-an-undirected-graph.py rename to problems/python/number-of-connected-components-in-an-undirected-graph.py diff --git a/problems/number-of-islands-ii.py b/problems/python/number-of-islands-ii.py similarity index 100% rename from problems/number-of-islands-ii.py rename to problems/python/number-of-islands-ii.py diff --git a/problems/number-of-islands.py b/problems/python/number-of-islands.py similarity index 100% rename from problems/number-of-islands.py rename to problems/python/number-of-islands.py diff --git a/problems/number-of-longest-increasing-subsequence.py b/problems/python/number-of-longest-increasing-subsequence.py similarity index 100% rename from problems/number-of-longest-increasing-subsequence.py rename to problems/python/number-of-longest-increasing-subsequence.py diff --git a/problems/number-of-matching-subsequences.py b/problems/python/number-of-matching-subsequences.py similarity index 100% rename from problems/number-of-matching-subsequences.py rename to problems/python/number-of-matching-subsequences.py diff --git a/problems/number-of-provinces.py b/problems/python/number-of-provinces.py similarity index 100% rename from problems/number-of-provinces.py rename to problems/python/number-of-provinces.py diff --git a/problems/number-of-recent-calls.py b/problems/python/number-of-recent-calls.py similarity index 100% rename from problems/number-of-recent-calls.py rename to problems/python/number-of-recent-calls.py diff --git a/problems/number-of-squareful-arrays.py b/problems/python/number-of-squareful-arrays.py similarity index 100% rename from problems/number-of-squareful-arrays.py rename to problems/python/number-of-squareful-arrays.py diff --git a/problems/number-of-substrings-containing-all-thre.py b/problems/python/number-of-substrings-containing-all-thre.py similarity index 100% rename from problems/number-of-substrings-containing-all-thre.py rename to problems/python/number-of-substrings-containing-all-thre.py diff --git a/problems/number-of-ways-to-arrive-at-destination.py b/problems/python/number-of-ways-to-arrive-at-destination.py similarity index 100% rename from problems/number-of-ways-to-arrive-at-destination.py rename to problems/python/number-of-ways-to-arrive-at-destination.py diff --git a/problems/odd-even-jump.py b/problems/python/odd-even-jump.py similarity index 100% rename from problems/odd-even-jump.py rename to problems/python/odd-even-jump.py diff --git a/problems/ones-and-zeroes.py b/problems/python/ones-and-zeroes.py similarity index 100% rename from problems/ones-and-zeroes.py rename to problems/python/ones-and-zeroes.py diff --git a/problems/open-the-lock.py b/problems/python/open-the-lock.py similarity index 100% rename from problems/open-the-lock.py rename to problems/python/open-the-lock.py diff --git a/problems/out-of-boundary-paths.py b/problems/python/out-of-boundary-paths.py similarity index 100% rename from problems/out-of-boundary-paths.py rename to problems/python/out-of-boundary-paths.py diff --git a/problems/pacific-atlantic-water-flow.py b/problems/python/pacific-atlantic-water-flow.py similarity index 100% rename from problems/pacific-atlantic-water-flow.py rename to problems/python/pacific-atlantic-water-flow.py diff --git a/problems/pairs-of-songs-with-total-durations-divisible-by-60.py b/problems/python/pairs-of-songs-with-total-durations-divisible-by-60.py similarity index 100% rename from problems/pairs-of-songs-with-total-durations-divisible-by-60.py rename to problems/python/pairs-of-songs-with-total-durations-divisible-by-60.py diff --git a/problems/palindrome-number.py b/problems/python/palindrome-number.py similarity index 100% rename from problems/palindrome-number.py rename to problems/python/palindrome-number.py diff --git a/problems/palindrome-pairs.py b/problems/python/palindrome-pairs.py similarity index 100% rename from problems/palindrome-pairs.py rename to problems/python/palindrome-pairs.py diff --git a/problems/palindrome-partitioning-iii.py b/problems/python/palindrome-partitioning-iii.py similarity index 100% rename from problems/palindrome-partitioning-iii.py rename to problems/python/palindrome-partitioning-iii.py diff --git a/problems/palindrome-partitioning.py b/problems/python/palindrome-partitioning.py similarity index 100% rename from problems/palindrome-partitioning.py rename to problems/python/palindrome-partitioning.py diff --git a/problems/palindromic-substrings.py b/problems/python/palindromic-substrings.py similarity index 100% rename from problems/palindromic-substrings.py rename to problems/python/palindromic-substrings.py diff --git a/problems/partition-array-for-maximum-sum.py b/problems/python/partition-array-for-maximum-sum.py similarity index 100% rename from problems/partition-array-for-maximum-sum.py rename to problems/python/partition-array-for-maximum-sum.py diff --git a/problems/partition-labels.py b/problems/python/partition-labels.py similarity index 100% rename from problems/partition-labels.py rename to problems/python/partition-labels.py diff --git a/problems/partition-to-k-equal-sum-subsets.py b/problems/python/partition-to-k-equal-sum-subsets.py similarity index 100% rename from problems/partition-to-k-equal-sum-subsets.py rename to problems/python/partition-to-k-equal-sum-subsets.py diff --git a/problems/path-sum-ii.py b/problems/python/path-sum-ii.py similarity index 100% rename from problems/path-sum-ii.py rename to problems/python/path-sum-ii.py diff --git a/problems/path-sum-iii.py b/problems/python/path-sum-iii.py similarity index 100% rename from problems/path-sum-iii.py rename to problems/python/path-sum-iii.py diff --git a/problems/path-sum.py b/problems/python/path-sum.py similarity index 100% rename from problems/path-sum.py rename to problems/python/path-sum.py diff --git a/problems/path-with-maximum-probability.py b/problems/python/path-with-maximum-probability.py similarity index 100% rename from problems/path-with-maximum-probability.py rename to problems/python/path-with-maximum-probability.py diff --git a/problems/peak-index-in-a-mountain-array.PY b/problems/python/peak-index-in-a-mountain-array.py similarity index 100% rename from problems/peak-index-in-a-mountain-array.PY rename to problems/python/peak-index-in-a-mountain-array.py diff --git a/problems/perfect-squares.py b/problems/python/perfect-squares.py similarity index 100% rename from problems/perfect-squares.py rename to problems/python/perfect-squares.py diff --git a/problems/permutation-in-string.py b/problems/python/permutation-in-string.py similarity index 100% rename from problems/permutation-in-string.py rename to problems/python/permutation-in-string.py diff --git a/problems/permutation-sequence.py b/problems/python/permutation-sequence.py similarity index 100% rename from problems/permutation-sequence.py rename to problems/python/permutation-sequence.py diff --git a/problems/permutations-ii.py b/problems/python/permutations-ii.py similarity index 100% rename from problems/permutations-ii.py rename to problems/python/permutations-ii.py diff --git a/problems/permutations.py b/problems/python/permutations.py similarity index 100% rename from problems/permutations.py rename to problems/python/permutations.py diff --git a/problems/populating-next-right-pointers-in-each-node-ii.py b/problems/python/populating-next-right-pointers-in-each-node-ii.py similarity index 100% rename from problems/populating-next-right-pointers-in-each-node-ii.py rename to problems/python/populating-next-right-pointers-in-each-node-ii.py diff --git a/problems/populating-next-right-pointers-in-each-node.py b/problems/python/populating-next-right-pointers-in-each-node.py similarity index 100% rename from problems/populating-next-right-pointers-in-each-node.py rename to problems/python/populating-next-right-pointers-in-each-node.py diff --git a/problems/powx-n.py b/problems/python/powx-n.py similarity index 100% rename from problems/powx-n.py rename to problems/python/powx-n.py diff --git a/problems/product-of-array-except-self.py b/problems/python/product-of-array-except-self.py similarity index 100% rename from problems/product-of-array-except-self.py rename to problems/python/product-of-array-except-self.py diff --git a/problems/profitable-schemes.py b/problems/python/profitable-schemes.py similarity index 100% rename from problems/profitable-schemes.py rename to problems/python/profitable-schemes.py diff --git a/problems/queue-reconstruction-by-height.py b/problems/python/queue-reconstruction-by-height.py similarity index 100% rename from problems/queue-reconstruction-by-height.py rename to problems/python/queue-reconstruction-by-height.py diff --git a/problems/random-pick-with-weight.py b/problems/python/random-pick-with-weight.py similarity index 100% rename from problems/random-pick-with-weight.py rename to problems/python/random-pick-with-weight.py diff --git a/problems/range-addition.py b/problems/python/range-addition.py similarity index 100% rename from problems/range-addition.py rename to problems/python/range-addition.py diff --git a/problems/range-sum-of-bst.py b/problems/python/range-sum-of-bst.py similarity index 100% rename from problems/range-sum-of-bst.py rename to problems/python/range-sum-of-bst.py diff --git a/problems/range-sum-query-immutable.py b/problems/python/range-sum-query-immutable.py similarity index 100% rename from problems/range-sum-query-immutable.py rename to problems/python/range-sum-query-immutable.py diff --git a/problems/range-sum-query-mutable.py b/problems/python/range-sum-query-mutable.py similarity index 100% rename from problems/range-sum-query-mutable.py rename to problems/python/range-sum-query-mutable.py diff --git a/problems/rearrange-string-k-distance-apart.py b/problems/python/rearrange-string-k-distance-apart.py similarity index 100% rename from problems/rearrange-string-k-distance-apart.py rename to problems/python/rearrange-string-k-distance-apart.py diff --git a/problems/reconstruct-itinerary.py b/problems/python/reconstruct-itinerary.py similarity index 100% rename from problems/reconstruct-itinerary.py rename to problems/python/reconstruct-itinerary.py diff --git a/problems/recover-binary-search-tree.py b/problems/python/recover-binary-search-tree.py similarity index 100% rename from problems/recover-binary-search-tree.py rename to problems/python/recover-binary-search-tree.py diff --git a/problems/redundant-connection.py b/problems/python/redundant-connection.py similarity index 100% rename from problems/redundant-connection.py rename to problems/python/redundant-connection.py diff --git a/problems/remove-all-adjacent-duplicates-in-string.py b/problems/python/remove-all-adjacent-duplicates-in-string.py similarity index 100% rename from problems/remove-all-adjacent-duplicates-in-string.py rename to problems/python/remove-all-adjacent-duplicates-in-string.py diff --git a/problems/remove-all-ones-with-row-and-column-flips.py b/problems/python/remove-all-ones-with-row-and-column-flips.py similarity index 100% rename from problems/remove-all-ones-with-row-and-column-flips.py rename to problems/python/remove-all-ones-with-row-and-column-flips.py diff --git a/problems/remove-duplicates-from-sorted-array-ii.py b/problems/python/remove-duplicates-from-sorted-array-ii.py similarity index 100% rename from problems/remove-duplicates-from-sorted-array-ii.py rename to problems/python/remove-duplicates-from-sorted-array-ii.py diff --git a/problems/remove-duplicates-from-sorted-array.py b/problems/python/remove-duplicates-from-sorted-array.py similarity index 100% rename from problems/remove-duplicates-from-sorted-array.py rename to problems/python/remove-duplicates-from-sorted-array.py diff --git a/problems/remove-duplicates-from-sorted-list.py b/problems/python/remove-duplicates-from-sorted-list.py similarity index 100% rename from problems/remove-duplicates-from-sorted-list.py rename to problems/python/remove-duplicates-from-sorted-list.py diff --git a/problems/remove-element.py b/problems/python/remove-element.py similarity index 100% rename from problems/remove-element.py rename to problems/python/remove-element.py diff --git a/problems/remove-invalid-parentheses.py b/problems/python/remove-invalid-parentheses.py similarity index 100% rename from problems/remove-invalid-parentheses.py rename to problems/python/remove-invalid-parentheses.py diff --git a/problems/remove-linked-list-elements.py b/problems/python/remove-linked-list-elements.py similarity index 100% rename from problems/remove-linked-list-elements.py rename to problems/python/remove-linked-list-elements.py diff --git a/problems/remove-nth-node-from-end-of-list.py b/problems/python/remove-nth-node-from-end-of-list.py similarity index 100% rename from problems/remove-nth-node-from-end-of-list.py rename to problems/python/remove-nth-node-from-end-of-list.py diff --git a/problems/reorder-list.py b/problems/python/reorder-list.py similarity index 100% rename from problems/reorder-list.py rename to problems/python/reorder-list.py diff --git a/problems/repeated-string-match.py b/problems/python/repeated-string-match.py similarity index 100% rename from problems/repeated-string-match.py rename to problems/python/repeated-string-match.py diff --git a/problems/replace-the-substring-for-balanced-string.py b/problems/python/replace-the-substring-for-balanced-string.py similarity index 100% rename from problems/replace-the-substring-for-balanced-string.py rename to problems/python/replace-the-substring-for-balanced-string.py diff --git a/problems/restore-ip-addresses.py b/problems/python/restore-ip-addresses.py similarity index 100% rename from problems/restore-ip-addresses.py rename to problems/python/restore-ip-addresses.py diff --git a/problems/reverse-integer.py b/problems/python/reverse-integer.py similarity index 100% rename from problems/reverse-integer.py rename to problems/python/reverse-integer.py diff --git a/problems/reverse-linked-list.py b/problems/python/reverse-linked-list.py similarity index 100% rename from problems/reverse-linked-list.py rename to problems/python/reverse-linked-list.py diff --git a/problems/reverse-string.py b/problems/python/reverse-string.py similarity index 100% rename from problems/reverse-string.py rename to problems/python/reverse-string.py diff --git a/problems/reverse-vowels-of-a-string.py b/problems/python/reverse-vowels-of-a-string.py similarity index 100% rename from problems/reverse-vowels-of-a-string.py rename to problems/python/reverse-vowels-of-a-string.py diff --git a/problems/reverse-words-in-a-string.py b/problems/python/reverse-words-in-a-string.py similarity index 100% rename from problems/reverse-words-in-a-string.py rename to problems/python/reverse-words-in-a-string.py diff --git a/problems/robot-bounded-in-circle.py b/problems/python/robot-bounded-in-circle.py similarity index 100% rename from problems/robot-bounded-in-circle.py rename to problems/python/robot-bounded-in-circle.py diff --git a/problems/roman-to-integer.py b/problems/python/roman-to-integer.py similarity index 100% rename from problems/roman-to-integer.py rename to problems/python/roman-to-integer.py diff --git a/problems/rotate-array.py b/problems/python/rotate-array.py similarity index 100% rename from problems/rotate-array.py rename to problems/python/rotate-array.py diff --git a/problems/rotate-image.py b/problems/python/rotate-image.py similarity index 100% rename from problems/rotate-image.py rename to problems/python/rotate-image.py diff --git a/problems/russian-doll-envelopes.py b/problems/python/russian-doll-envelopes.py similarity index 100% rename from problems/russian-doll-envelopes.py rename to problems/python/russian-doll-envelopes.py diff --git a/problems/same-tree.py b/problems/python/same-tree.py similarity index 100% rename from problems/same-tree.py rename to problems/python/same-tree.py diff --git a/problems/satisfiability-of-equality-equations.py b/problems/python/satisfiability-of-equality-equations.py similarity index 100% rename from problems/satisfiability-of-equality-equations.py rename to problems/python/satisfiability-of-equality-equations.py diff --git a/problems/score-of-parentheses.py b/problems/python/score-of-parentheses.py similarity index 100% rename from problems/score-of-parentheses.py rename to problems/python/score-of-parentheses.py diff --git a/problems/search-a-2d-matrix.py b/problems/python/search-a-2d-matrix.py similarity index 100% rename from problems/search-a-2d-matrix.py rename to problems/python/search-a-2d-matrix.py diff --git a/problems/search-in-a-binary-search-tree.py b/problems/python/search-in-a-binary-search-tree.py similarity index 100% rename from problems/search-in-a-binary-search-tree.py rename to problems/python/search-in-a-binary-search-tree.py diff --git a/problems/search-in-rotated-sorted-array-ii.py b/problems/python/search-in-rotated-sorted-array-ii.py similarity index 100% rename from problems/search-in-rotated-sorted-array-ii.py rename to problems/python/search-in-rotated-sorted-array-ii.py diff --git a/problems/search-in-rotated-sorted-array.py b/problems/python/search-in-rotated-sorted-array.py similarity index 100% rename from problems/search-in-rotated-sorted-array.py rename to problems/python/search-in-rotated-sorted-array.py diff --git a/problems/search-insert-position.py b/problems/python/search-insert-position.py similarity index 100% rename from problems/search-insert-position.py rename to problems/python/search-insert-position.py diff --git a/problems/search-suggestions-system.py b/problems/python/search-suggestions-system.py similarity index 100% rename from problems/search-suggestions-system.py rename to problems/python/search-suggestions-system.py diff --git a/problems/second-highest-salary.sql b/problems/python/second-highest-salary.sql similarity index 100% rename from problems/second-highest-salary.sql rename to problems/python/second-highest-salary.sql diff --git a/problems/sell-diminishing-valued-colored-balls.py b/problems/python/sell-diminishing-valued-colored-balls.py similarity index 100% rename from problems/sell-diminishing-valued-colored-balls.py rename to problems/python/sell-diminishing-valued-colored-balls.py diff --git a/problems/serialize-and-deserialize-binary-tree.py b/problems/python/serialize-and-deserialize-binary-tree.py similarity index 100% rename from problems/serialize-and-deserialize-binary-tree.py rename to problems/python/serialize-and-deserialize-binary-tree.py diff --git a/problems/serialize-and-deserialize-bst.py b/problems/python/serialize-and-deserialize-bst.py similarity index 100% rename from problems/serialize-and-deserialize-bst.py rename to problems/python/serialize-and-deserialize-bst.py diff --git a/problems/set-matrix-zeroes.py b/problems/python/set-matrix-zeroes.py similarity index 100% rename from problems/set-matrix-zeroes.py rename to problems/python/set-matrix-zeroes.py diff --git a/problems/shortest-bridge.py b/problems/python/shortest-bridge.py similarity index 100% rename from problems/shortest-bridge.py rename to problems/python/shortest-bridge.py diff --git a/problems/shortest-common-supersequence.py b/problems/python/shortest-common-supersequence.py similarity index 100% rename from problems/shortest-common-supersequence.py rename to problems/python/shortest-common-supersequence.py diff --git a/problems/shortest-distance-from-all-buildings.py b/problems/python/shortest-distance-from-all-buildings.py similarity index 100% rename from problems/shortest-distance-from-all-buildings.py rename to problems/python/shortest-distance-from-all-buildings.py diff --git a/problems/shortest-path-in-a-grid-with-obstacles-elimination.py b/problems/python/shortest-path-in-a-grid-with-obstacles-elimination.py similarity index 100% rename from problems/shortest-path-in-a-grid-with-obstacles-elimination.py rename to problems/python/shortest-path-in-a-grid-with-obstacles-elimination.py diff --git a/problems/shortest-path-in-binary-matrix.py b/problems/python/shortest-path-in-binary-matrix.py similarity index 100% rename from problems/shortest-path-in-binary-matrix.py rename to problems/python/shortest-path-in-binary-matrix.py diff --git a/problems/shortest-path-to-get-food.py b/problems/python/shortest-path-to-get-food.py similarity index 100% rename from problems/shortest-path-to-get-food.py rename to problems/python/shortest-path-to-get-food.py diff --git a/problems/shuffle-an-array.py b/problems/python/shuffle-an-array.py similarity index 100% rename from problems/shuffle-an-array.py rename to problems/python/shuffle-an-array.py diff --git a/problems/simplify-path.py b/problems/python/simplify-path.py similarity index 100% rename from problems/simplify-path.py rename to problems/python/simplify-path.py diff --git a/problems/single-threaded-cpu.py b/problems/python/single-threaded-cpu.py similarity index 100% rename from problems/single-threaded-cpu.py rename to problems/python/single-threaded-cpu.py diff --git a/problems/sliding-window-maximum.py b/problems/python/sliding-window-maximum.py similarity index 100% rename from problems/sliding-window-maximum.py rename to problems/python/sliding-window-maximum.py diff --git a/problems/snapshot-array.py b/problems/python/snapshot-array.py similarity index 100% rename from problems/snapshot-array.py rename to problems/python/snapshot-array.py diff --git a/problems/sort-colors.py b/problems/python/sort-colors.py similarity index 100% rename from problems/sort-colors.py rename to problems/python/sort-colors.py diff --git a/problems/sort-list.py b/problems/python/sort-list.py similarity index 100% rename from problems/sort-list.py rename to problems/python/sort-list.py diff --git a/problems/spiral-matrix.py b/problems/python/spiral-matrix.py similarity index 100% rename from problems/spiral-matrix.py rename to problems/python/spiral-matrix.py diff --git a/problems/split-array-into-fibonacci-sequence.py b/problems/python/split-array-into-fibonacci-sequence.py similarity index 100% rename from problems/split-array-into-fibonacci-sequence.py rename to problems/python/split-array-into-fibonacci-sequence.py diff --git a/problems/split-array-largest-sum.py b/problems/python/split-array-largest-sum.py similarity index 100% rename from problems/split-array-largest-sum.py rename to problems/python/split-array-largest-sum.py diff --git a/problems/sqrtx.py b/problems/python/sqrtx.py similarity index 100% rename from problems/sqrtx.py rename to problems/python/sqrtx.py diff --git a/problems/squares-of-a-sorted-array.py b/problems/python/squares-of-a-sorted-array.py similarity index 100% rename from problems/squares-of-a-sorted-array.py rename to problems/python/squares-of-a-sorted-array.py diff --git a/problems/step-by-step-directions-from-a-binary-tree-node-to-another.py b/problems/python/step-by-step-directions-from-a-binary-tree-node-to-another.py similarity index 100% rename from problems/step-by-step-directions-from-a-binary-tree-node-to-another.py rename to problems/python/step-by-step-directions-from-a-binary-tree-node-to-another.py diff --git a/problems/stock-price-fluctuation.py b/problems/python/stock-price-fluctuation.py similarity index 100% rename from problems/stock-price-fluctuation.py rename to problems/python/stock-price-fluctuation.py diff --git a/problems/stone-game-ii.py b/problems/python/stone-game-ii.py similarity index 100% rename from problems/stone-game-ii.py rename to problems/python/stone-game-ii.py diff --git a/problems/student-attendance-record-ii.py b/problems/python/student-attendance-record-ii.py similarity index 100% rename from problems/student-attendance-record-ii.py rename to problems/python/student-attendance-record-ii.py diff --git a/problems/subarray-sum-equals-k.py b/problems/python/subarray-sum-equals-k.py similarity index 100% rename from problems/subarray-sum-equals-k.py rename to problems/python/subarray-sum-equals-k.py diff --git a/problems/subarrays-with-k-different-integers.py b/problems/python/subarrays-with-k-different-integers.py similarity index 100% rename from problems/subarrays-with-k-different-integers.py rename to problems/python/subarrays-with-k-different-integers.py diff --git a/problems/subdomain-visit-count.py b/problems/python/subdomain-visit-count.py similarity index 100% rename from problems/subdomain-visit-count.py rename to problems/python/subdomain-visit-count.py diff --git a/problems/subsets-ii.py b/problems/python/subsets-ii.py similarity index 100% rename from problems/subsets-ii.py rename to problems/python/subsets-ii.py diff --git a/problems/subsets.py b/problems/python/subsets.py similarity index 100% rename from problems/subsets.py rename to problems/python/subsets.py diff --git a/problems/substring-with-concatenation-of-all-words.py b/problems/python/substring-with-concatenation-of-all-words.py similarity index 100% rename from problems/substring-with-concatenation-of-all-words.py rename to problems/python/substring-with-concatenation-of-all-words.py diff --git a/problems/subtree-of-another-tree.py b/problems/python/subtree-of-another-tree.py similarity index 100% rename from problems/subtree-of-another-tree.py rename to problems/python/subtree-of-another-tree.py diff --git a/problems/sum-of-subarray-minimums.py b/problems/python/sum-of-subarray-minimums.py similarity index 100% rename from problems/sum-of-subarray-minimums.py rename to problems/python/sum-of-subarray-minimums.py diff --git a/problems/sum-root-to-leaf-numbers.py b/problems/python/sum-root-to-leaf-numbers.py similarity index 100% rename from problems/sum-root-to-leaf-numbers.py rename to problems/python/sum-root-to-leaf-numbers.py diff --git a/problems/summary-ranges.py b/problems/python/summary-ranges.py similarity index 100% rename from problems/summary-ranges.py rename to problems/python/summary-ranges.py diff --git a/problems/super-ugly-number.py b/problems/python/super-ugly-number.py similarity index 100% rename from problems/super-ugly-number.py rename to problems/python/super-ugly-number.py diff --git a/problems/swap-adjacent-in-lr-string.py b/problems/python/swap-adjacent-in-lr-string.py similarity index 100% rename from problems/swap-adjacent-in-lr-string.py rename to problems/python/swap-adjacent-in-lr-string.py diff --git a/problems/swap-nodes-in-pairs.py b/problems/python/swap-nodes-in-pairs.py similarity index 100% rename from problems/swap-nodes-in-pairs.py rename to problems/python/swap-nodes-in-pairs.py diff --git a/problems/swim-in-rising-water.py b/problems/python/swim-in-rising-water.py similarity index 100% rename from problems/swim-in-rising-water.py rename to problems/python/swim-in-rising-water.py diff --git a/problems/symmetric-tree.py b/problems/python/symmetric-tree.py similarity index 100% rename from problems/symmetric-tree.py rename to problems/python/symmetric-tree.py diff --git a/problems/tallest-billboard.py b/problems/python/tallest-billboard.py similarity index 100% rename from problems/tallest-billboard.py rename to problems/python/tallest-billboard.py diff --git a/problems/target-sum.py b/problems/python/target-sum.py similarity index 100% rename from problems/target-sum.py rename to problems/python/target-sum.py diff --git a/problems/task-scheduler.py b/problems/python/task-scheduler.py similarity index 100% rename from problems/task-scheduler.py rename to problems/python/task-scheduler.py diff --git a/problems/text-justification.py b/problems/python/text-justification.py similarity index 100% rename from problems/text-justification.py rename to problems/python/text-justification.py diff --git a/problems/the-kth-factor-of-n.py b/problems/python/the-kth-factor-of-n.py similarity index 100% rename from problems/the-kth-factor-of-n.py rename to problems/python/the-kth-factor-of-n.py diff --git a/problems/the-maze-ii.py b/problems/python/the-maze-ii.py similarity index 100% rename from problems/the-maze-ii.py rename to problems/python/the-maze-ii.py diff --git a/problems/time-based-key-value-store.py b/problems/python/time-based-key-value-store.py similarity index 100% rename from problems/time-based-key-value-store.py rename to problems/python/time-based-key-value-store.py diff --git a/problems/to-lower-case.py b/problems/python/to-lower-case.py similarity index 100% rename from problems/to-lower-case.py rename to problems/python/to-lower-case.py diff --git a/problems/toeplitz-matrix.py b/problems/python/toeplitz-matrix.py similarity index 100% rename from problems/toeplitz-matrix.py rename to problems/python/toeplitz-matrix.py diff --git a/problems/top-k-frequent-elements.py b/problems/python/top-k-frequent-elements.py similarity index 100% rename from problems/top-k-frequent-elements.py rename to problems/python/top-k-frequent-elements.py diff --git a/problems/trapping-rain-water-ii.py b/problems/python/trapping-rain-water-ii.py similarity index 100% rename from problems/trapping-rain-water-ii.py rename to problems/python/trapping-rain-water-ii.py diff --git a/problems/trapping-rain-water.py b/problems/python/trapping-rain-water.py similarity index 100% rename from problems/trapping-rain-water.py rename to problems/python/trapping-rain-water.py diff --git a/problems/trim-a-binary-search-tree.py b/problems/python/trim-a-binary-search-tree.py similarity index 100% rename from problems/trim-a-binary-search-tree.py rename to problems/python/trim-a-binary-search-tree.py diff --git a/problems/two-out-of-three.py b/problems/python/two-out-of-three.py similarity index 100% rename from problems/two-out-of-three.py rename to problems/python/two-out-of-three.py diff --git a/problems/two-sum-ii-input-array-is-sorted.py b/problems/python/two-sum-ii-input-array-is-sorted.py similarity index 100% rename from problems/two-sum-ii-input-array-is-sorted.py rename to problems/python/two-sum-ii-input-array-is-sorted.py diff --git a/problems/two-sum.py b/problems/python/two-sum.py similarity index 100% rename from problems/two-sum.py rename to problems/python/two-sum.py diff --git a/problems/ugly-number-ii.py b/problems/python/ugly-number-ii.py similarity index 100% rename from problems/ugly-number-ii.py rename to problems/python/ugly-number-ii.py diff --git a/problems/ugly-number.py b/problems/python/ugly-number.py similarity index 100% rename from problems/ugly-number.py rename to problems/python/ugly-number.py diff --git a/problems/umber-of-islands-ii.py b/problems/python/umber-of-islands-ii.py similarity index 100% rename from problems/umber-of-islands-ii.py rename to problems/python/umber-of-islands-ii.py diff --git a/problems/unique-binary-search-trees-ii,py b/problems/python/unique-binary-search-trees-ii,py similarity index 100% rename from problems/unique-binary-search-trees-ii,py rename to problems/python/unique-binary-search-trees-ii,py diff --git a/problems/unique-binary-search-trees.py b/problems/python/unique-binary-search-trees.py similarity index 100% rename from problems/unique-binary-search-trees.py rename to problems/python/unique-binary-search-trees.py diff --git a/problems/unique-email-addres.py b/problems/python/unique-email-addres.py similarity index 100% rename from problems/unique-email-addres.py rename to problems/python/unique-email-addres.py diff --git a/problems/unique-paths.py b/problems/python/unique-paths.py similarity index 100% rename from problems/unique-paths.py rename to problems/python/unique-paths.py diff --git a/problems/univalued-binary-tree.py b/problems/python/univalued-binary-tree.py similarity index 100% rename from problems/univalued-binary-tree.py rename to problems/python/univalued-binary-tree.py diff --git a/problems/valid-anagram.py b/problems/python/valid-anagram.py similarity index 100% rename from problems/valid-anagram.py rename to problems/python/valid-anagram.py diff --git a/problems/valid-number.py b/problems/python/valid-number.py similarity index 100% rename from problems/valid-number.py rename to problems/python/valid-number.py diff --git a/problems/valid-palindrome-ii.py b/problems/python/valid-palindrome-ii.py similarity index 100% rename from problems/valid-palindrome-ii.py rename to problems/python/valid-palindrome-ii.py diff --git a/problems/valid-palindrome.py b/problems/python/valid-palindrome.py similarity index 100% rename from problems/valid-palindrome.py rename to problems/python/valid-palindrome.py diff --git a/problems/valid-parentheses.py b/problems/python/valid-parentheses.py similarity index 100% rename from problems/valid-parentheses.py rename to problems/python/valid-parentheses.py diff --git a/problems/valid-word-abbreviation.py b/problems/python/valid-word-abbreviation.py similarity index 100% rename from problems/valid-word-abbreviation.py rename to problems/python/valid-word-abbreviation.py diff --git a/problems/validate-binary-search-tree.py b/problems/python/validate-binary-search-tree.py similarity index 100% rename from problems/validate-binary-search-tree.py rename to problems/python/validate-binary-search-tree.py diff --git a/problems/verify-preorder-serialization-of-a-binary-tree.py b/problems/python/verify-preorder-serialization-of-a-binary-tree.py similarity index 100% rename from problems/verify-preorder-serialization-of-a-binary-tree.py rename to problems/python/verify-preorder-serialization-of-a-binary-tree.py diff --git a/problems/vertical-order-traversal-of-a-binary-tree.py b/problems/python/vertical-order-traversal-of-a-binary-tree.py similarity index 100% rename from problems/vertical-order-traversal-of-a-binary-tree.py rename to problems/python/vertical-order-traversal-of-a-binary-tree.py diff --git a/problems/wiggle-subsequence.py b/problems/python/wiggle-subsequence.py similarity index 100% rename from problems/wiggle-subsequence.py rename to problems/python/wiggle-subsequence.py diff --git a/problems/word-break.py b/problems/python/word-break.py similarity index 100% rename from problems/word-break.py rename to problems/python/word-break.py diff --git a/problems/word-ladder-ii.py b/problems/python/word-ladder-ii.py similarity index 100% rename from problems/word-ladder-ii.py rename to problems/python/word-ladder-ii.py diff --git a/problems/word-ladder.py b/problems/python/word-ladder.py similarity index 100% rename from problems/word-ladder.py rename to problems/python/word-ladder.py diff --git a/problems/word-search-ii.py b/problems/python/word-search-ii.py similarity index 100% rename from problems/word-search-ii.py rename to problems/python/word-search-ii.py diff --git a/problems/word-search.py b/problems/python/word-search.py similarity index 100% rename from problems/word-search.py rename to problems/python/word-search.py From 54dd56f812405539a86e67f8b983db77850b62dd Mon Sep 17 00:00:00 2001 From: wuduhren Date: Mon, 25 Apr 2022 19:22:59 +0800 Subject: [PATCH 152/187] no message --- problems/python3/container-with-most-water.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 problems/python3/container-with-most-water.py diff --git a/problems/python3/container-with-most-water.py b/problems/python3/container-with-most-water.py new file mode 100644 index 0000000..e69de29 From 740f1600b60a7b8f5f3d50828b245ca984446ce3 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Mon, 25 Apr 2022 19:43:25 +0800 Subject: [PATCH 153/187] no message --- problems/python3/container-with-most-water.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/problems/python3/container-with-most-water.py b/problems/python3/container-with-most-water.py index e69de29..c24f0c9 100644 --- a/problems/python3/container-with-most-water.py +++ b/problems/python3/container-with-most-water.py @@ -0,0 +1,25 @@ +""" +Time: O(N) +Space: O(1) + +i and j starts from the leftest and rightest. Move the one that has less height. + +Why we won't miss any i and j? +For example, currently i is heigher than j. +If between i~j, there are no height that is larger or equal to i, than since the area is `min(height[i], height[j]) * (j-i)`, you cannot find any area that is larger than the current one. +If between i~j, there is a height that is larger or equal to i, j will on it, and it will be tested. +Thus, given any i and j, any other future i and j that have the potential of forming larger area will be tested. +""" +class Solution: + def maxArea(self, height: List[int]) -> int: + i = 0 + j = len(height)-1 + ans = 0 + + while iheight[j]: + j -= 1 + else: + i += 1 + return ans \ No newline at end of file From b9c2a701c30e025e0150c83004b45d0f807e2567 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 26 Apr 2022 10:42:50 +0800 Subject: [PATCH 154/187] no message --- problems/python3/3sum.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 problems/python3/3sum.py diff --git a/problems/python3/3sum.py b/problems/python3/3sum.py new file mode 100644 index 0000000..c29d989 --- /dev/null +++ b/problems/python3/3sum.py @@ -0,0 +1,40 @@ +""" +Time: O(N^2) +Space: O(1) + +First of all, we need to sort the list, so that it is easier to know where to move the pointers. +(Keep in mind that sorting takes O(NLogN) of time, but since judging from the problem this solution might takes at least O(N^2), so it is ok to sort.) + +Now, we have 3 unique pointers at the list. i, j, k, where i List[List[int]]: + ans = [] + nums.sort() + + for i in range(len(nums)): + if 00: break #[1] + + j, k = i+1, len(nums)-1 + while j0: + k -= 1 + elif nums[i]+nums[j]+nums[k]<0: + j += 1 + else: + ans.append((nums[i], nums[j], nums[k])) + while 0 Date: Thu, 28 Apr 2022 18:16:35 +0800 Subject: [PATCH 155/187] no message --- common/heap-sort.py | 56 +++++++++++++++----------------- problems/python3/3sum-closest.py | 24 ++++++++++++++ 2 files changed, 51 insertions(+), 29 deletions(-) create mode 100644 problems/python3/3sum-closest.py diff --git a/common/heap-sort.py b/common/heap-sort.py index eb2e11c..3d56e39 100644 --- a/common/heap-sort.py +++ b/common/heap-sort.py @@ -1,35 +1,33 @@ +#O(LogN), used when part of the array is already heapified. +def heapify(A, N, i): + largest = i + l = i*2+1 + r = i*2+2 + + if lA[largest]: largest = l + if rA[largest]: largest = r + if largest!=i: + A[largest], A[i] = A[i], A[largest] + heapify(A, N, largest) + +#O(NLogN) def heapSort(A): - #build max heap - def heapify(A, n, i): - if i>=n: return - l, r = i*2+1, i*2+2 - left = A[l] if lA[i] or right>A[i]: - if left>right: - A[i], A[l] = A[l], A[i] - heapify(A, n, l) - else: - A[i], A[r] = A[r], A[i] - heapify(A, n, r) - - n = len(A) - - for i in reversed(xrange(n)): - heapify(A, n, i) - - for i in reversed(xrange(1, n)): - A[i], A[0] = A[0], A[i] + N = len(A) + + #build max heap, O(NLogN). Can be optimized to the O(N). + for i in range(N//2-1, -1, -1): + heapify(A, N, i) + + #keep swapping the largest + for i in range(N-1, -1, -1): + A[0], A[i] = A[i], A[0] heapify(A, i, 0) - -A = [21, 4, 1, 3, 9, 20, 25, 6, 21, 14] +A = [12, 11, 13, 5, 6, 7] heapSort(A) -print A +print(A) -""" -Time Complexity O(NLogN) in best, average, worst case. -Space Complexity O(1) -""" \ No newline at end of file +A = [1, 3, 5, 4, 6, 13, 10, 9, 8, 15, 17] +heapSort(A) +print(A) \ No newline at end of file diff --git a/problems/python3/3sum-closest.py b/problems/python3/3sum-closest.py new file mode 100644 index 0000000..472c80f --- /dev/null +++ b/problems/python3/3sum-closest.py @@ -0,0 +1,24 @@ +""" +Time: O(N^2) +Space: O(1) +""" +class Solution: + def threeSumClosest(self, nums: List[int], target: int) -> int: + nums.sort() + + N = len(nums) + ans = float('inf') + + for i in range(N): + j = i+1 + k = N-1 + + while jabs(target-total): ans = total + if total>target: + k -= 1 + elif total Date: Thu, 5 May 2022 09:29:22 +0800 Subject: [PATCH 156/187] no message --- ...bstring-with-concatenation-of-all-words.py | 4 +- problems/python3/3sum-smaller.py | 18 ++++++++ problems/python3/3sum.py | 24 ++++++++++ problems/python3/4sum.py | 33 +++++++++++++ problems/python3/balanced-binary-tree.py | 18 ++++++++ problems/python3/diameter-of-binary-tree.py | 17 +++++++ problems/python3/invert-binary-tree.py | 36 +++++++++++++++ .../python3/maximum-depth-of-binary-tree.py | 8 ++++ ...bstring-with-concatenation-of-all-words.py | 46 +++++++++++++++++++ 9 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 problems/python3/3sum-smaller.py create mode 100644 problems/python3/4sum.py create mode 100644 problems/python3/balanced-binary-tree.py create mode 100644 problems/python3/diameter-of-binary-tree.py create mode 100644 problems/python3/invert-binary-tree.py create mode 100644 problems/python3/maximum-depth-of-binary-tree.py create mode 100644 problems/python3/substring-with-concatenation-of-all-words.py diff --git a/problems/python/substring-with-concatenation-of-all-words.py b/problems/python/substring-with-concatenation-of-all-words.py index b11bb81..e3e6420 100644 --- a/problems/python/substring-with-concatenation-of-all-words.py +++ b/problems/python/substring-with-concatenation-of-all-words.py @@ -47,4 +47,6 @@ def test(self, s, wl, countExpected): return True - \ No newline at end of file + + + diff --git a/problems/python3/3sum-smaller.py b/problems/python3/3sum-smaller.py new file mode 100644 index 0000000..3291586 --- /dev/null +++ b/problems/python3/3sum-smaller.py @@ -0,0 +1,18 @@ +class Solution: + def threeSumSmaller(self, nums: List[int], target: int) -> int: + N = len(nums) + ans = 0 + + nums.sort() + + + for i in range(N): + j = i+1 + k = N-1 + while j List[List[int]]: k -= 1 j += 1 + return ans + + +""" +No Sort. +Use set to dedupe and check needed. + +Time: O(N^2) +Space: O(N) +""" +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + ans = set() + seen = set() + N = len(nums) + + for i, v1 in enumerate(nums): + if v1 in seen: continue + seen.add(v1) + needed = set() + for j, v2 in enumerate(nums[i+1:]): + if v2 in needed: + ans.add(tuple(sorted((v1, v2, -v1-v2)))) + needed.add(-v1-v2) return ans \ No newline at end of file diff --git a/problems/python3/4sum.py b/problems/python3/4sum.py new file mode 100644 index 0000000..4757233 --- /dev/null +++ b/problems/python3/4sum.py @@ -0,0 +1,33 @@ +""" +Time: O(N^(K-1)) -> O(N^3) +Space: O(K) -> O(1) +""" +class Solution: + def fourSum(self, nums: List[int], target: int) -> List[List[int]]: + def kSum(k, start, target): + if k>2: + for i in range(start, len(nums)-k+1): + if i!=start and nums[i]==nums[i-1]: continue + temp.append(nums[i]) + kSum(k-1, i+1, target-nums[i]) + temp.pop() + else: + l, r = start, len(nums)-1 + + while ltarget: + r -= 1 + elif nums[l]+nums[r] bool: + def getHeight(node) -> (bool, int): + if not node: return True, 0 + leftIsBalanced, leftHeight = getHeight(node.left) + if not leftIsBalanced: return False, 0 + + rightIsBalanced, rightHeight = getHeight(node.right) + if not rightIsBalanced: return False, 0 + + return abs(leftHeight-rightHeight)<2, 1+max(leftHeight, rightHeight) + + isBalanced, h = getHeight(root) + return isBalanced \ No newline at end of file diff --git a/problems/python3/diameter-of-binary-tree.py b/problems/python3/diameter-of-binary-tree.py new file mode 100644 index 0000000..1f9704d --- /dev/null +++ b/problems/python3/diameter-of-binary-tree.py @@ -0,0 +1,17 @@ +""" +Time: O(N) +Space: O(LogN) for the recursion stack. If the tree is balanced. +""" +class Solution: + def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int: + def helper(node): + if not node: return 0 + l = helper(node.left) + r = helper(node.right) + self.ans = max(self.ans, 1+l+r) + return 1+max(l, r) + + self.ans = 0 + + helper(root) + return self.ans-1 \ No newline at end of file diff --git a/problems/python3/invert-binary-tree.py b/problems/python3/invert-binary-tree.py new file mode 100644 index 0000000..d69daec --- /dev/null +++ b/problems/python3/invert-binary-tree.py @@ -0,0 +1,36 @@ +""" +Recursive +Time: O(N) +Space: O(LogN) +""" +class Solution: + def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: + if not root: return root + left = root.left + right = root.right + root.left = self.invertTree(right) + root.right = self.invertTree(left) + return root + + +""" +Iterative +Time: O(N) +Space: O(N) +""" +class Solution: + def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: + if not root: return root + q = collections.deque([root]) + + while q: + node = q.popleft() + left = node.left + right = node.right + node.right = left + node.left = right + + if node.left: q.append(node.left) + if node.right: q.append(node.right) + + return root \ No newline at end of file diff --git a/problems/python3/maximum-depth-of-binary-tree.py b/problems/python3/maximum-depth-of-binary-tree.py new file mode 100644 index 0000000..3146dcf --- /dev/null +++ b/problems/python3/maximum-depth-of-binary-tree.py @@ -0,0 +1,8 @@ +""" +Time: O(N) +Space:O(LogN), for recursion stack space. +""" +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + if not root: return 0 + return 1+max(self.maxDepth(root.left), self.maxDepth(root.right)) \ No newline at end of file diff --git a/problems/python3/substring-with-concatenation-of-all-words.py b/problems/python3/substring-with-concatenation-of-all-words.py new file mode 100644 index 0000000..164dfa6 --- /dev/null +++ b/problems/python3/substring-with-concatenation-of-all-words.py @@ -0,0 +1,46 @@ +""" +Time: O(W * N/W * W), there will be W time of iteration in the first loop ([0]), N/W of iteration in the second loop ([1]). In each loop, creating substring "word" and "popWord" takes O(W). +Space: O(MW) for "wordSet". +""" +class Solution: + def findSubstring(self, s: str, words: List[str]) -> List[int]: + N = len(s) + M = len(words) + W = len(words[0]) + wordSet = set(words) + ans = [] + counter = collections.Counter(words) + + for i in range(W): #[0] + windowCounter = collections.Counter() #counter for the word in words + notInWords = 0 #number of word not in the wordSet + theSame = 0 #number of word with the same count with "counter" + j = i + + while jcounter[word]: + theSame -= 1 + else: + notInWords += 1 + + popStart = j-M*W + if popStart>=0: + popWord = s[popStart:popStart+W] + if popWord in wordSet: + windowCounter[popWord] -= 1 + if windowCounter[popWord]==counter[popWord]: + theSame += 1 + elif windowCounter[popWord] Date: Sat, 14 May 2022 09:15:48 +0800 Subject: [PATCH 157/187] no message --- .../binary-tree-level-order-traversal.py | 39 +++++++++++++++++++ ...common-ancestor-of-a-binary-search-tree.py | 28 +++++++++++++ problems/python3/same-tree.py | 16 ++++++++ problems/python3/subtree-of-another-tree.py | 10 +++++ 4 files changed, 93 insertions(+) create mode 100644 problems/python3/binary-tree-level-order-traversal.py create mode 100644 problems/python3/lowest-common-ancestor-of-a-binary-search-tree.py create mode 100644 problems/python3/same-tree.py create mode 100644 problems/python3/subtree-of-another-tree.py diff --git a/problems/python3/binary-tree-level-order-traversal.py b/problems/python3/binary-tree-level-order-traversal.py new file mode 100644 index 0000000..2ddb875 --- /dev/null +++ b/problems/python3/binary-tree-level-order-traversal.py @@ -0,0 +1,39 @@ +""" +Time: O(N), since we need to go through all the nodes. +Space: O(LogN) for recursion stack. (if the tree is balanced). This do not take the output into account. +""" +class Solution: + def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + def helper(node, level): + if not node: return + if level==len(ans): ans.append([]) + ans[level].append(node.val) + helper(node.left, level+1) + helper(node.right, level+1) + + ans = [] + helper(root, 0) + + return ans + + +""" +Time: O(N), since we need to go through all the nodes. +Space: O(N) for queue. +""" +class Solution: + def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + if not root: return [] + + q = collections.deque([(root, 0)]) + ans = [] + + while q: + node, level = q.popleft() + + if level==len(ans): ans.append([]) + ans[level].append(node.val) + if node.left: q.append((node.left, level+1)) + if node.right: q.append((node.right, level+1)) + + return ans \ No newline at end of file diff --git a/problems/python3/lowest-common-ancestor-of-a-binary-search-tree.py b/problems/python3/lowest-common-ancestor-of-a-binary-search-tree.py new file mode 100644 index 0000000..12e1743 --- /dev/null +++ b/problems/python3/lowest-common-ancestor-of-a-binary-search-tree.py @@ -0,0 +1,28 @@ +""" +Recursive +Time: O(LogN) if the tree is balanced. +Space: O(LogN) for the recursion stack. +""" +class Solution: + def lowestCommonAncestor(self, node: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': + if q.val<=node.val<=p.val or p.val<=node.val<=q.val: + return node + elif q.val 'TreeNode': + while not (q.val<=node.val<=p.val or p.val<=node.val<=q.val): + if q.val bool: + if not node1 and not node2: + return True + + if (not node1 and node2) or (node1 and not node2): + return False + + if node1.val!=node2.val: + return False + + return self.isSameTree(node1.left, node2.left) and self.isSameTree(node1.right, node2.right) \ No newline at end of file diff --git a/problems/python3/subtree-of-another-tree.py b/problems/python3/subtree-of-another-tree.py new file mode 100644 index 0000000..7871f8c --- /dev/null +++ b/problems/python3/subtree-of-another-tree.py @@ -0,0 +1,10 @@ +class Solution: + def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: + if not root or not subRoot: return root==subRoot + if self.isSame(root, subRoot): return True + return self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot) + + def isSame(self, p, q): + if not p or not q: return p==q + if p.val!=q.val: return False + return self.isSame(p.left, q.left) and self.isSame(p.right, q.right) \ No newline at end of file From c6ba939032264fe976069706354196181d1a9e3d Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 17 May 2022 08:58:35 +0800 Subject: [PATCH 158/187] no message --- .../python3/binary-tree-right-side-view.py | 18 ++++++++++++++ .../count-good-nodes-in-binary-tree.py | 16 +++++++++++++ .../python3/validate-binary-search-tree.py | 24 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 problems/python3/binary-tree-right-side-view.py create mode 100644 problems/python3/count-good-nodes-in-binary-tree.py create mode 100644 problems/python3/validate-binary-search-tree.py diff --git a/problems/python3/binary-tree-right-side-view.py b/problems/python3/binary-tree-right-side-view.py new file mode 100644 index 0000000..53b4d13 --- /dev/null +++ b/problems/python3/binary-tree-right-side-view.py @@ -0,0 +1,18 @@ +""" +Time: O(N) +Space: O(LogN) if the tree is balanced. + +BFS is a more intuitive way to do this, but the time complexity will be at least O(N). +Using recursion instead, will take O(LogN) for the recursion stack size. +""" +class Solution: + def rightSideView(self, root: Optional[TreeNode]) -> List[int]: + def helper(node, level): + if not node: return + if len(ans) int: + def helper(node, maxVal): + nonlocal count + if not node: return + if node.val>=maxVal: count += 1 + helper(node.left, max(maxVal, node.val)) + helper(node.right, max(maxVal, node.val)) + + count = 0 + helper(root, float('-inf')) + return count \ No newline at end of file diff --git a/problems/python3/validate-binary-search-tree.py b/problems/python3/validate-binary-search-tree.py new file mode 100644 index 0000000..4185bc6 --- /dev/null +++ b/problems/python3/validate-binary-search-tree.py @@ -0,0 +1,24 @@ +""" +The inorder travsersal of a BST is always increasing. + +Time: O(N) +Space: O(N) +""" +class Solution: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + lastVal = float('-inf') + stack = [] + + node = root + while stack or node: + while node: + stack.append(node) + node = node.left + + node = stack.pop() + + if not lastVal Date: Mon, 30 May 2022 07:39:09 +0800 Subject: [PATCH 159/187] 20220530 --- .gitignore | 0 README.md | 0 "common/bellman\342\200\223ford.py" | 0 common/binary-search-tree.py | 0 common/bst-in-order.py | 0 common/dijkstra.py | 0 common/heap-sort.py | 0 common/insertion-sort.py | 0 common/knapsack.py | 0 common/merge-sort-in-place.py | 0 common/merge-sort.py | 0 common/min-heap.py | 0 common/quick-sort.py | 0 common/radix-sort.py | 0 common/trie.py | 0 problems/python/01-matrix.py | 0 problems/python/3sum-closest.py | 0 problems/python/3sum.py | 0 problems/python/4sum.py | 0 problems/python/accounts-merge.py | 0 problems/python/add-binary.py | 0 problems/python/add-digits.py | 0 problems/python/add-strings.py | 0 problems/python/add-two-numbers-ii.py | 0 problems/python/add-two-numbers.py | 0 problems/python/alien-dictionary.py | 0 .../all-nodes-distance-k-in-binary-tree.py | 0 .../amount-of-new-area-painted-each-day.py | 0 .../analyze-user-website-visit-pattern.py | 0 problems/python/backspace-string-compare.py | 0 .../python/balance-a-binary-search-tree.py | 0 problems/python/balanced-binary-tree.py | 0 problems/python/basic-calculator-ii.py | 0 problems/python/best-time-to-buy-an-stock.py | 0 .../best-time-to-buy-and-sell-stock-iii.py | 0 ...ime-to-buy-and-sell-stock-with-cooldown.py | 0 .../python/best-time-to-buy-and-sell-stock.py | 0 problems/python/big-countries.sql | 0 .../python/binary-search-tree-iterator.py | 0 problems/python/binary-search.py | 0 problems/python/binary-subarrays-with-sum.py | 0 .../python/binary-tree-inorder-traversal.py | 0 .../binary-tree-level-order-traversal-ii.py | 0 .../binary-tree-level-order-traversal.py | 0 ...inary-tree-longest-consecutive-sequence.py | 0 .../python/binary-tree-maximum-path-sum.py | 0 problems/python/binary-tree-paths.py | 0 problems/python/binary-tree-pruning.py | 0 .../python/binary-tree-right-side-view.py | 0 .../binary-tree-vertical-order-traversal.py | 0 problems/python/binary-watch.py | 0 .../python/buildings-with-an-ocean-view.py | 0 problems/python/burst-balloons.py | 0 problems/python/campus-bikes-ii.py | 0 problems/python/candy.py | 0 ...capacity-to-ship-packages-within-d-days.py | 0 .../python/cheapest-flights-within-k-stops.py | 0 problems/python/climbing-stairs.py | 0 problems/python/clone-graph.py | 0 .../closest-binary-search-tree-value.py | 0 problems/python/coin-change.py | 0 problems/python/coloring-a-border.py | 0 problems/python/combination-sum-ii.py | 0 problems/python/combination-sum-iii.py | 0 problems/python/combination-sum-iv.py | 0 problems/python/combination-sum.py | 0 problems/python/combinations.py | 0 problems/python/combine-two-tables.sql | 0 problems/python/compare-version-numbers.py | 0 .../connecting-cities-with-minimum-cost.py | 0 problems/python/consecutive-numbers-sum.py | 0 ...ee-from-inorder-and-postorder-traversal.py | 0 ...ree-from-preorder-and-inorder-traversal.py | 0 problems/python/container-with-most-water.py | 0 problems/python/contains-duplicate-ii.py | 0 problems/python/contains-duplicate-iii.py | 0 problems/python/contains-duplicate.py | 0 problems/python/continuous-subarray-sum.py | 0 ...earch-tree-to-sorted-doubly-linked-list.py | 0 ...vert-sorted-array-to-binary-search-tree.py | 0 ...nvert-sorted-list-to-binary-search-tree.py | 0 .../python/copy-list-with-random-pointer.py | 0 ...ount-all-valid-pickup-and-delivery-opti.py | 0 problems/python/count-binary-substrings.py | 0 problems/python/count-complete-tree-nodes.py | 0 .../python/count-number-of-nice-subarrays.py | 0 ...ers-of-all-substrings-of-a-given-string.py | 0 problems/python/course-schedule-ii.py | 0 problems/python/course-schedule.py | 0 problems/python/custom-sort-string.py | 0 problems/python/cutting-ribbons.py | 0 .../data-stream-as-disjoint-intervals.py | 0 problems/python/decode-string.py | 0 problems/python/decode-ways.py | 0 problems/python/delete-and-earn.py | 0 .../delete-duplicate-folders-in-system.py | 0 problems/python/delete-node-in-a-bst.py | 0 .../delete-operation-for-two-strings.py | 0 ...ign-add-and-search-words-data-structure.py | 0 .../python/design-in-memory-file-system.py | 0 problems/python/design-linked-list.py | 0 problems/python/design-tic-tac-toe.py | 0 problems/python/diagonal-traverse.py | 0 problems/python/diameter-of-binary-tree.py | 0 .../different-ways-to-add-parentheses.py | 0 problems/python/distinct-subsequences.py | 0 .../python/distribute-coins-in-binary-tree.py | 0 problems/python/domino-and-tromino-tiling.py | 0 .../dot-product-of-two-sparse-vectors.py | 0 problems/python/dungeon-game.py | 0 problems/python/edit-distance.py | 0 problems/python/egions-cut-by-slashes.py | 0 problems/python/evaluate-division.py | 0 .../evaluate-reverse-polish-notation.py | 0 .../python/exclusive-time-of-functions.py | 0 problems/python/expression-add-operators.py | 0 problems/python/filling-bookcase-shelves.py | 0 ...ll-possible-recipes-from-given-supplies.py | 0 problems/python/find-and-replace-in-string.py | 0 .../python/find-distance-in-a-binary-tree.py | 0 problems/python/find-duplicate-subtrees.py | 0 problems/python/find-eventual-safe-states.py | 0 ...ast-position-of-element-in-sorted-array.py | 0 problems/python/find-k-closest-elements.py | 0 .../python/find-k-pairs-with-smallest-sums.py | 0 problems/python/find-leaves-of-binary-tree.py | 0 .../python/find-median-from-data-stream.py | 0 ...find-minimum-in-rotated-sorted-array-ii.py | 0 .../find-minimum-in-rotated-sorted-array.py | 0 .../python/find-mode-in-binary-search-tree.py | 0 .../find-original-array-from-doubled-array,py | 0 problems/python/find-peak-element.py | 0 problems/python/find-the-duplicate-number.py | 0 problems/python/first-bad-version.py | 0 problems/python/first-missing-positive.py | 0 .../first-unique-character-in-a-string.py | 0 problems/python/fizz-buzz.py | 0 .../flatten-binary-tree-to-linked-list.py | 0 ...binary-tree-to-match-preorder-traversal.py | 0 .../flip-string-to-monotone-increasing.py | 0 problems/python/flood-fill.py | 0 problems/python/friend-circles.py | 0 problems/python/fruit-into-baskets.py | 0 problems/python/game-of-life.py | 0 problems/python/generate-parentheses.py | 0 problems/python/graph-valid-tree.py | 0 .../python/greatest-sum-divisible-by-three.py | 0 problems/python/group-anagrams.py | 0 problems/python/group-shifted-strings.py | 0 .../python/guess-number-higher-or-lower-ii.py | 0 .../python/guess-number-higher-or-lower.py | 0 problems/python/guess-the-word.py | 0 problems/python/h-index-ii.py | 0 problems/python/h-index.py | 0 problems/python/hamming-distance.py | 0 problems/python/house-robber-ii.py | 0 problems/python/house-robber-iii.py | 0 problems/python/house-robber.py | 0 problems/python/implement-trie-prefix-tree.py | 0 .../python/increasing-triplet-subsequence.py | 0 .../python/inorder-successor-in-bst-ii.py | 0 problems/python/inorder-successor-in-bst.py | 0 problems/python/insert-interval.py | 0 .../insert-into-a-binary-search-tree.py | 0 ...sert-into-a-sorted-circular-linked-list.py | 0 problems/python/insertion-sort-list.py | 0 problems/python/integer-to-english-words.py | 0 problems/python/interleaving-string.py | 0 .../python/intersection-of-two-arrays-ii.py | 0 problems/python/intersection-of-two-arrays.py | 0 problems/python/invert-binary-tree.py | 0 problems/python/is-graph-bipartite.py | 0 problems/python/is-subsequence.py | 0 problems/python/isomorphic-strings.py | 0 problems/python/jewels-and-stones.py | 0 problems/python/jump-game.py | 0 problems/python/k-closest-points-to-origin.py | 0 problems/python/k-empty-slots.py | 0 problems/python/keys-and-rooms.py | 0 problems/python/knight-dialer.py | 0 .../knight-probability-in-chessboard.py | 0 problems/python/koko-eating-bananas.py | 0 .../python/kth-largest-element-in-an-array.py | 0 .../python/kth-smallest-element-in-a-bst.py | 0 ...kth-smallest-element-in-a-sorted-matrix.py | 0 problems/python/largest-1-bordered-square.py | 0 problems/python/largest-bst-subtree.py | 0 problems/python/largest-sum-of-averages.py | 0 problems/python/last-stone-weight-ii.py | 0 problems/python/last-stone-weight.py | 0 ...ber-of-unique-integers-after-k-removals.py | 0 problems/python/letter-case-permutation.py | 0 .../letter-combinations-of-a-phone-number.py | 0 problems/python/license-key-formatting.py | 0 problems/python/linked-list-cycle-ii.py | 0 problems/python/linked-list-cycle.py | 0 problems/python/linked-list-random-node.py | 0 problems/python/logger-rate-limiter.py | 0 problems/python/longest-common-prefix.py | 0 problems/python/longest-common-subsequence.py | 0 .../python/longest-consecutive-sequence.py | 0 .../longest-increasing-path-in-a-matrix.py | 0 .../python/longest-increasing-subsequence.py | 0 .../python/longest-palindromic-subsequence.py | 0 .../python/longest-palindromic-substring.py | 0 ...longest-repeating-character-replacement.py | 0 problems/python/longest-string-chain.py | 0 ...ng-with-at-least-k-repeating-characters.py | 0 ...-substring-without-repeating-characters.py | 0 problems/python/longest-univalue-path.py | 0 ...common-ancestor-of-a-binary-search-tree.py | 0 ...west-common-ancestor-of-a-binary-search.py | 0 ...est-common-ancestor-of-a-binary-tree-ii.py | 0 ...st-common-ancestor-of-a-binary-tree-iii.py | 0 ...est-common-ancestor-of-a-binary-tree-iv.py | 0 ...lowest-common-ancestor-of-a-binary-tree.py | 0 ...owest-common-ancestor-of-deepest-leaves.py | 0 problems/python/lru-cache.py | 0 problems/python/majority-element-ii.py | 0 problems/python/majority-element.py | 0 problems/python/making-a-large-island.py | 0 problems/python/max-area-of-island.py | 0 problems/python/max-consecutive-ones-iii.py | 0 problems/python/max-stack.py | 0 .../max-sum-of-rectangle-no-larger-than-k.py | 0 problems/python/maximal-square.py | 0 problems/python/maximum-average-subtree.py | 0 .../python/maximum-compatibility-score-sum.py | 0 .../python/maximum-depth-of-binary-tree.py | 0 problems/python/maximum-gap.py | 0 .../maximum-length-of-repeated-subarray.py | 0 ...m-number-of-events-that-can-be-attended.py | 0 .../maximum-number-of-points-with-cost.py | 0 .../maximum-number-of-visible-points.py | 0 .../maximum-product-of-three-numbers.py | 0 problems/python/maximum-product-subarray.py | 0 .../maximum-subarray-sum-with-one-deletion.py | 0 problems/python/maximum-subarray.py | 0 problems/python/maximum-swap.py | 0 problems/python/maximum-units-on-a-truck.py | 0 .../python/median-of-two-sorted-arrays.py | 0 problems/python/meeting-rooms-ii.py | 0 problems/python/meeting-rooms.py | 0 problems/python/merge-intervals.py | 0 problems/python/merge-k-sorted-lists.py | 0 problems/python/merge-sorted-array.py | 0 problems/python/merge-two-sorted-lists.py | 0 problems/python/min-cost-climbing-stairs.py | 0 problems/python/min-stack.py | 0 problems/python/minimize-malware-spread.py | 0 .../minimum-absolute-difference-in-bst.py | 0 ...inimum-ascii-delete-sum-for-two-strings.py | 0 .../python/minimum-cost-to-connect-sticks.py | 0 .../python/minimum-cost-to-hire-k-workers.py | 0 ...-make-at-least-one-valid-path-in-a-grid.py | 0 ...nimum-cost-to-reach-city-with-discounts.py | 0 .../python/minimum-depth-of-binary-tree.py | 0 .../minimum-difficulty-of-a-job-schedule.py | 0 .../python/minimum-falling-path-sum-ii.py | 0 problems/python/minimum-knight-moves.py | 0 ...to-convert-binary-matrix-to-zero-matrix.py | 0 problems/python/minimum-path-sum.py | 0 .../minimum-score-triangulation-of-polygon.py | 0 problems/python/minimum-size-subarray-sum.py | 0 .../minimum-swaps-to-group-all-1s-together.py | 0 ...imum-swaps-to-make-sequences-increasing.py | 0 problems/python/minimum-time-difference.py | 0 problems/python/minimum-window-substring.py | 0 .../python/minimum-xor-sum-of-two-arrays.py | 0 problems/python/missing-number.py | 0 problems/python/most-frequent-subtree-sum.py | 0 ...-stones-removed-with-same-row-or-column.py | 0 problems/python/move-zeroes.py | 0 .../python/moving-average-from-data-stream.py | 0 problems/python/my-calendar-ii.py | 0 .../n-ary-tree-level-order-traversal.py | 0 .../python/n-ary-tree-postorder-traversal.py | 0 .../python/n-ary-tree-preorder-traversal.py | 0 problems/python/nested-list-weight-sum.py | 0 problems/python/network-delay-time.py | 0 problems/python/next-closest-time.py | 0 problems/python/next-permutation.py | 0 problems/python/number-complement.py | 0 ...ected-components-in-an-undirected-graph.py | 0 problems/python/number-of-islands-ii.py | 0 problems/python/number-of-islands.py | 0 ...umber-of-longest-increasing-subsequence.py | 0 .../python/number-of-matching-subsequences.py | 0 problems/python/number-of-provinces.py | 0 problems/python/number-of-recent-calls.py | 0 problems/python/number-of-squareful-arrays.py | 0 ...umber-of-substrings-containing-all-thre.py | 0 ...number-of-ways-to-arrive-at-destination.py | 0 problems/python/odd-even-jump.py | 0 problems/python/ones-and-zeroes.py | 0 problems/python/open-the-lock.py | 0 problems/python/out-of-boundary-paths.py | 0 .../python/pacific-atlantic-water-flow.py | 0 ...gs-with-total-durations-divisible-by-60.py | 0 problems/python/palindrome-number.py | 0 problems/python/palindrome-pairs.py | 0 .../python/palindrome-partitioning-iii.py | 0 problems/python/palindrome-partitioning.py | 0 problems/python/palindromic-substrings.py | 0 .../python/partition-array-for-maximum-sum.py | 0 problems/python/partition-labels.py | 0 .../partition-to-k-equal-sum-subsets.py | 0 problems/python/path-sum-ii.py | 0 problems/python/path-sum-iii.py | 0 problems/python/path-sum.py | 0 .../python/path-with-maximum-probability.py | 0 .../python/peak-index-in-a-mountain-array.py | 0 problems/python/perfect-squares.py | 0 problems/python/permutation-in-string.py | 0 problems/python/permutation-sequence.py | 0 problems/python/permutations-ii.py | 0 problems/python/permutations.py | 0 ...ing-next-right-pointers-in-each-node-ii.py | 0 ...lating-next-right-pointers-in-each-node.py | 0 problems/python/powx-n.py | 0 .../python/product-of-array-except-self.py | 0 problems/python/profitable-schemes.py | 0 .../python/queue-reconstruction-by-height.py | 0 problems/python/random-pick-with-weight.py | 0 problems/python/range-addition.py | 0 problems/python/range-sum-of-bst.py | 0 problems/python/range-sum-query-immutable.py | 0 problems/python/range-sum-query-mutable.py | 0 .../rearrange-string-k-distance-apart.py | 0 problems/python/reconstruct-itinerary.py | 0 problems/python/recover-binary-search-tree.py | 0 problems/python/redundant-connection.py | 0 ...emove-all-adjacent-duplicates-in-string.py | 0 ...move-all-ones-with-row-and-column-flips.py | 0 .../remove-duplicates-from-sorted-array-ii.py | 0 .../remove-duplicates-from-sorted-array.py | 0 .../remove-duplicates-from-sorted-list.py | 0 problems/python/remove-element.py | 0 problems/python/remove-invalid-parentheses.py | 0 .../python/remove-linked-list-elements.py | 0 .../remove-nth-node-from-end-of-list.py | 0 problems/python/reorder-list.py | 0 problems/python/repeated-string-match.py | 0 ...place-the-substring-for-balanced-string.py | 0 problems/python/restore-ip-addresses.py | 0 problems/python/reverse-integer.py | 0 problems/python/reverse-linked-list.py | 0 problems/python/reverse-string.py | 0 problems/python/reverse-vowels-of-a-string.py | 0 problems/python/reverse-words-in-a-string.py | 0 problems/python/robot-bounded-in-circle.py | 0 problems/python/roman-to-integer.py | 0 problems/python/rotate-array.py | 0 problems/python/rotate-image.py | 0 problems/python/russian-doll-envelopes.py | 0 problems/python/same-tree.py | 0 .../satisfiability-of-equality-equations.py | 0 problems/python/score-of-parentheses.py | 0 problems/python/search-a-2d-matrix.py | 0 .../python/search-in-a-binary-search-tree.py | 0 .../search-in-rotated-sorted-array-ii.py | 0 .../python/search-in-rotated-sorted-array.py | 0 problems/python/search-insert-position.py | 0 problems/python/search-suggestions-system.py | 0 problems/python/second-highest-salary.sql | 0 .../sell-diminishing-valued-colored-balls.py | 0 .../serialize-and-deserialize-binary-tree.py | 0 .../python/serialize-and-deserialize-bst.py | 0 problems/python/set-matrix-zeroes.py | 0 problems/python/shortest-bridge.py | 0 .../python/shortest-common-supersequence.py | 0 .../shortest-distance-from-all-buildings.py | 0 ...th-in-a-grid-with-obstacles-elimination.py | 0 .../python/shortest-path-in-binary-matrix.py | 0 problems/python/shortest-path-to-get-food.py | 0 problems/python/shuffle-an-array.py | 0 problems/python/simplify-path.py | 0 problems/python/single-threaded-cpu.py | 0 problems/python/sliding-window-maximum.py | 0 problems/python/snapshot-array.py | 0 problems/python/sort-colors.py | 0 problems/python/sort-list.py | 0 problems/python/spiral-matrix.py | 0 .../split-array-into-fibonacci-sequence.py | 0 problems/python/split-array-largest-sum.py | 0 problems/python/sqrtx.py | 0 problems/python/squares-of-a-sorted-array.py | 0 ...ions-from-a-binary-tree-node-to-another.py | 0 problems/python/stock-price-fluctuation.py | 0 problems/python/stone-game-ii.py | 0 .../python/student-attendance-record-ii.py | 0 problems/python/subarray-sum-equals-k.py | 0 .../subarrays-with-k-different-integers.py | 0 problems/python/subdomain-visit-count.py | 0 problems/python/subsets-ii.py | 0 problems/python/subsets.py | 0 ...bstring-with-concatenation-of-all-words.py | 0 problems/python/subtree-of-another-tree.py | 0 problems/python/sum-of-subarray-minimums.py | 0 problems/python/sum-root-to-leaf-numbers.py | 0 problems/python/summary-ranges.py | 0 problems/python/super-ugly-number.py | 0 problems/python/swap-adjacent-in-lr-string.py | 0 problems/python/swap-nodes-in-pairs.py | 0 problems/python/swim-in-rising-water.py | 0 problems/python/symmetric-tree.py | 0 problems/python/tallest-billboard.py | 0 problems/python/target-sum.py | 0 problems/python/task-scheduler.py | 0 problems/python/text-justification.py | 0 problems/python/the-kth-factor-of-n.py | 0 problems/python/the-maze-ii.py | 0 problems/python/time-based-key-value-store.py | 0 problems/python/to-lower-case.py | 0 problems/python/toeplitz-matrix.py | 0 problems/python/top-k-frequent-elements.py | 0 problems/python/trapping-rain-water-ii.py | 0 problems/python/trapping-rain-water.py | 0 problems/python/trim-a-binary-search-tree.py | 0 problems/python/two-out-of-three.py | 0 .../two-sum-ii-input-array-is-sorted.py | 0 problems/python/two-sum.py | 0 problems/python/ugly-number-ii.py | 0 problems/python/ugly-number.py | 0 problems/python/umber-of-islands-ii.py | 0 .../python/unique-binary-search-trees-ii,py | 0 problems/python/unique-binary-search-trees.py | 0 problems/python/unique-email-addres.py | 0 problems/python/unique-paths.py | 0 problems/python/univalued-binary-tree.py | 0 problems/python/valid-anagram.py | 0 problems/python/valid-number.py | 0 problems/python/valid-palindrome-ii.py | 0 problems/python/valid-palindrome.py | 0 problems/python/valid-parentheses.py | 0 problems/python/valid-word-abbreviation.py | 0 .../python/validate-binary-search-tree.py | 0 ...preorder-serialization-of-a-binary-tree.py | 0 ...rtical-order-traversal-of-a-binary-tree.py | 0 problems/python/wiggle-subsequence.py | 0 problems/python/word-break.py | 0 problems/python/word-ladder-ii.py | 0 problems/python/word-ladder.py | 0 problems/python/word-search-ii.py | 0 problems/python/word-search.py | 0 problems/python3/3sum-closest.py | 0 problems/python3/3sum-smaller.py | 0 problems/python3/3sum.py | 28 +++++++++++++++ problems/python3/4sum.py | 0 problems/python3/balanced-binary-tree.py | 0 .../binary-tree-level-order-traversal.py | 0 .../python3/binary-tree-maximum-path-sum.py | 27 ++++++++++++++ .../python3/binary-tree-right-side-view.py | 0 ...ree-from-preorder-and-inorder-traversal.py | 34 ++++++++++++++++++ problems/python3/container-with-most-water.py | 17 +++++++++ .../count-good-nodes-in-binary-tree.py | 0 problems/python3/diameter-of-binary-tree.py | 0 problems/python3/invert-binary-tree.py | 0 .../python3/kth-smallest-element-in-a-bst.py | 21 +++++++++++ ...common-ancestor-of-a-binary-search-tree.py | 0 .../python3/maximum-depth-of-binary-tree.py | 0 problems/python3/same-tree.py | 0 .../serialize-and-deserialize-binary-tree.py | 22 ++++++++++++ problems/python3/subsets.py | 22 ++++++++++++ ...bstring-with-concatenation-of-all-words.py | 0 problems/python3/subtree-of-another-tree.py | 0 problems/python3/trapping-rain-water.py | 35 +++++++++++++++++++ .../two-sum-ii-input-array-is-sorted.py | 11 ++++++ problems/python3/valid-palindrome.py | 15 ++++++++ .../python3/validate-binary-search-tree.py | 0 470 files changed, 232 insertions(+) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 README.md mode change 100644 => 100755 "common/bellman\342\200\223ford.py" mode change 100644 => 100755 common/binary-search-tree.py mode change 100644 => 100755 common/bst-in-order.py mode change 100644 => 100755 common/dijkstra.py mode change 100644 => 100755 common/heap-sort.py mode change 100644 => 100755 common/insertion-sort.py mode change 100644 => 100755 common/knapsack.py mode change 100644 => 100755 common/merge-sort-in-place.py mode change 100644 => 100755 common/merge-sort.py mode change 100644 => 100755 common/min-heap.py mode change 100644 => 100755 common/quick-sort.py mode change 100644 => 100755 common/radix-sort.py mode change 100644 => 100755 common/trie.py mode change 100644 => 100755 problems/python/01-matrix.py mode change 100644 => 100755 problems/python/3sum-closest.py mode change 100644 => 100755 problems/python/3sum.py mode change 100644 => 100755 problems/python/4sum.py mode change 100644 => 100755 problems/python/accounts-merge.py mode change 100644 => 100755 problems/python/add-binary.py mode change 100644 => 100755 problems/python/add-digits.py mode change 100644 => 100755 problems/python/add-strings.py mode change 100644 => 100755 problems/python/add-two-numbers-ii.py mode change 100644 => 100755 problems/python/add-two-numbers.py mode change 100644 => 100755 problems/python/alien-dictionary.py mode change 100644 => 100755 problems/python/all-nodes-distance-k-in-binary-tree.py mode change 100644 => 100755 problems/python/amount-of-new-area-painted-each-day.py mode change 100644 => 100755 problems/python/analyze-user-website-visit-pattern.py mode change 100644 => 100755 problems/python/backspace-string-compare.py mode change 100644 => 100755 problems/python/balance-a-binary-search-tree.py mode change 100644 => 100755 problems/python/balanced-binary-tree.py mode change 100644 => 100755 problems/python/basic-calculator-ii.py mode change 100644 => 100755 problems/python/best-time-to-buy-an-stock.py mode change 100644 => 100755 problems/python/best-time-to-buy-and-sell-stock-iii.py mode change 100644 => 100755 problems/python/best-time-to-buy-and-sell-stock-with-cooldown.py mode change 100644 => 100755 problems/python/best-time-to-buy-and-sell-stock.py mode change 100644 => 100755 problems/python/big-countries.sql mode change 100644 => 100755 problems/python/binary-search-tree-iterator.py mode change 100644 => 100755 problems/python/binary-search.py mode change 100644 => 100755 problems/python/binary-subarrays-with-sum.py mode change 100644 => 100755 problems/python/binary-tree-inorder-traversal.py mode change 100644 => 100755 problems/python/binary-tree-level-order-traversal-ii.py mode change 100644 => 100755 problems/python/binary-tree-level-order-traversal.py mode change 100644 => 100755 problems/python/binary-tree-longest-consecutive-sequence.py mode change 100644 => 100755 problems/python/binary-tree-maximum-path-sum.py mode change 100644 => 100755 problems/python/binary-tree-paths.py mode change 100644 => 100755 problems/python/binary-tree-pruning.py mode change 100644 => 100755 problems/python/binary-tree-right-side-view.py mode change 100644 => 100755 problems/python/binary-tree-vertical-order-traversal.py mode change 100644 => 100755 problems/python/binary-watch.py mode change 100644 => 100755 problems/python/buildings-with-an-ocean-view.py mode change 100644 => 100755 problems/python/burst-balloons.py mode change 100644 => 100755 problems/python/campus-bikes-ii.py mode change 100644 => 100755 problems/python/candy.py mode change 100644 => 100755 problems/python/capacity-to-ship-packages-within-d-days.py mode change 100644 => 100755 problems/python/cheapest-flights-within-k-stops.py mode change 100644 => 100755 problems/python/climbing-stairs.py mode change 100644 => 100755 problems/python/clone-graph.py mode change 100644 => 100755 problems/python/closest-binary-search-tree-value.py mode change 100644 => 100755 problems/python/coin-change.py mode change 100644 => 100755 problems/python/coloring-a-border.py mode change 100644 => 100755 problems/python/combination-sum-ii.py mode change 100644 => 100755 problems/python/combination-sum-iii.py mode change 100644 => 100755 problems/python/combination-sum-iv.py mode change 100644 => 100755 problems/python/combination-sum.py mode change 100644 => 100755 problems/python/combinations.py mode change 100644 => 100755 problems/python/combine-two-tables.sql mode change 100644 => 100755 problems/python/compare-version-numbers.py mode change 100644 => 100755 problems/python/connecting-cities-with-minimum-cost.py mode change 100644 => 100755 problems/python/consecutive-numbers-sum.py mode change 100644 => 100755 problems/python/construct-binary-tree-from-inorder-and-postorder-traversal.py mode change 100644 => 100755 problems/python/construct-binary-tree-from-preorder-and-inorder-traversal.py mode change 100644 => 100755 problems/python/container-with-most-water.py mode change 100644 => 100755 problems/python/contains-duplicate-ii.py mode change 100644 => 100755 problems/python/contains-duplicate-iii.py mode change 100644 => 100755 problems/python/contains-duplicate.py mode change 100644 => 100755 problems/python/continuous-subarray-sum.py mode change 100644 => 100755 problems/python/convert-binary-search-tree-to-sorted-doubly-linked-list.py mode change 100644 => 100755 problems/python/convert-sorted-array-to-binary-search-tree.py mode change 100644 => 100755 problems/python/convert-sorted-list-to-binary-search-tree.py mode change 100644 => 100755 problems/python/copy-list-with-random-pointer.py mode change 100644 => 100755 problems/python/count-all-valid-pickup-and-delivery-opti.py mode change 100644 => 100755 problems/python/count-binary-substrings.py mode change 100644 => 100755 problems/python/count-complete-tree-nodes.py mode change 100644 => 100755 problems/python/count-number-of-nice-subarrays.py mode change 100644 => 100755 problems/python/count-unique-characters-of-all-substrings-of-a-given-string.py mode change 100644 => 100755 problems/python/course-schedule-ii.py mode change 100644 => 100755 problems/python/course-schedule.py mode change 100644 => 100755 problems/python/custom-sort-string.py mode change 100644 => 100755 problems/python/cutting-ribbons.py mode change 100644 => 100755 problems/python/data-stream-as-disjoint-intervals.py mode change 100644 => 100755 problems/python/decode-string.py mode change 100644 => 100755 problems/python/decode-ways.py mode change 100644 => 100755 problems/python/delete-and-earn.py mode change 100644 => 100755 problems/python/delete-duplicate-folders-in-system.py mode change 100644 => 100755 problems/python/delete-node-in-a-bst.py mode change 100644 => 100755 problems/python/delete-operation-for-two-strings.py mode change 100644 => 100755 problems/python/design-add-and-search-words-data-structure.py mode change 100644 => 100755 problems/python/design-in-memory-file-system.py mode change 100644 => 100755 problems/python/design-linked-list.py mode change 100644 => 100755 problems/python/design-tic-tac-toe.py mode change 100644 => 100755 problems/python/diagonal-traverse.py mode change 100644 => 100755 problems/python/diameter-of-binary-tree.py mode change 100644 => 100755 problems/python/different-ways-to-add-parentheses.py mode change 100644 => 100755 problems/python/distinct-subsequences.py mode change 100644 => 100755 problems/python/distribute-coins-in-binary-tree.py mode change 100644 => 100755 problems/python/domino-and-tromino-tiling.py mode change 100644 => 100755 problems/python/dot-product-of-two-sparse-vectors.py mode change 100644 => 100755 problems/python/dungeon-game.py mode change 100644 => 100755 problems/python/edit-distance.py mode change 100644 => 100755 problems/python/egions-cut-by-slashes.py mode change 100644 => 100755 problems/python/evaluate-division.py mode change 100644 => 100755 problems/python/evaluate-reverse-polish-notation.py mode change 100644 => 100755 problems/python/exclusive-time-of-functions.py mode change 100644 => 100755 problems/python/expression-add-operators.py mode change 100644 => 100755 problems/python/filling-bookcase-shelves.py mode change 100644 => 100755 problems/python/find-all-possible-recipes-from-given-supplies.py mode change 100644 => 100755 problems/python/find-and-replace-in-string.py mode change 100644 => 100755 problems/python/find-distance-in-a-binary-tree.py mode change 100644 => 100755 problems/python/find-duplicate-subtrees.py mode change 100644 => 100755 problems/python/find-eventual-safe-states.py mode change 100644 => 100755 problems/python/find-first-and-last-position-of-element-in-sorted-array.py mode change 100644 => 100755 problems/python/find-k-closest-elements.py mode change 100644 => 100755 problems/python/find-k-pairs-with-smallest-sums.py mode change 100644 => 100755 problems/python/find-leaves-of-binary-tree.py mode change 100644 => 100755 problems/python/find-median-from-data-stream.py mode change 100644 => 100755 problems/python/find-minimum-in-rotated-sorted-array-ii.py mode change 100644 => 100755 problems/python/find-minimum-in-rotated-sorted-array.py mode change 100644 => 100755 problems/python/find-mode-in-binary-search-tree.py mode change 100644 => 100755 problems/python/find-original-array-from-doubled-array,py mode change 100644 => 100755 problems/python/find-peak-element.py mode change 100644 => 100755 problems/python/find-the-duplicate-number.py mode change 100644 => 100755 problems/python/first-bad-version.py mode change 100644 => 100755 problems/python/first-missing-positive.py mode change 100644 => 100755 problems/python/first-unique-character-in-a-string.py mode change 100644 => 100755 problems/python/fizz-buzz.py mode change 100644 => 100755 problems/python/flatten-binary-tree-to-linked-list.py mode change 100644 => 100755 problems/python/flip-binary-tree-to-match-preorder-traversal.py mode change 100644 => 100755 problems/python/flip-string-to-monotone-increasing.py mode change 100644 => 100755 problems/python/flood-fill.py mode change 100644 => 100755 problems/python/friend-circles.py mode change 100644 => 100755 problems/python/fruit-into-baskets.py mode change 100644 => 100755 problems/python/game-of-life.py mode change 100644 => 100755 problems/python/generate-parentheses.py mode change 100644 => 100755 problems/python/graph-valid-tree.py mode change 100644 => 100755 problems/python/greatest-sum-divisible-by-three.py mode change 100644 => 100755 problems/python/group-anagrams.py mode change 100644 => 100755 problems/python/group-shifted-strings.py mode change 100644 => 100755 problems/python/guess-number-higher-or-lower-ii.py mode change 100644 => 100755 problems/python/guess-number-higher-or-lower.py mode change 100644 => 100755 problems/python/guess-the-word.py mode change 100644 => 100755 problems/python/h-index-ii.py mode change 100644 => 100755 problems/python/h-index.py mode change 100644 => 100755 problems/python/hamming-distance.py mode change 100644 => 100755 problems/python/house-robber-ii.py mode change 100644 => 100755 problems/python/house-robber-iii.py mode change 100644 => 100755 problems/python/house-robber.py mode change 100644 => 100755 problems/python/implement-trie-prefix-tree.py mode change 100644 => 100755 problems/python/increasing-triplet-subsequence.py mode change 100644 => 100755 problems/python/inorder-successor-in-bst-ii.py mode change 100644 => 100755 problems/python/inorder-successor-in-bst.py mode change 100644 => 100755 problems/python/insert-interval.py mode change 100644 => 100755 problems/python/insert-into-a-binary-search-tree.py mode change 100644 => 100755 problems/python/insert-into-a-sorted-circular-linked-list.py mode change 100644 => 100755 problems/python/insertion-sort-list.py mode change 100644 => 100755 problems/python/integer-to-english-words.py mode change 100644 => 100755 problems/python/interleaving-string.py mode change 100644 => 100755 problems/python/intersection-of-two-arrays-ii.py mode change 100644 => 100755 problems/python/intersection-of-two-arrays.py mode change 100644 => 100755 problems/python/invert-binary-tree.py mode change 100644 => 100755 problems/python/is-graph-bipartite.py mode change 100644 => 100755 problems/python/is-subsequence.py mode change 100644 => 100755 problems/python/isomorphic-strings.py mode change 100644 => 100755 problems/python/jewels-and-stones.py mode change 100644 => 100755 problems/python/jump-game.py mode change 100644 => 100755 problems/python/k-closest-points-to-origin.py mode change 100644 => 100755 problems/python/k-empty-slots.py mode change 100644 => 100755 problems/python/keys-and-rooms.py mode change 100644 => 100755 problems/python/knight-dialer.py mode change 100644 => 100755 problems/python/knight-probability-in-chessboard.py mode change 100644 => 100755 problems/python/koko-eating-bananas.py mode change 100644 => 100755 problems/python/kth-largest-element-in-an-array.py mode change 100644 => 100755 problems/python/kth-smallest-element-in-a-bst.py mode change 100644 => 100755 problems/python/kth-smallest-element-in-a-sorted-matrix.py mode change 100644 => 100755 problems/python/largest-1-bordered-square.py mode change 100644 => 100755 problems/python/largest-bst-subtree.py mode change 100644 => 100755 problems/python/largest-sum-of-averages.py mode change 100644 => 100755 problems/python/last-stone-weight-ii.py mode change 100644 => 100755 problems/python/last-stone-weight.py mode change 100644 => 100755 problems/python/least-number-of-unique-integers-after-k-removals.py mode change 100644 => 100755 problems/python/letter-case-permutation.py mode change 100644 => 100755 problems/python/letter-combinations-of-a-phone-number.py mode change 100644 => 100755 problems/python/license-key-formatting.py mode change 100644 => 100755 problems/python/linked-list-cycle-ii.py mode change 100644 => 100755 problems/python/linked-list-cycle.py mode change 100644 => 100755 problems/python/linked-list-random-node.py mode change 100644 => 100755 problems/python/logger-rate-limiter.py mode change 100644 => 100755 problems/python/longest-common-prefix.py mode change 100644 => 100755 problems/python/longest-common-subsequence.py mode change 100644 => 100755 problems/python/longest-consecutive-sequence.py mode change 100644 => 100755 problems/python/longest-increasing-path-in-a-matrix.py mode change 100644 => 100755 problems/python/longest-increasing-subsequence.py mode change 100644 => 100755 problems/python/longest-palindromic-subsequence.py mode change 100644 => 100755 problems/python/longest-palindromic-substring.py mode change 100644 => 100755 problems/python/longest-repeating-character-replacement.py mode change 100644 => 100755 problems/python/longest-string-chain.py mode change 100644 => 100755 problems/python/longest-substring-with-at-least-k-repeating-characters.py mode change 100644 => 100755 problems/python/longest-substring-without-repeating-characters.py mode change 100644 => 100755 problems/python/longest-univalue-path.py mode change 100644 => 100755 problems/python/lowest-common-ancestor-of-a-binary-search-tree.py mode change 100644 => 100755 problems/python/lowest-common-ancestor-of-a-binary-search.py mode change 100644 => 100755 problems/python/lowest-common-ancestor-of-a-binary-tree-ii.py mode change 100644 => 100755 problems/python/lowest-common-ancestor-of-a-binary-tree-iii.py mode change 100644 => 100755 problems/python/lowest-common-ancestor-of-a-binary-tree-iv.py mode change 100644 => 100755 problems/python/lowest-common-ancestor-of-a-binary-tree.py mode change 100644 => 100755 problems/python/lowest-common-ancestor-of-deepest-leaves.py mode change 100644 => 100755 problems/python/lru-cache.py mode change 100644 => 100755 problems/python/majority-element-ii.py mode change 100644 => 100755 problems/python/majority-element.py mode change 100644 => 100755 problems/python/making-a-large-island.py mode change 100644 => 100755 problems/python/max-area-of-island.py mode change 100644 => 100755 problems/python/max-consecutive-ones-iii.py mode change 100644 => 100755 problems/python/max-stack.py mode change 100644 => 100755 problems/python/max-sum-of-rectangle-no-larger-than-k.py mode change 100644 => 100755 problems/python/maximal-square.py mode change 100644 => 100755 problems/python/maximum-average-subtree.py mode change 100644 => 100755 problems/python/maximum-compatibility-score-sum.py mode change 100644 => 100755 problems/python/maximum-depth-of-binary-tree.py mode change 100644 => 100755 problems/python/maximum-gap.py mode change 100644 => 100755 problems/python/maximum-length-of-repeated-subarray.py mode change 100644 => 100755 problems/python/maximum-number-of-events-that-can-be-attended.py mode change 100644 => 100755 problems/python/maximum-number-of-points-with-cost.py mode change 100644 => 100755 problems/python/maximum-number-of-visible-points.py mode change 100644 => 100755 problems/python/maximum-product-of-three-numbers.py mode change 100644 => 100755 problems/python/maximum-product-subarray.py mode change 100644 => 100755 problems/python/maximum-subarray-sum-with-one-deletion.py mode change 100644 => 100755 problems/python/maximum-subarray.py mode change 100644 => 100755 problems/python/maximum-swap.py mode change 100644 => 100755 problems/python/maximum-units-on-a-truck.py mode change 100644 => 100755 problems/python/median-of-two-sorted-arrays.py mode change 100644 => 100755 problems/python/meeting-rooms-ii.py mode change 100644 => 100755 problems/python/meeting-rooms.py mode change 100644 => 100755 problems/python/merge-intervals.py mode change 100644 => 100755 problems/python/merge-k-sorted-lists.py mode change 100644 => 100755 problems/python/merge-sorted-array.py mode change 100644 => 100755 problems/python/merge-two-sorted-lists.py mode change 100644 => 100755 problems/python/min-cost-climbing-stairs.py mode change 100644 => 100755 problems/python/min-stack.py mode change 100644 => 100755 problems/python/minimize-malware-spread.py mode change 100644 => 100755 problems/python/minimum-absolute-difference-in-bst.py mode change 100644 => 100755 problems/python/minimum-ascii-delete-sum-for-two-strings.py mode change 100644 => 100755 problems/python/minimum-cost-to-connect-sticks.py mode change 100644 => 100755 problems/python/minimum-cost-to-hire-k-workers.py mode change 100644 => 100755 problems/python/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py mode change 100644 => 100755 problems/python/minimum-cost-to-reach-city-with-discounts.py mode change 100644 => 100755 problems/python/minimum-depth-of-binary-tree.py mode change 100644 => 100755 problems/python/minimum-difficulty-of-a-job-schedule.py mode change 100644 => 100755 problems/python/minimum-falling-path-sum-ii.py mode change 100644 => 100755 problems/python/minimum-knight-moves.py mode change 100644 => 100755 problems/python/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py mode change 100644 => 100755 problems/python/minimum-path-sum.py mode change 100644 => 100755 problems/python/minimum-score-triangulation-of-polygon.py mode change 100644 => 100755 problems/python/minimum-size-subarray-sum.py mode change 100644 => 100755 problems/python/minimum-swaps-to-group-all-1s-together.py mode change 100644 => 100755 problems/python/minimum-swaps-to-make-sequences-increasing.py mode change 100644 => 100755 problems/python/minimum-time-difference.py mode change 100644 => 100755 problems/python/minimum-window-substring.py mode change 100644 => 100755 problems/python/minimum-xor-sum-of-two-arrays.py mode change 100644 => 100755 problems/python/missing-number.py mode change 100644 => 100755 problems/python/most-frequent-subtree-sum.py mode change 100644 => 100755 problems/python/most-stones-removed-with-same-row-or-column.py mode change 100644 => 100755 problems/python/move-zeroes.py mode change 100644 => 100755 problems/python/moving-average-from-data-stream.py mode change 100644 => 100755 problems/python/my-calendar-ii.py mode change 100644 => 100755 problems/python/n-ary-tree-level-order-traversal.py mode change 100644 => 100755 problems/python/n-ary-tree-postorder-traversal.py mode change 100644 => 100755 problems/python/n-ary-tree-preorder-traversal.py mode change 100644 => 100755 problems/python/nested-list-weight-sum.py mode change 100644 => 100755 problems/python/network-delay-time.py mode change 100644 => 100755 problems/python/next-closest-time.py mode change 100644 => 100755 problems/python/next-permutation.py mode change 100644 => 100755 problems/python/number-complement.py mode change 100644 => 100755 problems/python/number-of-connected-components-in-an-undirected-graph.py mode change 100644 => 100755 problems/python/number-of-islands-ii.py mode change 100644 => 100755 problems/python/number-of-islands.py mode change 100644 => 100755 problems/python/number-of-longest-increasing-subsequence.py mode change 100644 => 100755 problems/python/number-of-matching-subsequences.py mode change 100644 => 100755 problems/python/number-of-provinces.py mode change 100644 => 100755 problems/python/number-of-recent-calls.py mode change 100644 => 100755 problems/python/number-of-squareful-arrays.py mode change 100644 => 100755 problems/python/number-of-substrings-containing-all-thre.py mode change 100644 => 100755 problems/python/number-of-ways-to-arrive-at-destination.py mode change 100644 => 100755 problems/python/odd-even-jump.py mode change 100644 => 100755 problems/python/ones-and-zeroes.py mode change 100644 => 100755 problems/python/open-the-lock.py mode change 100644 => 100755 problems/python/out-of-boundary-paths.py mode change 100644 => 100755 problems/python/pacific-atlantic-water-flow.py mode change 100644 => 100755 problems/python/pairs-of-songs-with-total-durations-divisible-by-60.py mode change 100644 => 100755 problems/python/palindrome-number.py mode change 100644 => 100755 problems/python/palindrome-pairs.py mode change 100644 => 100755 problems/python/palindrome-partitioning-iii.py mode change 100644 => 100755 problems/python/palindrome-partitioning.py mode change 100644 => 100755 problems/python/palindromic-substrings.py mode change 100644 => 100755 problems/python/partition-array-for-maximum-sum.py mode change 100644 => 100755 problems/python/partition-labels.py mode change 100644 => 100755 problems/python/partition-to-k-equal-sum-subsets.py mode change 100644 => 100755 problems/python/path-sum-ii.py mode change 100644 => 100755 problems/python/path-sum-iii.py mode change 100644 => 100755 problems/python/path-sum.py mode change 100644 => 100755 problems/python/path-with-maximum-probability.py mode change 100644 => 100755 problems/python/peak-index-in-a-mountain-array.py mode change 100644 => 100755 problems/python/perfect-squares.py mode change 100644 => 100755 problems/python/permutation-in-string.py mode change 100644 => 100755 problems/python/permutation-sequence.py mode change 100644 => 100755 problems/python/permutations-ii.py mode change 100644 => 100755 problems/python/permutations.py mode change 100644 => 100755 problems/python/populating-next-right-pointers-in-each-node-ii.py mode change 100644 => 100755 problems/python/populating-next-right-pointers-in-each-node.py mode change 100644 => 100755 problems/python/powx-n.py mode change 100644 => 100755 problems/python/product-of-array-except-self.py mode change 100644 => 100755 problems/python/profitable-schemes.py mode change 100644 => 100755 problems/python/queue-reconstruction-by-height.py mode change 100644 => 100755 problems/python/random-pick-with-weight.py mode change 100644 => 100755 problems/python/range-addition.py mode change 100644 => 100755 problems/python/range-sum-of-bst.py mode change 100644 => 100755 problems/python/range-sum-query-immutable.py mode change 100644 => 100755 problems/python/range-sum-query-mutable.py mode change 100644 => 100755 problems/python/rearrange-string-k-distance-apart.py mode change 100644 => 100755 problems/python/reconstruct-itinerary.py mode change 100644 => 100755 problems/python/recover-binary-search-tree.py mode change 100644 => 100755 problems/python/redundant-connection.py mode change 100644 => 100755 problems/python/remove-all-adjacent-duplicates-in-string.py mode change 100644 => 100755 problems/python/remove-all-ones-with-row-and-column-flips.py mode change 100644 => 100755 problems/python/remove-duplicates-from-sorted-array-ii.py mode change 100644 => 100755 problems/python/remove-duplicates-from-sorted-array.py mode change 100644 => 100755 problems/python/remove-duplicates-from-sorted-list.py mode change 100644 => 100755 problems/python/remove-element.py mode change 100644 => 100755 problems/python/remove-invalid-parentheses.py mode change 100644 => 100755 problems/python/remove-linked-list-elements.py mode change 100644 => 100755 problems/python/remove-nth-node-from-end-of-list.py mode change 100644 => 100755 problems/python/reorder-list.py mode change 100644 => 100755 problems/python/repeated-string-match.py mode change 100644 => 100755 problems/python/replace-the-substring-for-balanced-string.py mode change 100644 => 100755 problems/python/restore-ip-addresses.py mode change 100644 => 100755 problems/python/reverse-integer.py mode change 100644 => 100755 problems/python/reverse-linked-list.py mode change 100644 => 100755 problems/python/reverse-string.py mode change 100644 => 100755 problems/python/reverse-vowels-of-a-string.py mode change 100644 => 100755 problems/python/reverse-words-in-a-string.py mode change 100644 => 100755 problems/python/robot-bounded-in-circle.py mode change 100644 => 100755 problems/python/roman-to-integer.py mode change 100644 => 100755 problems/python/rotate-array.py mode change 100644 => 100755 problems/python/rotate-image.py mode change 100644 => 100755 problems/python/russian-doll-envelopes.py mode change 100644 => 100755 problems/python/same-tree.py mode change 100644 => 100755 problems/python/satisfiability-of-equality-equations.py mode change 100644 => 100755 problems/python/score-of-parentheses.py mode change 100644 => 100755 problems/python/search-a-2d-matrix.py mode change 100644 => 100755 problems/python/search-in-a-binary-search-tree.py mode change 100644 => 100755 problems/python/search-in-rotated-sorted-array-ii.py mode change 100644 => 100755 problems/python/search-in-rotated-sorted-array.py mode change 100644 => 100755 problems/python/search-insert-position.py mode change 100644 => 100755 problems/python/search-suggestions-system.py mode change 100644 => 100755 problems/python/second-highest-salary.sql mode change 100644 => 100755 problems/python/sell-diminishing-valued-colored-balls.py mode change 100644 => 100755 problems/python/serialize-and-deserialize-binary-tree.py mode change 100644 => 100755 problems/python/serialize-and-deserialize-bst.py mode change 100644 => 100755 problems/python/set-matrix-zeroes.py mode change 100644 => 100755 problems/python/shortest-bridge.py mode change 100644 => 100755 problems/python/shortest-common-supersequence.py mode change 100644 => 100755 problems/python/shortest-distance-from-all-buildings.py mode change 100644 => 100755 problems/python/shortest-path-in-a-grid-with-obstacles-elimination.py mode change 100644 => 100755 problems/python/shortest-path-in-binary-matrix.py mode change 100644 => 100755 problems/python/shortest-path-to-get-food.py mode change 100644 => 100755 problems/python/shuffle-an-array.py mode change 100644 => 100755 problems/python/simplify-path.py mode change 100644 => 100755 problems/python/single-threaded-cpu.py mode change 100644 => 100755 problems/python/sliding-window-maximum.py mode change 100644 => 100755 problems/python/snapshot-array.py mode change 100644 => 100755 problems/python/sort-colors.py mode change 100644 => 100755 problems/python/sort-list.py mode change 100644 => 100755 problems/python/spiral-matrix.py mode change 100644 => 100755 problems/python/split-array-into-fibonacci-sequence.py mode change 100644 => 100755 problems/python/split-array-largest-sum.py mode change 100644 => 100755 problems/python/sqrtx.py mode change 100644 => 100755 problems/python/squares-of-a-sorted-array.py mode change 100644 => 100755 problems/python/step-by-step-directions-from-a-binary-tree-node-to-another.py mode change 100644 => 100755 problems/python/stock-price-fluctuation.py mode change 100644 => 100755 problems/python/stone-game-ii.py mode change 100644 => 100755 problems/python/student-attendance-record-ii.py mode change 100644 => 100755 problems/python/subarray-sum-equals-k.py mode change 100644 => 100755 problems/python/subarrays-with-k-different-integers.py mode change 100644 => 100755 problems/python/subdomain-visit-count.py mode change 100644 => 100755 problems/python/subsets-ii.py mode change 100644 => 100755 problems/python/subsets.py mode change 100644 => 100755 problems/python/substring-with-concatenation-of-all-words.py mode change 100644 => 100755 problems/python/subtree-of-another-tree.py mode change 100644 => 100755 problems/python/sum-of-subarray-minimums.py mode change 100644 => 100755 problems/python/sum-root-to-leaf-numbers.py mode change 100644 => 100755 problems/python/summary-ranges.py mode change 100644 => 100755 problems/python/super-ugly-number.py mode change 100644 => 100755 problems/python/swap-adjacent-in-lr-string.py mode change 100644 => 100755 problems/python/swap-nodes-in-pairs.py mode change 100644 => 100755 problems/python/swim-in-rising-water.py mode change 100644 => 100755 problems/python/symmetric-tree.py mode change 100644 => 100755 problems/python/tallest-billboard.py mode change 100644 => 100755 problems/python/target-sum.py mode change 100644 => 100755 problems/python/task-scheduler.py mode change 100644 => 100755 problems/python/text-justification.py mode change 100644 => 100755 problems/python/the-kth-factor-of-n.py mode change 100644 => 100755 problems/python/the-maze-ii.py mode change 100644 => 100755 problems/python/time-based-key-value-store.py mode change 100644 => 100755 problems/python/to-lower-case.py mode change 100644 => 100755 problems/python/toeplitz-matrix.py mode change 100644 => 100755 problems/python/top-k-frequent-elements.py mode change 100644 => 100755 problems/python/trapping-rain-water-ii.py mode change 100644 => 100755 problems/python/trapping-rain-water.py mode change 100644 => 100755 problems/python/trim-a-binary-search-tree.py mode change 100644 => 100755 problems/python/two-out-of-three.py mode change 100644 => 100755 problems/python/two-sum-ii-input-array-is-sorted.py mode change 100644 => 100755 problems/python/two-sum.py mode change 100644 => 100755 problems/python/ugly-number-ii.py mode change 100644 => 100755 problems/python/ugly-number.py mode change 100644 => 100755 problems/python/umber-of-islands-ii.py mode change 100644 => 100755 problems/python/unique-binary-search-trees-ii,py mode change 100644 => 100755 problems/python/unique-binary-search-trees.py mode change 100644 => 100755 problems/python/unique-email-addres.py mode change 100644 => 100755 problems/python/unique-paths.py mode change 100644 => 100755 problems/python/univalued-binary-tree.py mode change 100644 => 100755 problems/python/valid-anagram.py mode change 100644 => 100755 problems/python/valid-number.py mode change 100644 => 100755 problems/python/valid-palindrome-ii.py mode change 100644 => 100755 problems/python/valid-palindrome.py mode change 100644 => 100755 problems/python/valid-parentheses.py mode change 100644 => 100755 problems/python/valid-word-abbreviation.py mode change 100644 => 100755 problems/python/validate-binary-search-tree.py mode change 100644 => 100755 problems/python/verify-preorder-serialization-of-a-binary-tree.py mode change 100644 => 100755 problems/python/vertical-order-traversal-of-a-binary-tree.py mode change 100644 => 100755 problems/python/wiggle-subsequence.py mode change 100644 => 100755 problems/python/word-break.py mode change 100644 => 100755 problems/python/word-ladder-ii.py mode change 100644 => 100755 problems/python/word-ladder.py mode change 100644 => 100755 problems/python/word-search-ii.py mode change 100644 => 100755 problems/python/word-search.py mode change 100644 => 100755 problems/python3/3sum-closest.py mode change 100644 => 100755 problems/python3/3sum-smaller.py mode change 100644 => 100755 problems/python3/3sum.py mode change 100644 => 100755 problems/python3/4sum.py mode change 100644 => 100755 problems/python3/balanced-binary-tree.py mode change 100644 => 100755 problems/python3/binary-tree-level-order-traversal.py create mode 100644 problems/python3/binary-tree-maximum-path-sum.py mode change 100644 => 100755 problems/python3/binary-tree-right-side-view.py create mode 100644 problems/python3/construct-binary-tree-from-preorder-and-inorder-traversal.py mode change 100644 => 100755 problems/python3/container-with-most-water.py mode change 100644 => 100755 problems/python3/count-good-nodes-in-binary-tree.py mode change 100644 => 100755 problems/python3/diameter-of-binary-tree.py mode change 100644 => 100755 problems/python3/invert-binary-tree.py create mode 100755 problems/python3/kth-smallest-element-in-a-bst.py mode change 100644 => 100755 problems/python3/lowest-common-ancestor-of-a-binary-search-tree.py mode change 100644 => 100755 problems/python3/maximum-depth-of-binary-tree.py mode change 100644 => 100755 problems/python3/same-tree.py create mode 100644 problems/python3/serialize-and-deserialize-binary-tree.py create mode 100644 problems/python3/subsets.py mode change 100644 => 100755 problems/python3/substring-with-concatenation-of-all-words.py mode change 100644 => 100755 problems/python3/subtree-of-another-tree.py create mode 100644 problems/python3/trapping-rain-water.py create mode 100644 problems/python3/two-sum-ii-input-array-is-sorted.py create mode 100644 problems/python3/valid-palindrome.py mode change 100644 => 100755 problems/python3/validate-binary-search-tree.py diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git "a/common/bellman\342\200\223ford.py" "b/common/bellman\342\200\223ford.py" old mode 100644 new mode 100755 diff --git a/common/binary-search-tree.py b/common/binary-search-tree.py old mode 100644 new mode 100755 diff --git a/common/bst-in-order.py b/common/bst-in-order.py old mode 100644 new mode 100755 diff --git a/common/dijkstra.py b/common/dijkstra.py old mode 100644 new mode 100755 diff --git a/common/heap-sort.py b/common/heap-sort.py old mode 100644 new mode 100755 diff --git a/common/insertion-sort.py b/common/insertion-sort.py old mode 100644 new mode 100755 diff --git a/common/knapsack.py b/common/knapsack.py old mode 100644 new mode 100755 diff --git a/common/merge-sort-in-place.py b/common/merge-sort-in-place.py old mode 100644 new mode 100755 diff --git a/common/merge-sort.py b/common/merge-sort.py old mode 100644 new mode 100755 diff --git a/common/min-heap.py b/common/min-heap.py old mode 100644 new mode 100755 diff --git a/common/quick-sort.py b/common/quick-sort.py old mode 100644 new mode 100755 diff --git a/common/radix-sort.py b/common/radix-sort.py old mode 100644 new mode 100755 diff --git a/common/trie.py b/common/trie.py old mode 100644 new mode 100755 diff --git a/problems/python/01-matrix.py b/problems/python/01-matrix.py old mode 100644 new mode 100755 diff --git a/problems/python/3sum-closest.py b/problems/python/3sum-closest.py old mode 100644 new mode 100755 diff --git a/problems/python/3sum.py b/problems/python/3sum.py old mode 100644 new mode 100755 diff --git a/problems/python/4sum.py b/problems/python/4sum.py old mode 100644 new mode 100755 diff --git a/problems/python/accounts-merge.py b/problems/python/accounts-merge.py old mode 100644 new mode 100755 diff --git a/problems/python/add-binary.py b/problems/python/add-binary.py old mode 100644 new mode 100755 diff --git a/problems/python/add-digits.py b/problems/python/add-digits.py old mode 100644 new mode 100755 diff --git a/problems/python/add-strings.py b/problems/python/add-strings.py old mode 100644 new mode 100755 diff --git a/problems/python/add-two-numbers-ii.py b/problems/python/add-two-numbers-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/add-two-numbers.py b/problems/python/add-two-numbers.py old mode 100644 new mode 100755 diff --git a/problems/python/alien-dictionary.py b/problems/python/alien-dictionary.py old mode 100644 new mode 100755 diff --git a/problems/python/all-nodes-distance-k-in-binary-tree.py b/problems/python/all-nodes-distance-k-in-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/amount-of-new-area-painted-each-day.py b/problems/python/amount-of-new-area-painted-each-day.py old mode 100644 new mode 100755 diff --git a/problems/python/analyze-user-website-visit-pattern.py b/problems/python/analyze-user-website-visit-pattern.py old mode 100644 new mode 100755 diff --git a/problems/python/backspace-string-compare.py b/problems/python/backspace-string-compare.py old mode 100644 new mode 100755 diff --git a/problems/python/balance-a-binary-search-tree.py b/problems/python/balance-a-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/balanced-binary-tree.py b/problems/python/balanced-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/basic-calculator-ii.py b/problems/python/basic-calculator-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/best-time-to-buy-an-stock.py b/problems/python/best-time-to-buy-an-stock.py old mode 100644 new mode 100755 diff --git a/problems/python/best-time-to-buy-and-sell-stock-iii.py b/problems/python/best-time-to-buy-and-sell-stock-iii.py old mode 100644 new mode 100755 diff --git a/problems/python/best-time-to-buy-and-sell-stock-with-cooldown.py b/problems/python/best-time-to-buy-and-sell-stock-with-cooldown.py old mode 100644 new mode 100755 diff --git a/problems/python/best-time-to-buy-and-sell-stock.py b/problems/python/best-time-to-buy-and-sell-stock.py old mode 100644 new mode 100755 diff --git a/problems/python/big-countries.sql b/problems/python/big-countries.sql old mode 100644 new mode 100755 diff --git a/problems/python/binary-search-tree-iterator.py b/problems/python/binary-search-tree-iterator.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-search.py b/problems/python/binary-search.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-subarrays-with-sum.py b/problems/python/binary-subarrays-with-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-tree-inorder-traversal.py b/problems/python/binary-tree-inorder-traversal.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-tree-level-order-traversal-ii.py b/problems/python/binary-tree-level-order-traversal-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-tree-level-order-traversal.py b/problems/python/binary-tree-level-order-traversal.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-tree-longest-consecutive-sequence.py b/problems/python/binary-tree-longest-consecutive-sequence.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-tree-maximum-path-sum.py b/problems/python/binary-tree-maximum-path-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-tree-paths.py b/problems/python/binary-tree-paths.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-tree-pruning.py b/problems/python/binary-tree-pruning.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-tree-right-side-view.py b/problems/python/binary-tree-right-side-view.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-tree-vertical-order-traversal.py b/problems/python/binary-tree-vertical-order-traversal.py old mode 100644 new mode 100755 diff --git a/problems/python/binary-watch.py b/problems/python/binary-watch.py old mode 100644 new mode 100755 diff --git a/problems/python/buildings-with-an-ocean-view.py b/problems/python/buildings-with-an-ocean-view.py old mode 100644 new mode 100755 diff --git a/problems/python/burst-balloons.py b/problems/python/burst-balloons.py old mode 100644 new mode 100755 diff --git a/problems/python/campus-bikes-ii.py b/problems/python/campus-bikes-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/candy.py b/problems/python/candy.py old mode 100644 new mode 100755 diff --git a/problems/python/capacity-to-ship-packages-within-d-days.py b/problems/python/capacity-to-ship-packages-within-d-days.py old mode 100644 new mode 100755 diff --git a/problems/python/cheapest-flights-within-k-stops.py b/problems/python/cheapest-flights-within-k-stops.py old mode 100644 new mode 100755 diff --git a/problems/python/climbing-stairs.py b/problems/python/climbing-stairs.py old mode 100644 new mode 100755 diff --git a/problems/python/clone-graph.py b/problems/python/clone-graph.py old mode 100644 new mode 100755 diff --git a/problems/python/closest-binary-search-tree-value.py b/problems/python/closest-binary-search-tree-value.py old mode 100644 new mode 100755 diff --git a/problems/python/coin-change.py b/problems/python/coin-change.py old mode 100644 new mode 100755 diff --git a/problems/python/coloring-a-border.py b/problems/python/coloring-a-border.py old mode 100644 new mode 100755 diff --git a/problems/python/combination-sum-ii.py b/problems/python/combination-sum-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/combination-sum-iii.py b/problems/python/combination-sum-iii.py old mode 100644 new mode 100755 diff --git a/problems/python/combination-sum-iv.py b/problems/python/combination-sum-iv.py old mode 100644 new mode 100755 diff --git a/problems/python/combination-sum.py b/problems/python/combination-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/combinations.py b/problems/python/combinations.py old mode 100644 new mode 100755 diff --git a/problems/python/combine-two-tables.sql b/problems/python/combine-two-tables.sql old mode 100644 new mode 100755 diff --git a/problems/python/compare-version-numbers.py b/problems/python/compare-version-numbers.py old mode 100644 new mode 100755 diff --git a/problems/python/connecting-cities-with-minimum-cost.py b/problems/python/connecting-cities-with-minimum-cost.py old mode 100644 new mode 100755 diff --git a/problems/python/consecutive-numbers-sum.py b/problems/python/consecutive-numbers-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/construct-binary-tree-from-inorder-and-postorder-traversal.py b/problems/python/construct-binary-tree-from-inorder-and-postorder-traversal.py old mode 100644 new mode 100755 diff --git a/problems/python/construct-binary-tree-from-preorder-and-inorder-traversal.py b/problems/python/construct-binary-tree-from-preorder-and-inorder-traversal.py old mode 100644 new mode 100755 diff --git a/problems/python/container-with-most-water.py b/problems/python/container-with-most-water.py old mode 100644 new mode 100755 diff --git a/problems/python/contains-duplicate-ii.py b/problems/python/contains-duplicate-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/contains-duplicate-iii.py b/problems/python/contains-duplicate-iii.py old mode 100644 new mode 100755 diff --git a/problems/python/contains-duplicate.py b/problems/python/contains-duplicate.py old mode 100644 new mode 100755 diff --git a/problems/python/continuous-subarray-sum.py b/problems/python/continuous-subarray-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/convert-binary-search-tree-to-sorted-doubly-linked-list.py b/problems/python/convert-binary-search-tree-to-sorted-doubly-linked-list.py old mode 100644 new mode 100755 diff --git a/problems/python/convert-sorted-array-to-binary-search-tree.py b/problems/python/convert-sorted-array-to-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/convert-sorted-list-to-binary-search-tree.py b/problems/python/convert-sorted-list-to-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/copy-list-with-random-pointer.py b/problems/python/copy-list-with-random-pointer.py old mode 100644 new mode 100755 diff --git a/problems/python/count-all-valid-pickup-and-delivery-opti.py b/problems/python/count-all-valid-pickup-and-delivery-opti.py old mode 100644 new mode 100755 diff --git a/problems/python/count-binary-substrings.py b/problems/python/count-binary-substrings.py old mode 100644 new mode 100755 diff --git a/problems/python/count-complete-tree-nodes.py b/problems/python/count-complete-tree-nodes.py old mode 100644 new mode 100755 diff --git a/problems/python/count-number-of-nice-subarrays.py b/problems/python/count-number-of-nice-subarrays.py old mode 100644 new mode 100755 diff --git a/problems/python/count-unique-characters-of-all-substrings-of-a-given-string.py b/problems/python/count-unique-characters-of-all-substrings-of-a-given-string.py old mode 100644 new mode 100755 diff --git a/problems/python/course-schedule-ii.py b/problems/python/course-schedule-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/course-schedule.py b/problems/python/course-schedule.py old mode 100644 new mode 100755 diff --git a/problems/python/custom-sort-string.py b/problems/python/custom-sort-string.py old mode 100644 new mode 100755 diff --git a/problems/python/cutting-ribbons.py b/problems/python/cutting-ribbons.py old mode 100644 new mode 100755 diff --git a/problems/python/data-stream-as-disjoint-intervals.py b/problems/python/data-stream-as-disjoint-intervals.py old mode 100644 new mode 100755 diff --git a/problems/python/decode-string.py b/problems/python/decode-string.py old mode 100644 new mode 100755 diff --git a/problems/python/decode-ways.py b/problems/python/decode-ways.py old mode 100644 new mode 100755 diff --git a/problems/python/delete-and-earn.py b/problems/python/delete-and-earn.py old mode 100644 new mode 100755 diff --git a/problems/python/delete-duplicate-folders-in-system.py b/problems/python/delete-duplicate-folders-in-system.py old mode 100644 new mode 100755 diff --git a/problems/python/delete-node-in-a-bst.py b/problems/python/delete-node-in-a-bst.py old mode 100644 new mode 100755 diff --git a/problems/python/delete-operation-for-two-strings.py b/problems/python/delete-operation-for-two-strings.py old mode 100644 new mode 100755 diff --git a/problems/python/design-add-and-search-words-data-structure.py b/problems/python/design-add-and-search-words-data-structure.py old mode 100644 new mode 100755 diff --git a/problems/python/design-in-memory-file-system.py b/problems/python/design-in-memory-file-system.py old mode 100644 new mode 100755 diff --git a/problems/python/design-linked-list.py b/problems/python/design-linked-list.py old mode 100644 new mode 100755 diff --git a/problems/python/design-tic-tac-toe.py b/problems/python/design-tic-tac-toe.py old mode 100644 new mode 100755 diff --git a/problems/python/diagonal-traverse.py b/problems/python/diagonal-traverse.py old mode 100644 new mode 100755 diff --git a/problems/python/diameter-of-binary-tree.py b/problems/python/diameter-of-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/different-ways-to-add-parentheses.py b/problems/python/different-ways-to-add-parentheses.py old mode 100644 new mode 100755 diff --git a/problems/python/distinct-subsequences.py b/problems/python/distinct-subsequences.py old mode 100644 new mode 100755 diff --git a/problems/python/distribute-coins-in-binary-tree.py b/problems/python/distribute-coins-in-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/domino-and-tromino-tiling.py b/problems/python/domino-and-tromino-tiling.py old mode 100644 new mode 100755 diff --git a/problems/python/dot-product-of-two-sparse-vectors.py b/problems/python/dot-product-of-two-sparse-vectors.py old mode 100644 new mode 100755 diff --git a/problems/python/dungeon-game.py b/problems/python/dungeon-game.py old mode 100644 new mode 100755 diff --git a/problems/python/edit-distance.py b/problems/python/edit-distance.py old mode 100644 new mode 100755 diff --git a/problems/python/egions-cut-by-slashes.py b/problems/python/egions-cut-by-slashes.py old mode 100644 new mode 100755 diff --git a/problems/python/evaluate-division.py b/problems/python/evaluate-division.py old mode 100644 new mode 100755 diff --git a/problems/python/evaluate-reverse-polish-notation.py b/problems/python/evaluate-reverse-polish-notation.py old mode 100644 new mode 100755 diff --git a/problems/python/exclusive-time-of-functions.py b/problems/python/exclusive-time-of-functions.py old mode 100644 new mode 100755 diff --git a/problems/python/expression-add-operators.py b/problems/python/expression-add-operators.py old mode 100644 new mode 100755 diff --git a/problems/python/filling-bookcase-shelves.py b/problems/python/filling-bookcase-shelves.py old mode 100644 new mode 100755 diff --git a/problems/python/find-all-possible-recipes-from-given-supplies.py b/problems/python/find-all-possible-recipes-from-given-supplies.py old mode 100644 new mode 100755 diff --git a/problems/python/find-and-replace-in-string.py b/problems/python/find-and-replace-in-string.py old mode 100644 new mode 100755 diff --git a/problems/python/find-distance-in-a-binary-tree.py b/problems/python/find-distance-in-a-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/find-duplicate-subtrees.py b/problems/python/find-duplicate-subtrees.py old mode 100644 new mode 100755 diff --git a/problems/python/find-eventual-safe-states.py b/problems/python/find-eventual-safe-states.py old mode 100644 new mode 100755 diff --git a/problems/python/find-first-and-last-position-of-element-in-sorted-array.py b/problems/python/find-first-and-last-position-of-element-in-sorted-array.py old mode 100644 new mode 100755 diff --git a/problems/python/find-k-closest-elements.py b/problems/python/find-k-closest-elements.py old mode 100644 new mode 100755 diff --git a/problems/python/find-k-pairs-with-smallest-sums.py b/problems/python/find-k-pairs-with-smallest-sums.py old mode 100644 new mode 100755 diff --git a/problems/python/find-leaves-of-binary-tree.py b/problems/python/find-leaves-of-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/find-median-from-data-stream.py b/problems/python/find-median-from-data-stream.py old mode 100644 new mode 100755 diff --git a/problems/python/find-minimum-in-rotated-sorted-array-ii.py b/problems/python/find-minimum-in-rotated-sorted-array-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/find-minimum-in-rotated-sorted-array.py b/problems/python/find-minimum-in-rotated-sorted-array.py old mode 100644 new mode 100755 diff --git a/problems/python/find-mode-in-binary-search-tree.py b/problems/python/find-mode-in-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/find-original-array-from-doubled-array,py b/problems/python/find-original-array-from-doubled-array,py old mode 100644 new mode 100755 diff --git a/problems/python/find-peak-element.py b/problems/python/find-peak-element.py old mode 100644 new mode 100755 diff --git a/problems/python/find-the-duplicate-number.py b/problems/python/find-the-duplicate-number.py old mode 100644 new mode 100755 diff --git a/problems/python/first-bad-version.py b/problems/python/first-bad-version.py old mode 100644 new mode 100755 diff --git a/problems/python/first-missing-positive.py b/problems/python/first-missing-positive.py old mode 100644 new mode 100755 diff --git a/problems/python/first-unique-character-in-a-string.py b/problems/python/first-unique-character-in-a-string.py old mode 100644 new mode 100755 diff --git a/problems/python/fizz-buzz.py b/problems/python/fizz-buzz.py old mode 100644 new mode 100755 diff --git a/problems/python/flatten-binary-tree-to-linked-list.py b/problems/python/flatten-binary-tree-to-linked-list.py old mode 100644 new mode 100755 diff --git a/problems/python/flip-binary-tree-to-match-preorder-traversal.py b/problems/python/flip-binary-tree-to-match-preorder-traversal.py old mode 100644 new mode 100755 diff --git a/problems/python/flip-string-to-monotone-increasing.py b/problems/python/flip-string-to-monotone-increasing.py old mode 100644 new mode 100755 diff --git a/problems/python/flood-fill.py b/problems/python/flood-fill.py old mode 100644 new mode 100755 diff --git a/problems/python/friend-circles.py b/problems/python/friend-circles.py old mode 100644 new mode 100755 diff --git a/problems/python/fruit-into-baskets.py b/problems/python/fruit-into-baskets.py old mode 100644 new mode 100755 diff --git a/problems/python/game-of-life.py b/problems/python/game-of-life.py old mode 100644 new mode 100755 diff --git a/problems/python/generate-parentheses.py b/problems/python/generate-parentheses.py old mode 100644 new mode 100755 diff --git a/problems/python/graph-valid-tree.py b/problems/python/graph-valid-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/greatest-sum-divisible-by-three.py b/problems/python/greatest-sum-divisible-by-three.py old mode 100644 new mode 100755 diff --git a/problems/python/group-anagrams.py b/problems/python/group-anagrams.py old mode 100644 new mode 100755 diff --git a/problems/python/group-shifted-strings.py b/problems/python/group-shifted-strings.py old mode 100644 new mode 100755 diff --git a/problems/python/guess-number-higher-or-lower-ii.py b/problems/python/guess-number-higher-or-lower-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/guess-number-higher-or-lower.py b/problems/python/guess-number-higher-or-lower.py old mode 100644 new mode 100755 diff --git a/problems/python/guess-the-word.py b/problems/python/guess-the-word.py old mode 100644 new mode 100755 diff --git a/problems/python/h-index-ii.py b/problems/python/h-index-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/h-index.py b/problems/python/h-index.py old mode 100644 new mode 100755 diff --git a/problems/python/hamming-distance.py b/problems/python/hamming-distance.py old mode 100644 new mode 100755 diff --git a/problems/python/house-robber-ii.py b/problems/python/house-robber-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/house-robber-iii.py b/problems/python/house-robber-iii.py old mode 100644 new mode 100755 diff --git a/problems/python/house-robber.py b/problems/python/house-robber.py old mode 100644 new mode 100755 diff --git a/problems/python/implement-trie-prefix-tree.py b/problems/python/implement-trie-prefix-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/increasing-triplet-subsequence.py b/problems/python/increasing-triplet-subsequence.py old mode 100644 new mode 100755 diff --git a/problems/python/inorder-successor-in-bst-ii.py b/problems/python/inorder-successor-in-bst-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/inorder-successor-in-bst.py b/problems/python/inorder-successor-in-bst.py old mode 100644 new mode 100755 diff --git a/problems/python/insert-interval.py b/problems/python/insert-interval.py old mode 100644 new mode 100755 diff --git a/problems/python/insert-into-a-binary-search-tree.py b/problems/python/insert-into-a-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/insert-into-a-sorted-circular-linked-list.py b/problems/python/insert-into-a-sorted-circular-linked-list.py old mode 100644 new mode 100755 diff --git a/problems/python/insertion-sort-list.py b/problems/python/insertion-sort-list.py old mode 100644 new mode 100755 diff --git a/problems/python/integer-to-english-words.py b/problems/python/integer-to-english-words.py old mode 100644 new mode 100755 diff --git a/problems/python/interleaving-string.py b/problems/python/interleaving-string.py old mode 100644 new mode 100755 diff --git a/problems/python/intersection-of-two-arrays-ii.py b/problems/python/intersection-of-two-arrays-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/intersection-of-two-arrays.py b/problems/python/intersection-of-two-arrays.py old mode 100644 new mode 100755 diff --git a/problems/python/invert-binary-tree.py b/problems/python/invert-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/is-graph-bipartite.py b/problems/python/is-graph-bipartite.py old mode 100644 new mode 100755 diff --git a/problems/python/is-subsequence.py b/problems/python/is-subsequence.py old mode 100644 new mode 100755 diff --git a/problems/python/isomorphic-strings.py b/problems/python/isomorphic-strings.py old mode 100644 new mode 100755 diff --git a/problems/python/jewels-and-stones.py b/problems/python/jewels-and-stones.py old mode 100644 new mode 100755 diff --git a/problems/python/jump-game.py b/problems/python/jump-game.py old mode 100644 new mode 100755 diff --git a/problems/python/k-closest-points-to-origin.py b/problems/python/k-closest-points-to-origin.py old mode 100644 new mode 100755 diff --git a/problems/python/k-empty-slots.py b/problems/python/k-empty-slots.py old mode 100644 new mode 100755 diff --git a/problems/python/keys-and-rooms.py b/problems/python/keys-and-rooms.py old mode 100644 new mode 100755 diff --git a/problems/python/knight-dialer.py b/problems/python/knight-dialer.py old mode 100644 new mode 100755 diff --git a/problems/python/knight-probability-in-chessboard.py b/problems/python/knight-probability-in-chessboard.py old mode 100644 new mode 100755 diff --git a/problems/python/koko-eating-bananas.py b/problems/python/koko-eating-bananas.py old mode 100644 new mode 100755 diff --git a/problems/python/kth-largest-element-in-an-array.py b/problems/python/kth-largest-element-in-an-array.py old mode 100644 new mode 100755 diff --git a/problems/python/kth-smallest-element-in-a-bst.py b/problems/python/kth-smallest-element-in-a-bst.py old mode 100644 new mode 100755 diff --git a/problems/python/kth-smallest-element-in-a-sorted-matrix.py b/problems/python/kth-smallest-element-in-a-sorted-matrix.py old mode 100644 new mode 100755 diff --git a/problems/python/largest-1-bordered-square.py b/problems/python/largest-1-bordered-square.py old mode 100644 new mode 100755 diff --git a/problems/python/largest-bst-subtree.py b/problems/python/largest-bst-subtree.py old mode 100644 new mode 100755 diff --git a/problems/python/largest-sum-of-averages.py b/problems/python/largest-sum-of-averages.py old mode 100644 new mode 100755 diff --git a/problems/python/last-stone-weight-ii.py b/problems/python/last-stone-weight-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/last-stone-weight.py b/problems/python/last-stone-weight.py old mode 100644 new mode 100755 diff --git a/problems/python/least-number-of-unique-integers-after-k-removals.py b/problems/python/least-number-of-unique-integers-after-k-removals.py old mode 100644 new mode 100755 diff --git a/problems/python/letter-case-permutation.py b/problems/python/letter-case-permutation.py old mode 100644 new mode 100755 diff --git a/problems/python/letter-combinations-of-a-phone-number.py b/problems/python/letter-combinations-of-a-phone-number.py old mode 100644 new mode 100755 diff --git a/problems/python/license-key-formatting.py b/problems/python/license-key-formatting.py old mode 100644 new mode 100755 diff --git a/problems/python/linked-list-cycle-ii.py b/problems/python/linked-list-cycle-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/linked-list-cycle.py b/problems/python/linked-list-cycle.py old mode 100644 new mode 100755 diff --git a/problems/python/linked-list-random-node.py b/problems/python/linked-list-random-node.py old mode 100644 new mode 100755 diff --git a/problems/python/logger-rate-limiter.py b/problems/python/logger-rate-limiter.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-common-prefix.py b/problems/python/longest-common-prefix.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-common-subsequence.py b/problems/python/longest-common-subsequence.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-consecutive-sequence.py b/problems/python/longest-consecutive-sequence.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-increasing-path-in-a-matrix.py b/problems/python/longest-increasing-path-in-a-matrix.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-increasing-subsequence.py b/problems/python/longest-increasing-subsequence.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-palindromic-subsequence.py b/problems/python/longest-palindromic-subsequence.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-palindromic-substring.py b/problems/python/longest-palindromic-substring.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-repeating-character-replacement.py b/problems/python/longest-repeating-character-replacement.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-string-chain.py b/problems/python/longest-string-chain.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-substring-with-at-least-k-repeating-characters.py b/problems/python/longest-substring-with-at-least-k-repeating-characters.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-substring-without-repeating-characters.py b/problems/python/longest-substring-without-repeating-characters.py old mode 100644 new mode 100755 diff --git a/problems/python/longest-univalue-path.py b/problems/python/longest-univalue-path.py old mode 100644 new mode 100755 diff --git a/problems/python/lowest-common-ancestor-of-a-binary-search-tree.py b/problems/python/lowest-common-ancestor-of-a-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/lowest-common-ancestor-of-a-binary-search.py b/problems/python/lowest-common-ancestor-of-a-binary-search.py old mode 100644 new mode 100755 diff --git a/problems/python/lowest-common-ancestor-of-a-binary-tree-ii.py b/problems/python/lowest-common-ancestor-of-a-binary-tree-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/lowest-common-ancestor-of-a-binary-tree-iii.py b/problems/python/lowest-common-ancestor-of-a-binary-tree-iii.py old mode 100644 new mode 100755 diff --git a/problems/python/lowest-common-ancestor-of-a-binary-tree-iv.py b/problems/python/lowest-common-ancestor-of-a-binary-tree-iv.py old mode 100644 new mode 100755 diff --git a/problems/python/lowest-common-ancestor-of-a-binary-tree.py b/problems/python/lowest-common-ancestor-of-a-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/lowest-common-ancestor-of-deepest-leaves.py b/problems/python/lowest-common-ancestor-of-deepest-leaves.py old mode 100644 new mode 100755 diff --git a/problems/python/lru-cache.py b/problems/python/lru-cache.py old mode 100644 new mode 100755 diff --git a/problems/python/majority-element-ii.py b/problems/python/majority-element-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/majority-element.py b/problems/python/majority-element.py old mode 100644 new mode 100755 diff --git a/problems/python/making-a-large-island.py b/problems/python/making-a-large-island.py old mode 100644 new mode 100755 diff --git a/problems/python/max-area-of-island.py b/problems/python/max-area-of-island.py old mode 100644 new mode 100755 diff --git a/problems/python/max-consecutive-ones-iii.py b/problems/python/max-consecutive-ones-iii.py old mode 100644 new mode 100755 diff --git a/problems/python/max-stack.py b/problems/python/max-stack.py old mode 100644 new mode 100755 diff --git a/problems/python/max-sum-of-rectangle-no-larger-than-k.py b/problems/python/max-sum-of-rectangle-no-larger-than-k.py old mode 100644 new mode 100755 diff --git a/problems/python/maximal-square.py b/problems/python/maximal-square.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-average-subtree.py b/problems/python/maximum-average-subtree.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-compatibility-score-sum.py b/problems/python/maximum-compatibility-score-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-depth-of-binary-tree.py b/problems/python/maximum-depth-of-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-gap.py b/problems/python/maximum-gap.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-length-of-repeated-subarray.py b/problems/python/maximum-length-of-repeated-subarray.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-number-of-events-that-can-be-attended.py b/problems/python/maximum-number-of-events-that-can-be-attended.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-number-of-points-with-cost.py b/problems/python/maximum-number-of-points-with-cost.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-number-of-visible-points.py b/problems/python/maximum-number-of-visible-points.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-product-of-three-numbers.py b/problems/python/maximum-product-of-three-numbers.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-product-subarray.py b/problems/python/maximum-product-subarray.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-subarray-sum-with-one-deletion.py b/problems/python/maximum-subarray-sum-with-one-deletion.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-subarray.py b/problems/python/maximum-subarray.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-swap.py b/problems/python/maximum-swap.py old mode 100644 new mode 100755 diff --git a/problems/python/maximum-units-on-a-truck.py b/problems/python/maximum-units-on-a-truck.py old mode 100644 new mode 100755 diff --git a/problems/python/median-of-two-sorted-arrays.py b/problems/python/median-of-two-sorted-arrays.py old mode 100644 new mode 100755 diff --git a/problems/python/meeting-rooms-ii.py b/problems/python/meeting-rooms-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/meeting-rooms.py b/problems/python/meeting-rooms.py old mode 100644 new mode 100755 diff --git a/problems/python/merge-intervals.py b/problems/python/merge-intervals.py old mode 100644 new mode 100755 diff --git a/problems/python/merge-k-sorted-lists.py b/problems/python/merge-k-sorted-lists.py old mode 100644 new mode 100755 diff --git a/problems/python/merge-sorted-array.py b/problems/python/merge-sorted-array.py old mode 100644 new mode 100755 diff --git a/problems/python/merge-two-sorted-lists.py b/problems/python/merge-two-sorted-lists.py old mode 100644 new mode 100755 diff --git a/problems/python/min-cost-climbing-stairs.py b/problems/python/min-cost-climbing-stairs.py old mode 100644 new mode 100755 diff --git a/problems/python/min-stack.py b/problems/python/min-stack.py old mode 100644 new mode 100755 diff --git a/problems/python/minimize-malware-spread.py b/problems/python/minimize-malware-spread.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-absolute-difference-in-bst.py b/problems/python/minimum-absolute-difference-in-bst.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-ascii-delete-sum-for-two-strings.py b/problems/python/minimum-ascii-delete-sum-for-two-strings.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-cost-to-connect-sticks.py b/problems/python/minimum-cost-to-connect-sticks.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-cost-to-hire-k-workers.py b/problems/python/minimum-cost-to-hire-k-workers.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py b/problems/python/minimum-cost-to-make-at-least-one-valid-path-in-a-grid.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-cost-to-reach-city-with-discounts.py b/problems/python/minimum-cost-to-reach-city-with-discounts.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-depth-of-binary-tree.py b/problems/python/minimum-depth-of-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-difficulty-of-a-job-schedule.py b/problems/python/minimum-difficulty-of-a-job-schedule.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-falling-path-sum-ii.py b/problems/python/minimum-falling-path-sum-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-knight-moves.py b/problems/python/minimum-knight-moves.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py b/problems/python/minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-path-sum.py b/problems/python/minimum-path-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-score-triangulation-of-polygon.py b/problems/python/minimum-score-triangulation-of-polygon.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-size-subarray-sum.py b/problems/python/minimum-size-subarray-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-swaps-to-group-all-1s-together.py b/problems/python/minimum-swaps-to-group-all-1s-together.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-swaps-to-make-sequences-increasing.py b/problems/python/minimum-swaps-to-make-sequences-increasing.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-time-difference.py b/problems/python/minimum-time-difference.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-window-substring.py b/problems/python/minimum-window-substring.py old mode 100644 new mode 100755 diff --git a/problems/python/minimum-xor-sum-of-two-arrays.py b/problems/python/minimum-xor-sum-of-two-arrays.py old mode 100644 new mode 100755 diff --git a/problems/python/missing-number.py b/problems/python/missing-number.py old mode 100644 new mode 100755 diff --git a/problems/python/most-frequent-subtree-sum.py b/problems/python/most-frequent-subtree-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/most-stones-removed-with-same-row-or-column.py b/problems/python/most-stones-removed-with-same-row-or-column.py old mode 100644 new mode 100755 diff --git a/problems/python/move-zeroes.py b/problems/python/move-zeroes.py old mode 100644 new mode 100755 diff --git a/problems/python/moving-average-from-data-stream.py b/problems/python/moving-average-from-data-stream.py old mode 100644 new mode 100755 diff --git a/problems/python/my-calendar-ii.py b/problems/python/my-calendar-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/n-ary-tree-level-order-traversal.py b/problems/python/n-ary-tree-level-order-traversal.py old mode 100644 new mode 100755 diff --git a/problems/python/n-ary-tree-postorder-traversal.py b/problems/python/n-ary-tree-postorder-traversal.py old mode 100644 new mode 100755 diff --git a/problems/python/n-ary-tree-preorder-traversal.py b/problems/python/n-ary-tree-preorder-traversal.py old mode 100644 new mode 100755 diff --git a/problems/python/nested-list-weight-sum.py b/problems/python/nested-list-weight-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/network-delay-time.py b/problems/python/network-delay-time.py old mode 100644 new mode 100755 diff --git a/problems/python/next-closest-time.py b/problems/python/next-closest-time.py old mode 100644 new mode 100755 diff --git a/problems/python/next-permutation.py b/problems/python/next-permutation.py old mode 100644 new mode 100755 diff --git a/problems/python/number-complement.py b/problems/python/number-complement.py old mode 100644 new mode 100755 diff --git a/problems/python/number-of-connected-components-in-an-undirected-graph.py b/problems/python/number-of-connected-components-in-an-undirected-graph.py old mode 100644 new mode 100755 diff --git a/problems/python/number-of-islands-ii.py b/problems/python/number-of-islands-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/number-of-islands.py b/problems/python/number-of-islands.py old mode 100644 new mode 100755 diff --git a/problems/python/number-of-longest-increasing-subsequence.py b/problems/python/number-of-longest-increasing-subsequence.py old mode 100644 new mode 100755 diff --git a/problems/python/number-of-matching-subsequences.py b/problems/python/number-of-matching-subsequences.py old mode 100644 new mode 100755 diff --git a/problems/python/number-of-provinces.py b/problems/python/number-of-provinces.py old mode 100644 new mode 100755 diff --git a/problems/python/number-of-recent-calls.py b/problems/python/number-of-recent-calls.py old mode 100644 new mode 100755 diff --git a/problems/python/number-of-squareful-arrays.py b/problems/python/number-of-squareful-arrays.py old mode 100644 new mode 100755 diff --git a/problems/python/number-of-substrings-containing-all-thre.py b/problems/python/number-of-substrings-containing-all-thre.py old mode 100644 new mode 100755 diff --git a/problems/python/number-of-ways-to-arrive-at-destination.py b/problems/python/number-of-ways-to-arrive-at-destination.py old mode 100644 new mode 100755 diff --git a/problems/python/odd-even-jump.py b/problems/python/odd-even-jump.py old mode 100644 new mode 100755 diff --git a/problems/python/ones-and-zeroes.py b/problems/python/ones-and-zeroes.py old mode 100644 new mode 100755 diff --git a/problems/python/open-the-lock.py b/problems/python/open-the-lock.py old mode 100644 new mode 100755 diff --git a/problems/python/out-of-boundary-paths.py b/problems/python/out-of-boundary-paths.py old mode 100644 new mode 100755 diff --git a/problems/python/pacific-atlantic-water-flow.py b/problems/python/pacific-atlantic-water-flow.py old mode 100644 new mode 100755 diff --git a/problems/python/pairs-of-songs-with-total-durations-divisible-by-60.py b/problems/python/pairs-of-songs-with-total-durations-divisible-by-60.py old mode 100644 new mode 100755 diff --git a/problems/python/palindrome-number.py b/problems/python/palindrome-number.py old mode 100644 new mode 100755 diff --git a/problems/python/palindrome-pairs.py b/problems/python/palindrome-pairs.py old mode 100644 new mode 100755 diff --git a/problems/python/palindrome-partitioning-iii.py b/problems/python/palindrome-partitioning-iii.py old mode 100644 new mode 100755 diff --git a/problems/python/palindrome-partitioning.py b/problems/python/palindrome-partitioning.py old mode 100644 new mode 100755 diff --git a/problems/python/palindromic-substrings.py b/problems/python/palindromic-substrings.py old mode 100644 new mode 100755 diff --git a/problems/python/partition-array-for-maximum-sum.py b/problems/python/partition-array-for-maximum-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/partition-labels.py b/problems/python/partition-labels.py old mode 100644 new mode 100755 diff --git a/problems/python/partition-to-k-equal-sum-subsets.py b/problems/python/partition-to-k-equal-sum-subsets.py old mode 100644 new mode 100755 diff --git a/problems/python/path-sum-ii.py b/problems/python/path-sum-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/path-sum-iii.py b/problems/python/path-sum-iii.py old mode 100644 new mode 100755 diff --git a/problems/python/path-sum.py b/problems/python/path-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/path-with-maximum-probability.py b/problems/python/path-with-maximum-probability.py old mode 100644 new mode 100755 diff --git a/problems/python/peak-index-in-a-mountain-array.py b/problems/python/peak-index-in-a-mountain-array.py old mode 100644 new mode 100755 diff --git a/problems/python/perfect-squares.py b/problems/python/perfect-squares.py old mode 100644 new mode 100755 diff --git a/problems/python/permutation-in-string.py b/problems/python/permutation-in-string.py old mode 100644 new mode 100755 diff --git a/problems/python/permutation-sequence.py b/problems/python/permutation-sequence.py old mode 100644 new mode 100755 diff --git a/problems/python/permutations-ii.py b/problems/python/permutations-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/permutations.py b/problems/python/permutations.py old mode 100644 new mode 100755 diff --git a/problems/python/populating-next-right-pointers-in-each-node-ii.py b/problems/python/populating-next-right-pointers-in-each-node-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/populating-next-right-pointers-in-each-node.py b/problems/python/populating-next-right-pointers-in-each-node.py old mode 100644 new mode 100755 diff --git a/problems/python/powx-n.py b/problems/python/powx-n.py old mode 100644 new mode 100755 diff --git a/problems/python/product-of-array-except-self.py b/problems/python/product-of-array-except-self.py old mode 100644 new mode 100755 diff --git a/problems/python/profitable-schemes.py b/problems/python/profitable-schemes.py old mode 100644 new mode 100755 diff --git a/problems/python/queue-reconstruction-by-height.py b/problems/python/queue-reconstruction-by-height.py old mode 100644 new mode 100755 diff --git a/problems/python/random-pick-with-weight.py b/problems/python/random-pick-with-weight.py old mode 100644 new mode 100755 diff --git a/problems/python/range-addition.py b/problems/python/range-addition.py old mode 100644 new mode 100755 diff --git a/problems/python/range-sum-of-bst.py b/problems/python/range-sum-of-bst.py old mode 100644 new mode 100755 diff --git a/problems/python/range-sum-query-immutable.py b/problems/python/range-sum-query-immutable.py old mode 100644 new mode 100755 diff --git a/problems/python/range-sum-query-mutable.py b/problems/python/range-sum-query-mutable.py old mode 100644 new mode 100755 diff --git a/problems/python/rearrange-string-k-distance-apart.py b/problems/python/rearrange-string-k-distance-apart.py old mode 100644 new mode 100755 diff --git a/problems/python/reconstruct-itinerary.py b/problems/python/reconstruct-itinerary.py old mode 100644 new mode 100755 diff --git a/problems/python/recover-binary-search-tree.py b/problems/python/recover-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/redundant-connection.py b/problems/python/redundant-connection.py old mode 100644 new mode 100755 diff --git a/problems/python/remove-all-adjacent-duplicates-in-string.py b/problems/python/remove-all-adjacent-duplicates-in-string.py old mode 100644 new mode 100755 diff --git a/problems/python/remove-all-ones-with-row-and-column-flips.py b/problems/python/remove-all-ones-with-row-and-column-flips.py old mode 100644 new mode 100755 diff --git a/problems/python/remove-duplicates-from-sorted-array-ii.py b/problems/python/remove-duplicates-from-sorted-array-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/remove-duplicates-from-sorted-array.py b/problems/python/remove-duplicates-from-sorted-array.py old mode 100644 new mode 100755 diff --git a/problems/python/remove-duplicates-from-sorted-list.py b/problems/python/remove-duplicates-from-sorted-list.py old mode 100644 new mode 100755 diff --git a/problems/python/remove-element.py b/problems/python/remove-element.py old mode 100644 new mode 100755 diff --git a/problems/python/remove-invalid-parentheses.py b/problems/python/remove-invalid-parentheses.py old mode 100644 new mode 100755 diff --git a/problems/python/remove-linked-list-elements.py b/problems/python/remove-linked-list-elements.py old mode 100644 new mode 100755 diff --git a/problems/python/remove-nth-node-from-end-of-list.py b/problems/python/remove-nth-node-from-end-of-list.py old mode 100644 new mode 100755 diff --git a/problems/python/reorder-list.py b/problems/python/reorder-list.py old mode 100644 new mode 100755 diff --git a/problems/python/repeated-string-match.py b/problems/python/repeated-string-match.py old mode 100644 new mode 100755 diff --git a/problems/python/replace-the-substring-for-balanced-string.py b/problems/python/replace-the-substring-for-balanced-string.py old mode 100644 new mode 100755 diff --git a/problems/python/restore-ip-addresses.py b/problems/python/restore-ip-addresses.py old mode 100644 new mode 100755 diff --git a/problems/python/reverse-integer.py b/problems/python/reverse-integer.py old mode 100644 new mode 100755 diff --git a/problems/python/reverse-linked-list.py b/problems/python/reverse-linked-list.py old mode 100644 new mode 100755 diff --git a/problems/python/reverse-string.py b/problems/python/reverse-string.py old mode 100644 new mode 100755 diff --git a/problems/python/reverse-vowels-of-a-string.py b/problems/python/reverse-vowels-of-a-string.py old mode 100644 new mode 100755 diff --git a/problems/python/reverse-words-in-a-string.py b/problems/python/reverse-words-in-a-string.py old mode 100644 new mode 100755 diff --git a/problems/python/robot-bounded-in-circle.py b/problems/python/robot-bounded-in-circle.py old mode 100644 new mode 100755 diff --git a/problems/python/roman-to-integer.py b/problems/python/roman-to-integer.py old mode 100644 new mode 100755 diff --git a/problems/python/rotate-array.py b/problems/python/rotate-array.py old mode 100644 new mode 100755 diff --git a/problems/python/rotate-image.py b/problems/python/rotate-image.py old mode 100644 new mode 100755 diff --git a/problems/python/russian-doll-envelopes.py b/problems/python/russian-doll-envelopes.py old mode 100644 new mode 100755 diff --git a/problems/python/same-tree.py b/problems/python/same-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/satisfiability-of-equality-equations.py b/problems/python/satisfiability-of-equality-equations.py old mode 100644 new mode 100755 diff --git a/problems/python/score-of-parentheses.py b/problems/python/score-of-parentheses.py old mode 100644 new mode 100755 diff --git a/problems/python/search-a-2d-matrix.py b/problems/python/search-a-2d-matrix.py old mode 100644 new mode 100755 diff --git a/problems/python/search-in-a-binary-search-tree.py b/problems/python/search-in-a-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/search-in-rotated-sorted-array-ii.py b/problems/python/search-in-rotated-sorted-array-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/search-in-rotated-sorted-array.py b/problems/python/search-in-rotated-sorted-array.py old mode 100644 new mode 100755 diff --git a/problems/python/search-insert-position.py b/problems/python/search-insert-position.py old mode 100644 new mode 100755 diff --git a/problems/python/search-suggestions-system.py b/problems/python/search-suggestions-system.py old mode 100644 new mode 100755 diff --git a/problems/python/second-highest-salary.sql b/problems/python/second-highest-salary.sql old mode 100644 new mode 100755 diff --git a/problems/python/sell-diminishing-valued-colored-balls.py b/problems/python/sell-diminishing-valued-colored-balls.py old mode 100644 new mode 100755 diff --git a/problems/python/serialize-and-deserialize-binary-tree.py b/problems/python/serialize-and-deserialize-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/serialize-and-deserialize-bst.py b/problems/python/serialize-and-deserialize-bst.py old mode 100644 new mode 100755 diff --git a/problems/python/set-matrix-zeroes.py b/problems/python/set-matrix-zeroes.py old mode 100644 new mode 100755 diff --git a/problems/python/shortest-bridge.py b/problems/python/shortest-bridge.py old mode 100644 new mode 100755 diff --git a/problems/python/shortest-common-supersequence.py b/problems/python/shortest-common-supersequence.py old mode 100644 new mode 100755 diff --git a/problems/python/shortest-distance-from-all-buildings.py b/problems/python/shortest-distance-from-all-buildings.py old mode 100644 new mode 100755 diff --git a/problems/python/shortest-path-in-a-grid-with-obstacles-elimination.py b/problems/python/shortest-path-in-a-grid-with-obstacles-elimination.py old mode 100644 new mode 100755 diff --git a/problems/python/shortest-path-in-binary-matrix.py b/problems/python/shortest-path-in-binary-matrix.py old mode 100644 new mode 100755 diff --git a/problems/python/shortest-path-to-get-food.py b/problems/python/shortest-path-to-get-food.py old mode 100644 new mode 100755 diff --git a/problems/python/shuffle-an-array.py b/problems/python/shuffle-an-array.py old mode 100644 new mode 100755 diff --git a/problems/python/simplify-path.py b/problems/python/simplify-path.py old mode 100644 new mode 100755 diff --git a/problems/python/single-threaded-cpu.py b/problems/python/single-threaded-cpu.py old mode 100644 new mode 100755 diff --git a/problems/python/sliding-window-maximum.py b/problems/python/sliding-window-maximum.py old mode 100644 new mode 100755 diff --git a/problems/python/snapshot-array.py b/problems/python/snapshot-array.py old mode 100644 new mode 100755 diff --git a/problems/python/sort-colors.py b/problems/python/sort-colors.py old mode 100644 new mode 100755 diff --git a/problems/python/sort-list.py b/problems/python/sort-list.py old mode 100644 new mode 100755 diff --git a/problems/python/spiral-matrix.py b/problems/python/spiral-matrix.py old mode 100644 new mode 100755 diff --git a/problems/python/split-array-into-fibonacci-sequence.py b/problems/python/split-array-into-fibonacci-sequence.py old mode 100644 new mode 100755 diff --git a/problems/python/split-array-largest-sum.py b/problems/python/split-array-largest-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/sqrtx.py b/problems/python/sqrtx.py old mode 100644 new mode 100755 diff --git a/problems/python/squares-of-a-sorted-array.py b/problems/python/squares-of-a-sorted-array.py old mode 100644 new mode 100755 diff --git a/problems/python/step-by-step-directions-from-a-binary-tree-node-to-another.py b/problems/python/step-by-step-directions-from-a-binary-tree-node-to-another.py old mode 100644 new mode 100755 diff --git a/problems/python/stock-price-fluctuation.py b/problems/python/stock-price-fluctuation.py old mode 100644 new mode 100755 diff --git a/problems/python/stone-game-ii.py b/problems/python/stone-game-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/student-attendance-record-ii.py b/problems/python/student-attendance-record-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/subarray-sum-equals-k.py b/problems/python/subarray-sum-equals-k.py old mode 100644 new mode 100755 diff --git a/problems/python/subarrays-with-k-different-integers.py b/problems/python/subarrays-with-k-different-integers.py old mode 100644 new mode 100755 diff --git a/problems/python/subdomain-visit-count.py b/problems/python/subdomain-visit-count.py old mode 100644 new mode 100755 diff --git a/problems/python/subsets-ii.py b/problems/python/subsets-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/subsets.py b/problems/python/subsets.py old mode 100644 new mode 100755 diff --git a/problems/python/substring-with-concatenation-of-all-words.py b/problems/python/substring-with-concatenation-of-all-words.py old mode 100644 new mode 100755 diff --git a/problems/python/subtree-of-another-tree.py b/problems/python/subtree-of-another-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/sum-of-subarray-minimums.py b/problems/python/sum-of-subarray-minimums.py old mode 100644 new mode 100755 diff --git a/problems/python/sum-root-to-leaf-numbers.py b/problems/python/sum-root-to-leaf-numbers.py old mode 100644 new mode 100755 diff --git a/problems/python/summary-ranges.py b/problems/python/summary-ranges.py old mode 100644 new mode 100755 diff --git a/problems/python/super-ugly-number.py b/problems/python/super-ugly-number.py old mode 100644 new mode 100755 diff --git a/problems/python/swap-adjacent-in-lr-string.py b/problems/python/swap-adjacent-in-lr-string.py old mode 100644 new mode 100755 diff --git a/problems/python/swap-nodes-in-pairs.py b/problems/python/swap-nodes-in-pairs.py old mode 100644 new mode 100755 diff --git a/problems/python/swim-in-rising-water.py b/problems/python/swim-in-rising-water.py old mode 100644 new mode 100755 diff --git a/problems/python/symmetric-tree.py b/problems/python/symmetric-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/tallest-billboard.py b/problems/python/tallest-billboard.py old mode 100644 new mode 100755 diff --git a/problems/python/target-sum.py b/problems/python/target-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/task-scheduler.py b/problems/python/task-scheduler.py old mode 100644 new mode 100755 diff --git a/problems/python/text-justification.py b/problems/python/text-justification.py old mode 100644 new mode 100755 diff --git a/problems/python/the-kth-factor-of-n.py b/problems/python/the-kth-factor-of-n.py old mode 100644 new mode 100755 diff --git a/problems/python/the-maze-ii.py b/problems/python/the-maze-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/time-based-key-value-store.py b/problems/python/time-based-key-value-store.py old mode 100644 new mode 100755 diff --git a/problems/python/to-lower-case.py b/problems/python/to-lower-case.py old mode 100644 new mode 100755 diff --git a/problems/python/toeplitz-matrix.py b/problems/python/toeplitz-matrix.py old mode 100644 new mode 100755 diff --git a/problems/python/top-k-frequent-elements.py b/problems/python/top-k-frequent-elements.py old mode 100644 new mode 100755 diff --git a/problems/python/trapping-rain-water-ii.py b/problems/python/trapping-rain-water-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/trapping-rain-water.py b/problems/python/trapping-rain-water.py old mode 100644 new mode 100755 diff --git a/problems/python/trim-a-binary-search-tree.py b/problems/python/trim-a-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/two-out-of-three.py b/problems/python/two-out-of-three.py old mode 100644 new mode 100755 diff --git a/problems/python/two-sum-ii-input-array-is-sorted.py b/problems/python/two-sum-ii-input-array-is-sorted.py old mode 100644 new mode 100755 diff --git a/problems/python/two-sum.py b/problems/python/two-sum.py old mode 100644 new mode 100755 diff --git a/problems/python/ugly-number-ii.py b/problems/python/ugly-number-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/ugly-number.py b/problems/python/ugly-number.py old mode 100644 new mode 100755 diff --git a/problems/python/umber-of-islands-ii.py b/problems/python/umber-of-islands-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/unique-binary-search-trees-ii,py b/problems/python/unique-binary-search-trees-ii,py old mode 100644 new mode 100755 diff --git a/problems/python/unique-binary-search-trees.py b/problems/python/unique-binary-search-trees.py old mode 100644 new mode 100755 diff --git a/problems/python/unique-email-addres.py b/problems/python/unique-email-addres.py old mode 100644 new mode 100755 diff --git a/problems/python/unique-paths.py b/problems/python/unique-paths.py old mode 100644 new mode 100755 diff --git a/problems/python/univalued-binary-tree.py b/problems/python/univalued-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/valid-anagram.py b/problems/python/valid-anagram.py old mode 100644 new mode 100755 diff --git a/problems/python/valid-number.py b/problems/python/valid-number.py old mode 100644 new mode 100755 diff --git a/problems/python/valid-palindrome-ii.py b/problems/python/valid-palindrome-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/valid-palindrome.py b/problems/python/valid-palindrome.py old mode 100644 new mode 100755 diff --git a/problems/python/valid-parentheses.py b/problems/python/valid-parentheses.py old mode 100644 new mode 100755 diff --git a/problems/python/valid-word-abbreviation.py b/problems/python/valid-word-abbreviation.py old mode 100644 new mode 100755 diff --git a/problems/python/validate-binary-search-tree.py b/problems/python/validate-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/verify-preorder-serialization-of-a-binary-tree.py b/problems/python/verify-preorder-serialization-of-a-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/vertical-order-traversal-of-a-binary-tree.py b/problems/python/vertical-order-traversal-of-a-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python/wiggle-subsequence.py b/problems/python/wiggle-subsequence.py old mode 100644 new mode 100755 diff --git a/problems/python/word-break.py b/problems/python/word-break.py old mode 100644 new mode 100755 diff --git a/problems/python/word-ladder-ii.py b/problems/python/word-ladder-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/word-ladder.py b/problems/python/word-ladder.py old mode 100644 new mode 100755 diff --git a/problems/python/word-search-ii.py b/problems/python/word-search-ii.py old mode 100644 new mode 100755 diff --git a/problems/python/word-search.py b/problems/python/word-search.py old mode 100644 new mode 100755 diff --git a/problems/python3/3sum-closest.py b/problems/python3/3sum-closest.py old mode 100644 new mode 100755 diff --git a/problems/python3/3sum-smaller.py b/problems/python3/3sum-smaller.py old mode 100644 new mode 100755 diff --git a/problems/python3/3sum.py b/problems/python3/3sum.py old mode 100644 new mode 100755 index 0a92eb9..97f3388 --- a/problems/python3/3sum.py +++ b/problems/python3/3sum.py @@ -61,4 +61,32 @@ def threeSum(self, nums: List[int]) -> List[List[int]]: if v2 in needed: ans.add(tuple(sorted((v1, v2, -v1-v2)))) needed.add(-v1-v2) + return ans + + + +class Solution: + def threeSum(self, nums: List[int]) -> List[List[int]]: + ans = [] + + nums.sort() + + for i in range(len(nums)): + if nums[i]>0: break + if i>0 and nums[i]==nums[i-1]: continue + + j = i+1 + k = len(nums)-1 + while j0: + k -= 1 + elif nums[j]+nums[k]+nums[i]<0: + j += 1 + else: + ans.append((nums[i], nums[j], nums[k])) + + while j int: + def helper(node): + nonlocal ans + + if not node: return 0 + left = max(helper(node.left), 0) #[3] + right = max(helper(node.right), 0) #[3] + ans = max(ans, node.val+left+right) #[1] + return node.val+max(left, right) #[0] + + ans = float('-inf') + helper(root) + return ans \ No newline at end of file diff --git a/problems/python3/binary-tree-right-side-view.py b/problems/python3/binary-tree-right-side-view.py old mode 100644 new mode 100755 diff --git a/problems/python3/construct-binary-tree-from-preorder-and-inorder-traversal.py b/problems/python3/construct-binary-tree-from-preorder-and-inorder-traversal.py new file mode 100644 index 0000000..eb7f19c --- /dev/null +++ b/problems/python3/construct-binary-tree-from-preorder-and-inorder-traversal.py @@ -0,0 +1,34 @@ +""" +preorder: [root][left][right] +inorder: [left][root][right] + +[0] +As you can see, the root is always located at the first index of the preorder list. + +[2] +Using the same logic, we can recursively get the left and right node +Inorder to do that, we need to define left and right nodes' range. +And we can get the length of the left subtree by locating the index of the root in the in order list. [1] +i and j is the startIndex and the (endIndex+1) of the preorder list. +k and l is the startIndex and the (endIndex+1) of the inorder list. + +Time: O(N) +Space: O(N) +""" +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + def helper(i, j, k, l): + if i==j or k==l: return None + + root = TreeNode(preorder[i]) #[0] + + rootInorderIndex = getInorderIndex[root.val] #[1] + leftLen = rootInorderIndex-k + + root.left = helper(i+1, i+1+leftLen, k, k+leftLen) #[2] + root.right = helper(i+1+leftLen, j, rootInorderIndex+1, l) + return root + + getInorderIndex = {} + for i, v in enumerate(inorder): getInorderIndex[v] = i + return helper(0, len(preorder), 0, len(inorder)) \ No newline at end of file diff --git a/problems/python3/container-with-most-water.py b/problems/python3/container-with-most-water.py old mode 100644 new mode 100755 index c24f0c9..a560441 --- a/problems/python3/container-with-most-water.py +++ b/problems/python3/container-with-most-water.py @@ -18,6 +18,23 @@ def maxArea(self, height: List[int]) -> int: while iheight[j]: + j -= 1 + else: + i += 1 + return ans + + + +class Solution: + def maxArea(self, height: List[int]) -> int: + i = 0 + j = len(height)-1 + ans = 0 + + while iheight[j]: j -= 1 else: diff --git a/problems/python3/count-good-nodes-in-binary-tree.py b/problems/python3/count-good-nodes-in-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python3/diameter-of-binary-tree.py b/problems/python3/diameter-of-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python3/invert-binary-tree.py b/problems/python3/invert-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python3/kth-smallest-element-in-a-bst.py b/problems/python3/kth-smallest-element-in-a-bst.py new file mode 100755 index 0000000..c8a1555 --- /dev/null +++ b/problems/python3/kth-smallest-element-in-a-bst.py @@ -0,0 +1,21 @@ +""" +Time: O(N) for the inorder traversal +Space: O(LogN) if the tree is balanced. +""" +class Solution: + def kthSmallest(self, root: Optional[TreeNode], k: int) -> int: + count = 0 + stack = [] + node = root + + while stack or node: + while node: + stack.append(node) + node = node.left + node = stack.pop() + + count += 1 + if count==k: return node.val + + node = node.right + return 0 \ No newline at end of file diff --git a/problems/python3/lowest-common-ancestor-of-a-binary-search-tree.py b/problems/python3/lowest-common-ancestor-of-a-binary-search-tree.py old mode 100644 new mode 100755 diff --git a/problems/python3/maximum-depth-of-binary-tree.py b/problems/python3/maximum-depth-of-binary-tree.py old mode 100644 new mode 100755 diff --git a/problems/python3/same-tree.py b/problems/python3/same-tree.py old mode 100644 new mode 100755 diff --git a/problems/python3/serialize-and-deserialize-binary-tree.py b/problems/python3/serialize-and-deserialize-binary-tree.py new file mode 100644 index 0000000..1b057d0 --- /dev/null +++ b/problems/python3/serialize-and-deserialize-binary-tree.py @@ -0,0 +1,22 @@ +class Codec: + + def serialize(self, root): + if not root: return '#' + return str(root.val)+','+self.serialize(root.left)+','+self.serialize(root.right) + + + def deserialize(self, data): + def helper(): + if data[self.i]=='#': + self.i += 1 + return None + + node = TreeNode(int(data[self.i])) + self.i += 1 + node.left = helper() + node.right = helper() + return node + + data = data.split(",") + self.i = 0 + return helper() \ No newline at end of file diff --git a/problems/python3/subsets.py b/problems/python3/subsets.py new file mode 100644 index 0000000..9cfcc00 --- /dev/null +++ b/problems/python3/subsets.py @@ -0,0 +1,22 @@ +""" +Time: O(N * 2^N) +Space: O(N) for "subset". +""" +class Solution: + def subsets(self, nums: List[int]) -> List[List[int]]: + def helper(i): + if not i int: + ans = 0 + l = 0 + r = len(height)-1 + + leftMax = float('-inf') + rightMax = float('-inf') + + while l<=r: + if leftMax=leftMax: + leftMax = height[l] + else: + ans += leftMax-height[l] + l += 1 + else: + if height[r]>=rightMax: + rightMax = height[r] + else: + ans += rightMax-height[r] + r -= 1 + return ans \ No newline at end of file diff --git a/problems/python3/two-sum-ii-input-array-is-sorted.py b/problems/python3/two-sum-ii-input-array-is-sorted.py new file mode 100644 index 0000000..2890404 --- /dev/null +++ b/problems/python3/two-sum-ii-input-array-is-sorted.py @@ -0,0 +1,11 @@ +class Solution: + def twoSum(self, numbers: List[int], target: int) -> List[int]: + i = 0 + j = len(numbers)-1 + + while numbers[i]+numbers[j] != target: + if numbers[i]+numbers[j] > target: + j -= 1 + else: + i += 1 + return (i+1, j+1) \ No newline at end of file diff --git a/problems/python3/valid-palindrome.py b/problems/python3/valid-palindrome.py new file mode 100644 index 0000000..0069c83 --- /dev/null +++ b/problems/python3/valid-palindrome.py @@ -0,0 +1,15 @@ +class Solution: + def isPalindrome(self, s: str) -> bool: + i = 0 + j = len(s)-1 + + while i<=j: + while i Date: Tue, 31 May 2022 09:02:47 +0800 Subject: [PATCH 160/187] combination-sum --- problems/python3/combination-sum.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 problems/python3/combination-sum.py diff --git a/problems/python3/combination-sum.py b/problems/python3/combination-sum.py new file mode 100644 index 0000000..256cefa --- /dev/null +++ b/problems/python3/combination-sum.py @@ -0,0 +1,29 @@ +""" +Time: O(N^K), assuming the number of element in the combination that sums up to "target" is K. +For each element, there is N choices. +Which means the number of combination is N*N*N... for K times. +~= O(N^K) + +Space: O(K) + +K is approximate to target/min(candidates). +""" +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + def helper(i, currSum, target): + if currSum>target: + return + + if currSum==target: + ans.append(combination.copy()) + return + + for j in range(i, len(candidates)): + combination.append(candidates[j]) + helper(j, currSum+candidates[j], target) + combination.pop() + + ans = [] + combination = [] + helper(0, 0, target) + return ans \ No newline at end of file From ec99f026ffa60f6fe8a9710dddd1ab195d5476a3 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Wed, 1 Jun 2022 09:10:09 +0800 Subject: [PATCH 161/187] permutation --- problems/python3/permutations.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 problems/python3/permutations.py diff --git a/problems/python3/permutations.py b/problems/python3/permutations.py new file mode 100644 index 0000000..98d536d --- /dev/null +++ b/problems/python3/permutations.py @@ -0,0 +1,28 @@ +""" +Time: O(N!), since we call helper() N! times. +Space: O(N) for recursion stacks. + +Whenever we call `helper()`, we pick a num that is not "used" and add it to the `permutation`. +Recursively call the `helper()` until we filled the `permutation`. +Resotre `permutation` and `used` and try another `num`. +""" +class Solution: + def permute(self, nums: List[int]) -> List[List[int]]: + def helper(): + if len(permutation)==len(nums): + ans.append(permutation.copy()) + return + + for num in nums: + if num in used: continue + used.add(num) + permutation.append(num) + helper() + used.remove(num) + permutation.pop() + + ans = [] + permutation = [] + used = set() + helper() + return ans \ No newline at end of file From 06dd433f726e47c155d77dd3524fc57316a67676 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Thu, 2 Jun 2022 14:13:23 +0800 Subject: [PATCH 162/187] subsets-ii --- problems/python3/subsets-ii.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 problems/python3/subsets-ii.py diff --git a/problems/python3/subsets-ii.py b/problems/python3/subsets-ii.py new file mode 100644 index 0000000..8d6771c --- /dev/null +++ b/problems/python3/subsets-ii.py @@ -0,0 +1,19 @@ +class Solution: + def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: + def helper(i): + if i==len(nums): + ans.append(subset.copy()) + return + + subset.append(nums[i]) + helper(i+1) + subset.pop() + + while i+1 Date: Fri, 3 Jun 2022 09:10:29 +0800 Subject: [PATCH 163/187] combination-sum-ii --- problems/python3/combination-sum-ii.py | 22 ++++++++++++++++++++++ problems/python3/subsets-ii.py | 4 ++++ 2 files changed, 26 insertions(+) create mode 100644 problems/python3/combination-sum-ii.py diff --git a/problems/python3/combination-sum-ii.py b/problems/python3/combination-sum-ii.py new file mode 100644 index 0000000..c9f8957 --- /dev/null +++ b/problems/python3/combination-sum-ii.py @@ -0,0 +1,22 @@ +class Solution: + def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]: + def helper(i, target): + if target==0: + ans.append(combination.copy()) + return + + if i==len(candidates) or candidates[i]>target: + return + + combination.append(candidates[i]) + helper(i+1, target-candidates[i]) + combination.pop() + + while i+1 List[List[int]]: def helper(i): From 66f6f8d6c5801228688efc0eb6073a7703572774 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 7 Jun 2022 08:14:41 +0800 Subject: [PATCH 164/187] update --- .../letter-combinations-of-a-phone-number.py | 25 ++++++++ problems/python3/palindrome-partitioning.py | 64 +++++++++++++++++++ problems/python3/word-search.py | 27 ++++++++ 3 files changed, 116 insertions(+) create mode 100644 problems/python3/letter-combinations-of-a-phone-number.py create mode 100644 problems/python3/palindrome-partitioning.py create mode 100644 problems/python3/word-search.py diff --git a/problems/python3/letter-combinations-of-a-phone-number.py b/problems/python3/letter-combinations-of-a-phone-number.py new file mode 100644 index 0000000..582106c --- /dev/null +++ b/problems/python3/letter-combinations-of-a-phone-number.py @@ -0,0 +1,25 @@ +""" +Time: O(4^N * N), there are around 4^N of combination. Each taking O(N) to form. +Space: O(N). O(N) for recursion stack. O(N). O(N) for `combination`. O(N+N) ~= O(N). +""" +class Solution: + def letterCombinations(self, digits: str) -> List[str]: + def helper(i): + if i==len(digits): + ans.append(''.join(combination)) + return + + for c in mapping[digits[i]]: + combination.append(c) + helper(i+1) + combination.pop() + + mapping = {'2': ('a', 'b', 'c'), '3': ('d', 'e', 'f'), + '4': ('g', 'h', 'i'), '5': ('j', 'k', 'l'), '6': ('m', 'n', 'o'), + '7': ('p', 'q', 'r', 's'), '8': ('t', 'u', 'v'), '9': ('w', 'x', 'y', 'z')} + + if not digits: return [] + ans = [] + combination = [] + helper(0) + return ans \ No newline at end of file diff --git a/problems/python3/palindrome-partitioning.py b/problems/python3/palindrome-partitioning.py new file mode 100644 index 0000000..d02ef17 --- /dev/null +++ b/problems/python3/palindrome-partitioning.py @@ -0,0 +1,64 @@ +""" +`helper(i)` finds all the palindrome substring from i to j see if we can get an answer by recursively calling `helper(j+1)`. + +Time: O(2^N * N), for a string length S, there will be 2^N combination of substrings. For each substring, it will take O(N) to test if they are all palindrome. +Space: O(N). `partition` will takes O(N) and recursion stack will also take O(N). O(N + N) ~= O(N) +""" +class Solution: + def partition(self, s: str) -> List[List[str]]: + def helper(i): + if i>=len(s): + ans.append(partition.copy()) + return + + for j in range(i, len(s)): + if isPalindrome(i, j): + partition.append(s[i:j+1]) + helper(j+1) + partition.pop() + + def isPalindrome(i, j): + while i<=j: + if s[i]!=s[j]: return False + i += 1 + j -= 1 + return True + + ans = [] + partition = [] + helper(0) + return ans + +""" +If you look closely you can see that we execute `isPalindrome` on many repeated substrings. +We can optimize this by storing the result in `dp` and reuse it. +Since all the less difference i and j (shorter substring s[i:j+1]) will be process first in the `isPalindrome`. +When checking if s[i:j+1] is a palindrome or not, we can simply check the if s[i]==s[j] and the previous result (dp[i+1][j-1]) + +Time: O(2^N * N), The overall time complexity is the same, but isPalindrome is actually a lot faster. +Space: O(N^2) for `dp`. +""" +class Solution: + def partition(self, s: str) -> List[List[str]]: + def helper(i): + if i>=N: + ans.append(partition.copy()) + return + + for j in range(i, N): + if isPalindrome(i, j): + partition.append(s[i:j+1]) + helper(j+1) + partition.pop() + + def isPalindrome(i, j): + dp[i][j] = i==j or (j-i==1 and s[i]==s[j]) or (s[i]==s[j] and dp[i+1][j-1]) #len==1 palindrome or len==2 palindrome or len>=3 palindrome + return dp[i][j] + + N = len(s) + ans = [] + partition = [] + dp = [[False]*N for _ in range(N)] + + helper(0) + return ans \ No newline at end of file diff --git a/problems/python3/word-search.py b/problems/python3/word-search.py new file mode 100644 index 0000000..b7ebb09 --- /dev/null +++ b/problems/python3/word-search.py @@ -0,0 +1,27 @@ +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + def helper(x, i, j): + if i<0 or i>=N or j<0 or j>=M: return False + if (i, j) in usedWords: return False + usedWords.add((i, j)) + + if word[x]==board[i][j]: + if x==len(word)-1: + return True + else: + if helper(x+1, i+1, j): return True + if helper(x+1, i, j+1): return True + if helper(x+1, i-1, j): return True + if helper(x+1, i, j-1): return True + + + usedWords.remove((i, j)) + return False + + usedWords = set() + N = len(board) + M = len(board[0]) + for i in range(N): + for j in range(M): + if helper(0, i, j): return True + return False \ No newline at end of file From 777337b4fa073c7946eb05933875435b86335d73 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Fri, 10 Jun 2022 08:22:21 +0800 Subject: [PATCH 165/187] updates --- problems/python3/binary-search.py | 16 +++++++++ problems/python3/n-queens.py | 45 ++++++++++++++++++++++++++ problems/python3/search-a-2d-matrix.py | 22 +++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 problems/python3/binary-search.py create mode 100644 problems/python3/n-queens.py create mode 100644 problems/python3/search-a-2d-matrix.py diff --git a/problems/python3/binary-search.py b/problems/python3/binary-search.py new file mode 100644 index 0000000..2e65a63 --- /dev/null +++ b/problems/python3/binary-search.py @@ -0,0 +1,16 @@ +class Solution: + def search(self, nums: List[int], target: int) -> int: + l = 0 + r = len(nums)-1 + + while l<=r: + m = l + int((r-l)/2) + + if nums[m]>target: + r = m-1 + elif nums[m] List[List[str]]: + def helper(row: int): + if row==n: + ans.append(convertFormat(queenCols)) + return + + for col in range(n): + posDiag = row+col + negDiag = row-col + + if col in colUsed or posDiag in posDiagUsed or negDiag in negDiagUsed: continue + + queenCols.append(col) + colUsed.add(col) + posDiagUsed.add(posDiag) + negDiagUsed.add(negDiag) + + helper(row+1) + + queenCols.pop() + colUsed.remove(col) + posDiagUsed.remove(posDiag) + negDiagUsed.remove(negDiag) + + def convertFormat(queenCols: List[int]) -> List[str]: + output = [] + for col in queenCols: + row = '' + for i in range(n): + if i==col: + row += 'Q' + else: + row += '.' + output.append(row) + return output + + ans = [] + queenCols = [] + colUsed = set() + posDiagUsed = set() + negDiagUsed = set() + + helper(0) + return ans \ No newline at end of file diff --git a/problems/python3/search-a-2d-matrix.py b/problems/python3/search-a-2d-matrix.py new file mode 100644 index 0000000..2afe301 --- /dev/null +++ b/problems/python3/search-a-2d-matrix.py @@ -0,0 +1,22 @@ +class Solution: + def searchMatrix(self, matrix: List[List[int]], target: int) -> bool: + N = len(matrix) + M = len(matrix[0]) + + l = 0 + r = N*M-1 + + while l<=r: + m = l + int((r-l)/2) + + i = int(m/M) + j = m%M + + if matrix[i][j]target: + r = m-1 + else: + return True + + return False \ No newline at end of file From 756886863aaffd597dafada0668da0ae7316ea30 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Thu, 16 Jun 2022 10:19:12 +0800 Subject: [PATCH 166/187] updates --- .../find-minimum-in-rotated-sorted-array.py | 22 +++++++++++++++ problems/python3/koko-eating-bananas.py | 21 ++++++++++++++ .../python3/median-of-two-sorted-arrays.py | 27 ++++++++++++++++++ .../python3/time-based-key-value-store.py | 28 +++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 problems/python3/find-minimum-in-rotated-sorted-array.py create mode 100644 problems/python3/koko-eating-bananas.py create mode 100644 problems/python3/median-of-two-sorted-arrays.py create mode 100644 problems/python3/time-based-key-value-store.py diff --git a/problems/python3/find-minimum-in-rotated-sorted-array.py b/problems/python3/find-minimum-in-rotated-sorted-array.py new file mode 100644 index 0000000..c9af305 --- /dev/null +++ b/problems/python3/find-minimum-in-rotated-sorted-array.py @@ -0,0 +1,22 @@ +""" +Usually the binary search problem, the hard part is to clear all the edge cases. +What will be the edge case? It will be when the recursive function executed at the deepest level. Usually the list with only one or two element. +So I will suggest before submit, try out the case like [0,1] or [1,0] to make sure it will not run unstop. +""" +class Solution: + def findMin(self, nums: List[int]) -> int: + def helper(l, r): + nonlocal ans + if l>r: return + + m = l + int((r-l)/2) + if nums[l]<=nums[m]: + ans = min(ans, nums[l]) + helper(m+1, r) + else: + ans = min(ans, nums[m+1]) + helper(l, m) + + ans = float('inf') + helper(0, len(nums)-1) + return ans \ No newline at end of file diff --git a/problems/python3/koko-eating-bananas.py b/problems/python3/koko-eating-bananas.py new file mode 100644 index 0000000..fe03197 --- /dev/null +++ b/problems/python3/koko-eating-bananas.py @@ -0,0 +1,21 @@ +class Solution: + def minEatingSpeed(self, piles: List[int], h: int) -> int: + def canFinish(k): + timeNeeded = 0 + for pile in piles: + timeNeeded += math.ceil(pile/k) + return timeNeeded<=h + + kMin = 1 + kMax = max(piles) + ans = kMax + + while kMin<=kMax: + k = kMin + int((kMax-kMin)/2) + if canFinish(k): + ans = min(ans, k) + kMax = k-1 + else: + kMin = k+1 + + return ans \ No newline at end of file diff --git a/problems/python3/median-of-two-sorted-arrays.py b/problems/python3/median-of-two-sorted-arrays.py new file mode 100644 index 0000000..e38e5ee --- /dev/null +++ b/problems/python3/median-of-two-sorted-arrays.py @@ -0,0 +1,27 @@ +class Solution: + def findMedianSortedArrays(self, A: List[int], B: List[int]) -> float: + if len(A)>len(B): A, B = B, A + + total = len(A)+len(B) + half = total//2 + l = 0 + r = len(A)-1 + + while True: + i = l + (r-l)//2 + j = half-(i+1)-1 + + Aleft = A[i] if i>=0 else float('-inf') + Aright = A[i+1] if i+1=0 else float('-inf') + Bright = B[j+1] if j+1Bright: + r = i-1 + else: + l = i+1 \ No newline at end of file diff --git a/problems/python3/time-based-key-value-store.py b/problems/python3/time-based-key-value-store.py new file mode 100644 index 0000000..f43facf --- /dev/null +++ b/problems/python3/time-based-key-value-store.py @@ -0,0 +1,28 @@ +class TimeMap: + + def __init__(self): + self.data = collections.defaultdict(list) + + def set(self, key: str, value: str, timestamp: int) -> None: + self.data[key].append((timestamp, value)) + + def get(self, key: str, timestamp: int) -> str: + dataList = self.data[key] + l = 0 + r = len(dataList)-1 + ans = '' + + while l<=r: + m = l + int((r-l)/2) + t = dataList[m][0] + + if ttimestamp: + r = m-1 + else: + ans = dataList[m][1] + break + + return ans \ No newline at end of file From b17819091e771eec5ad9ef71d963e535503adf84 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 21 Jun 2022 09:15:56 +0800 Subject: [PATCH 167/187] updates --- problems/python3/gas-station.py | 23 +++++++++++++++++++ problems/python3/jump-game-ii.py | 22 ++++++++++++++++++ problems/python3/jump-game.py | 10 ++++++++ problems/python3/maximum-subarray.py | 17 ++++++++++++++ .../python3/median-of-two-sorted-arrays.py | 13 +++++++++++ 5 files changed, 85 insertions(+) create mode 100644 problems/python3/gas-station.py create mode 100644 problems/python3/jump-game-ii.py create mode 100644 problems/python3/jump-game.py create mode 100644 problems/python3/maximum-subarray.py diff --git a/problems/python3/gas-station.py b/problems/python3/gas-station.py new file mode 100644 index 0000000..017eaa6 --- /dev/null +++ b/problems/python3/gas-station.py @@ -0,0 +1,23 @@ +""" +First thing, you must understand that if sum(gas)>=sum(cost) there must be an answer. Guaranteed. +If we know there is an answer, we can simply test all the index. +If the currGas ever drops to below 0, it means that we need to switch a "start". + +Time: O(N) +Space: O(1) +""" +class Solution: + def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int: + if sum(gas) int: + l = r = 0 + steps = 0 + + while r bool: + maxIndex = 0 + + for i, num in enumerate(nums): + if maxIndex int: + ans = float('-inf') + currSum = 0 + + for num in nums: + if currSum<0: currSum = 0 + currSum += num + ans = max(ans, currSum) + return ans \ No newline at end of file diff --git a/problems/python3/median-of-two-sorted-arrays.py b/problems/python3/median-of-two-sorted-arrays.py index e38e5ee..0fa31da 100644 --- a/problems/python3/median-of-two-sorted-arrays.py +++ b/problems/python3/median-of-two-sorted-arrays.py @@ -1,3 +1,16 @@ +""" +Try to find a i on array A and corespoding j on array B. + +Aleft = A[i] +Aright = A[i+1] +Bleft = B[j] +Bright = B[j+1] + +Such that Aleft<=Bright and Bleft<=Aright + +This means that A[:i+1] and B[:j+1] holds all the elements that is less than the median. +Aright A[i+1:] and B[j+1:] holds all the elements that is larger or equal to the median. +""" class Solution: def findMedianSortedArrays(self, A: List[int], B: List[int]) -> float: if len(A)>len(B): A, B = B, A From ab00993db54f12ce78a71b3e072637c5ab63b66b Mon Sep 17 00:00:00 2001 From: wuduhren Date: Wed, 6 Jul 2022 08:07:03 +0200 Subject: [PATCH 168/187] updates --- problems/python3/contains-duplicate.py | 7 +++++ problems/python3/hand-of-straights.py | 18 +++++++++++++ .../merge-triplets-to-form-target-triplet.py | 15 +++++++++++ problems/python3/partition-labels.py | 26 +++++++++++++++++++ problems/python3/two-sum.py | 8 ++++++ problems/python3/valid-anagram.py | 17 ++++++++++++ problems/python3/valid-parenthesis-string.py | 23 ++++++++++++++++ 7 files changed, 114 insertions(+) create mode 100644 problems/python3/contains-duplicate.py create mode 100644 problems/python3/hand-of-straights.py create mode 100644 problems/python3/merge-triplets-to-form-target-triplet.py create mode 100644 problems/python3/partition-labels.py create mode 100644 problems/python3/two-sum.py create mode 100644 problems/python3/valid-anagram.py create mode 100644 problems/python3/valid-parenthesis-string.py diff --git a/problems/python3/contains-duplicate.py b/problems/python3/contains-duplicate.py new file mode 100644 index 0000000..7849e84 --- /dev/null +++ b/problems/python3/contains-duplicate.py @@ -0,0 +1,7 @@ +class Solution: + def containsDuplicate(self, nums: List[int]) -> bool: + seen = set() + for num in nums: + if num in seen: return True + seen.add(num) + return False \ No newline at end of file diff --git a/problems/python3/hand-of-straights.py b/problems/python3/hand-of-straights.py new file mode 100644 index 0000000..f20c32d --- /dev/null +++ b/problems/python3/hand-of-straights.py @@ -0,0 +1,18 @@ +class Solution: + def isNStraightHand(self, hand: List[int], groupSize: int) -> bool: + if len(hand)%groupSize!=0: return False + + counter = collections.Counter(hand) + h = list(counter.keys()) + heapq.heapify(h) + + while h: + minNum = h[0] + for n in range(minNum, minNum+groupSize): + if counter[n]<=0: return False + counter[n] -= 1 + if counter[n]==0: + if h[0]!=n: return False + heapq.heappop(h) + + return True \ No newline at end of file diff --git a/problems/python3/merge-triplets-to-form-target-triplet.py b/problems/python3/merge-triplets-to-form-target-triplet.py new file mode 100644 index 0000000..4708e4f --- /dev/null +++ b/problems/python3/merge-triplets-to-form-target-triplet.py @@ -0,0 +1,15 @@ +""" +If any element in the triplets is larger than the element in target, it cannot be used. +Check if we have all 3 index found the same value. +""" +class Solution: + def mergeTriplets(self, triplets: List[List[int]], target: List[int]) -> bool: + okIndex = set() + + for a, b, c in triplets: + if a>target[0] or b>target[1] or c>target[2]: continue + if a==target[0]: okIndex.add(0) + if b==target[1]: okIndex.add(1) + if c==target[2]: okIndex.add(2) + + return len(okIndex)==3 \ No newline at end of file diff --git a/problems/python3/partition-labels.py b/problems/python3/partition-labels.py new file mode 100644 index 0000000..0c12d00 --- /dev/null +++ b/problems/python3/partition-labels.py @@ -0,0 +1,26 @@ +""" +Time: O(N) +Space: O(N) + +For each char, store its max index in maxIndex. +Iterate through the string, update the "currMax" along the way. +currMax is the place we can partition unless it get updated again. +If the current index is the currMax, update "ans". +""" +class Solution: + def partitionLabels(self, s: str) -> List[int]: + ans = [] + maxIndex = {} + + for i, c in enumerate(s): + maxIndex[c] = i + + currMax = 0 + processedLength = 0 + for i, c in enumerate(s): + currMax = max(currMax, maxIndex[c]) + if i==currMax: + ans.append(i+1 - processedLength) + processedLength += ans[-1] + + return ans \ No newline at end of file diff --git a/problems/python3/two-sum.py b/problems/python3/two-sum.py new file mode 100644 index 0000000..aa90d66 --- /dev/null +++ b/problems/python3/two-sum.py @@ -0,0 +1,8 @@ +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + #needed: {number required : counter part index} + needed = {} + for i, num in enumerate(nums): + if num in needed: + return (needed[num], i) + needed[target-num] = i \ No newline at end of file diff --git a/problems/python3/valid-anagram.py b/problems/python3/valid-anagram.py new file mode 100644 index 0000000..6c37cb0 --- /dev/null +++ b/problems/python3/valid-anagram.py @@ -0,0 +1,17 @@ +class Solution: + def isAnagram(self, s: str, t: str) -> bool: + counter = collections.Counter() + + for c in s: + counter[c] += 1 + + for c in t: + if c not in counter: + return False + counter[c] -= 1 + + for c in counter: + if counter[c]>0: + return False + + return True \ No newline at end of file diff --git a/problems/python3/valid-parenthesis-string.py b/problems/python3/valid-parenthesis-string.py new file mode 100644 index 0000000..52ea446 --- /dev/null +++ b/problems/python3/valid-parenthesis-string.py @@ -0,0 +1,23 @@ +class Solution: + def checkValidString(self, s: str) -> bool: + leftMin = 0 + leftMax = 0 + + for c in s: + if c=='(': + leftMin += 1 + leftMax += 1 + elif c==')': + leftMin -= 1 + leftMax -= 1 + else: + leftMin -= 1 + leftMax += 1 + + if leftMax<0: + return False + + if leftMin<0: + leftMin = 0 + + return leftMin == 0 \ No newline at end of file From 881c58db2e6c7027d287ac0072444253850c51d7 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sun, 17 Jul 2022 09:24:20 +0200 Subject: [PATCH 169/187] updates --- problems/python3/encode-and-decode-strings.py | 23 ++++++++ problems/python3/group-anagrams.py | 23 ++++++++ .../python3/product-of-array-except-self.py | 45 ++++++++++++++++ problems/python3/top-k-frequent-elements.py | 53 +++++++++++++++++++ problems/python3/valid-sudoku.py | 37 +++++++++++++ 5 files changed, 181 insertions(+) create mode 100644 problems/python3/encode-and-decode-strings.py create mode 100644 problems/python3/group-anagrams.py create mode 100644 problems/python3/product-of-array-except-self.py create mode 100644 problems/python3/top-k-frequent-elements.py create mode 100644 problems/python3/valid-sudoku.py diff --git a/problems/python3/encode-and-decode-strings.py b/problems/python3/encode-and-decode-strings.py new file mode 100644 index 0000000..f38c4e4 --- /dev/null +++ b/problems/python3/encode-and-decode-strings.py @@ -0,0 +1,23 @@ +class Codec: + def encode(self, strs: List[str]) -> str: + output = '' + for string in strs: + output += str(len(string))+'#'+string + return output + + + def decode(self, s: str) -> List[str]: + output = [] + i = 0 + + while i List[List[str]]: + def normalize(string: str) -> str: + counter = collections.Counter() + ans = '' + + for c in string: + counter[c] += 1 + + for c in 'abcdefghijklmnopqrstuvwxyz': + if counter[c]>0: + ans += c+str(counter[c]) + return ans + + group = collections.defaultdict(list) + ans = [] + + for string in strs: + group[normalize(string)].append(string) + + for normalizedString in group: + ans.append(group[normalizedString]) + return ans \ No newline at end of file diff --git a/problems/python3/product-of-array-except-self.py b/problems/python3/product-of-array-except-self.py new file mode 100644 index 0000000..2309896 --- /dev/null +++ b/problems/python3/product-of-array-except-self.py @@ -0,0 +1,45 @@ +class Solution: + def productExceptSelf(self, nums: List[int]) -> List[int]: + #left[i] := product of all nums left of nums[i] (not include nums[i]) + left = [1] + temp = 1 + for num in nums: + temp *= num + left.append(temp) + + #right[i] := product of all nums right of nums[i] (not include nums[i]) + right = [] + temp = 1 + for num in reversed(nums): + temp *= num + right.append(temp) + right.reverse() + right.append(1) + right = right[1:] + + ans = [] + for i in range(len(nums)): + ans.append(left[i]*right[i]) + return ans + +#In Place +class Solution: + def productExceptSelf(self, nums: List[int]) -> List[int]: + N = len(nums) + ans = [0]*N + + #generate "left" + ans[0] = 1 + for i in range(1, N): + ans[i] = ans[i-1]*nums[i-1] + + #generate "right" + temp = 1 + for i in range(N-2, -1, -1): + temp *= nums[i+1] + ans[i] *= temp + + return ans + + + \ No newline at end of file diff --git a/problems/python3/top-k-frequent-elements.py b/problems/python3/top-k-frequent-elements.py new file mode 100644 index 0000000..7d728cb --- /dev/null +++ b/problems/python3/top-k-frequent-elements.py @@ -0,0 +1,53 @@ +#Bucket Sort +class Solution: + def topKFrequent(self, nums: List[int], k: int) -> List[int]: + bucket = collections.defaultdict(list) + counter = collections.Counter(nums) + ans = [] + + for num in counter: + bucket[counter[num]].append(num) + + tempCount = len(nums) + while len(ans) List[int]: + def quickSelect(freqs, s, e, K): + i = s + t = s + j = e + pivot = freqs[(s+e)//2][1] + + while t<=j: + if freqs[t][1]pivot: + freqs[j], freqs[t] = freqs[t], freqs[j] + j -= 1 + else: + t += 1 + if e-j>=K: + return quickSelect(freqs, j+1, e, K) + elif e-(i-1)>=K: + return pivot + else: + return quickSelect(freqs, s, i-1, K-(e-i+1)) + + counts = collections.Counter(nums) + freqs = [(num, counts[num]) for num in counts] + ans = [] + + KthLargestFreq = quickSelect(freqs, 0, len(freqs)-1, K) + + for num, freq in freqs: + if freq>=KthLargestFreq: + ans.append(num) + return ans \ No newline at end of file diff --git a/problems/python3/valid-sudoku.py b/problems/python3/valid-sudoku.py new file mode 100644 index 0000000..b2e6fa7 --- /dev/null +++ b/problems/python3/valid-sudoku.py @@ -0,0 +1,37 @@ +class Solution: + def isValidSudoku(self, board: List[List[str]]) -> bool: + def rowIsValid(i): + used = set() + for j in range(N): + if board[i][j]=='.': continue + if board[i][j] in used: return False + used.add(board[i][j]) + return True + + def columnIsValid(i): + used = set() + for j in range(N): + if board[j][i]=='.': continue + if board[j][i] in used: return False + used.add(board[j][i]) + return True + + def isBoxValid(i1, i2, j1, j2): + used = set() + for i in range(i1, i2+1): + for j in range(j1, j2+1): + if board[i][j]=='.': continue + if board[i][j] in used: return False + used.add(board[i][j]) + return True + + N = 9 + for i in range(N): + if not rowIsValid(i): return False + if not columnIsValid(i): return False + + for i in range(0, N, 3): + for j in range(0, N, 3): + if not isBoxValid(i, i+2, j, j+2): return False + + return True \ No newline at end of file From 53d11bc54af366f05292b39cc100faceda21b716 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sat, 23 Jul 2022 09:02:24 +0200 Subject: [PATCH 170/187] updates --- .../best-time-to-buy-and-sell-stock.py | 10 +++++++ .../python3/longest-consecutive-sequence.py | 15 ++++++++++ ...longest-repeating-character-replacement.py | 13 +++++++++ ...ongest-substring-without-repeating-char.py | 14 ++++++++++ problems/python3/permutation-in-string.py | 28 +++++++++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 problems/python3/best-time-to-buy-and-sell-stock.py create mode 100644 problems/python3/longest-consecutive-sequence.py create mode 100644 problems/python3/longest-repeating-character-replacement.py create mode 100644 problems/python3/longest-substring-without-repeating-char.py create mode 100644 problems/python3/permutation-in-string.py diff --git a/problems/python3/best-time-to-buy-and-sell-stock.py b/problems/python3/best-time-to-buy-and-sell-stock.py new file mode 100644 index 0000000..f04ad91 --- /dev/null +++ b/problems/python3/best-time-to-buy-and-sell-stock.py @@ -0,0 +1,10 @@ +class Solution: + def maxProfit(self, prices: List[int]) -> int: + minPrice = prices[0] + ans = 0 + + for i in range(1, len(prices)): + ans = max(ans, prices[i]-minPrice) + minPrice = min(prices[i], minPrice) + + return ans \ No newline at end of file diff --git a/problems/python3/longest-consecutive-sequence.py b/problems/python3/longest-consecutive-sequence.py new file mode 100644 index 0000000..dec2cfa --- /dev/null +++ b/problems/python3/longest-consecutive-sequence.py @@ -0,0 +1,15 @@ +class Solution: + def longestConsecutive(self, nums: List[int]) -> int: + numSet = set(nums) + ans = 0 + + for num in nums: + isStart = num-1 not in numSet + if isStart: + count = 0 + temp = num + while temp in numSet: + count += 1 + temp += 1 + ans = max(count, ans) + return ans \ No newline at end of file diff --git a/problems/python3/longest-repeating-character-replacement.py b/problems/python3/longest-repeating-character-replacement.py new file mode 100644 index 0000000..714d8f1 --- /dev/null +++ b/problems/python3/longest-repeating-character-replacement.py @@ -0,0 +1,13 @@ +class Solution: + def characterReplacement(self, s: str, k: int) -> int: + counter = collections.Counter() + l = 0 + ans = 0 + + for r in range(len(s)): + counter[s[r]] += 1 + while (r-l+1)-max(counter.values()) > k: + counter[s[l]] -= 1 + l += 1 + ans = max(ans, r-l+1) + return ans \ No newline at end of file diff --git a/problems/python3/longest-substring-without-repeating-char.py b/problems/python3/longest-substring-without-repeating-char.py new file mode 100644 index 0000000..9902bb5 --- /dev/null +++ b/problems/python3/longest-substring-without-repeating-char.py @@ -0,0 +1,14 @@ +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + ans = 0 + l = 0 + seen = set() + + for r in range(len(s)): + while s[r] in seen: + seen.remove(s[l]) + l += 1 + seen.add(s[r]) + ans = max(ans, r-l+1) + + return ans \ No newline at end of file diff --git a/problems/python3/permutation-in-string.py b/problems/python3/permutation-in-string.py new file mode 100644 index 0000000..cd22781 --- /dev/null +++ b/problems/python3/permutation-in-string.py @@ -0,0 +1,28 @@ +class Solution: + def checkInclusion(self, s1: str, s2: str) -> bool: + if len(s1)>len(s2): return False + + counter1 = collections.Counter(s1) + counter2 = collections.Counter(s2[:len(s1)]) + matches = 0 + for c in 'abcdefghijklmnopqrstuvwxyz': + if counter1[c]==counter2[c]: matches += 1 + if matches==26: return True + + l = 0 + for r in range(len(s1), len(s2)): + counter2[s2[r]] += 1 + if counter1[s2[r]]==counter2[s2[r]]: + matches += 1 + elif counter1[s2[r]]+1==counter2[s2[r]]: + matches -= 1 + + counter2[s2[l]] -= 1 + if counter1[s2[l]]==counter2[s2[l]]: + matches += 1 + elif counter1[s2[l]]-1==counter2[s2[l]]: + matches -= 1 + l += 1 + + if matches==26: return True + return False \ No newline at end of file From b68839f9141a93ad4e002480b308651ab4c35565 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Mon, 1 Aug 2022 08:06:03 +0200 Subject: [PATCH 171/187] update --- problems/python3/minimum-window-substring.py | 25 ++++++++++++++++++++ problems/python3/sliding-window-maximum.py | 18 ++++++++++++++ problems/python3/valid-parentheses.py | 17 +++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 problems/python3/minimum-window-substring.py create mode 100644 problems/python3/sliding-window-maximum.py create mode 100644 problems/python3/valid-parentheses.py diff --git a/problems/python3/minimum-window-substring.py b/problems/python3/minimum-window-substring.py new file mode 100644 index 0000000..1a23a82 --- /dev/null +++ b/problems/python3/minimum-window-substring.py @@ -0,0 +1,25 @@ +class Solution: + def minWindow(self, s: str, t: str) -> str: + if len(t)>len(s): return "" + + ans = "" + counter1 = collections.Counter(t) + charSet = set(t) + counter2 = collections.Counter() #sliding window in string s, index between l and r + charSet2 = set(s) + matchCount = 0 #count of char in the sliding window that counts are larger than the char count in t. + + l = 0 + for r in range(len(s)): + counter2[s[r]] += 1 + + if s[r] in charSet and counter1[s[r]]==counter2[s[r]]: matchCount += 1 + + while lcounter1[s[l]]): + counter2[s[l]] -= 1 + l += 1 + + if matchCount==len(charSet) and (ans=="" or r-l+1 List[int]: + ans = [] + q = collections.deque() + l = r = 0 + + while r bool: + mapping = {')': '(', ']': '[', '}':'{'} + stack = [] + + for c in s: + if c not in mapping: + #open parentheses + stack.append(c) + else: + #close parentheses + if stack and stack[-1]==mapping[c]: + stack.pop() + else: + return False + + return not stack \ No newline at end of file From 612e17e73b2f8f3df6158cfd68f837f7a942eed3 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 9 Aug 2022 07:17:56 +0200 Subject: [PATCH 172/187] update --- problems/python3/car-fleet.py | 16 +++++++++++++ problems/python3/daily-temperatures.py | 12 ++++++++++ .../evaluate-reverse-polish-notation.py | 22 ++++++++++++++++++ problems/python3/generate-parentheses.py | 20 ++++++++++++++++ problems/python3/min-stack.py | 23 +++++++++++++++++++ 5 files changed, 93 insertions(+) create mode 100644 problems/python3/car-fleet.py create mode 100644 problems/python3/daily-temperatures.py create mode 100644 problems/python3/evaluate-reverse-polish-notation.py create mode 100644 problems/python3/generate-parentheses.py create mode 100644 problems/python3/min-stack.py diff --git a/problems/python3/car-fleet.py b/problems/python3/car-fleet.py new file mode 100644 index 0000000..24ccba8 --- /dev/null +++ b/problems/python3/car-fleet.py @@ -0,0 +1,16 @@ +class Solution: + def carFleet(self, target: int, position: List[int], speed: List[int]) -> int: + N = len(position) + + timeInfo = [] + for i in range(N): + timeInfo.append((position[i], (target-position[i])/speed[i])) + timeInfo.sort(reverse=True) + + stack = [] + for _, time in timeInfo: + stack.append(time) + if len(stack)>=2 and stack[-2]>=stack[-1]: + stack.pop() + + return len(stack) \ No newline at end of file diff --git a/problems/python3/daily-temperatures.py b/problems/python3/daily-temperatures.py new file mode 100644 index 0000000..d6e4c98 --- /dev/null +++ b/problems/python3/daily-temperatures.py @@ -0,0 +1,12 @@ +class Solution: + def dailyTemperatures(self, temperatures: List[int]) -> List[int]: + ans = [0]*len(temperatures) + stack = [] + + for i, temp in enumerate(temperatures): + while stack and stack[-1][0] int: + operators = set(['+', '-', '*', '/']) + stack = [] + + for c in tokens: + if c in operators: + n2 = stack.pop() + n1 = stack.pop() + + if c=='+': + stack.append(n1+n2) + elif c=='-': + stack.append(n1-n2) + elif c=='*': + stack.append(n1*n2) + elif c=='/': + stack.append(int(n1/n2)) + else: + stack.append(int(c)) + + return stack.pop() \ No newline at end of file diff --git a/problems/python3/generate-parentheses.py b/problems/python3/generate-parentheses.py new file mode 100644 index 0000000..9b96ef9 --- /dev/null +++ b/problems/python3/generate-parentheses.py @@ -0,0 +1,20 @@ +class Solution: + def generateParenthesis(self, n: int) -> List[str]: + def helper(parentheses, left, right): + if len(parentheses)==n*2: + ans.append("".join(parentheses)) + return + + if leftright: + parentheses.append(')') + helper(parentheses, left, right+1) + parentheses.pop() + + ans = [] + helper([], 0, 0) + return ans \ No newline at end of file diff --git a/problems/python3/min-stack.py b/problems/python3/min-stack.py new file mode 100644 index 0000000..8fe03de --- /dev/null +++ b/problems/python3/min-stack.py @@ -0,0 +1,23 @@ +#"stack" is just a normal stack. +#"minStack" stores the min of the stack element in the same position. +#i.e. At the time stack[x] put in to the stack. minStack[x] is the min. + +class MinStack: + + def __init__(self): + self.stack = [] + self.minStack = [] + + def push(self, val: int) -> None: + self.stack.append(val) + self.minStack.append(val if (not self.minStack or val None: + self.minStack.pop() + return self.stack.pop() + + def top(self) -> int: + return self.stack[-1] + + def getMin(self) -> int: + return self.minStack[-1] \ No newline at end of file From 102969667a38c53844cfa5b2b94353e4ad547d4e Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sun, 14 Aug 2022 14:52:03 +0200 Subject: [PATCH 173/187] Updates --- .../python3/copy-list-with-random-pointer.py | 34 ++++++++++++++ .../python3/largest-rectangle-in-histogram.py | 21 +++++++++ problems/python3/merge-two-sorted-lists.py | 15 ++++++ .../remove-nth-node-from-end-of-list.py | 47 +++++++++++++++++++ problems/python3/reorder-list.py | 37 +++++++++++++++ problems/python3/reverse-linked-list.py | 21 +++++++++ 6 files changed, 175 insertions(+) create mode 100644 problems/python3/copy-list-with-random-pointer.py create mode 100644 problems/python3/largest-rectangle-in-histogram.py create mode 100644 problems/python3/merge-two-sorted-lists.py create mode 100644 problems/python3/remove-nth-node-from-end-of-list.py create mode 100644 problems/python3/reorder-list.py create mode 100644 problems/python3/reverse-linked-list.py diff --git a/problems/python3/copy-list-with-random-pointer.py b/problems/python3/copy-list-with-random-pointer.py new file mode 100644 index 0000000..4436b78 --- /dev/null +++ b/problems/python3/copy-list-with-random-pointer.py @@ -0,0 +1,34 @@ +""" +Time: O(N) +Space: O(1) + +The easiest way would be maintaining a hash map for original node to the copy and the other way around. Then the rest is easy. +But this will take us O(N) of extra space. + +Two pass solution with constant space. +First pass. +Create a copy of the original and store it inside "random". +The copy points to original's next and original's random. + +Second pass. +Iterate through the nodes again. +This time we adjust the copy to point to the other copies. +""" +class Solution: + def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]': + if not head: return head + + node = head + while node: + copy = Node(node.val, node.next, node.random) + node.random = copy + node = node.next + + node = head + while node: + newNode = node.random + if node.next: newNode.next = node.next.random + if newNode.random: newNode.random = newNode.random.random + node = node.next + + return head.random \ No newline at end of file diff --git a/problems/python3/largest-rectangle-in-histogram.py b/problems/python3/largest-rectangle-in-histogram.py new file mode 100644 index 0000000..1cf8508 --- /dev/null +++ b/problems/python3/largest-rectangle-in-histogram.py @@ -0,0 +1,21 @@ +""" +[0] For each height, if the it is lower than the previous one, it means that the previous are not able to extend anymore. So we calculate its area. + +[1] If the previous area, is larger than the current one, it means that the current one are able to extand backward. +""" +class Solution: + def largestRectangleArea(self, heights: List[int]) -> int: + maxArea = 0 + stack = [] + + heights.append(0) #dummy for the ending + + for i, h in enumerate(heights): + start = i + while stack and h Optional[ListNode]: + head = ListNode() #dummy + node = head + while list1 and list2: + if list1.val Optional[ListNode]: + #count the length of the linked list + node = head + count = 0 + while node: + count += 1 + node = node.next + + + node = head + steps = count-n-1 + + #steps==-1 means that we need to remove the first node + if steps==-1: return head.next + + #traverse to the node before the node we wanted to remove + while steps>0: + node = node.next + steps -= 1 + + #remove "node.next" + node.next = node.next.next + + return head + + +#One pass. Fast pointer is ahead of slow pointer by n+1 +#So slow pointer will stop at the node before the node we wanted to remove +class Solution: + def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]: + dummy = ListNode() + dummy.next = head + + ahead = n+1 + fast = dummy + slow = dummy + + while fast: + fast = fast.next + ahead -= 1 + if ahead<0: slow = slow.next + + slow.next = slow.next.next + + return dummy.next \ No newline at end of file diff --git a/problems/python3/reorder-list.py b/problems/python3/reorder-list.py new file mode 100644 index 0000000..89c6ba2 --- /dev/null +++ b/problems/python3/reorder-list.py @@ -0,0 +1,37 @@ +class Solution: + def reorderList(self, head: Optional[ListNode]) -> None: + #find the middle point + slow = head + fast = head + while fast and fast.next: + slow = slow.next + fast = fast.next.next + middle = slow.next + + #reverse the linked list after the middle point + middle = self.reverseList(middle) + + #separate the linked list before the middle + slow.next = None + + #merge two linked list + node = head + while middle and node: + nextNode = node.next + node.next = middle + middle = middle.next + node.next.next = nextNode + node = nextNode + return head + + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + pre = None + node = head + + while node: + nextNode = node.next + node.next = pre + if not nextNode: return node + pre = node + node = nextNode + \ No newline at end of file diff --git a/problems/python3/reverse-linked-list.py b/problems/python3/reverse-linked-list.py new file mode 100644 index 0000000..c9c0655 --- /dev/null +++ b/problems/python3/reverse-linked-list.py @@ -0,0 +1,21 @@ +#Recursive +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + if not head or not head.next: return head + temp = self.reverseList(head.next) + head.next.next = head + head.next = None + return temp + +#Iterative +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + pre = None + node = head + + while node: + nextNode = node.next + node.next = pre + if not nextNode: return node + pre = node + node = nextNode \ No newline at end of file From 543e1f893e54b6bb47139db24531ea84ddd92534 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sat, 20 Aug 2022 09:32:32 +0200 Subject: [PATCH 174/187] updates --- problems/python3/add-two-numbers.py | 19 ++++++++ problems/python3/find-the-duplicate-number.py | 16 +++++++ .../kth-largest-element-in-a-stream.py | 14 ++++++ problems/python3/last-stone-weight.py | 12 +++++ problems/python3/linked-list-cycle.py | 16 +++++++ problems/python3/lru-cache.py | 47 +++++++++++++++++++ 6 files changed, 124 insertions(+) create mode 100644 problems/python3/add-two-numbers.py create mode 100644 problems/python3/find-the-duplicate-number.py create mode 100644 problems/python3/kth-largest-element-in-a-stream.py create mode 100644 problems/python3/last-stone-weight.py create mode 100644 problems/python3/linked-list-cycle.py create mode 100644 problems/python3/lru-cache.py diff --git a/problems/python3/add-two-numbers.py b/problems/python3/add-two-numbers.py new file mode 100644 index 0000000..ed9dee4 --- /dev/null +++ b/problems/python3/add-two-numbers.py @@ -0,0 +1,19 @@ +class Solution: + def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]: + carry = 0 + dummy = ListNode() + curr = dummy + + while l1 or l2 or carry: + n = (l1.val if l1 else 0) + (l2.val if l2 else 0) + carry + if n>=10: + curr.next = ListNode(n-10) + carry = 1 + else: + curr.next = ListNode(n) + carry = 0 + curr = curr.next + if l1: l1 = l1.next + if l2: l2 = l2.next + + return dummy.next \ No newline at end of file diff --git a/problems/python3/find-the-duplicate-number.py b/problems/python3/find-the-duplicate-number.py new file mode 100644 index 0000000..41636df --- /dev/null +++ b/problems/python3/find-the-duplicate-number.py @@ -0,0 +1,16 @@ +class Solution: + def findDuplicate(self, nums: List[int]) -> int: + head = nums[0] + slow = head + fast = head + + while True: + slow = nums[slow] + fast = nums[nums[fast]] + if slow==fast: break + + slow = head + while slow!=fast: + slow = nums[slow] + fast = nums[fast] + return slow \ No newline at end of file diff --git a/problems/python3/kth-largest-element-in-a-stream.py b/problems/python3/kth-largest-element-in-a-stream.py new file mode 100644 index 0000000..1eb9095 --- /dev/null +++ b/problems/python3/kth-largest-element-in-a-stream.py @@ -0,0 +1,14 @@ +class KthLargest: + + def __init__(self, k: int, nums: List[int]): + self.k = k + self.nums = nums + + heapq.heapify(self.nums) + while len(self.nums)>self.k: heapq.heappop(self.nums) + + + def add(self, val: int) -> int: + heapq.heappush(self.nums, val) + if len(self.nums)>self.k: heapq.heappop(self.nums) + return self.nums[0] \ No newline at end of file diff --git a/problems/python3/last-stone-weight.py b/problems/python3/last-stone-weight.py new file mode 100644 index 0000000..9b30665 --- /dev/null +++ b/problems/python3/last-stone-weight.py @@ -0,0 +1,12 @@ +class Solution: + def lastStoneWeight(self, stones: List[int]) -> int: + stones = [-stone for stone in stones] + heapq.heapify(stones) + + while len(stones)>=2: + w1 = -heapq.heappop(stones) + w2 = -heapq.heappop(stones) + + if w1-w2>0: heapq.heappush(stones, -(w1-w2)) + + return -stones[0] if stones else 0 \ No newline at end of file diff --git a/problems/python3/linked-list-cycle.py b/problems/python3/linked-list-cycle.py new file mode 100644 index 0000000..d2e5395 --- /dev/null +++ b/problems/python3/linked-list-cycle.py @@ -0,0 +1,16 @@ +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + if not head: return False + + slow = head + fast = head + + while fast: + slow = slow.next + + if not fast.next: return False + fast = fast.next.next + + if slow==fast: return True + + return False \ No newline at end of file diff --git a/problems/python3/lru-cache.py b/problems/python3/lru-cache.py new file mode 100644 index 0000000..7cb1822 --- /dev/null +++ b/problems/python3/lru-cache.py @@ -0,0 +1,47 @@ +class Node: + def __init__(self, key: int, val: int): + self.key = key + self.val = val + self.next = None + self.prev = None + +class LRUCache: + + def __init__(self, capacity: int): + self.capacity = capacity + self.dic = {} #[0] + self.head = Node(0, 0) #[3] + self.tail = Node(0, 0) #[3] + self.head.next = self.tail + self.tail.prev = self.head + + def remove(self, node): + node.prev.next = node.next + node.next.prev = node.prev + + def promote(self, node): #[1] + #set the node next to head + temp = self.head.next + node.next = temp + temp.prev = node + self.head.next = node + node.prev = self.head + + def get(self, key: int) -> int: + if key in self.dic: + node = self.dic[key] + self.remove(node) + self.promote(node) + return node.val + return -1 + + def put(self, key: int, value: int) -> None: + if key in self.dic: + self.remove(self.dic[key]) + node = Node(key, value) + self.promote(node) + self.dic[key] = node + + if len(self.dic)>self.capacity: #[2] + del self.dic[self.tail.prev.key] + self.remove(self.tail.prev) From 758ba68d95d77c4fe7e73a3caec7f79331c73fd0 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Thu, 25 Aug 2022 08:36:37 +0200 Subject: [PATCH 175/187] Updates --- problems/python3/design-twitter.py | 49 +++++++++++++++++++ .../python3/find-median-from-data-stream.py | 32 ++++++++++++ .../python3/k-closest-points-to-origin.py | 10 ++++ problems/python3/task-scheduler.py | 23 +++++++++ 4 files changed, 114 insertions(+) create mode 100644 problems/python3/design-twitter.py create mode 100644 problems/python3/find-median-from-data-stream.py create mode 100644 problems/python3/k-closest-points-to-origin.py create mode 100644 problems/python3/task-scheduler.py diff --git a/problems/python3/design-twitter.py b/problems/python3/design-twitter.py new file mode 100644 index 0000000..a2781ae --- /dev/null +++ b/problems/python3/design-twitter.py @@ -0,0 +1,49 @@ +class Twitter: + + def __init__(self): + self.followData = collections.defaultdict(set) + self.tweetData = collections.defaultdict(list) + self.count = 0 + + + def postTweet(self, userId: int, tweetId: int) -> None: + self.tweetData[userId].append((self.count, tweetId)) + self.count -= 1 + + + def getNewsFeed(self, userId: int) -> List[int]: + newsFeed = [] + h = [] + + self.followData[userId].add(userId) + for followeeId in self.followData[userId]: + if followeeId not in self.tweetData: continue + index = len(self.tweetData[followeeId])-1 + count, tweetId = self.tweetData[followeeId][index] + h.append((count, tweetId, followeeId, index-1)) + heapq.heapify(h) + + while h and len(newsFeed)<10: + _, tweetId, userId, index = heapq.heappop(h) + newsFeed.append(tweetId) + if index>=0: + count, tweetId2 = self.tweetData[userId][index] + heapq.heappush(h, (count, tweetId2, userId, index-1)) + return newsFeed + + + + def follow(self, followerId: int, followeeId: int) -> None: + self.followData[followerId].add(followeeId) + + def unfollow(self, followerId: int, followeeId: int) -> None: + if followerId not in self.followData: return + self.followData[followerId].remove(followeeId) + + +# Your Twitter object will be instantiated and called as such: +# obj = Twitter() +# obj.postTweet(userId,tweetId) +# param_2 = obj.getNewsFeed(userId) +# obj.follow(followerId,followeeId) +# obj.unfollow(followerId,followeeId) \ No newline at end of file diff --git a/problems/python3/find-median-from-data-stream.py b/problems/python3/find-median-from-data-stream.py new file mode 100644 index 0000000..f83ee40 --- /dev/null +++ b/problems/python3/find-median-from-data-stream.py @@ -0,0 +1,32 @@ +class MedianFinder: + + def __init__(self): + self.large = [] #store nums larger or equal to the median + self.small = [] #store nums samaller to the median + + def addNum(self, num: int) -> None: + if not self.large and not self.small: + heapq.heappush(self.large, num) + elif num>=self.findMedian(): + heapq.heappush(self.large, num) + self.balance() + else: + heapq.heappush(self.small, -num) + self.balance() + + def balance(self) -> None: + #make the length of two heaps as even as posible + if len(self.large)>len(self.small)+1: + num = heapq.heappop(self.large) + heapq.heappush(self.small, -num) + + if len(self.small)>len(self.large): + num = -heapq.heappop(self.small) + heapq.heappush(self.large, num) + + + def findMedian(self) -> float: + if (len(self.large)+len(self.small))%2==0: + return (self.large[0]-self.small[0])/2 + else: + return self.large[0] \ No newline at end of file diff --git a/problems/python3/k-closest-points-to-origin.py b/problems/python3/k-closest-points-to-origin.py new file mode 100644 index 0000000..8f08e89 --- /dev/null +++ b/problems/python3/k-closest-points-to-origin.py @@ -0,0 +1,10 @@ +class Solution: + def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]: + h = [] + + for x, y in points: + dis = (x**2+y**2)**0.5 + heapq.heappush(h, (-dis, x, y)) + if len(h)>k: heapq.heappop(h) + + return [(x, y) for dis, x, y in h] \ No newline at end of file diff --git a/problems/python3/task-scheduler.py b/problems/python3/task-scheduler.py new file mode 100644 index 0000000..ddc4625 --- /dev/null +++ b/problems/python3/task-scheduler.py @@ -0,0 +1,23 @@ +class Solution: + def leastInterval(self, tasks: List[str], n: int) -> int: + q = collections.deque() + h = [] + time = 0 + + counter = collections.Counter(tasks) + for task in counter: + heapq.heappush(h, (-counter[task], task)) + + while h or q: + if q and q[0][0]<=time: + _, count, task = q.popleft() + heapq.heappush(h, (-count, task)) + + if h: + count, task = heapq.heappop(h) + count*=-1 + count -= 1 + if count>0: q.append((time+n+1, count, task)) + time += 1 + + return time \ No newline at end of file From 91179a34bf0c718a86696aebf151f5e3e1f45101 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Fri, 2 Sep 2022 11:09:53 +0200 Subject: [PATCH 176/187] updates --- problems/python3/merge-intervals.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 problems/python3/merge-intervals.py diff --git a/problems/python3/merge-intervals.py b/problems/python3/merge-intervals.py new file mode 100644 index 0000000..c8a4678 --- /dev/null +++ b/problems/python3/merge-intervals.py @@ -0,0 +1,17 @@ +""" +Time: O(NLogN) for sorting +Space: O(1) excluding the output. +""" +class Solution: + def merge(self, intervals: List[List[int]]) -> List[List[int]]: + ans = [] + intervals.sort() + + for s, e in intervals: + if not ans: + ans.append([s, e]) + elif ans[-1][1]>=s: + ans[-1][1] = max(ans[-1][1], e) + else: + ans.append([s, e]) + return ans \ No newline at end of file From dddf785deb5d9faae06e29b008d7a11aea93e6f5 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Fri, 2 Sep 2022 11:10:23 +0200 Subject: [PATCH 177/187] updates --- problems/python3/insert-interval.py | 23 +++++++++++++++++++ problems/python3/meeting-rooms-ii.py | 12 ++++++++++ problems/python3/meeting-rooms.py | 10 ++++++++ .../minimum-interval-to-include-each-query.py | 23 +++++++++++++++++++ problems/python3/non-overlapping-intervals.py | 17 ++++++++++++++ 5 files changed, 85 insertions(+) create mode 100644 problems/python3/insert-interval.py create mode 100644 problems/python3/meeting-rooms-ii.py create mode 100644 problems/python3/meeting-rooms.py create mode 100644 problems/python3/minimum-interval-to-include-each-query.py create mode 100644 problems/python3/non-overlapping-intervals.py diff --git a/problems/python3/insert-interval.py b/problems/python3/insert-interval.py new file mode 100644 index 0000000..667ba04 --- /dev/null +++ b/problems/python3/insert-interval.py @@ -0,0 +1,23 @@ +class Solution: + def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]: + ans = [] + i = 0 + + #add intervals before newInterval + while i int: + intervals.sort() + h = [] + ans = 0 + + for s, e in intervals: + while h and s>=h[0][0]: + heapq.heappop(h) + heapq.heappush(h, (e, s)) + ans = max(ans, len(h)) + return ans \ No newline at end of file diff --git a/problems/python3/meeting-rooms.py b/problems/python3/meeting-rooms.py new file mode 100644 index 0000000..60cf429 --- /dev/null +++ b/problems/python3/meeting-rooms.py @@ -0,0 +1,10 @@ +class Solution: + def canAttendMeetings(self, intervals: List[List[int]]) -> bool: + intervals.sort() + lastEnd = float('-inf') + for s, e in intervals: + if lastEnd>s: + return False + else: + lastEnd = e + return True \ No newline at end of file diff --git a/problems/python3/minimum-interval-to-include-each-query.py b/problems/python3/minimum-interval-to-include-each-query.py new file mode 100644 index 0000000..ca43de3 --- /dev/null +++ b/problems/python3/minimum-interval-to-include-each-query.py @@ -0,0 +1,23 @@ +class Solution: + def minInterval(self, intervals: List[List[int]], queries: List[int]) -> List[int]: + ans = [-1]*len(queries) + queries = sorted([(query, i) for i, query in enumerate(queries)]) + intervals.sort() + h = [] + + itervalIndex = 0 + for query, queryIndex in queries: + #push all intervals that include 'query' to the min heap + while itervalIndex int: + intervals.sort() + + ans = 0 + prevEnd = intervals[0][1] + + for s, e in intervals[1:]: + if s>=prevEnd: + prevEnd = e + else: + ans += 1 + prevEnd = min(prevEnd, e) + return ans \ No newline at end of file From 5a67c5f093445a44278d7a1e9eeb02c2a5a858fd Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 20 Sep 2022 07:46:21 +0200 Subject: [PATCH 178/187] updates --- problems/python3/clone-graph.py | 16 ++++++ problems/python3/course-schedule-ii.py | 30 +++++++++++ problems/python3/course-schedule.py | 23 ++++++++ ...ign-add-and-search-words-data-structure.py | 33 ++++++++++++ .../python3/implement-trie-prefix-tree.py | 26 +++++++++ problems/python3/max-area-of-island.py | 23 ++++++++ problems/python3/number-of-islands.py | 22 ++++++++ .../python3/pacific-atlantic-water-flow.py | 30 +++++++++++ problems/python3/rotting-oranges.py | 35 ++++++++++++ problems/python3/surrounded-regions.py | 34 ++++++++++++ problems/python3/walls-and-gates.py | 29 ++++++++++ problems/python3/word-search-ii.py | 54 +++++++++++++++++++ 12 files changed, 355 insertions(+) create mode 100644 problems/python3/clone-graph.py create mode 100644 problems/python3/course-schedule-ii.py create mode 100644 problems/python3/course-schedule.py create mode 100644 problems/python3/design-add-and-search-words-data-structure.py create mode 100644 problems/python3/implement-trie-prefix-tree.py create mode 100644 problems/python3/max-area-of-island.py create mode 100644 problems/python3/number-of-islands.py create mode 100644 problems/python3/pacific-atlantic-water-flow.py create mode 100644 problems/python3/rotting-oranges.py create mode 100644 problems/python3/surrounded-regions.py create mode 100644 problems/python3/walls-and-gates.py create mode 100644 problems/python3/word-search-ii.py diff --git a/problems/python3/clone-graph.py b/problems/python3/clone-graph.py new file mode 100644 index 0000000..9a6765f --- /dev/null +++ b/problems/python3/clone-graph.py @@ -0,0 +1,16 @@ +class Solution: + def cloneGraph(self, start: 'Node') -> 'Node': + def dfs(node): + if node in clones: return clones[node] + + copy = Node(node.val) + clones[node] = copy + + for neighbor in node.neighbors: + copy.neighbors.append(dfs(neighbor)) + + return clones[node] + if not start: return start + clones = {} + dfs(start) + return clones[start] \ No newline at end of file diff --git a/problems/python3/course-schedule-ii.py b/problems/python3/course-schedule-ii.py new file mode 100644 index 0000000..00725b4 --- /dev/null +++ b/problems/python3/course-schedule-ii.py @@ -0,0 +1,30 @@ +#Topological Sort +class Solution: + def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]: + sortedCourse = [] + G = collections.defaultdict(list) #graph + inbounds = collections.Counter() + q = collections.deque() + + #build graph + for c1, c2 in prerequisites: + G[c2].append(c1) + inbounds[c1] += 1 + + #add the starting point to the q. (the ones that have 0 inbounds) + for course in range(numCourses): + if inbounds[course]==0: q.append(course) + + #add the course that have 0 inbounds to the sortedCourse. + #after that, imagine we remove it from the graph, so nextCourse inbound will -1 + #add to q if nextCourse have 0 inbounds + while q: + course = q.popleft() + + sortedCourse.append(course) + + for nextCourse in G[course]: + inbounds[nextCourse] -= 1 + if inbounds[nextCourse]==0: q.append(nextCourse) + + return sortedCourse if len(sortedCourse)==numCourses else [] \ No newline at end of file diff --git a/problems/python3/course-schedule.py b/problems/python3/course-schedule.py new file mode 100644 index 0000000..f52d07d --- /dev/null +++ b/problems/python3/course-schedule.py @@ -0,0 +1,23 @@ +class Solution: + def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool: + sortedCourse = [] + inbounds = collections.Counter() + G = collections.defaultdict(list) + q = collections.deque() + + for c1, c2 in prerequisites: + G[c2].append(c1) + inbounds[c1] += 1 + + for c in range(numCourses): + if inbounds[c]==0: q.append(c) + + while q: + c = q.popleft() + + for c2 in G[c]: + inbounds[c2] -= 1 + if inbounds[c2]==0: q.append(c2) + sortedCourse.append(c) + + return len(sortedCourse)==numCourses \ No newline at end of file diff --git a/problems/python3/design-add-and-search-words-data-structure.py b/problems/python3/design-add-and-search-words-data-structure.py new file mode 100644 index 0000000..52effc8 --- /dev/null +++ b/problems/python3/design-add-and-search-words-data-structure.py @@ -0,0 +1,33 @@ +class WordDictionary: + + def __init__(self): + self.root = {} + + def addWord(self, word: str) -> None: + node = self.root + for c in word: + if c not in node: node[c] = {} + node = node[c] + node['$'] = {} #'.' means the end of the word + + def search(self, word: str) -> bool: + def helper(node, i): + if i==len(word): return '$' in node + + if word[i]=='.': + for c in node: + if helper(node[c], i+1): return True + return False + else: + if word[i] not in node: return False + return helper(node[word[i]], i+1) + return helper(self.root, 0) + + + + + + + + + \ No newline at end of file diff --git a/problems/python3/implement-trie-prefix-tree.py b/problems/python3/implement-trie-prefix-tree.py new file mode 100644 index 0000000..1118e97 --- /dev/null +++ b/problems/python3/implement-trie-prefix-tree.py @@ -0,0 +1,26 @@ +class Trie: + + def __init__(self): + self.root = {} + + def insert(self, word: str) -> None: + node = self.root + for c in word: + if c not in node: node[c] = {} + node = node[c] + node['.'] = {} #'.' means the end of the word + + + def search(self, word: str) -> bool: + node = self.root + for c in word: + if c not in node: return False + node = node[c] + return '.' in node + + def startsWith(self, prefix: str) -> bool: + node = self.root + for c in prefix: + if c not in node: return False + node = node[c] + return True diff --git a/problems/python3/max-area-of-island.py b/problems/python3/max-area-of-island.py new file mode 100644 index 0000000..fd55a94 --- /dev/null +++ b/problems/python3/max-area-of-island.py @@ -0,0 +1,23 @@ +class Solution: + def maxAreaOfIsland(self, grid: List[List[int]]) -> int: + def dfs(i, j) -> int: + if i<0 or j<0 or i>=MAX_ROW or j>=MAX_COL: return 0 + if grid[i][j]==0 or grid[i][j]==2: return 0 + + grid[i][j] = 2 #mark as visited + + area = 1 + area += dfs(i+1, j) + area += dfs(i-1, j) + area += dfs(i, j+1) + area += dfs(i, j-1) + return area + + ans = 0 + MAX_ROW = len(grid) + MAX_COL = len(grid[0]) + + for i in range(MAX_ROW): + for j in range(MAX_COL): + ans = max(ans, dfs(i, j)) + return ans \ No newline at end of file diff --git a/problems/python3/number-of-islands.py b/problems/python3/number-of-islands.py new file mode 100644 index 0000000..6cc325e --- /dev/null +++ b/problems/python3/number-of-islands.py @@ -0,0 +1,22 @@ +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + def dfs(i, j): + if i<0 or j<0 or i>=MAX_ROWS or j>=MAX_COLS: return + if grid[i][j]!='1': return + + grid[i][j] = '2' + dfs(i+1, j) + dfs(i-1, j) + dfs(i, j+1) + dfs(i, j-1) + + count = 0 + MAX_ROWS = len(grid) + MAX_COLS = len(grid[0]) + + for i in range(MAX_ROWS): + for j in range(MAX_COLS): + if grid[i][j]=='1': + dfs(i, j) + count += 1 + return count \ No newline at end of file diff --git a/problems/python3/pacific-atlantic-water-flow.py b/problems/python3/pacific-atlantic-water-flow.py new file mode 100644 index 0000000..05032b0 --- /dev/null +++ b/problems/python3/pacific-atlantic-water-flow.py @@ -0,0 +1,30 @@ +class Solution: + def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]: + def bfs(q, ocian): + while q: + i0, j0 = q.popleft() + if (i0, j0) in ocian: continue + ocian.add((i0, j0)) + + for i, j in ((i0+1, j0), (i0-1, j0), (i0, j0+1), (i0, j0-1)): + if i<0 or j<0 or i>=MAX_ROW or j>=MAX_COL: continue + if heights[i][j]>=heights[i0][j0]: q.append((i, j)) + + MAX_ROW = len(heights) + MAX_COL = len(heights[0]) + + #add the top and left to q1 + pacific = set() + q1 = collections.deque() + for j in range(MAX_COL): q1.append((0, j)) + for i in range(MAX_ROW): q1.append((i, 0)) + + #add botton and right to q2 + atlantic = set() + q2 = collections.deque() + for j in range(MAX_COL): q2.append((MAX_ROW-1, j)) + for i in range(MAX_ROW): q2.append((i, MAX_COL-1)) + + bfs(q1, pacific) + bfs(q2, atlantic) + return pacific.intersection(atlantic) \ No newline at end of file diff --git a/problems/python3/rotting-oranges.py b/problems/python3/rotting-oranges.py new file mode 100644 index 0000000..2e1216a --- /dev/null +++ b/problems/python3/rotting-oranges.py @@ -0,0 +1,35 @@ +class Solution: + def orangesRotting(self, grid: List[List[int]]) -> int: + time = 0 + rotten = set() + aboutToRot = set() + fresh = set() + + for i in range(len(grid)): + for j in range((len(grid[0]))): + if grid[i][j]==2: + rotten.add((i, j)) + elif grid[i][j]==1: + fresh.add((i, j)) + + while rotten: + i0, j0 = rotten.pop() #randomly get one + grid[i0][j0] = 2 + + for i, j in ((i0+1, j0), (i0-1, j0), (i0, j0+1), (i0, j0-1)): + if i<0 or j<0 or i>=len(grid) or j>=len(grid[0]): continue + if (i, j) in rotten or (i, j) in aboutToRot: continue + if (i, j) in fresh: + fresh.remove((i, j)) + aboutToRot.add((i, j)) + + if not rotten and not aboutToRot: break + + if not rotten: + time += 1 + rotten = aboutToRot + aboutToRot = set() + + if fresh: return -1 + + return time \ No newline at end of file diff --git a/problems/python3/surrounded-regions.py b/problems/python3/surrounded-regions.py new file mode 100644 index 0000000..42aa4c0 --- /dev/null +++ b/problems/python3/surrounded-regions.py @@ -0,0 +1,34 @@ +""" +Time: O(N) +Space: O(N) +""" +class Solution: + def solve(self, board: List[List[str]]) -> None: + def dfs(i0, j0): + if i0<0 or j0<0 or i0>=MAX_ROW or j0>=MAX_COL: return + if board[i0][j0]!='O': return + if (i0, j0) in survived: return + + survived.add((i0, j0)) + dfs(i0+1, j0) + dfs(i0-1, j0) + dfs(i0, j0+1) + dfs(i0, j0-1) + + + MAX_ROW = len(board) + MAX_COL = len(board[0]) + survived = set() + + for i in range(MAX_ROW): + dfs(i, 0) + dfs(i, MAX_COL-1) + + for j in range(MAX_COL): + dfs(0, j) + dfs(MAX_ROW-1, j) + + for i in range(MAX_ROW): + for j in range(MAX_COL): + board[i][j] = 'O' if (i, j) in survived else 'X' + return board \ No newline at end of file diff --git a/problems/python3/walls-and-gates.py b/problems/python3/walls-and-gates.py new file mode 100644 index 0000000..5f27f9a --- /dev/null +++ b/problems/python3/walls-and-gates.py @@ -0,0 +1,29 @@ +class Solution: + def wallsAndGates(self, rooms: List[List[int]]) -> None: + def bfs(i0, j0) -> None: + q = collections.deque([(i0+1, j0, 1), (i0-1, j0, 1), (i0, j0+1, 1), (i0, j0-1, 1)]) + visited = set() + + while q: + i, j, dis = q.popleft() + + if i<0 or j<0 or i>=MAX_ROW or j>=MAX_COL: continue + if rooms[i][j]==0 or rooms[i][j]==-1: continue + if (i, j, dis) in visited: continue + visited.add((i, j, dis)) + + if dis List[str]: + def dfs(r, c, node, word): + if c<0 or r<0 or c==COLS or r==ROWS: return + if board[r][c] not in node.children: return + if (r, c) in visited: return + + visited.add((r, c)) + node = node.children[board[r][c]] + word += board[r][c] + if node.isEnd: + ans.add(word) + node.isEnd = False + + dfs(r+1, c, node, word) + dfs(r-1, c, node, word) + dfs(r, c+1, node, word) + dfs(r, c-1, node, word) + + visited.remove((r, c)) + + + root = TrieNode() + for word in words: + root.addWord(word) + + ROWS = len(board) + COLS = len(board[0]) + + visited = set() + ans = set() + node = root + for r in range(ROWS): + for c in range(COLS): + dfs(r, c, root, '') + return ans \ No newline at end of file From 02d6d3b63e5ffcbb88eb4b893b94499411f7d60b Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sun, 25 Sep 2022 10:46:21 +0200 Subject: [PATCH 179/187] update --- problems/python3/graph-valid-tree.py | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 problems/python3/graph-valid-tree.py diff --git a/problems/python3/graph-valid-tree.py b/problems/python3/graph-valid-tree.py new file mode 100644 index 0000000..2168e9a --- /dev/null +++ b/problems/python3/graph-valid-tree.py @@ -0,0 +1,33 @@ +class Solution: + def validTree(self, N: int, edges: List[List[int]]) -> bool: + def union(n1, n2) -> bool: + p1 = find(n1) + p2 = find(n2) + + if p1==p2: + return False + elif p1 int: + p = parents[n] + while p!=parents[p]: p = find(p) + parents[n] = p + return p + + parents = [n for n in range(N)] + + for n1, n2 in edges: + if not union(n1, n2): return False + + #check if all node trace back to the same root + root = find(0) + for n in range(1, N): + if root!=find(n): return False + + return True \ No newline at end of file From 3af72365974096fdff631de776b4a26384012e91 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sun, 25 Sep 2022 10:46:41 +0200 Subject: [PATCH 180/187] updates --- ...ected-components-in-an-undirected-graph.py | 25 +++++++++++++++ problems/python3/redundant-connection.py | 32 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 problems/python3/number-of-connected-components-in-an-undirected-graph.py create mode 100644 problems/python3/redundant-connection.py diff --git a/problems/python3/number-of-connected-components-in-an-undirected-graph.py b/problems/python3/number-of-connected-components-in-an-undirected-graph.py new file mode 100644 index 0000000..28571ea --- /dev/null +++ b/problems/python3/number-of-connected-components-in-an-undirected-graph.py @@ -0,0 +1,25 @@ +class Solution: + def countComponents(self, N: int, edges: List[List[int]]) -> int: + def union(n1, n2): + p1 = find(n1) + p2 = find(n2) + if p1==p2: + return + elif p1 List[int]: + def union(n1, n2): + p1 = find(n1) + p2 = find(n2) + + if p1==p2: + return False #union failed, already united. + elif p1 Date: Sat, 8 Oct 2022 10:26:40 +0200 Subject: [PATCH 181/187] updates --- problems/python3/alien-dictionary.py | 36 +++++++++++++++++ .../cheapest-flights-within-k-stops.py | 17 ++++++++ problems/python3/climbing-stairs.py | 10 +++++ problems/python3/min-cost-climbing-stairs.py | 16 ++++++++ .../python3/min-cost-to-connect-all-points.py | 28 +++++++++++++ problems/python3/network-delay-time.py | 23 +++++++++++ problems/python3/reconstruct-itinerary.py | 27 +++++++++++++ problems/python3/swim-in-rising-water.py | 23 +++++++++++ problems/python3/word-ladder.py | 40 +++++++++++++++++++ 9 files changed, 220 insertions(+) create mode 100644 problems/python3/alien-dictionary.py create mode 100644 problems/python3/cheapest-flights-within-k-stops.py create mode 100644 problems/python3/climbing-stairs.py create mode 100644 problems/python3/min-cost-climbing-stairs.py create mode 100644 problems/python3/min-cost-to-connect-all-points.py create mode 100644 problems/python3/network-delay-time.py create mode 100644 problems/python3/reconstruct-itinerary.py create mode 100644 problems/python3/swim-in-rising-water.py create mode 100644 problems/python3/word-ladder.py diff --git a/problems/python3/alien-dictionary.py b/problems/python3/alien-dictionary.py new file mode 100644 index 0000000..23ca1ee --- /dev/null +++ b/problems/python3/alien-dictionary.py @@ -0,0 +1,36 @@ +class Solution: + def alienOrder(self, words: List[str]) -> str: + adj = collections.defaultdict(list) + inbounds = collections.Counter() + q = collections.deque() + ans = '' + + adj = {c: set() for word in words for c in word} + for i in range(len(words)-1): + w1, w2 = words[i], words[i+1] + minLen = min(len(w1), len(w2)) + if w1[:minLen]==w2[:minLen] and len(w1)>len(w2): return "" + + for j in range(minLen): + if w1[j]!=w2[j]: + adj[w1[j]].add(w2[j]) + break + + for c in adj: + for nc in list(adj[c]): + inbounds[nc] += 1 + + for c in adj: + if inbounds[c]==0: q.append(c) + + while q: + c = q.popleft() + + ans += c + + for nc in adj[c]: + inbounds[nc] -= 1 + if inbounds[nc]==0: q.append(nc) + + return ans if len(ans)==len(adj) else '' + diff --git a/problems/python3/cheapest-flights-within-k-stops.py b/problems/python3/cheapest-flights-within-k-stops.py new file mode 100644 index 0000000..4595802 --- /dev/null +++ b/problems/python3/cheapest-flights-within-k-stops.py @@ -0,0 +1,17 @@ +""" +Bellman-Ford. +Time: O(KE) +""" +class Solution: + def findCheapestPrice(self, N: int, flights: List[List[int]], src: int, dst: int, K: int) -> int: + prices = {n:float('inf') for n in range(N)} + prices[src] = 0 + + for k in range(K+1): + temp = prices.copy() + for source, destination, price in flights: + if prices[source]==float('inf'): continue + if prices[source]+price int: + dp = [0]*(N+1) + dp[0] = 1 + for i in range(len(dp)): + if i-1>=0: + dp[i] += dp[i-1] + if i-2>=0: + dp[i] += dp[i-2] + return dp[-1] \ No newline at end of file diff --git a/problems/python3/min-cost-climbing-stairs.py b/problems/python3/min-cost-climbing-stairs.py new file mode 100644 index 0000000..c59c446 --- /dev/null +++ b/problems/python3/min-cost-climbing-stairs.py @@ -0,0 +1,16 @@ +""" +Time: O(N) +Space: O(N), can further reduce to using only 2 variables -> O(1). + +dp[i] := the cost to get to index i. +""" +class Solution: + def minCostClimbingStairs(self, cost: List[int]) -> int: + N = len(cost) + dp = [float('inf')]*(N+1) + dp[0] = 0 + dp[1] = 0 + + for i in range(2, len(dp)): + dp[i] = min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2]) + return dp[-1] \ No newline at end of file diff --git a/problems/python3/min-cost-to-connect-all-points.py b/problems/python3/min-cost-to-connect-all-points.py new file mode 100644 index 0000000..4cd6ada --- /dev/null +++ b/problems/python3/min-cost-to-connect-all-points.py @@ -0,0 +1,28 @@ +class Solution: + def minCostConnectPoints(self, points: List[List[int]]) -> int: + ans = 0 + visited = set() + adj = collections.defaultdict(list) + N = len(points) + + #build adjacency list + for i in range(N): + x0, y0 = points[i] + for j in range(i+1, N): + x1, y1 = points[j] + dis = abs(x0-x1)+abs(y0-y1) + adj[(x0, y0)].append((dis, x1, y1)) + adj[(x1, y1)].append((dis, x0, y0)) + + h = [(0, points[0][0], points[0][1])] #min heap + while len(visited) int: + ans = 0 + adj = collections.defaultdict(list) + h = [] + visited = set() + + for u, v, w in times: + adj[u].append((v, w)) + + heapq.heappush(h, (0, k)) + while h: + timeNeededToGetHere, node = heapq.heappop(h) + + if node in visited: continue + visited.add(node) + ans = max(ans, timeNeededToGetHere) + + for nei, time in adj[node]: + if nei in visited: continue + heapq.heappush(h, (time+timeNeededToGetHere, nei)) + + return ans if len(visited)==n else -1 \ No newline at end of file diff --git a/problems/python3/reconstruct-itinerary.py b/problems/python3/reconstruct-itinerary.py new file mode 100644 index 0000000..14c928f --- /dev/null +++ b/problems/python3/reconstruct-itinerary.py @@ -0,0 +1,27 @@ +""" +DFS with backtracking. +""" +class Solution: + def findItinerary(self, tickets: List[List[str]]) -> List[str]: + def dfs(start) -> bool: + if len(ans)==len(tickets)+1: return True + if start not in adj: return False + + temp = list(adj[start]) + for i, arr in enumerate(temp): + adj[start].pop(i) + ans.append(arr) + if dfs(arr): return True + adj[start].insert(i, arr) + ans.pop() + return False + + ans = ['JFK'] + adj = collections.defaultdict(list) + + tickets.sort() + for des, arr in tickets: + adj[des].append(arr) + + dfs('JFK') + return ans \ No newline at end of file diff --git a/problems/python3/swim-in-rising-water.py b/problems/python3/swim-in-rising-water.py new file mode 100644 index 0000000..dd5dbef --- /dev/null +++ b/problems/python3/swim-in-rising-water.py @@ -0,0 +1,23 @@ +""" +Time: O(N^2 * LogN^2) = O(N^2 * 2LogN) = O(N^2LogN), N is the number of elements in a row or column. +Space: O(N^2) +""" +class Solution: + def swimInWater(self, grid: List[List[int]]) -> int: + ROWS = len(grid) + COLS = len(grid[0]) + + visited = set() + h = [(grid[0][0], 0, 0)] + + while h: + t, r0, c0 = heapq.heappop(h) + + if (r0, c0) in visited: continue + visited.add((r0, c0)) + if r0==ROWS-1 and c0==COLS-1: return t + + for r, c in ((r0+1, c0), (r0-1, c0), (r0, c0+1), (r0, c0-1)): + if r<0 or c<0 or r>=ROWS or c>=COLS: continue + if (r, c) in visited: continue + heapq.heappush(h, (max(t, grid[r][c]), r, c)) \ No newline at end of file diff --git a/problems/python3/word-ladder.py b/problems/python3/word-ladder.py new file mode 100644 index 0000000..453fb4a --- /dev/null +++ b/problems/python3/word-ladder.py @@ -0,0 +1,40 @@ +""" +Time: O(NxM^2). N is the number of words. M is the length of the word. +Note that, getPatterns() takes O(M^2) since creating new string will also takes O(M) and for each word we do that O(M) times. + +Space: O(NxM^2) +""" +class Solution: + def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: + def getPatterns(word) -> List[str]: + patterns = [] + for i in range(len(word)): + pattern = word[:i]+'*'+word[i+1:] + patterns.append(pattern) + return patterns + + + if endWord not in wordList: return 0 + wordList.append(beginWord) + + #build adjacency list + nei = collections.defaultdict(list) + for word in wordList: + for pattern in getPatterns(word): + nei[pattern].append(word) + + #BFS + q = collections.deque([(beginWord, 1)]) + visited = set() + while q: + word, steps = q.popleft() + + if word in visited: continue + visited.add(word) + if word==endWord: return steps + + for pattern in getPatterns(word): + for nextWord in nei[pattern]: + if nextWord in visited: continue + q.append((nextWord, steps+1)) + return 0 \ No newline at end of file From 82ca4d9a5ff1a4e3efce92cfaa0bc067394e16dc Mon Sep 17 00:00:00 2001 From: wuduhren Date: Tue, 1 Nov 2022 08:24:43 +0100 Subject: [PATCH 182/187] updates --- problems/python3/coin-change.py | 14 ++++++ problems/python3/decode-ways.py | 14 ++++++ problems/python3/house-robber-ii.py | 18 ++++++++ problems/python3/house-robber.py | 17 +++++++ .../python3/longest-common-subsequence.py | 16 +++++++ .../python3/longest-palindromic-substring.py | 45 +++++++++++++++++++ problems/python3/maximum-product-subarray.py | 25 +++++++++++ problems/python3/palindromic-substrings.py | 16 +++++++ .../python3/partition-equal-subset-sum.py | 20 +++++++++ problems/python3/unique-paths.py | 11 +++++ problems/python3/word-break.py | 23 ++++++++++ 11 files changed, 219 insertions(+) create mode 100644 problems/python3/coin-change.py create mode 100644 problems/python3/decode-ways.py create mode 100644 problems/python3/house-robber-ii.py create mode 100644 problems/python3/house-robber.py create mode 100644 problems/python3/longest-common-subsequence.py create mode 100644 problems/python3/longest-palindromic-substring.py create mode 100644 problems/python3/maximum-product-subarray.py create mode 100644 problems/python3/palindromic-substrings.py create mode 100644 problems/python3/partition-equal-subset-sum.py create mode 100644 problems/python3/unique-paths.py create mode 100644 problems/python3/word-break.py diff --git a/problems/python3/coin-change.py b/problems/python3/coin-change.py new file mode 100644 index 0000000..19571e4 --- /dev/null +++ b/problems/python3/coin-change.py @@ -0,0 +1,14 @@ +class Solution: + def coinChange(self, coins: List[int], amount: int) -> int: + dp = [float('inf')]*(amount+1) + dp[0] = 0 + for coin in coins: + if coin int: + mapping = set([str(n) for n in range(1, 27)]) + N = len(s) + dp = [0]*(N+1) + dp[0] = 1 + + for i in range(1, N+1): + if i-1>=0 and s[i-1] in mapping: dp[i] += dp[i-1] + if i-2>=0 and s[i-2:i] in mapping: dp[i] += dp[i-2] + return dp[-1] \ No newline at end of file diff --git a/problems/python3/house-robber-ii.py b/problems/python3/house-robber-ii.py new file mode 100644 index 0000000..1ed9b82 --- /dev/null +++ b/problems/python3/house-robber-ii.py @@ -0,0 +1,18 @@ +class Solution: + def rob(self, nums: List[int]) -> int: + if len(nums)<=1: return max(nums) + + N = len(nums) + dp = [[0, 0] for _ in range(N)] + dp[0][0] = nums[0] + + for i in range(1, N): + dp[i][0] = nums[i]+dp[i-1][1] + dp[i][1] = max(dp[i-1]) + + dp2 = [[0, 0] for _ in range(N)] + for i in range(1, N): + dp2[i][0] = nums[i]+dp2[i-1][1] + dp2[i][1] = max(dp2[i-1]) + + return max(dp[-1][1], dp2[-1][0]) \ No newline at end of file diff --git a/problems/python3/house-robber.py b/problems/python3/house-robber.py new file mode 100644 index 0000000..fbd86a5 --- /dev/null +++ b/problems/python3/house-robber.py @@ -0,0 +1,17 @@ +""" +Time: O(N) +Space: O(N), can reduece to O(1). + +dp[i][0] := max revenue if house i robbed +dp[i][1] := max revenue if house i not robbed +""" +class Solution: + def rob(self, nums: List[int]) -> int: + N = len(nums) + dp = [[0, 0] for _ in range(N)] + dp[0][0] = nums[0] + + for i in range(1, N): + dp[i][0] = nums[i]+dp[i-1][1] + dp[i][1] = max(dp[i-1]) + return max(dp[-1]) \ No newline at end of file diff --git a/problems/python3/longest-common-subsequence.py b/problems/python3/longest-common-subsequence.py new file mode 100644 index 0000000..5ba3a68 --- /dev/null +++ b/problems/python3/longest-common-subsequence.py @@ -0,0 +1,16 @@ +class Solution: + def longestCommonSubsequence(self, text1: str, text2: str) -> int: + #dp[i][j] := number of longest Common Subsequence with text2[:i] and text2[:j] + + N = len(text1) + M = len(text2) + + dp = [[0]*(M+1) for _ in range(N+1)] + + for i in range(1, N+1): + for j in range(1, M+1): + if text1[i-1]==text2[j-1]: + dp[i][j] = dp[i-1][j-1]+1 + else: + dp[i][j] = max(dp[i][j-1], dp[i-1][j]) + return dp[-1][-1] \ No newline at end of file diff --git a/problems/python3/longest-palindromic-substring.py b/problems/python3/longest-palindromic-substring.py new file mode 100644 index 0000000..9edb477 --- /dev/null +++ b/problems/python3/longest-palindromic-substring.py @@ -0,0 +1,45 @@ +""" +Time: O(N^2) +Space: O(N^2) + +DP, TLE +""" +class Solution: + def longestPalindrome(self, s: str) -> str: + ans = s[0] + N = len(s) + dp = [[False]*N for _ in range(N)] + + for i in range(N): dp[i][i] = True + + for l in range(2, N+1): + for i in range(N): + j = i+l-1 + if j>=N: continue + dp[i][j] = s[i]==s[j] and (dp[i+1][j-1] or j-1 str: + N = len(s) + ans = s[0] + + for i in range(N): + l, r = i, i + while l>=0 and rlen(ans): ans = s[l:r+1] + l -= 1 + r += 1 + + l, r = i, i+1 + while l>=0 and rlen(ans): ans = s[l:r+1] + l -= 1 + r += 1 + return ans \ No newline at end of file diff --git a/problems/python3/maximum-product-subarray.py b/problems/python3/maximum-product-subarray.py new file mode 100644 index 0000000..243bf41 --- /dev/null +++ b/problems/python3/maximum-product-subarray.py @@ -0,0 +1,25 @@ +""" +Time: O(N) +Space: O(N), can be reduce to O(1) + +dp[i][0] := The max product from subarray that end with nums[i] +dp[i][1] := The min product from subarray that end with nums[i] +""" +class Solution: + def maxProduct(self, nums: List[int]) -> int: + N = len(nums) + dp = [[1, 1] for _ in range(N+1)] + ans = float('-inf') + + for i in range(1, N+1): + dp[i][0] = dp[i][1] = nums[i-1] + + if nums[i-1]>0: + dp[i][0] = max(dp[i][0], nums[i-1]*dp[i-1][0]) + dp[i][1] = min(dp[i][1], nums[i-1]*dp[i-1][1]) + else: + dp[i][0] = max(dp[i][0], nums[i-1]*dp[i-1][1]) + dp[i][1] = min(dp[i][1], nums[i-1]*dp[i-1][0]) + ans = max(ans, dp[i][0]) + + return ans \ No newline at end of file diff --git a/problems/python3/palindromic-substrings.py b/problems/python3/palindromic-substrings.py new file mode 100644 index 0000000..7ef7e96 --- /dev/null +++ b/problems/python3/palindromic-substrings.py @@ -0,0 +1,16 @@ +class Solution: + def countSubstrings(self, s: str) -> int: + def countPalindrome(l, r) -> int: + count = 0 + while l>=0 and r bool: + total = sum(nums) + if total%2!=0: return False + + target = total/2 + possibleSum = set() + possibleSum.add(0) + for num in nums: + temp = set() + for p in possibleSum: + if p==target or p+num==target: return True + temp.add(p) + temp.add(p+num) + possibleSum = temp + return False \ No newline at end of file diff --git a/problems/python3/unique-paths.py b/problems/python3/unique-paths.py new file mode 100644 index 0000000..9c7ce40 --- /dev/null +++ b/problems/python3/unique-paths.py @@ -0,0 +1,11 @@ +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + m = m-1 #number of steps need to move down + n = n-1 #number of steps need to move right + + #the total combination of m and n to sort will be (m+n)! + #since all "move down" are consider the same, we need to remove the repeatition of it sorting: m!. + #since all "move right" are consider the same, we need to remove the repeatition of it sorting: n!. + #(m+n)!/m!n! + + return math.factorial(m+n)//(math.factorial(m)*math.factorial(n)) \ No newline at end of file diff --git a/problems/python3/word-break.py b/problems/python3/word-break.py new file mode 100644 index 0000000..8d2c817 --- /dev/null +++ b/problems/python3/word-break.py @@ -0,0 +1,23 @@ +""" +Time: O(N^2 * M). N is the length of the s. M is the number of word in wordDict. +Note that s[i:i+len(word)]==word takes O(N) time. + +Space: O(N) for the recursion memory stack size. + +dfs(i) := will return starting at index i, if i to the end the string can be separated. +""" +class Solution: + def wordBreak(self, s: str, wordDict: List[str]) -> bool: + def dfs(i): + if i==len(s): return True + if i in history and not history[i]: return False + + for word in wordDict: + if i+len(word)<=len(s) and s[i:i+len(word)]==word: + history[i] = True + if dfs(i+len(word)): return True + history[i] = False + return False + + history = {} + return dfs(0) \ No newline at end of file From bcef8a4a0835589cc686a72614455ac723caef94 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Sun, 27 Nov 2022 10:41:31 +0100 Subject: [PATCH 183/187] updates --- ...ime-to-buy-and-sell-stock-with-cooldown.py | 16 ++++++++ problems/python3/burst-balloons.py | 28 ++++++++++++++ problems/python3/coin-change-ii.py | 12 ++++++ problems/python3/counting-bits.py | 9 +++++ problems/python3/distinct-subsequences.py | 17 +++++++++ problems/python3/edit-distance.py | 37 +++++++++++++++++++ problems/python3/interleaving-string.py | 13 +++++++ .../longest-increasing-path-in-a-matrix.py | 26 +++++++++++++ problems/python3/number-of-1-bits.py | 10 +++++ .../python3/regular-expression-matching.py | 24 ++++++++++++ problems/python3/reverse-bits.py | 7 ++++ problems/python3/single-number.py | 15 ++++++++ problems/python3/target-sum.py | 25 +++++++++++++ 13 files changed, 239 insertions(+) create mode 100644 problems/python3/best-time-to-buy-and-sell-stock-with-cooldown.py create mode 100644 problems/python3/burst-balloons.py create mode 100644 problems/python3/coin-change-ii.py create mode 100644 problems/python3/counting-bits.py create mode 100644 problems/python3/distinct-subsequences.py create mode 100644 problems/python3/edit-distance.py create mode 100644 problems/python3/interleaving-string.py create mode 100644 problems/python3/longest-increasing-path-in-a-matrix.py create mode 100644 problems/python3/number-of-1-bits.py create mode 100644 problems/python3/regular-expression-matching.py create mode 100644 problems/python3/reverse-bits.py create mode 100644 problems/python3/single-number.py create mode 100644 problems/python3/target-sum.py diff --git a/problems/python3/best-time-to-buy-and-sell-stock-with-cooldown.py b/problems/python3/best-time-to-buy-and-sell-stock-with-cooldown.py new file mode 100644 index 0000000..06644e3 --- /dev/null +++ b/problems/python3/best-time-to-buy-and-sell-stock-with-cooldown.py @@ -0,0 +1,16 @@ +#dp[i][0] := max profit when last action is buy +#dp[i][1] := max profit when last action is sell +class Solution: + def maxProfit(self, prices: List[int]) -> int: + if not prices or len(prices)<=1: return 0 + + N = len(prices) + dp = [[0, 0] for _ in range(N)] + dp[0] = [-prices[0], 0] + dp[1][0] = max(-prices[1], -prices[0]) + dp[1][1] = max(prices[1]+dp[0][0], dp[0][1]) + + for i in range(2, N): + dp[i][0] = max(dp[i-2][1]-prices[i], dp[i-1][0]) + dp[i][1] = max(prices[i]+dp[i-1][0], dp[i-1][1]) + return max(dp[-1][0], dp[-1][1], 0) \ No newline at end of file diff --git a/problems/python3/burst-balloons.py b/problems/python3/burst-balloons.py new file mode 100644 index 0000000..aae31be --- /dev/null +++ b/problems/python3/burst-balloons.py @@ -0,0 +1,28 @@ +""" +dfs(l, r) return the max coins that we can get at range l to r. + +``` +for i in range(l, r+1): + dp[(l, r)] = max(dp[(l, r)], nums[l-1]*nums[i]*nums[r+1] + dfs(l, i-1) + dfs(i+1, r)) +``` +Assuming i is the last one we extract, the max coins we can get. + +Start from the last becasue, we are not able to track the neighbor if we start from the first we extract. + +Time: O(N^3) +Space: O(N^2) +""" +class Solution: + def maxCoins(self, nums: List[int]) -> int: + def dfs(l, r)->int: + if l>r: return 0 + if (l, r) in dp: return dp[(l, r)] + + dp[(l, r)] = 0 + for i in range(l, r+1): + dp[(l, r)] = max(dp[(l, r)], nums[l-1]*nums[i]*nums[r+1] + dfs(l, i-1) + dfs(i+1, r)) + return dp[(l, r)] + + nums = [1]+nums+[1] + dp = {} + return dfs(1, len(nums)-2) \ No newline at end of file diff --git a/problems/python3/coin-change-ii.py b/problems/python3/coin-change-ii.py new file mode 100644 index 0000000..8b4ad26 --- /dev/null +++ b/problems/python3/coin-change-ii.py @@ -0,0 +1,12 @@ +class Solution: + def change(self, amount: int, coins: List[int]) -> int: + dp = [0]*(amount+1) + dp[0] = 1 + + coins.sort() + + for coin in coins: + for a in range(1, amount+1): + if a-coin<0: continue + dp[a] += dp[a-coin] + return dp[-1] \ No newline at end of file diff --git a/problems/python3/counting-bits.py b/problems/python3/counting-bits.py new file mode 100644 index 0000000..7325596 --- /dev/null +++ b/problems/python3/counting-bits.py @@ -0,0 +1,9 @@ +class Solution: + def countBits(self, n: int) -> List[int]: + ans = [0]*(n+1) + offset = 1 + + for i in range(1, n+1): + if offset*2==i: offset = offset*2 + ans[i] = 1+ans[i-offset] + return ans \ No newline at end of file diff --git a/problems/python3/distinct-subsequences.py b/problems/python3/distinct-subsequences.py new file mode 100644 index 0000000..d84fcf6 --- /dev/null +++ b/problems/python3/distinct-subsequences.py @@ -0,0 +1,17 @@ +class Solution: + def numDistinct(self, s: str, t: str) -> int: + def dfs(i, j): + if (i, j) in visited: return visited[(i, j)] + + if j>=len(t): return 1 + if i>=len(s): return 0 + + if s[i]==t[j]: + visited[(i, j)] = dfs(i+1, j+1)+dfs(i+1, j) + else: + visited[(i, j)] = dfs(i+1, j) + return visited[(i, j)] + + visited = {} + dfs(0, 0) + return dfs(0, 0) \ No newline at end of file diff --git a/problems/python3/edit-distance.py b/problems/python3/edit-distance.py new file mode 100644 index 0000000..c8fa8f4 --- /dev/null +++ b/problems/python3/edit-distance.py @@ -0,0 +1,37 @@ +""" +dfs(i, j) +i being the unprocessed index in word1. +j, word2. + +MAIN LOGIC: +if word1[i]==word2[j], no operation need, return dfs(i+1, j+1) +if not, need 1 operation, so +replace: dfs(i+1, j+1) +insert: dfs(i, j+1) +delete: dfs(i+1, j) + +BASE CASE: +If both string are empty (i==N and j==M), no operation needed. +If one string are empty, then the remain operation is the length of the non-empty one. +""" +class Solution: + def minDistance(self, word1: str, word2: str) -> int: + N = len(word1) + M = len(word2) + def dfs(i, j)->int: + if i==N and j==M: return 0 + if i==N: return M-j + if j==M: return N-i + + if (i, j) in history: + return history[(i, j)] + + if word1[i]==word2[j]: + history[(i, j)] = dfs(i+1, j+1) + else: + history[(i, j)] = 1+min(dfs(i+1, j+1), dfs(i+1, j), dfs(i, j+1)) + + return history[(i, j)] + + history = {} + return dfs(0, 0) \ No newline at end of file diff --git a/problems/python3/interleaving-string.py b/problems/python3/interleaving-string.py new file mode 100644 index 0000000..76f9837 --- /dev/null +++ b/problems/python3/interleaving-string.py @@ -0,0 +1,13 @@ +class Solution: + def isInterleave(self, s1: str, s2: str, s3: str) -> bool: + def dfs(i, j): + if (i, j) in history: return False + if i+j==len(s3): return True + if i int: + def dfs(i0, j0): + if (i0, j0) in memo: return memo[(i0, j0)] + ans = 1 + + for i, j in ((i0+1, j0), (i0-1, j0), (i0, j0+1),(i0, j0-1)): + if i<0 or i>=N or j<0 or j>=M: continue + if matrix[i][j]<=matrix[i0][j0]: continue + ans = max(ans, 1+dfs(i, j)) + + memo[(i0, j0)] = ans + return ans + + N = len(matrix) + M = len(matrix[0]) + memo = {} + ans = 0 + for i in range(N): + for j in range(M): + ans = max(ans, dfs(i, j)) + return ans \ No newline at end of file diff --git a/problems/python3/number-of-1-bits.py b/problems/python3/number-of-1-bits.py new file mode 100644 index 0000000..2273859 --- /dev/null +++ b/problems/python3/number-of-1-bits.py @@ -0,0 +1,10 @@ +""" +n = n&(n-1) will turn the right most 1 to 0. +""" +class Solution: + def hammingWeight(self, n: int) -> int: + ans = 0 + while n>0: + n = n&(n-1) + ans += 1 + return ans \ No newline at end of file diff --git a/problems/python3/regular-expression-matching.py b/problems/python3/regular-expression-matching.py new file mode 100644 index 0000000..93b44e6 --- /dev/null +++ b/problems/python3/regular-expression-matching.py @@ -0,0 +1,24 @@ +class Solution: + def isMatch(self, s: str, p: str) -> bool: + def dfs(i, j): + if (i, j) in cache: return cache[(i, j)] + if i>=M and j>=N: return True + if j>=N: return False + + match = i int: + res = 0 + for i in range(32): + bit = (n >> i) & 1 + res = res | (bit << (31 - i)) + return res \ No newline at end of file diff --git a/problems/python3/single-number.py b/problems/python3/single-number.py new file mode 100644 index 0000000..daa3268 --- /dev/null +++ b/problems/python3/single-number.py @@ -0,0 +1,15 @@ +""" +^ (XOR) +The same will be 0 +0^0 = 0 +1^1 = 0 + +Different will be 1 +1^0 = 1 +0^1 = 1 +""" +class Solution: + def singleNumber(self, nums: List[int]) -> int: + ans = 0 + for num in nums: ans ^= num + return ans \ No newline at end of file diff --git a/problems/python3/target-sum.py b/problems/python3/target-sum.py new file mode 100644 index 0000000..832fadd --- /dev/null +++ b/problems/python3/target-sum.py @@ -0,0 +1,25 @@ +""" +Time: O(NS), S is sum(nums), N is len(nums). This is the max possible number of element in "history". Which will be lesser than 2^N. +Space: O(NS) +""" +class Solution: + def findTargetSumWays(self, nums: List[int], target: int) -> int: + def dfs(i, curr): + #cache + if (i, curr) in history: + return history[(i, curr)] + + #ending condition + if i==len(nums): + if curr==target: + history[(i, curr)] = 1 + else: + history[(i, curr)] = 0 + return history[(i, curr)] + + history[(i, curr)] = dfs(i+1, curr+nums[i])+dfs(i+1, curr-nums[i]) + return history[(i, curr)] + + ans = 0 + history = {} + return dfs(0, 0) \ No newline at end of file From f14be0f429850344c738edc9f18e35e561c724d1 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Thu, 1 Dec 2022 08:00:24 +0100 Subject: [PATCH 184/187] updates --- README.md | 1 + problems/python3/missing-number.py | 12 ++++++++++++ problems/python3/reverse-integer.py | 16 ++++++++++++++++ problems/python3/sum-of-two-integers.py | 12 ++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 problems/python3/missing-number.py create mode 100644 problems/python3/reverse-integer.py create mode 100644 problems/python3/sum-of-two-integers.py diff --git a/README.md b/README.md index 8e05de7..28486a9 100755 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Please [BUY ME A COFFEE](https://www.buymeacoffee.com/chriswu) if you want to sh # Leetcode Problem Lists I found it makes sense to solve similar problems together, so that we can recognize the problem faster when we encounter a new one. My suggestion is to skip the HARD problems when you first go through these list. +* https://neetcode.io/practice (150 problems with video explaination) * https://www.programcreek.com/2013/08/leetcode-problem-classification/ * https://github.com/wisdompeak/LeetCode * https://docs.google.com/spreadsheets/d/1SbpY-04Cz8EWw3A_LBUmDEXKUMO31DBjfeMoA0dlfIA/edit#gid=126913158 ([huahua](https://www.youtube.com/user/xxfflower/videos)). diff --git a/problems/python3/missing-number.py b/problems/python3/missing-number.py new file mode 100644 index 0000000..f0531f6 --- /dev/null +++ b/problems/python3/missing-number.py @@ -0,0 +1,12 @@ +class Solution: + def missingNumber(self, nums: List[int]) -> int: + N = len(nums) + ans = 0 + + for n in range(N+1): + ans ^= n + + for n in nums: + ans ^= n + + return ans \ No newline at end of file diff --git a/problems/python3/reverse-integer.py b/problems/python3/reverse-integer.py new file mode 100644 index 0000000..76137ab --- /dev/null +++ b/problems/python3/reverse-integer.py @@ -0,0 +1,16 @@ +class Solution: + def reverse(self, x: int) -> int: + MAX = 2**31-1 + MIN = -2**31 + ans = 0 + + while x: + digit = int(math.fmod(x, 10)) + x = int(x/10) + + if ans>MAX//10 or (ans==MAX//10 and digit>MAX%10): return 0 + if ans int: + ans = a^b + carry = (a&b)<<1 + + while carry!=0: + ans, carry = ans^carry, (ans&carry)<<1 + + return ans \ No newline at end of file From dbaa78d7677b5e6092997972188e2b5d1266e3d7 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Mon, 5 Dec 2022 08:15:04 +0100 Subject: [PATCH 185/187] updates --- problems/python3/rotate-image.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 problems/python3/rotate-image.py diff --git a/problems/python3/rotate-image.py b/problems/python3/rotate-image.py new file mode 100644 index 0000000..c8a872a --- /dev/null +++ b/problems/python3/rotate-image.py @@ -0,0 +1,16 @@ +class Solution: + def rotate(self, matrix: List[List[int]]) -> None: + l, r = 0, len(matrix[0])-1 + + while l Date: Mon, 5 Dec 2022 08:15:18 +0100 Subject: [PATCH 186/187] updates --- problems/python3/set-matrix-zeroes.py | 28 +++++++++ problems/python3/spiral-matrix.py | 90 +++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 problems/python3/set-matrix-zeroes.py create mode 100644 problems/python3/spiral-matrix.py diff --git a/problems/python3/set-matrix-zeroes.py b/problems/python3/set-matrix-zeroes.py new file mode 100644 index 0000000..dd836e5 --- /dev/null +++ b/problems/python3/set-matrix-zeroes.py @@ -0,0 +1,28 @@ +class Solution: + def setZeroes(self, matrix: List[List[int]]) -> None: + M = len(matrix) + N = len(matrix[0]) + firstRowZero = False + + for i in range(M): + for j in range(N): + if matrix[i][j]==0: + matrix[0][j] = 0 + if i==0: + firstRowZero = True + else: + matrix[i][0] = 0 + + for i in range(1, M): + if matrix[i][0]==0: + for j in range(N): + matrix[i][j] = 0 + + for j in range(N): + if matrix[0][j]==0: + for i in range(M): + matrix[i][j] = 0 + + if firstRowZero: + for j in range(N): + matrix[0][j] = 0 \ No newline at end of file diff --git a/problems/python3/spiral-matrix.py b/problems/python3/spiral-matrix.py new file mode 100644 index 0000000..ddce35c --- /dev/null +++ b/problems/python3/spiral-matrix.py @@ -0,0 +1,90 @@ +""" +Original's solution +Time: O(MN) +Space: O(1) +""" +class Solution: + def spiralOrder(self, matrix: List[List[int]]) -> List[int]: + ans = [] + x0 = 0 + y0 = 0 + dx = len(matrix[0])-1 + dy = len(matrix)-1 + direction = 'right' + isFirst = True + + ans.append(matrix[x0][y0]) + while True: + if direction=='right': + for x in range(x0+1, x0+dx+1): + ans.append(matrix[y0][x]) + x0 += dx + direction = 'down' + + if isFirst: + isFirst = False + else: + dx -= 1 + + if dy==0: break + + elif direction=='left': + for x in range(x0-1, x0-dx-1, -1): + ans.append(matrix[y0][x]) + x0 -= dx + direction = 'up' + dx -= 1 + if dy==0: break + + elif direction=='down': + for y in range(y0+1, y0+dy+1): + ans.append(matrix[y][x0]) + y0 += dy + direction = 'left' + dy -= 1 + if dx==0: break + + elif direction=='up': + for y in range(y0-1, y0-dy-1, -1): + ans.append(matrix[y][x0]) + y0 -= dy + direction = 'right' + dy -= 1 + if dx==0: break + return ans + + +""" +Answer from Neetcode, more elegant. +left, right, top, bottom is the border (index is exclusive on the border. +In other words, for matrix[i][j] +i: top List[int]: + res = [] + left, right = 0, len(matrix[0]) + top, bottom = 0, len(matrix) + + while left < right and top < bottom: + # get every i in the top row + for i in range(left, right): + res.append(matrix[top][i]) + top += 1 + # get every i in the right col + for i in range(top, bottom): + res.append(matrix[i][right - 1]) + right -= 1 + if not (left < right and top < bottom): + break + # get every i in the bottom row + for i in range(right - 1, left - 1, -1): + res.append(matrix[bottom - 1][i]) + bottom -= 1 + # get every i in the left col + for i in range(bottom - 1, top - 1, -1): + res.append(matrix[i][left]) + left += 1 + + return res \ No newline at end of file From 74a34466d44007399b6b67a051f0fcd800595ee8 Mon Sep 17 00:00:00 2001 From: wuduhren Date: Wed, 21 Dec 2022 08:11:55 +0100 Subject: [PATCH 187/187] update --- problems/python3/detect-squares.py | 22 ++++++++++++++++++++++ problems/python3/happy-number.py | 17 +++++++++++++++++ problems/python3/multiply-strings.py | 22 ++++++++++++++++++++++ problems/python3/plus-one.py | 16 ++++++++++++++++ problems/python3/powx-n.py | 14 ++++++++++++++ 5 files changed, 91 insertions(+) create mode 100644 problems/python3/detect-squares.py create mode 100644 problems/python3/happy-number.py create mode 100644 problems/python3/multiply-strings.py create mode 100644 problems/python3/plus-one.py create mode 100644 problems/python3/powx-n.py diff --git a/problems/python3/detect-squares.py b/problems/python3/detect-squares.py new file mode 100644 index 0000000..af86946 --- /dev/null +++ b/problems/python3/detect-squares.py @@ -0,0 +1,22 @@ +class DetectSquares: + + def __init__(self): + self.store = collections.Counter() + + def add(self, point: List[int]) -> None: + self.store[tuple(point)] += 1 + + def count(self, point: List[int]) -> int: + x, y = point + ans = 0 + + for dx, dy in self.store: + if abs(x-dx)!=abs(y-dy) or x==dx or y==dy: continue + ans += self.store[(dx, dy)]*self.store[(dx, y)]*self.store[(x, dy)] + return ans + + +# Your DetectSquares object will be instantiated and called as such: +# obj = DetectSquares() +# obj.add(point) +# param_2 = obj.count(point) \ No newline at end of file diff --git a/problems/python3/happy-number.py b/problems/python3/happy-number.py new file mode 100644 index 0000000..7756197 --- /dev/null +++ b/problems/python3/happy-number.py @@ -0,0 +1,17 @@ +class Solution: + def isHappy(self, n: int) -> bool: + def digitSquare(n) -> int: + ans = 0 + while n>0: + ans += (n%10)**2 + n = n//10 + return ans + + visited = set() + visited.add(1) + + while n not in visited: + visited.add(n) + n = digitSquare(n) + + return n==1 diff --git a/problems/python3/multiply-strings.py b/problems/python3/multiply-strings.py new file mode 100644 index 0000000..be9f675 --- /dev/null +++ b/problems/python3/multiply-strings.py @@ -0,0 +1,22 @@ +class Solution: + def multiply(self, num1: str, num2: str) -> str: + if num1=='0' or num2=='0': return '0' + M, N = len(num1), len(num2) + temp = [0]*(M+N+1) + + num1, num2 = num1[::-1], num2[::-1] + for i in range(M): + for j in range(N): + digits = int(num1[i])*int(num2[j]) + temp[i+j] += digits + temp[i+j+1] += temp[i+j]//10 + temp[i+j] = temp[i+j]%10 + + ans = '' + temp = temp[::-1] + isLeadingZero = True + for d in temp: + if d!=0 or not isLeadingZero: + isLeadingZero = False + ans += str(d) + return ans \ No newline at end of file diff --git a/problems/python3/plus-one.py b/problems/python3/plus-one.py new file mode 100644 index 0000000..8cfedb4 --- /dev/null +++ b/problems/python3/plus-one.py @@ -0,0 +1,16 @@ +class Solution: + def plusOne(self, digits: List[int]) -> List[int]: + i = len(digits)-1 + needAdditionDigit = True + + while i>=0 and needAdditionDigit: + if digits[i]==9: + digits[i] = 0 + i -= 1 + needAdditionDigit = True + else: + digits[i] += 1 + needAdditionDigit = False + if needAdditionDigit: digits.insert(0, 1) + return digits + \ No newline at end of file diff --git a/problems/python3/powx-n.py b/problems/python3/powx-n.py new file mode 100644 index 0000000..2b1b4fc --- /dev/null +++ b/problems/python3/powx-n.py @@ -0,0 +1,14 @@ +class Solution: + def myPow(self, x: float, k: int) -> float: + if k<0: return 1/self.myPow(x, -k) + + if k==0: + return 1 + elif k==1: + return x + elif k%2==0: + half = self.myPow(x, k//2) + return half * half + else: + half = self.myPow(x, (k-1)//2) + return half * half * x \ No newline at end of file