diff --git a/03. Data Structures/Queues/LEARN b/03. Data Structures/Queues/LEARN new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/03. Data Structures/Queues/LEARN @@ -0,0 +1 @@ + diff --git a/07. Functional Programming/enumerate.py b/07. Functional Programming/enumerate.py new file mode 100644 index 0000000..eef1904 --- /dev/null +++ b/07. Functional Programming/enumerate.py @@ -0,0 +1,4 @@ +fruits = ['apple', 'banana', 'cherry', 'grape'] + +for index, fruit in enumerate(fruits, 1): + print(index, fruit) diff --git a/14. Questions/barclays plc uk - online assesment.py b/14. Questions/barclays plc uk - online assesment.py new file mode 100644 index 0000000..a7221c6 --- /dev/null +++ b/14. Questions/barclays plc uk - online assesment.py @@ -0,0 +1,110 @@ +""" +Allie is working on a system that can allocate resources to the +applications in a manner efficient enough to allow the maximum number +of applications to be executed. There are N number of applications +and each application is identified by a unique integer ID (1 to N). +Only M types of resources are available with a unique resourceD. +Each application sends a request message to the system. +The request message includes the information regarding the request time, +the execution ending time, and the type of resource required for execution. +Time is in the MMSS format where MM is minutes and SS is seconds. + +If more than one application sends a request at the same time then only +one application will be approved by the system. The denied requests are +automatically destroyed by the system. When approving the request, the +system ensures that the request will be granted to the application in a +way that will maximize the number of executions. The system can execute +only one application at a time with a given resource. It will deny all +other requests for the resource until the previous application has finished. +Allie wants to know the maximum number of applications that have been +executed successfully. + +Write an algorithm to help Allie calculate the maximum number of applications +that are executed successfully by the system. + +Input +The first line of the input consists of two space-separated integers num and +constX, representing the number of applications (N) and constX is always 3. +The next N lines consist of constX space-separated integers representing the +request time, the execution ending time, and the resourceD of the resource +required by each application for successful execution. + +Output +Print an integer representing the maximum number of applications that are +executed successfully by the system. + + +Testcase 1 | Answer: 4 +4 3 +1000 1020 3 +1020 1030 3 +1030 1040 3 +1010 1045 2 + +Testcase 2 | Ans: 3 +5 3 +1200 1230 1 +1120 1125 2 +1015 1230 1 +1100 1230 1 +1200 1230 3 + +Testcase 3 | Ans: 4 +6 3 +1200 1250 1 +1210 1220 1 +1225 1230 1 +1330 1345 2 +1330 1340 2 +1340 1345 2 +""" + + +# to bucket all requests by resource type +def bucketRequestsByResource(arr): + buckets = dict() + for each_req in arr: + if buckets.get(each_req[2], False) != False: + buckets[each_req[2]].append((each_req[0], each_req[1])) + else: + buckets[each_req[2]] = [(each_req[0], each_req[1])] + + return buckets + + +# to get max number of executed tasks for a single bucket +def numExecutedAppsByBucket(arr): + arr.sort(key = lambda x: x[0]) + N = len(arr) + dont_execute = 0 + latest_end = arr[0][1] + + for i in range(1, N): + if arr[i][0] < latest_end: + dont_execute += 1 + latest_end = min(arr[i][1], latest_end) + else: + latest_end = arr[i][1] + + return (N - dont_execute) + + +# get the maximum number of executed tasks +def numExecutedApps(arr): + buckets = bucketRequestsByResource(arr) + num_execute = 0 + for each_bucket in buckets.values(): + num_execute += numExecutedAppsByBucket(each_bucket) + + return num_execute + + +# driver code +arr = [] +arr_rows, arr_cols = map(int, input().split()) +for idx in range(arr_rows): + arr.append(list(map(int, input().split()))) + +result = numExecutedApps(arr) +print (result) + diff --git a/14. Questions/leetcode 02 - add two numbers.py b/14. Questions/leetcode 02 - add two numbers.py new file mode 100644 index 0000000..e39d1d9 --- /dev/null +++ b/14. Questions/leetcode 02 - add two numbers.py @@ -0,0 +1,38 @@ +# add two numbers | leetcode 02 | https://leetcode.com/problems/add-two-numbers/ + +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val = val + self.next = next + +class Solution: + def addTwoNumbers(self, l1: list[ListNode], l2: list[ListNode]) -> list[ListNode]: + res = ListNode() + head = res + + while l1 != None or l2 != None: + if l1 == None: + this_val = res.val + l2.val + l2 = l2.next + elif l2 == None: + this_val = res.val + l1.val + l1 = l1.next + else: + this_val = res.val + l1.val + l2.val + l1, l2 = l1.next, l2.next + + this_digit = this_val % 10 + next_digit = this_val // 10 + + res.val = this_digit + if l1 != None or l2 != None: + res.next = ListNode(next_digit) + res = res.next + + if next_digit > 0: + res.next = ListNode(next_digit) + res = res.next + + return head + \ No newline at end of file diff --git a/14. Questions/leetcode 03 - longest substring without repeating characters.py b/14. Questions/leetcode 03 - longest substring without repeating characters.py new file mode 100644 index 0000000..d1a4c58 --- /dev/null +++ b/14. Questions/leetcode 03 - longest substring without repeating characters.py @@ -0,0 +1,18 @@ +# longest substring without repeating characters | leetcode 03 | https://leetcode.com/problems/longest-substring-without-repeating-characters +# sliding window; remove elements until last occurence of current duplicate + +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + ptrL = 0 + seen = dict() + longest = 0 + + for ptrR in range(len(s)): + while seen.get(s[ptrR]) is not None: + seen.pop(s[ptrL]) + ptrL += 1 + seen[s[ptrR]] = True + longest = max(ptrR - ptrL + 1, longest) + + return longest + \ No newline at end of file diff --git a/14. Questions/leetcode 100 - same tree.py b/14. Questions/leetcode 100 - same tree.py new file mode 100644 index 0000000..be1c083 --- /dev/null +++ b/14. Questions/leetcode 100 - same tree.py @@ -0,0 +1,24 @@ +# same tree | leetcode 100 | https://leetcode.com/problems/same-tree/ +# given a root of each of the two trees, check if the trees are the exact same or not +# method: (DFS) inorder traversal to compare left subtree, current node and right subtree + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def isSameTree(self, p, q): + if p is None and q is None: + return True + + if p is None or q is None: + return False + + lResult = self.isSameTree(p.left, q.left) + nResult = p.val == q.val + rResult = self.isSameTree(p.right, q.right) + + return lResult and nResult and rResult \ No newline at end of file diff --git a/14. Questions/leetcode 101 - symmetric tree.py b/14. Questions/leetcode 101 - symmetric tree.py new file mode 100644 index 0000000..c75c645 --- /dev/null +++ b/14. Questions/leetcode 101 - symmetric tree.py @@ -0,0 +1,22 @@ +# symmetric tree | leetcode 101 | https://leetcode.com/problems/symmetric-tree/ +# given the root of a binary tree, check whether it is a mirror of itself +# method: recursively compare two copies of the same tree + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def isSymmetric(self, root): + def checkSymm(copy1, copy2): + if copy1 is None and copy2 is None: + return True + if copy1 is None or copy2 is None: + return False + + return (copy1.val == copy2.val) and checkSymm(copy1.left, copy2.right) and checkSymm(copy1.right, copy2.left) + + return checkSymm(root, root) diff --git a/14. Questions/leetcode 1011 - capacity to ship packages.py b/14. Questions/leetcode 1011 - capacity to ship packages.py new file mode 100644 index 0000000..ad5e4da --- /dev/null +++ b/14. Questions/leetcode 1011 - capacity to ship packages.py @@ -0,0 +1,33 @@ +# capacity to ship packages within D days | leetcode 1011 | https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/ +# binary search on a range of min and max capacity required +# min capacity = max(weights) and max capacity = sum(weights) + +class Solution: + def shipWithinDays(self, weights: list[int], days: int) -> int: + low, high = max(weights), sum(weights) + res = high + + # check if days required for a capacity is less than D + def isPossible (capacity): + daysReq = 1 + window = capacity + for weight in weights: + if window - weight < 0: + window = capacity + daysReq += 1 + window -= weight + + return daysReq <= days + + # binary search on [min...max] + while low <= high: + mid = (high + low) // 2 + + if isPossible(mid): + res = min(res, mid) + high = mid - 1 + else: + low = mid + 1 + + return res + diff --git a/14. Questions/leetcode 102 - level order traversal of tree.py b/14. Questions/leetcode 102 - level order traversal of tree.py new file mode 100644 index 0000000..ca88b4e --- /dev/null +++ b/14. Questions/leetcode 102 - level order traversal of tree.py @@ -0,0 +1,39 @@ +# binary tree level order traversal | leetcode 102 | https://leetcode.com/problems/binary-tree-level-order-traversal/ +# order: from left to right, level by level +# method: breadth first search + +#Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + + # l to r, level by level + def levelOrder(self, root): + res = [] + tempQ = [] + + # queue to track visits + tempQ.append(root) + LtempQ = len(tempQ) + + # keep iterating till: + # the track queue is empty + while LtempQ is not 0: + LtempQ = len(tempQ) + level = [] + for i in range(LtempQ): + node = tempQ.pop(0) # pop this node from queue (visited) + if node is not None: + level.append(node.val) # add this node to the level + tempQ.append(node.left) # add left child to queue (to visit) + tempQ.append(node.right) # add right child to queue (to visit) + if len(level) is not 0: + res.append(level) + + return res + + \ No newline at end of file diff --git a/14. Questions/leetcode 1022 - sum of root-leaf binary num.py b/14. Questions/leetcode 1022 - sum of root-leaf binary num.py new file mode 100644 index 0000000..dd7718b --- /dev/null +++ b/14. Questions/leetcode 1022 - sum of root-leaf binary num.py @@ -0,0 +1,26 @@ +# sum of root to leaf binary numbers | leetcode 1022 | https://leetcode.com/problems/sum-of-root-to-leaf-binary-numbers/ +# method: (dfs) for each node, left-shift 1 bit and add val. +# return sum of both left and right subtree +# return sum till now at each leaf + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def sumRootToLeaf(self, root) -> int: + def dfsSum(root, total): + if root is None: + return 0 + + total = (total << 1) | root.val + + if root.left is None and root.right is None: + return total + + return dfsSum(root.left, total) + dfsSum(root.right, total) + + return dfsSum(root, 0) \ No newline at end of file diff --git a/14. Questions/leetcode 103 - zigzag level order traversal.py b/14. Questions/leetcode 103 - zigzag level order traversal.py new file mode 100644 index 0000000..59d42a8 --- /dev/null +++ b/14. Questions/leetcode 103 - zigzag level order traversal.py @@ -0,0 +1,37 @@ +# binary tree zigzag level order traversal | leetcode 103 | https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal +# use flag to keep track of reversed levels; O(n) because worst case is full level - n/2 elements + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def zigzagLevelOrder(self, root: TreeNode) -> list[list[int]]: + res = [] + tempQ = [] + zig = False + + # queue to track visits + tempQ.append(root) + LtempQ = len(tempQ) + + # keep iterating till: + # the track queue is empty + while LtempQ is not 0: + LtempQ = len(tempQ) + level = [] + for i in range(LtempQ): + node = tempQ.pop(0) # pop this node from queue (visited) + if node is not None: + level.append(node.val) # add this node to the level + tempQ.append(node.left) # add left child to queue (to visit) + tempQ.append(node.right) # add right child to queue (to visit) + + if len(level) is not 0: # add level and reverse if zig + res.append(reversed(level) if zig else level) + zig = not zig + + return res \ No newline at end of file diff --git a/14. Questions/leetcode 104 - max depth of binary tree.py b/14. Questions/leetcode 104 - max depth of binary tree.py new file mode 100644 index 0000000..1c0c7bb --- /dev/null +++ b/14. Questions/leetcode 104 - max depth of binary tree.py @@ -0,0 +1,26 @@ +# max depth of binary tree | leetcode 104 | https://leetcode.com/problems/maximum-depth-of-binary-tree/ +# given the root of a binary tree, return its maximum depth. +# method: recursively increment left and right count for each new node and return max + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def maxDepth(self, root): + def findDepth(node): + if node is None: + return -1 + + ldepth = findDepth(node.left) + rdepth = findDepth(node.right) + + if ldepth > rdepth: + return ldepth + 1 + else: + return rdepth + 1 + + return findDepth(root) + 1 diff --git a/14. Questions/leetcode 108 - sorted array to bst.py b/14. Questions/leetcode 108 - sorted array to bst.py new file mode 100644 index 0000000..7f2c59e --- /dev/null +++ b/14. Questions/leetcode 108 - sorted array to bst.py @@ -0,0 +1,23 @@ +# sorted array to bst | leetcode 108 | https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/ +# given a sorted array of int, convert it to a balanced binary search tree +# method: take middle element as root, use recursion for depth first, add each subtree as a balanced bst + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def sortedArrayToBST(self, nums): + if not nums: + return None + + mid = len(nums) // 2 + + root = TreeNode(val = nums[mid]) + root.left = self.sortedArrayToBST(nums[:mid]) + root.right = self.sortedArrayToBST(nums[mid+1:]) + + return root \ No newline at end of file diff --git a/14. Questions/leetcode 110 - balanced bst.py b/14. Questions/leetcode 110 - balanced bst.py new file mode 100644 index 0000000..beb839d --- /dev/null +++ b/14. Questions/leetcode 110 - balanced bst.py @@ -0,0 +1,22 @@ +# balanced bst | leetcode 110 | https://leetcode.com/problems/balance-a-binary-search-tree/ +# given a bst, check if it is balanced or not +# method: for each subtree, check if its left and right subtrees and balanced, and return the maxDepth + 1 + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def isBalanced(self, root) -> bool: + def dfs(root): + if root is None: return [True, 0] + + left, right = dfs(root.left), dfs(root.right) + balanced = left[0] and right[0] and abs(left[1] - right[1]) <= 1 + + return [balanced, max(left[1], right[1]) + 1] + + return dfs(root)[0] \ No newline at end of file diff --git a/14. Questions/leetcode 112 - path sum.py b/14. Questions/leetcode 112 - path sum.py new file mode 100644 index 0000000..3b3ef27 --- /dev/null +++ b/14. Questions/leetcode 112 - path sum.py @@ -0,0 +1,27 @@ +# path sum | leetcode 112 | https://leetcode.com/problems/path-sum/ +# given the root of a tree, check if there exists a path whose sum equals target +# method: (dfs) update curSum for each node, and return true or false for each subtree + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def hasPathSum(self, root, targetSum): + + def dfs(root, curSum): + if root is None: + return False + + curSum += root.val + if root.left is None and root.right is None: + return curSum == targetSum + + return dfs(root.left, curSum) or dfs(root.right, curSum) + + return dfs(root, 0) + + diff --git a/14. Questions/leetcode 114 - binary tree preorder traversal.py b/14. Questions/leetcode 114 - binary tree preorder traversal.py new file mode 100644 index 0000000..590e452 --- /dev/null +++ b/14. Questions/leetcode 114 - binary tree preorder traversal.py @@ -0,0 +1,24 @@ +# binary tree preorder traversal | leetcode 94 | https://leetcode.com/problems/binary-tree-preorder-traversal/ +# method: node, left subtree, right subtree recursively + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def inorderTraversal(self, root): + travList = [] + + def traverse(root, travList): + if root is None: + return None + + travList.append(root.val) # add this node + traverse(root.left, travList) # traverse left subtree and add nodes + traverse(root.right, travList) # traverse right subtree and add nodes + + traverse(root, travList) + return travList diff --git a/14. Questions/leetcode 128 - longest consecutive sequence.py b/14. Questions/leetcode 128 - longest consecutive sequence.py new file mode 100644 index 0000000..4427aec --- /dev/null +++ b/14. Questions/leetcode 128 - longest consecutive sequence.py @@ -0,0 +1,22 @@ +# longest consecutive sequence | leetcode 128 | https://leetcode.com/problems/longest-consecutive-sequence/ +# set to look-up previous and next numbers; nested while loop is O(2n) + +class Solution: + def longestConsecutive(self, nums: list[int]) -> int: + if nums == []: + return 0 + + all = set(nums) + longest = 0 + + for each in all: + if each - 1 not in all: + curr = each + seq = 1 + while curr + 1 in all: + seq += 1 + curr = curr + 1 + if seq > longest: + longest = seq + + return longest \ No newline at end of file diff --git a/14. Questions/leetcode 1302 - deepest leaves sum.py b/14. Questions/leetcode 1302 - deepest leaves sum.py new file mode 100644 index 0000000..4f45d46 --- /dev/null +++ b/14. Questions/leetcode 1302 - deepest leaves sum.py @@ -0,0 +1,36 @@ +# deepest leaves sum | leetcode 1302 | https://leetcode.com/problems/deepest-leaves-sum/ +# method: dfs + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def deepestLeavesSum(self, root) -> int: + result = 0 + maxHeight = 0 + + # dfs + def dfs(node, currHeight): + nonlocal result, maxHeight + if node is None: + return + + # reset if current height is not max + if currHeight > maxHeight: + result = 0 + maxHeight = currHeight + + # add to sum if current height is max + if currHeight == maxHeight: + result += node.val + + # recursively traverse left and right subtrees + dfs(node.left, currHeight + 1) + dfs(node.right, currHeight + 1) + + dfs(root, 0) + return result diff --git a/14. Questions/leetcode 1305 - all elements in two binary search trees.py b/14. Questions/leetcode 1305 - all elements in two binary search trees.py new file mode 100644 index 0000000..51f9f54 --- /dev/null +++ b/14. Questions/leetcode 1305 - all elements in two binary search trees.py @@ -0,0 +1,26 @@ +# all elements in two bst | leetcode 1305 | https://leetcode.com/problems/all-elements-in-two-binary-search-trees/ +# method: dfs, sort + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def getAllElements(self, root1: TreeNode, root2: TreeNode) -> list[int]: + elements = [] + + def dfs(node): + if node is None: + return + + dfs(node.left) + elements.append(node.val) + dfs(node.right) + + dfs(root1) + dfs(root2) + elements.sort() + return elements diff --git a/14. Questions/leetcode 133 - clone graph.py b/14. Questions/leetcode 133 - clone graph.py new file mode 100644 index 0000000..201c99e --- /dev/null +++ b/14. Questions/leetcode 133 - clone graph.py @@ -0,0 +1,25 @@ +# clone graph | leetcode 133 | https://leetcode.com/problems/clone-graph/ +# method: depth first search, recursively add neighbours + +# Definition for a Node. +class Node: + def __init__(self, val = 0, neighbors = None): + self.val = val + self.neighbors = neighbors if neighbors is not None else [] + +class Solution: + def cloneGraph(self, node: Node): + oldToNew = {} + + def dfs(node): + if node in oldToNew: + return oldToNew[node] + + duplicate = Node(node.val) + oldToNew[node] = duplicate + for neighbour in node.neighbors: + duplicate.neighbors.append(dfs(neighbour)) + + return duplicate + + return dfs(node) if node else None diff --git a/14. Questions/leetcode 1379 - corresponding target in cloned tree.py b/14. Questions/leetcode 1379 - corresponding target in cloned tree.py new file mode 100644 index 0000000..8578de4 --- /dev/null +++ b/14. Questions/leetcode 1379 - corresponding target in cloned tree.py @@ -0,0 +1,23 @@ +# corresponding node in a clone of the binary tree | leetcode 1379 | https://leetcode.com/problems/find-a-corresponding-node-of-a-binary-tree-in-a-clone-of-that-tree/ +# return a reference to the same node in a cloned tree +# method: traverse through the original and the cloned tree parallely until the original matches the target + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +class Solution: + def getTargetCopy(self, original: TreeNode, cloned: TreeNode, target: TreeNode) -> TreeNode: + self.clonedTarget = None + def inorderTraversal(original, cloned): + if original: + inorderTraversal(original.left, cloned.left) + if original is target: + self.clonedTarget = cloned + inorderTraversal(original.right, cloned.right) + + inorderTraversal(original, cloned) + return self.clonedTarget \ No newline at end of file diff --git a/14. Questions/leetcode 1382 - balance a bst.py b/14. Questions/leetcode 1382 - balance a bst.py new file mode 100644 index 0000000..8579edb --- /dev/null +++ b/14. Questions/leetcode 1382 - balance a bst.py @@ -0,0 +1,43 @@ +# balance a bst | leetcode 1382 | https://leetcode.com/problems/balance-a-binary-search-tree/ +# given a bst, return a balanced bst +# method: use inorder traversal to make a sorted array, convert sorted array to balanced bst + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + # convert sorted array to bst + def sortedArrayToBST(self, nums): + if not nums: + return None + + mid = len(nums) // 2 + + root = TreeNode(val = nums[mid]) + root.left = self.sortedArrayToBST(nums[:mid]) + root.right = self.sortedArrayToBST(nums[mid+1:]) + + return root + + # in-order traveral gives sorted array + def inorderTraversal(self, root): + travList = [] + + def traverse(root, travList): + if root is None: + return None + + traverse(root.left, travList) + travList.append(root.val) + traverse(root.right, travList) + + traverse(root, travList) + return travList + + # balance a binary search tree + def balanceBST(self, root): + return self.sortedArrayToBST(self.inorderTraversal(root)) \ No newline at end of file diff --git a/14. Questions/leetcode 15 - three sum.py b/14. Questions/leetcode 15 - three sum.py new file mode 100644 index 0000000..9178a13 --- /dev/null +++ b/14. Questions/leetcode 15 - three sum.py @@ -0,0 +1,29 @@ +# three sum | leetcode 15 | https://leetcode.com/problems/3sum/ +# - sorted; nested loop; outer loop for first element +# - inner loop for two sum on rest of list +# - avoid duplicates by shifting window till last occurrence + +class Solution: + def threeSum(self, nums: list[int]) -> list[list[int]]: + nums.sort() + N = len(nums) + triplets = [] + for i in range(N): + if i > 0 and nums[i] == nums[i - 1]: + continue + + ptrL = i + 1 + ptrR = N - 1 + while ptrL < ptrR: + s = nums[i] + nums[ptrL] + nums[ptrR] + if s > 0: + ptrR -= 1 + elif s < 0: + ptrL += 1 + else: + triplets.append([nums[i], nums[ptrL], nums[ptrR]]) + ptrL += 1 + while nums[ptrL] == nums[ptrL - 1] and ptrL < ptrR: + ptrL += 1 + + return triplets \ No newline at end of file diff --git a/14. Questions/leetcode 167 - two sum II.py b/14. Questions/leetcode 167 - two sum II.py new file mode 100644 index 0000000..f7f43bc --- /dev/null +++ b/14. Questions/leetcode 167 - two sum II.py @@ -0,0 +1,21 @@ +# two sum II - input array is sorted | leetcode 167 | https://leetcode.com/problems/two-sum-ii-input-array-is-sorted +# use two pointers on sorted array; if sum > target slide window left, else slide window right + +class Solution: + def twoSum(self, numbers: list[int], target: int) -> list[int]: + ptrL = 0 + ptrR = 1 + N = len(numbers) + + while ptrR < N: + s = numbers[ptrR] + numbers[ptrL] + if s == target: + return [ptrL + 1, ptrR + 1] + elif s < target: + ptrL += 1 + ptrR += 1 + else: + ptrL -= 1 + + # unreachable for testcases with exactly one solution + return [-1, -1] \ No newline at end of file diff --git a/14. Questions/leetcode 1971 - find if path exists in a graph.py b/14. Questions/leetcode 1971 - find if path exists in a graph.py new file mode 100644 index 0000000..317fb94 --- /dev/null +++ b/14. Questions/leetcode 1971 - find if path exists in a graph.py @@ -0,0 +1,42 @@ +# find if path exists in a graph | leetcode 1971 | https://leetcode.com/problems/find-if-path-exists-in-graph/ +# method: adjacency list, visited and toVisit lists + +from collections import defaultdict + +class Solution: + def validPath(self, n: int, edges: list[list[int]], source: int, destination: int) -> bool: + # edge case + if n == 1 and source == destination: + return True + + edgeMap = defaultdict(list) # adjacency list + for edge in edges: + edgeMap[edge[0]].append(edge[1]) + edgeMap[edge[1]].append(edge[0]) + + visited = set() # set of visited nodes + toVisit = [edgeMap[source]] # set of nodes to visit + + # while there are nodes to visit + while toVisit: + + # this node is now visited + nodes = toVisit.pop() + + # for each node in the adjacent nodes + for node in nodes: + if node == destination: + return True + + # if node wasn't visited + # visit its adjacent nodes + elif node not in visited: + visited.add(node) + toVisit.append(edgeMap[node]) + + # if node was visited + # do nothing + + # if no more nodes to visit + # and still no path + return False diff --git a/14. Questions/leetcode 207 - course schedule.py b/14. Questions/leetcode 207 - course schedule.py new file mode 100644 index 0000000..fdaf7f8 --- /dev/null +++ b/14. Questions/leetcode 207 - course schedule.py @@ -0,0 +1,46 @@ +# course schedule | leetcode 207 | https://leetcode.com/problems/course-schedule/ +# method: depth first search + +class Solution: + def canFinish(self, numCourses: int, prerequisites) -> bool: + + # init prequisite map + preqMap = {} + for i in range(numCourses): + preqMap[i] = [] + + # add mentioned prerequisites + for crs, pre in prerequisites: + preqMap[crs].append(pre) + + # init visit set + visitSet = set() + + # dfs + def checkPreq(crs): + + # if course is already visited + if crs in visitSet: + return False + + # if no prequisites left + if preqMap[crs] == []: + return True + + # visiting this course + visitSet.add(crs) + + # checking each prerequisite + for pre in preqMap[crs]: + if not checkPreq(pre): return False + + # all prerequisites are doable + visitSet.remove(crs) + preqMap[crs] = [] + return True + + # check prerequisites for each course + for crs in range(numCourses): + if not checkPreq(crs): return False + + return True diff --git a/14. Questions/leetcode 226 - invert binary tree.py b/14. Questions/leetcode 226 - invert binary tree.py new file mode 100644 index 0000000..e3d67c9 --- /dev/null +++ b/14. Questions/leetcode 226 - invert binary tree.py @@ -0,0 +1,26 @@ +# invert a binary tree | leetcode 226 | https://leetcode.com/problems/invert-binary-tree/ +# method: (dfs) keep recursively swapping left and right subtrees + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def invertTree(self, root): + + def dfs(root): + if root is None: + return + + if root.left is None and root.right is None: + return + + root.left, root.right = root.right, root.left + dfs(root.left) + dfs(root.right) + + dfs(root) + return root \ No newline at end of file diff --git a/14. Questions/leetcode 2265 - count nodes equal to average of subtree.py b/14. Questions/leetcode 2265 - count nodes equal to average of subtree.py new file mode 100644 index 0000000..f5d5004 --- /dev/null +++ b/14. Questions/leetcode 2265 - count nodes equal to average of subtree.py @@ -0,0 +1,29 @@ +# count nodes equal to average of subtree | leetcode 2265 | https://leetcode.com/problems/count-nodes-equal-to-average-of-subtree/ +# method: dfs, update size and sum of subtree at each node and check for average + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def averageOfSubtree(self, root: list[TreeNode]) -> int: + self.counter = 0 + def dfs(node): + if node is None: + return 0, 0 + + lSize, lSum = dfs(node.left) + rSize, rSum = dfs(node.right) + + nSize, nSum = lSize + rSize + 1, lSum + rSum + node.val + if (nSum // nSize) == node.val: + self.counter += 1 + + return nSize, nSum + + dfs(root) + return self.counter + diff --git a/14. Questions/leetcode 2306 - naming a company.py b/14. Questions/leetcode 2306 - naming a company.py new file mode 100644 index 0000000..1bb30b7 --- /dev/null +++ b/14. Questions/leetcode 2306 - naming a company.py @@ -0,0 +1,24 @@ +# naming a company | leetcode 2306 | https://leetcode.com/problems/naming-a-company +# bucket by starting character to make it n(26^2.n) and compare each set with each other + +class Solution: + def distinctNames(self, ideas: list[str]) -> int: + buckets = dict() + num_distinct = 0 + + for idea in ideas: + if buckets.get(idea[0]) is None: + buckets[idea[0]] = {idea[1:]} + else: + buckets[idea[0]].add(idea[1:]) + + for prefix_i, suffix_i in buckets.items(): + for prefix_j, suffix_j in buckets.items(): + if prefix_i == prefix_j: + continue + common = len(suffix_i & suffix_j) + common_i = len(suffix_i) - common + common_j = len(suffix_j) - common + num_distinct += common_i * common_j + + return num_distinct \ No newline at end of file diff --git a/14. Questions/leetcode 2331 - evaluate boolean binary tree.py b/14. Questions/leetcode 2331 - evaluate boolean binary tree.py new file mode 100644 index 0000000..9312bc8 --- /dev/null +++ b/14. Questions/leetcode 2331 - evaluate boolean binary tree.py @@ -0,0 +1,22 @@ +# evaluate boolean binary tree | leetcode 2331 | https://leetcode.com/problems/evaluate-boolean-binary-tree/ +# method: dfs, evaluate left and/or right, return node's value + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def evaluateTree(self, node): + if node.left is None and node.right is None: + return node.val + + if node.val == 2: + node.val = bool(self.evaluateTree(node.left)) or bool(self.evaluateTree(node.right)) + + if node.val == 3: + node.val = bool(self.evaluateTree(node.left)) and bool(self.evaluateTree(node.right)) + + return node.val diff --git a/14. Questions/leetcode 235 - lowest common ancestor in bst.py b/14. Questions/leetcode 235 - lowest common ancestor in bst.py new file mode 100644 index 0000000..121e420 --- /dev/null +++ b/14. Questions/leetcode 235 - lowest common ancestor in bst.py @@ -0,0 +1,23 @@ +# lowest common ancestor in binary search tree | leetcode 235 | https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/ +# method: iteration through each node, when p and q are in different subtrees, current node is LCA + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +class Solution: + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': + cur = root + + while cur: + if p.val > cur.val and q.val > cur.val: + cur = cur.right + elif p.val < cur.val and q.val < cur.val: + cur = cur.left + else: + return cur + + return root diff --git a/14. Questions/leetcode 238 - product of array except self.py b/14. Questions/leetcode 238 - product of array except self.py new file mode 100644 index 0000000..a9c54b0 --- /dev/null +++ b/14. Questions/leetcode 238 - product of array except self.py @@ -0,0 +1,24 @@ +# product of array except self | leetcode 238 | https://leetcode.com/problems/product-of-array-except-self/ +# save prefixes to result array and apply postfix in reverse +# (since output array doesnt increase space complexity) + +class Solution: + def productExceptSelf(self, nums: list[int]) -> list[int]: + result = [] + N = len(nums) + + # save prefix to result array + product = 1 + for i in range(N): + product = nums[i] * product + result.append(product) + + # update result array as per postfix + postfix = 1 + for i in range(N - 1, 0, -1): + result[i] = result[i - 1] * postfix + postfix = postfix * nums[i] + result[0] = postfix + + return result + \ No newline at end of file diff --git a/14. Questions/leetcode 257 - binary tree paths.py b/14. Questions/leetcode 257 - binary tree paths.py new file mode 100644 index 0000000..582439c --- /dev/null +++ b/14. Questions/leetcode 257 - binary tree paths.py @@ -0,0 +1,30 @@ +# binary tree paths | leetcode 257 | https://leetcode.com/problems/binary-tree-paths/ +# method: (dfs) in-order traversal and at each node, update path. if leaf, append to list of paths. + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]: + def dfs(root, path): + if root is None: + return + + if root.left is None and root.right is None: + path += str(root.val) + self.paths.append(path) + return + + path += str(root.val) + '->' + dfs(root.left, path) + dfs(root.right, path) + + self.paths = [] + dfs(root, "") + + return self.paths + diff --git a/14. Questions/leetcode 28 - index of first occurrence.py b/14. Questions/leetcode 28 - index of first occurrence.py new file mode 100644 index 0000000..e059e17 --- /dev/null +++ b/14. Questions/leetcode 28 - index of first occurrence.py @@ -0,0 +1,26 @@ +# find the index of the first occurrence of a string | leetcode 28 | https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string/ +# sliding window to match each character of the haystack with the needle; no slices. + +class Solution: + def strStr(self, haystack: str, needle: str) -> int: + # ----- using regex ----- + # if needle == '': + # return 0 + + # import re + # match = re.search(needle, haystack) + # return match.start() if match else -1 + + # ----- using sliding windows ----- + ptrL, ptrR = 0, 0 + N_needle, N_haystack = len(needle), len(haystack) + while ptrR < N_haystack: + if haystack[ptrR] == needle[ptrR - ptrL]: + ptrR += 1 + if ptrR - ptrL > N_needle - 1: + return ptrL + else: + ptrR = ptrL + 1 + ptrL += 1 + + return -1 diff --git a/14. Questions/leetcode 290 - word pattern.py b/14. Questions/leetcode 290 - word pattern.py new file mode 100644 index 0000000..0b5ea40 --- /dev/null +++ b/14. Questions/leetcode 290 - word pattern.py @@ -0,0 +1,26 @@ +# word pattern | leetcode 290 | https://leetcode.com/problems/word-pattern/ +# create a vocabulary to match pattern and a seen hashset to record seen words + +class Solution: + def wordPattern(self, pattern: str, s: str) -> bool: + vocab = dict() + seens = dict() + sent = s.split(" ") + + if len(sent) != len(pattern): + return False + + for i in range(len(pattern)): + i_patt = pattern[i] + i_sent = sent[i] + + if vocab.get(i_patt): + if vocab[i_patt] != i_sent: + return False + else: + if seens.get(i_sent): + return False + vocab[i_patt] = i_sent + seens[i_sent] = True + + return True \ No newline at end of file diff --git a/14. Questions/leetcode 347 - top k frequent elements.py b/14. Questions/leetcode 347 - top k frequent elements.py new file mode 100644 index 0000000..e9265e3 --- /dev/null +++ b/14. Questions/leetcode 347 - top k frequent elements.py @@ -0,0 +1,25 @@ +# top k frequency elements | leetcode 347 | https://leetcode.com/problems/top-k-frequent-elements/ +# use buckets with each bucket being the frequency of an element + +from collections import Counter + +class Solution: + def topKFrequent(self, nums: list[int], k: int) -> list[int]: + freq = Counter(nums) + N = len(nums) + + # create buckets where index = frequency of element + buckets = [[] for x in range(N + 1)] + for f in freq: + buckets[freq[f]].append(f) + + # get k elements starting from the end of the bucket + k_mf = [] + for x in buckets[::-1]: + if k > 0: + if x != []: + k_mf += x + k -= len(x) + else: + return k_mf + \ No newline at end of file diff --git a/14. Questions/leetcode 424 - longest repeating character replacement.py b/14. Questions/leetcode 424 - longest repeating character replacement.py new file mode 100644 index 0000000..92a5607 --- /dev/null +++ b/14. Questions/leetcode 424 - longest repeating character replacement.py @@ -0,0 +1,23 @@ +# longest repeating character replacement | leetcode 424 | https://leetcode.com/problems/longest-repeating-character-replacement/ +# keep track of max freq in sliding window and check if size of window - max freq > k + +class Solution: + def characterReplacement(self, s: str, k: int) -> int: + ptrL = 0 + ptrR = 0 + longest = 0 + freq = dict() + max_freq = 0 + w_size = 0 + + for ptrR in range(len(s)): + freq[s[ptrR]] = 1 + freq.get(s[ptrR], 0) + max_freq = max(max_freq, freq[s[ptrR]]) + + if (ptrR - ptrL + 1) - max_freq > k: + freq[s[ptrL]] -= 1 + ptrL += 1 + + longest = max(longest, (ptrR - ptrL + 1)) + + return longest \ No newline at end of file diff --git a/14. Questions/leetcode 427 - construct quad tree.py b/14. Questions/leetcode 427 - construct quad tree.py new file mode 100644 index 0000000..f2dba66 --- /dev/null +++ b/14. Questions/leetcode 427 - construct quad tree.py @@ -0,0 +1,37 @@ +# construct quad tree | leetcode 427 | https://leetcode.com/problems/construct-quad-tree/ +# recursively call each quad of the grid and check if each quad is uniform or not + +# Definition for a QuadTree node. +class Node: + def __init__(self, val, isLeaf, topLeft, topRight, bottomLeft, bottomRight): + self.val = val + self.isLeaf = isLeaf + self.topLeft = topLeft + self.topRight = topRight + self.bottomLeft = bottomLeft + self.bottomRight = bottomRight + + +class Solution: + def construct(self, grid: list[list[int]]) -> Node: + def checkThisQuad(row, col, n) -> bool: + for i in range(row, row + n): + for j in range(col, col + n): + if grid[i][j] != grid[row][col]: + return False + return True + + def quadTree(row, col, n): + if checkThisQuad(row, col, n): + return Node(grid[row][col], 1, None, None, None, None) + + + return Node(grid[row][col], 0, + quadTree(row, col, n//2), + quadTree(row, col + n//2, n//2), + quadTree(row + n//2, col, n//2), + quadTree(row + n//2, col + n//2, n//2) + ) + + return quadTree(0, 0, len(grid)) + diff --git a/14. Questions/leetcode 435 - non-overlapping intervals.py b/14. Questions/leetcode 435 - non-overlapping intervals.py new file mode 100644 index 0000000..836a8b9 --- /dev/null +++ b/14. Questions/leetcode 435 - non-overlapping intervals.py @@ -0,0 +1,17 @@ +# non-overlapping intervals | leetcode 435 | https://leetcode.com/problems/non-overlapping-intervals +# sort by starting times; keep track of latest ending time; always keep interval with min end time + +class Solution: + def eraseOverlapIntervals(self, intervals: list[list[int]]) -> int: + min_intervals_to_remove = 0 + intervals.sort(key = lambda x: x[0]) + latest_end = intervals[0][1] + + for i in range(1, len(intervals)): + if intervals[i][0] < latest_end: + min_intervals_to_remove += 1 + latest_end = min(intervals[i][1], latest_end) + else: + latest_end = intervals[i][1] + + return min_intervals_to_remove diff --git a/14. Questions/leetcode 438 - find all anagrams in string.py b/14. Questions/leetcode 438 - find all anagrams in string.py new file mode 100644 index 0000000..c57b15a --- /dev/null +++ b/14. Questions/leetcode 438 - find all anagrams in string.py @@ -0,0 +1,24 @@ +# find all anagrams in string | leetcode 438 | https://leetcode.com/problems/find-all-anagrams-in-a-string/ +# sliding window to track "which" substring; add ptr2 to counter, remove ptr1 from counter + + +from collections import Counter + +class Solution: + def findAnagrams(self, s: str, p: str) -> list[int]: + Ns, Np = len(s), len(p) + ptr1 = 0 + ptr2 = Np - 1 + anagrams = [] + freq_s, freq_p = Counter(s[ptr1:(ptr2 + 1)]), Counter(p) + + while ptr2 < Ns: + if freq_s == freq_p: + anagrams.append(ptr1) + freq_s[s[ptr1]] -= 1 + ptr1 += 1 + ptr2 += 1 + if ptr2 != Ns: + freq_s[s[ptr2]] = 1 + freq_s.get(s[ptr2], 0) + + return anagrams \ No newline at end of file diff --git a/14. Questions/leetcode 443 - string compression.py b/14. Questions/leetcode 443 - string compression.py new file mode 100644 index 0000000..098546c --- /dev/null +++ b/14. Questions/leetcode 443 - string compression.py @@ -0,0 +1,22 @@ +# string compression | leetcode 443 | https://leetcode.com/problems/string-compression/ +# sliding window to keep track of a char's occurence + +class Solution: + def compress(self, chars: list[str]) -> int: + ptrL, ptrR = 0, 0 + total = 0 + chars += " " + + while ptrR < len(chars): + if chars[ptrL] != chars[ptrR]: + chars[total] = chars[ptrL] + total += 1 + group = ptrR - ptrL + if group > 1: + for x in str(group): + chars[total] = x + total += 1 + ptrL = ptrR + ptrR += 1 + + return total diff --git a/14. Questions/leetcode 49 - group anagrams.py b/14. Questions/leetcode 49 - group anagrams.py new file mode 100644 index 0000000..2fb7f76 --- /dev/null +++ b/14. Questions/leetcode 49 - group anagrams.py @@ -0,0 +1,16 @@ +# group anagrams | leetcode 49 | https://leetcode.com/problems/group-anagrams/ +# method: dictionary with char counter as key + +from collections import defaultdict + +class Solution: + def groupAnagrams(self, strs): + grouped = defaultdict(list) + + for each_word in strs: + count_of_ch = [0] * 26 + for each_ch in each_word: + count_of_ch[ord(each_ch) - ord("a")] += 1 + grouped[tuple(count_of_ch)].append(each_word) + + return grouped.values() diff --git a/14. Questions/leetcode 494 - target sum.py b/14. Questions/leetcode 494 - target sum.py new file mode 100644 index 0000000..ddc9e1b --- /dev/null +++ b/14. Questions/leetcode 494 - target sum.py @@ -0,0 +1,22 @@ +# target sum | leetcode 494 | https://leetcode.com/problems/target-sum/ +# 0/1 knapsack to decide +/- and cache (index, total) + +class Solution: + def findTargetSumWays(self, nums: list[int], target: int) -> int: + N = len(nums) + mem = dict() + + if N == 0: + return 0 + + def knapsack(n, s): + if n == N: + return 1 if s == target else 0 + + if (n, s) in mem: + return mem[(n, s)] + + mem[(n, s)] = knapsack(n+1, s + nums[n]) + knapsack(n+1, s - nums[n]) + return mem[(n, s)] + + return knapsack(0, 0) diff --git a/14. Questions/leetcode 502 - ipo.py b/14. Questions/leetcode 502 - ipo.py new file mode 100644 index 0000000..e48b6e1 --- /dev/null +++ b/14. Questions/leetcode 502 - ipo.py @@ -0,0 +1,21 @@ +# IPO | leetcode 502 | https://leetcode.com/problems/ipo/ +# min-heap to track capital and max-heap to track profits + +import heapq + +class Solution: + def findMaximizedCapital(self, k: int, w: int, profits: list[int], capital: list[int]) -> int: + maxHeap = [] + minHeap = [(c, p) for c, p in zip(capital, profits)] + heapq.heapify(minHeap) + + for _ in range(k): + while minHeap and minHeap[0][0] <= w: + _, p = heapq.heappop(minHeap) + heapq.heappush(maxHeap, -1 * p) + if not maxHeap: + break + w += -1 * heapq.heappop(maxHeap) + + return w + diff --git a/14. Questions/leetcode 530 - minimum absolute difference in BST.py b/14. Questions/leetcode 530 - minimum absolute difference in BST.py new file mode 100644 index 0000000..481fc30 --- /dev/null +++ b/14. Questions/leetcode 530 - minimum absolute difference in BST.py @@ -0,0 +1,32 @@ +# minimum absolute difference in BST | leetcode 530 | https://leetcode.com/problems/minimum-absolute-difference-in-bst/ +# method: dfs, inorder traversal + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def getMinimumDifference(self, root: TreeNode): + minDiff = float('inf') + prevNod = None + + def dfs(node): + nonlocal minDiff, prevNod + if node is None: + return + + dfs(node.left) + + if prevNod != None: + minDiff = min(minDiff, abs(node.val - prevNod)) + prevNod = node.val + + dfs(node.right) + + dfs(root) + return minDiff + + diff --git a/14. Questions/leetcode 540 - single element in a sorted array.py b/14. Questions/leetcode 540 - single element in a sorted array.py new file mode 100644 index 0000000..fe28feb --- /dev/null +++ b/14. Questions/leetcode 540 - single element in a sorted array.py @@ -0,0 +1,24 @@ +# single element in a sorted array | leetcode 540 | https://leetcode.com/problems/single-element-in-a-sorted-array/ +# binary search over sorted array; check if mid is even and mid is the first of the duplicates + +class Solution: + def singleNonDuplicate(self, nums: list[int]) -> int: + N = len(nums) + if N < 2: + return nums[0] + low, high, mid = 0, N, 0 + while low <= high: + mid = low + ((high - low) // 2) + + if mid == N - 1: + return nums[mid] + + if nums[mid] == nums[mid - 1] or nums[mid] == nums[mid + 1]: + if (mid % 2 == 0) == (nums[mid] == nums[mid + 1]): + low = mid + else: + high = mid + else: + return nums[mid] + + return nums[mid] \ No newline at end of file diff --git a/14. Questions/leetcode 559 - max depth of n-ary tree.py b/14. Questions/leetcode 559 - max depth of n-ary tree.py new file mode 100644 index 0000000..d9d2659 --- /dev/null +++ b/14. Questions/leetcode 559 - max depth of n-ary tree.py @@ -0,0 +1,20 @@ +# max depth of n-ary tree | leetcode 559 | https://leetcode.com/problems/maximum-depth-of-n-ary-tree/ +# method: (dfs) return 1 + max(depths) at each node, return 1 if leaf + +# Definition for a Node. +class Node: + def __init__(self, val=None, children=None): + self.val = val + self.children = children + +class Solution: + def maxDepth(self, root): + if root is None: + return 0 + + depths = [self.maxDepth(child) for child in root.children] + + if depths: + return 1 + max(depths) + + return 1 \ No newline at end of file diff --git a/14. Questions/leetcode 590 - n-ary tree postorder.py b/14. Questions/leetcode 590 - n-ary tree postorder.py new file mode 100644 index 0000000..9abd574 --- /dev/null +++ b/14. Questions/leetcode 590 - n-ary tree postorder.py @@ -0,0 +1,22 @@ +# n-ary tree postorder traversal | leetcode 590 | https://leetcode.com/problems/n-ary-tree-postorder-traversal/submissions/ +# method: (dfs) postorder traversal is L R N, so iterate through all children and then save node + +# Definition for a Node. +class Node: + def __init__(self, val=None, children=None): + self.val = val + self.children = children + +class Solution: + def postorder(self, root: Node): + self.postTrv = [] + def dfs(root): + if root is None: + return None + + [dfs(child) for child in root.children] + self.postTrv.append(root.val) + + dfs(root) + return self.postTrv + \ No newline at end of file diff --git a/14. Questions/leetcode 598 - n-ary tree preorder.py b/14. Questions/leetcode 598 - n-ary tree preorder.py new file mode 100644 index 0000000..8f3d2e9 --- /dev/null +++ b/14. Questions/leetcode 598 - n-ary tree preorder.py @@ -0,0 +1,22 @@ +# n-ary tree postorder traversal | leetcode 590 | https://leetcode.com/problems/n-ary-tree-postorder-traversal/submissions/ +# method: (dfs) postorder traversal is L R N, so iterate through all children and then save node + + +# Definition for a Node. +class Node: + def __init__(self, val=None, children=None): + self.val = val + self.children = children + +class Solution: + def preorder(self, root): + def dfs(root): + if root is None: + return None + + self.postTrv.append(root.val) + [dfs(child) for child in root.children] + + self.postTrv = [] + dfs(root) + return self.postTrv \ No newline at end of file diff --git a/14. Questions/leetcode 617 - merge binary trees.py b/14. Questions/leetcode 617 - merge binary trees.py new file mode 100644 index 0000000..5f63427 --- /dev/null +++ b/14. Questions/leetcode 617 - merge binary trees.py @@ -0,0 +1,20 @@ +# merge two binary trees | leetcode 617 | https://leetcode.com/problems/merge-two-binary-trees/ +# method: merge current, then merge left and right + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def mergeTrees(self, root1, root2): + if root1 is None and root2 is None: + return None + + curr = TreeNode((root1.val if root1 else 0) + (root2.val if root2 else 0)) + curr.left = self.mergeTrees(root1.left if root1 else None, root2.left if root2 else None) + curr.right = self.mergeTrees(root1.right if root1 else None, root2.right if root2 else None) + + return curr \ No newline at end of file diff --git a/14. Questions/leetcode 637 - avg of levels in binary tree.py b/14. Questions/leetcode 637 - avg of levels in binary tree.py new file mode 100644 index 0000000..2027180 --- /dev/null +++ b/14. Questions/leetcode 637 - avg of levels in binary tree.py @@ -0,0 +1,31 @@ +# average of levels in binary tree | leetcode 637 | https://leetcode.com/problems/average-of-levels-in-binary-tree/ +# method: (bfs) level order traversal, but instead of appending level to a list, append its average + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def averageOfLevels(self, root): + res = [] + Q = [] + + Q.append(root) + lQ = len(Q) + + while lQ is not 0: + level = [] + lQ = len(Q) + for i in range(lQ): + node = Q.pop(0) + if node is not None: + level.append(node.val) + Q.append(node.left) + Q.append(node.right) + if level: + res.append(sum(level) / len(level)) + + return res \ No newline at end of file diff --git a/14. Questions/leetcode 653 - two sum with binary tree.py b/14. Questions/leetcode 653 - two sum with binary tree.py new file mode 100644 index 0000000..5dc4a6a --- /dev/null +++ b/14. Questions/leetcode 653 - two sum with binary tree.py @@ -0,0 +1,34 @@ +# two sum iv - input is a bst | leetcode 653 | https://leetcode.com/problems/two-sum-iv-input-is-a-bst/submissions/ +# method: (dfs) bst inorder traversal gives a sorted array, run array two-sum. + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def twoSum(self, nums, target): + prev = {} + + for i, num in enumerate(nums): + diff = target - num + if diff in prev: + return [prev[diff], i] + prev[num] = i + + def dfs(self, root): + if root is None: + return + + self.dfs(root.left) + self.trv.append(root.val) + self.dfs(root.right) + + def findTarget(self, root, k): + self.trv = [] + self.dfs(root) + return self.twoSum(self.trv, k) + + \ No newline at end of file diff --git a/14. Questions/leetcode 783 - minimum distance between bst nodes.py b/14. Questions/leetcode 783 - minimum distance between bst nodes.py new file mode 100644 index 0000000..9129953 --- /dev/null +++ b/14. Questions/leetcode 783 - minimum distance between bst nodes.py @@ -0,0 +1,33 @@ +# minimum distance between bst nodes | leetcode 783 | https://leetcode.com/problems/minimum-distance-between-bst-nodes +# dfs; inorder; keep track of last traversed node and check against minimum difference + + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + def minDiffInBST(self, root: TreeNode) -> int: + stack = [] + curr = root + last = None + minDiff = float("inf") + while True: + if curr is not None: + stack.append(curr) + curr = curr.left + elif stack: + curr = stack.pop() + if last is not None: + minDiff = min(abs(last.val - curr.val), minDiff) + last = curr + curr = curr.right + else: + break + + return int(minDiff) + diff --git a/14. Questions/leetcode 797 - all paths from source to target.py b/14. Questions/leetcode 797 - all paths from source to target.py new file mode 100644 index 0000000..199a51d --- /dev/null +++ b/14. Questions/leetcode 797 - all paths from source to target.py @@ -0,0 +1,16 @@ +# all paths from source to target | leetcode 797 | https://leetcode.com/problems/all-paths-from-source-to-target/ +# method: dfs + +class Solution: + def allPathsSourceTarget(self, graph: list[list[int]]) -> list[list[int]]: + possiblePaths = [] + + def dfs(node, visited): + if node == len(graph) - 1: + possiblePaths.append(visited) + + for neighbour in graph[node]: + dfs(neighbour, [*visited, node]) + + dfs(0, [0]) + return possiblePaths diff --git a/14. Questions/leetcode 872 - leaf-similar trees.py b/14. Questions/leetcode 872 - leaf-similar trees.py new file mode 100644 index 0000000..0bc34c7 --- /dev/null +++ b/14. Questions/leetcode 872 - leaf-similar trees.py @@ -0,0 +1,30 @@ +# leaf-similar trees | leetcode 872 | https://leetcode.com/problems/leaf-similar-trees/ +# match the leaves of both trees + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def leafSimilar(self, root1, root2) -> bool: + def getLeaves(root): + if root is None: + return + + getLeaves(root.left) + if root.left is None and root.right is None: + self.leaves.append(root.val) + getLeaves(root.right) + + self.leaves = [] + getLeaves(root1) + leaves1 = self.leaves + + self.leaves = [] + getLeaves(root2) + leaves2 = self.leaves + + return leaves1 == leaves2 \ No newline at end of file diff --git a/14. Questions/leetcode 897 - increasing order bst.py b/14. Questions/leetcode 897 - increasing order bst.py new file mode 100644 index 0000000..040c8ec --- /dev/null +++ b/14. Questions/leetcode 897 - increasing order bst.py @@ -0,0 +1,31 @@ +# increasing order search tree | leetcode 897 | https://leetcode.com/problems/increasing-order-search-tree/ +# rearrange a bst with each node having only a right child, and the originally left-most leaf as the new root +# method: inorder traversal to return sorted array, insert all elements as right child (since sorted array) + + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def increasingBST(self, root): + self.inorderTrv = [] + def inorder(root): + if root is None: + return None + + inorder(root.left) + self.inorderTrv.append(root.val) + inorder(root.right) + + inorder(root) + newRoot = TreeNode(self.inorderTrv[0]) + toReturn = newRoot + for x in self.inorderTrv[1:]: + newRoot.right = TreeNode(x) + newRoot = newRoot.right + + return toReturn \ No newline at end of file diff --git a/14. Questions/leetcode 94 - binary tree inorder traversal.py b/14. Questions/leetcode 94 - binary tree inorder traversal.py new file mode 100644 index 0000000..2c7b11d --- /dev/null +++ b/14. Questions/leetcode 94 - binary tree inorder traversal.py @@ -0,0 +1,24 @@ +# binary tree inorder traversal | leetcode 94 | https://leetcode.com/problems/binary-tree-inorder-traversal/ +# method: left subtree, node, right subtree recursively + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def inorderTraversal(self, root): + travList = [] + + def traverse(root, travList): + if root is None: + return None + + traverse(root.left, travList) # traverse left subtree and add nodes + travList.append(root.val) # add this node + traverse(root.right, travList) # traverse right subtree and add nodes + + traverse(root, travList) + return travList diff --git a/14. Questions/leetcode 944 - delete columns to make sorted.py b/14. Questions/leetcode 944 - delete columns to make sorted.py new file mode 100644 index 0000000..de41086 --- /dev/null +++ b/14. Questions/leetcode 944 - delete columns to make sorted.py @@ -0,0 +1,15 @@ +# delete columns to make sorted | leetcode 944 | https://leetcode.com/problems/delete-columns-to-make-sorted/ + +class Solution: + def minDeletionSize(self, strs: list[str]) -> int: + n_cols = len(strs[0]) + n_rows = len(strs) + cols_d = 0 + + for col in range(n_cols): + for row in range(1, n_rows): + if strs[row][col] < strs[row - 1][col]: + cols_d += 1 + break + + return cols_d \ No newline at end of file diff --git a/14. Questions/leetcode 96 - unique binary search trees.py b/14. Questions/leetcode 96 - unique binary search trees.py new file mode 100644 index 0000000..23b1287 --- /dev/null +++ b/14. Questions/leetcode 96 - unique binary search trees.py @@ -0,0 +1,21 @@ +# unique binary search trees | leetcode 96 | https://leetcode.com/problems/unique-binary-search-trees/ +# method: dp, use cached results for subtrees of all possible roots + +class Solution: + def numTrees(self, n: int) -> int: + # cache of possible trees + possibleTrees = [1] * (n + 1) + + # for each number of nodes + for numNodes in range(2, n + 1): + + # for each possible root + possibleSubTrees = 0 + for possibleRoot in range(1, numNodes + 1): + Left = possibleRoot - 1 + Right = numNodes - possibleRoot + possibleSubTrees += possibleTrees[Left] * possibleTrees[Right] + possibleTrees[numNodes] = possibleSubTrees + + return possibleTrees[n] + diff --git a/14. Questions/leetcode 98 - validate binary search tree.py b/14. Questions/leetcode 98 - validate binary search tree.py new file mode 100644 index 0000000..c8f5928 --- /dev/null +++ b/14. Questions/leetcode 98 - validate binary search tree.py @@ -0,0 +1,36 @@ +# validate binary search tree | leetcode 98 | https://leetcode.com/problems/validate-binary-search-tree/ +# Given the root of a binary tree, determine if it is a valid binary search tree (BST). +# method: in-order traversal of a valid bst gives a sorted array +# tip: use `prev` pointer instead of an array to keep space complexity as O(1) + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + + # initialise a prev pointer + def __init__(self): + self.prev = None + + # in-order traversal (L M R) + # should return a sorted array + def isValidBST(self, root) -> bool: + + # if this node is none, its a leaf + if root is None: + return True + + if not self.isValidBST(root.left): + return False + + if self.prev is not None and self.prev.val >= root.val: + return False + + self.prev = root + + return self.isValidBST(root.right) \ No newline at end of file diff --git a/14. Questions/leetcode 989 - add to array form of integer.py b/14. Questions/leetcode 989 - add to array form of integer.py new file mode 100644 index 0000000..6fbd9ef --- /dev/null +++ b/14. Questions/leetcode 989 - add to array form of integer.py @@ -0,0 +1,19 @@ +# add to array form of integer | leetcode 989 | https://leetcode.com/problems/add-to-array-form-of-integer + +class Solution: + def addToArrayForm(self, num: list[int], k: int) -> list[int]: + n = len(num) - 1 + carry = 0 + while k or carry: + k, digit = k // 10, k % 10 + each = carry + digit + if n < 0: + num.insert(0, each % 10) + else: + each = each + num[n] + num[n] = each % 10 + carry = each // 10 + n -= 1 + + return num + diff --git a/14. Questions/leetcode 997 - find the town judge.py b/14. Questions/leetcode 997 - find the town judge.py new file mode 100644 index 0000000..c22c04d --- /dev/null +++ b/14. Questions/leetcode 997 - find the town judge.py @@ -0,0 +1,21 @@ +# find the town judge | leetcode 997 | https://leetcode.com/problems/find-the-town-judge/submissions/ +# method: decrement trust value if you trust someone, increment if someone trusts you + +class Solution: + def findJudge(self, n: int, trust: list[list[int]]) -> int: + + # for each person + # trust += 1 if someone trusts you + # trust -= 1 if you trust someone + trustValue = [0] * (n + 1) + + for edge in trust: + trustValue[edge[0]] -= 1 + trustValue[edge[1]] += 1 + + for i in range(1, n + 1): + if trustValue[i] == (n - 1): + return i + + return -1 + diff --git a/loggerMiddleware.js b/loggerMiddleware.js new file mode 100644 index 0000000..25925e8 --- /dev/null +++ b/loggerMiddleware.js @@ -0,0 +1,29 @@ +const express = require('express'); +const app = express(); + +// Middleware function to log requests +app.use((req, res, next) => { + console.log(`Received a ${req.method} request to ${req.url}`); + next(); // Call next() to move to the next middleware or route handler +}); + +// Middleware function to check if the request contains a specific header +app.use((req, res, next) => { + if (req.headers.authorization) { + console.log('Authorization header present'); + } else { + console.log('Authorization header not present'); + } + next(); +}); + +// Route handler +app.get('/', (req, res) => { + res.send('Hello, World!'); +}); + +// Starting the server +const PORT = process.env.PORT || 3000; +app.listen(PORT, () => { + console.log(`Server is running on port ${PORT}`); +}); diff --git a/server.js b/server.js new file mode 100644 index 0000000..ec24f31 --- /dev/null +++ b/server.js @@ -0,0 +1,32 @@ +// Import required modules +const express = require('express'); + +// Create an Express application +const app = express(); + +// Middleware function to log requests +app.use((req, res, next) => { + console.log(`Received a ${req.method} request to ${req.url}`); + next(); // Call next() to move to the next middleware or route handler +}); + +// Middleware function to check if the request contains a specific header +app.use((req, res, next) => { + if (req.headers.authorization) { + console.log('Authorization header present'); + } else { + console.log('Authorization header not present'); + } + next(); +}); + +// Route handler +app.get('/', (req, res) => { + res.send('Hello, World!'); +}); + +// Starting the server +const PORT = process.env.PORT || 3000; +app.listen(PORT, () => { + console.log(`Server is running on port ${PORT}`); +});