forked from SamirPaulb/DSAlgo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Samir Paul
committed
Jun 12, 2022
1 parent
86c50be
commit 4cae70d
Showing
21 changed files
with
753 additions
and
3 deletions.
There are no files selected for viewing
24 changes: 24 additions & 0 deletions
24
02_Dynamic-Programming/09. DP on Grid/05. Minimum Path Cost in a Grid.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# https://leetcode.com/problems/minimum-path-cost-in-a-grid/ | ||
|
||
class Solution: | ||
def minPathCost(self, grid: List[List[int]], moveCost: List[List[int]]) -> int: | ||
row = len(grid) | ||
col = len(grid[0]) | ||
dp = [[0]*col for i in range(row)] | ||
|
||
for j in range(col): | ||
dp[0][j] = grid[0][j] | ||
|
||
for i in range(1, row): | ||
for j in range(col): | ||
cost = [0]*col | ||
for k in range(col): | ||
cost[k] = grid[i][j] + moveCost[grid[i-1][k]][j] + dp[i-1][k] | ||
dp[i][j] = min(cost) | ||
|
||
return min(dp[-1]) | ||
|
||
|
||
# Time: O(row * col * col) | ||
# Space: O(row * col) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# https://leetcode.com/problems/count-complete-tree-nodes/ | ||
# https://youtu.be/u-yWemKGWO0 | ||
|
||
''' | ||
Only traversing along the left and right boundary. | ||
If both left and right height are equal then | ||
the bottom level would be full from left to right and total no. of nodes in that subtree | ||
is 2^h - 1. | ||
If left and right height are not equal then add +1 for current root and go to left child | ||
and right child. | ||
''' | ||
class Solution: | ||
def countNodes(self, root: Optional[TreeNode]) -> int: | ||
if not root: return 0 | ||
|
||
leftHeight = self.getLeftHeight(root) | ||
rightHeight = self.getRightHeight(root) | ||
|
||
if leftHeight == rightHeight: | ||
return 2 ** leftHeight - 1 | ||
else: | ||
return 1 + self.countNodes(root.left) + self.countNodes(root.right) | ||
|
||
|
||
def getLeftHeight(self, node): | ||
height = 0 | ||
while node: | ||
height += 1 | ||
node = node.left | ||
return height | ||
|
||
def getRightHeight(self, node): | ||
height = 0 | ||
while node: | ||
height += 1 | ||
node = node.right | ||
return height | ||
|
||
# Height = H = log(n) where n = total number of nodes | ||
# Time: O(H * H) = O(log(n)^2) = O(Log^2 n) | ||
# Auxiliary Space: O(H) = O(log(n)) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# https://leetcode.com/problems/number-of-good-leaf-nodes-pairs/ | ||
|
||
''' | ||
Traverse from bottom to top (Postorder Traversal) and keep track of the distance of the | ||
leaf nodes to each node. Once those leaf nodes meet a Lowest Common Ancestor, | ||
we can immediately check whether they are good pairs. | ||
''' | ||
|
||
class Solution: | ||
def countPairs(self, root: TreeNode, distance: int) -> int: | ||
count = 0 | ||
|
||
def dfs(node): | ||
nonlocal count | ||
|
||
if not node: return [] | ||
if not node.left and not node.right: return [1] | ||
|
||
left = dfs(node.left) | ||
right = dfs(node.right) | ||
|
||
count += sum(l + r <= distance for l in left for r in right) | ||
return [n + 1 for n in left + right if n + 1 < distance] | ||
|
||
dfs(root) | ||
return count | ||
|
||
# Time: O(N) | ||
# Space: O(N) | ||
|
44 changes: 44 additions & 0 deletions
44
07_Graph/Dijkstras Shortest Path Algorithm on Graph/04. Path With Minimum Effort.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# https://leetcode.com/problems/path-with-minimum-effort/ | ||
|
||
# https://youtu.be/FabSLaGu0NI | ||
|
||
# Method 1 --------> using Dijkstra's Algorithm | ||
class Solution: | ||
def minimumEffortPath(self, heights: List[List[int]]) -> int: | ||
row = len(heights) | ||
col = len(heights[0]) | ||
|
||
minHeap = [] | ||
heapq.heappush(minHeap, (0, 0, 0)) # (distance, row, col) | ||
|
||
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] | ||
visited = set() | ||
dp = [[2**31]*col for i in range(row)] | ||
|
||
while minHeap: | ||
d, r, c = heapq.heappop(minHeap) | ||
if (r, c) in visited: continue | ||
visited.add((r,c)) | ||
dp[r][c] = d | ||
if r == row-1 and c == col-1: return dp[r][c] | ||
for direc in directions: | ||
nr = r + direc[0] | ||
nc = c + direc[1] | ||
if 0 <= nr < row and 0 <= nc < col: | ||
nd = max(dp[r][c], abs(heights[r][c] - heights[nr][nc])) | ||
if nd < dp[nr][nc]: | ||
heapq.heappush(minHeap, (nd, nr, nc)) | ||
|
||
return 0 | ||
|
||
# Time: O(r*c * log(r*c)) | ||
# Space: O(r * c) | ||
|
||
|
||
''' | ||
# Method 2 --------> using Binary Search | ||
class Solution: | ||
def minimumEffortPath(self, heights: List[List[int]]) -> int: | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# https://leetcode.com/problems/kth-largest-element-in-a-stream/ | ||
|
||
''' | ||
By default Min Heap is implemented by heapq library. | ||
In a Min-Heap the minimum element present at the root. In pop operation root node is removed. | ||
''' | ||
|
||
class KthLargest: | ||
|
||
def __init__(self, k: int, nums: List[int]): | ||
self.k = k | ||
self.minHeap = [] # Min Heap | ||
for num in nums: | ||
heapq.heappush(self.minHeap, num) # adding all elements to min heap | ||
|
||
while len(self.minHeap) > k: | ||
heapq.heappop(self.minHeap) # Only keeping k maximum elements | ||
|
||
|
||
def add(self, val: int) -> int: | ||
heapq.heappush(self.minHeap, val) # first add to min heap | ||
|
||
if len(self.minHeap) > self.k: # if length greater pop minimum element as root is the min | ||
heapq.heappop(self.minHeap) | ||
|
||
return self.minHeap[0] # root is minHeap[0] as root is k'th max | ||
|
||
# Time: O(N log(N)) # as heap size is N so heappush takes log(N) time | ||
# Space: O(N) | ||
|
||
|
||
|
||
# Method-2 Using the given add function to add only k elements so that we can save space | ||
import heapq | ||
class KthLargest: | ||
""" | ||
The idea is to ALWAYS maintain a MIN heap with only K elements | ||
- in this case, the K-the largest element (in the stream) | ||
- will always be at the root position | ||
""" | ||
def __init__(self, k: int, nums: List[int]): | ||
self.heap = [] | ||
self.k = k | ||
|
||
for num in nums: | ||
self.add(num) # add elements using the function below | ||
|
||
def add(self, val: int) -> int: | ||
|
||
heapq.heappush(self.heap, val) | ||
|
||
# if after adding the new item causes | ||
# the heap size to increase beyond k, | ||
# then pop out the smallest element | ||
if len(self.heap) > self.k: | ||
heapq.heappop(self.heap) | ||
|
||
return self.heap[0] # the root element | ||
|
||
# Time: O(N log(K)) # as heap size if k so heappush takes log(k) time | ||
# Space: O(K) # as only making heap of size k | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# https://leetcode.com/problems/find-median-from-data-stream/ | ||
# https://youtu.be/itmhHWaHupI | ||
|
||
# we can easyly solve using arr operations in O(N) time but to solve in log(N) time we have to use heap | ||
# using 2 heaps one is left side of median ig. self.small(maxheap) and another is right side of median self.large(minheap) | ||
|
||
import heapq | ||
class MedianFinder: | ||
|
||
def __init__(self): | ||
self.small = [] # Max Heap | ||
self.large = [] # Min Heap | ||
|
||
def addNum(self, num: int) -> None: | ||
heapq.heappush(self.small, -num) # always pushing on small (maxheap) then comparing | ||
|
||
if self.small and self.large and -self.small[0] > self.large[0]: # if newly added element greater | ||
val = -heapq.heappop(self.small) | ||
heapq.heappush(self.large, val) | ||
|
||
if len(self.small) > len(self.large) + 1: | ||
val = -heapq.heappop(self.small) | ||
heapq.heappush(self.large, val) | ||
|
||
if len(self.large) > len(self.small) + 1: | ||
val = heapq.heappop(self.large) | ||
heapq.heappush(self.small, -val) | ||
|
||
|
||
def findMedian(self) -> float: | ||
if len(self.small) > len(self.large): | ||
return -self.small[0] | ||
|
||
if len(self.large) > len(self.small): | ||
return self.large[0] | ||
|
||
return (-self.small[0] + self.large[0]) / 2 | ||
|
||
# Time: O(log(N)) | ||
# Space: O(N) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# https://leetcode.com/problems/kth-largest-element-in-an-array/ | ||
|
||
#------ Method 1 ---------- Using Min Heap Time: O(n log(k)) | ||
import heapq | ||
class Solution: | ||
def findKthLargest(self, nums, k): | ||
self.minHeap = [] # as root of min heap is minimum and root is removed in pop operation | ||
self.heapLength = 0 # for calculating length of heap in constant time else len() would take O(k) time | ||
|
||
def addToHeap(num): | ||
heapq.heappush(self.minHeap, num) | ||
self.heapLength += 1 | ||
if self.heapLength > k: # always trying to maintain heap length k | ||
heapq.heappop(self.minHeap) | ||
self.heapLength -= 1 | ||
|
||
for num in nums: | ||
addToHeap(num) | ||
|
||
return self.minHeap[0] | ||
|
||
# Time: O(N log(k)) ; O(N) for traversal and log(k) for pushing num to a heap of size k | ||
# Space: O(k) ; as the minHeap is always of size k | ||
|
||
|
||
#------ Method 2 ---------- Using QUick Quick-Select (idea Quick Sort) | ||
class Solution: | ||
def findKthLargest(self, nums, k): | ||
pivot = nums[0] | ||
|
||
left = [num for num in nums if num < pivot] | ||
equal = [num for num in nums if num == pivot] | ||
right = [num for num in nums if num > pivot] | ||
|
||
if k <= len(right): return self.findKthLargest(right, k) | ||
elif len(right) < k <= len(right) + len(equal): return equal[0] | ||
else: return self.findKthLargest(left, k - len(right) - len(equal)) | ||
|
||
# Average Time Complexity: O(N) | ||
# Worst Case Time Complexity: O(N^2) | ||
# Space Complexity: O(N) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# https://leetcode.com/problems/path-with-minimum-effort/ | ||
|
||
# https://youtu.be/FabSLaGu0NI | ||
|
||
# Method 1 --------> using Dijkstra's Algorithm | ||
class Solution: | ||
def minimumEffortPath(self, heights: List[List[int]]) -> int: | ||
row = len(heights) | ||
col = len(heights[0]) | ||
|
||
minHeap = [] | ||
heapq.heappush(minHeap, (0, 0, 0)) # (distance, row, col) | ||
|
||
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] | ||
visited = set() | ||
dp = [[2**31]*col for i in range(row)] | ||
|
||
while minHeap: | ||
d, r, c = heapq.heappop(minHeap) | ||
if (r, c) in visited: continue | ||
visited.add((r,c)) | ||
dp[r][c] = d | ||
if r == row-1 and c == col-1: return dp[r][c] | ||
for direc in directions: | ||
nr = r + direc[0] | ||
nc = c + direc[1] | ||
if 0 <= nr < row and 0 <= nc < col: | ||
nd = max(dp[r][c], abs(heights[r][c] - heights[nr][nc])) | ||
if nd < dp[nr][nc]: | ||
heapq.heappush(minHeap, (nd, nr, nc)) | ||
|
||
return 0 | ||
|
||
# Time: O(r*c * log(r*c)) | ||
# Space: O(r * c) | ||
|
||
|
||
''' | ||
# Method 2 --------> using Binary Search | ||
class Solution: | ||
def minimumEffortPath(self, heights: List[List[int]]) -> int: | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# https://leetcode.com/problems/fair-distribution-of-cookies/ | ||
|
||
class Solution: | ||
def distributeCookies(self, cookies: List[int], k: int) -> int: | ||
self.res = 2**31 | ||
children = [0] * k | ||
def dfs(i): | ||
if i >= len(cookies): | ||
self.res = min(self.res, max(children)) | ||
return | ||
if max(children) > self.res: return | ||
for j in range(k): | ||
children[j] += cookies[i] | ||
dfs(i+1) | ||
children[j] -= cookies[i] | ||
|
||
dfs(0) | ||
return self.res | ||
|
||
# Time: O(n^k) | ||
# Space: O(k) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# https://leetcode.com/problems/subarray-product-less-than-k/ | ||
|
||
class Solution: | ||
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int: | ||
l = 0 | ||
p = 1 | ||
res = 0 | ||
for r in range(len(nums)): | ||
p *= nums[r] | ||
while l <= r and p >= k: | ||
p //= nums[l] | ||
l += 1 | ||
res += r - l + 1 | ||
|
||
return res | ||
|
||
# Time: O(N) | ||
# Space: O(1) |
Oops, something went wrong.