diff --git a/.gitignore b/.gitignore index 3e65703..84ab534 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ .vscode/ __pycache__/ -.DS_Store \ No newline at end of file +.DS_Store +14. Questions/code.py +14. Questions/temp.py +14. Questions/tempCodeRunnerFile.py \ No newline at end of file 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/04. Algorithms/Searching/Alt_Binary_Search.py b/04. Algorithms/Searching/Alt_Binary_Search.py new file mode 100644 index 0000000..f29e8f1 --- /dev/null +++ b/04. Algorithms/Searching/Alt_Binary_Search.py @@ -0,0 +1,20 @@ +# alternative binary search +# - based on "efficient iteration" +# - make jumps and slow down as we get close to target +# - time complexity => O(logn) + +# iterative +def bsearch_alt(target, arr): + n = len(arr) + k = 0 + i = n // 2 + while (i >= 1): + while (k + i < n) and (arr[k + i] <= target): + k = k + 1 + i = i // 2 + + return k if arr[k] == target else -1 + + + +print(bsearch_alt(4, [1, 2, 3, 4, 5])) 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 01 - two sum.py b/14. Questions/leetcode 01 - two sum.py new file mode 100644 index 0000000..aeacc11 --- /dev/null +++ b/14. Questions/leetcode 01 - two sum.py @@ -0,0 +1,31 @@ +""" +Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. + +You may assume that each input would have exactly one solution, and you may not use the same element twice. + +You can return the answer in any order. + +Question: https://leetcode.com/problems/two-sum/ + +""" +#O(n)^2 solution - brute force +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + for i in range(len(nums)): + for j in range(i+1, len(nums)): + if nums[i] + nums[j] == target: + return [i,j] + return [] + +#O(n) solution - hash maps + +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + prevMap = {} + + for i, n in enumerate(nums): + diff = target-n + if diff in prevMap: + return[prevMap[diff],i] + prevMap[n] = i + return \ No newline at end of file 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 09 - palindrome number.py b/14. Questions/leetcode 09 - palindrome number.py new file mode 100644 index 0000000..117d6e7 --- /dev/null +++ b/14. Questions/leetcode 09 - palindrome number.py @@ -0,0 +1,25 @@ +""" +Given an integer x, return true if x is palindrome integer. + +An integer is a palindrome when it reads the same backward as forward. + +For example, 121 is a palindrome while 123 is not. + +Question: https://leetcode.com/problems/palindrome-number/ + +""" + + +class Solution: + def isPalindrome(self, x: int) -> bool: + if x < 0: + return False + c = x + b = 0 + + while c: + b = b * 10 + c % 10 + c //= 10 + + return b == x + \ 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 1147 - largest number at least twice of others.py b/14. Questions/leetcode 1147 - largest number at least twice of others.py new file mode 100644 index 0000000..8ddc939 --- /dev/null +++ b/14. Questions/leetcode 1147 - largest number at least twice of others.py @@ -0,0 +1,26 @@ +""" +You are given an integer array nums where the largest integer is unique. + +Determine whether the largest element in the array is at least twice as much as every other number in the array. If it is, return the index of the largest element, or return -1 otherwise. + +Question: https://leetcode.com/explore/learn/card/array-and-string/201/introduction-to-array/1147/ + +""" + +class Solution: + def dominantIndex(self, nums: List[int]) -> int: + if len(nums) == 1: + return 0 + a = max(nums) + for i in range(len(nums)): + if nums[i] == a: + b = i + nums.remove(a) + count = 0 + for i in nums: + if (a >= 2*i): + count = count +1 + if count == len(nums): + return b + else: + return -1 \ No newline at end of file diff --git a/14. Questions/leetcode 121 - best time to buy and sell stock.py b/14. Questions/leetcode 121 - best time to buy and sell stock.py new file mode 100644 index 0000000..ddf30ff --- /dev/null +++ b/14. Questions/leetcode 121 - best time to buy and sell stock.py @@ -0,0 +1,26 @@ +""" +You are given an array prices where prices[i] is the price of a given stock on the ith day. + +You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock. + +Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0. + +Question: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ + +""" +class Solution: + def maxProfit(self, prices: List[int]) -> int: + l = 0 + r = 1 + maxP = 0 + + while r 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 13 - roman to integer.py b/14. Questions/leetcode 13 - roman to integer.py new file mode 100644 index 0000000..ee75fe2 --- /dev/null +++ b/14. Questions/leetcode 13 - roman to integer.py @@ -0,0 +1,37 @@ +""" +Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. + +Symbol Value +I 1 +V 5 +X 10 +L 50 +C 100 +D 500 +M 1000 +For example, 2 is written as II in Roman numeral, just two one's added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II. + +Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used: + +I can be placed before V (5) and X (10) to make 4 and 9. +X can be placed before L (50) and C (100) to make 40 and 90. +C can be placed before D (500) and M (1000) to make 400 and 900. +Given a roman numeral, convert it to an integer. + +Questions: https://leetcode.com/problems/roman-to-integer/ + +""" + + +class Solution: + def romanToInt(self, s: str) -> int: + roman = {'I':1, 'V':5, 'X': 10, 'L':50, 'C':100, 'D':500, 'M':1000} + + res = 0 + + for i in range(len(s)): + if i+1 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 14 - longest common prefix.py b/14. Questions/leetcode 14 - longest common prefix.py new file mode 100644 index 0000000..162c57e --- /dev/null +++ b/14. Questions/leetcode 14 - longest common prefix.py @@ -0,0 +1,33 @@ +""" +Write a function to find the longest common prefix string amongst an array of strings. + +If there is no common prefix, return an empty string "". + +Questions: https://leetcode.com/problems/longest-common-prefix/ + +""" + +class Solution: + def longestCommonPrefix(self, strs: List[str]) -> str: + res = "" + n = len(strs) + strs.sort() + first = strs[0] + last = strs[n-1] + for i in range(len(first)): + if first[i] != last[i]: + return res + else: + res = res + first[i] + return res + + + +# for i in range(len(strs[0])): +# for s in strs: +# if i == len(s) or s[i] != strs[0][i]: +# return res + +# res += strs[0][i] + +# return res \ 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 162 - peak element.py b/14. Questions/leetcode 162 - peak element.py new file mode 100644 index 0000000..0a93f27 --- /dev/null +++ b/14. Questions/leetcode 162 - peak element.py @@ -0,0 +1,16 @@ +# find peak element | leetcode 162 | https://leetcode.com/problems/find-peak-element/ +# using binary search to determine +# if the "middle" element is on a +ve / -ve slope + +class Solution: + def findPeakElement(self, nums: list[int]) -> int: + a = 0 + b = len(nums) - 1 + while a < b: + k = (a + b) // 2 + if nums[k] > nums[k + 1]: + b = k + else: + a = k + 1 + + return a \ 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 1991 - find the middle index in array.py b/14. Questions/leetcode 1991 - find the middle index in array.py new file mode 100644 index 0000000..7346a54 --- /dev/null +++ b/14. Questions/leetcode 1991 - find the middle index in array.py @@ -0,0 +1,26 @@ +""" + +Given a 0-indexed integer array nums, find the leftmost middleIndex (i.e., the smallest amongst all the possible ones). + +A middleIndex is an index where nums[0] + nums[1] + ... + nums[middleIndex-1] == nums[middleIndex+1] + nums[middleIndex+2] + ... + nums[nums.length-1]. + +If middleIndex == 0, the left side sum is considered to be 0. Similarly, if middleIndex == nums.length - 1, the right side sum is considered to be 0. + +Return the leftmost middleIndex that satisfies the condition, or -1 if there is no such index. + +Question: https://leetcode.com/problems/find-the-middle-index-in-array/ + +""" + + +class Solution: + def findMiddleIndex(self, nums: List[int]) -> int: + total = sum(nums) + + leftSum = 0 + for i in range(len(nums)): + rightSum = total - nums[i] - leftSum + if leftSum == rightSum: + return i + leftSum += nums[i] + return -1 \ No newline at end of file diff --git a/14. Questions/leetcode 20 - valid parentheses.py b/14. Questions/leetcode 20 - valid parentheses.py new file mode 100644 index 0000000..74cb1a6 --- /dev/null +++ b/14. Questions/leetcode 20 - valid parentheses.py @@ -0,0 +1,53 @@ +""" +Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. + +An input string is valid if: + +Open brackets must be closed by the same type of brackets. +Open brackets must be closed in the correct order. + +Question: https://leetcode.com/problems/valid-parentheses/ + + +""" + + +class Solution: + def isValid(self, s: str) -> bool: + para = {')':'(', ']':'[', '}':'{'} + op = ['(','[', '{'] + stack = [] + + for c in s: + if c in op: + stack.append(c) + + elif c in para: + if len(stack) != 0 and stack[-1] == para[c]: + stack.pop() + else: + return False + + if len(stack) == 0: + return True + else: + return False + + + + + + +# if c in para: +# if len(stack) != 0 and stack[-1] == para[c]: +# stack.pop() +# else: +# return False + +# else: +# stack.append(c) + +# if len(stack) == 0: +# return True +# else: +# False \ No newline at end of file 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 21 - merge two sorted lists.py b/14. Questions/leetcode 21 - merge two sorted lists.py new file mode 100644 index 0000000..de17146 --- /dev/null +++ b/14. Questions/leetcode 21 - merge two sorted lists.py @@ -0,0 +1,35 @@ +""" +You are given the heads of two sorted linked lists list1 and list2. + +Merge the two lists in a one sorted list. The list should be made by splicing together the nodes of the first two lists. + +Return the head of the merged linked list. + +Question: https://leetcode.com/problems/merge-two-sorted-lists/ + +""" + + +class ListNode: + def __init__(self, val=0, next=None): + self.val = val + self.next = next +class Solution: + def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: + answer = ListNode() + tail = answer + while list1 and list2: + if list1.val < list2.val: + tail.next = list1 + list1 = list1.next + else: + tail.next = list2 + list2=list2.next + tail = tail.next + + if list1: + tail.next = list1 + elif list2: + tail.next = list2 + + return answer.next \ No newline at end of file diff --git a/14. Questions/leetcode 217 - contains duplicates.py b/14. Questions/leetcode 217 - contains duplicates.py new file mode 100644 index 0000000..11c77ed --- /dev/null +++ b/14. Questions/leetcode 217 - contains duplicates.py @@ -0,0 +1,16 @@ +""" +Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct. + +Question: https://leetcode.com/problems/contains-duplicate/ + +""" +class Solution: + def containsDuplicate(self, nums: List[int]) -> bool: + duplicates = {} + for i in nums: + if i in duplicates: + return True + else: + duplicates[i] = 1 + return False + \ No newline at end of file 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 234 - palindrome linked list.py b/14. Questions/leetcode 234 - palindrome linked list.py new file mode 100644 index 0000000..b026666 --- /dev/null +++ b/14. Questions/leetcode 234 - palindrome linked list.py @@ -0,0 +1,58 @@ +# palindrome linked list | leetcode 234 | https://leetcode.com/problems/palindrome-linked-list/ + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + + # to check if its palindrome + def isPalindrome(self, head) -> bool: + + # if underflow, is palindrome + if not head or not head.next: return True + + # get one before mid element + # and check if number of elements are even + mid, even = self.get_mid(head) + second = mid.next + if not even: second = second.next + + # reverse the first half of the linked list + first = self.rev_ll(head, mid) + + # match the reversed 1st and normal 2nd halves + while first and second: + if first.val != second.val: return False + first = first.next + second = second.next + return True + + + # to reverse the linked list half + def rev_ll(self, head, upto): + prev, curr = None, head + + while curr and prev != upto: + temp = curr.next + curr.next = prev + prev = curr + curr = temp + + return prev + + # to get the mid element + # and check for even + def get_mid(self, head): + prev = head + slow = head + fast = head.next + + while fast and fast.next: + prev = slow + slow = slow.next + fast = fast.next.next + + if not fast: return prev, False + return slow, True 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 26 - remove duplicates from sorted array.py b/14. Questions/leetcode 26 - remove duplicates from sorted array.py new file mode 100644 index 0000000..e42703e --- /dev/null +++ b/14. Questions/leetcode 26 - remove duplicates from sorted array.py @@ -0,0 +1,23 @@ +""" +Given an integer array nums sorted in non-decreasing order, remove the duplicates in-place such that each unique element appears only once. The relative order of the elements should be kept the same. + +Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements. + +Return k after placing the final result in the first k slots of nums. + +Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory. + +Question: https://leetcode.com/problems/remove-duplicates-from-sorted-array/ + +""" + +class Solution: + def removeDuplicates(self, nums: List[int]) -> int: + list = 1 + + for r in range(1, len(nums)): + if nums[r] != nums[r-1]: + nums[list] = nums[r] + list += 1 + + return list \ No newline at end of file diff --git a/14. Questions/leetcode 27 - remove element.py b/14. Questions/leetcode 27 - remove element.py new file mode 100644 index 0000000..d41b2c3 --- /dev/null +++ b/14. Questions/leetcode 27 - remove element.py @@ -0,0 +1,24 @@ +""" +Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The relative order of the elements may be changed. + +Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements. + +Return k after placing the final result in the first k slots of nums. + +Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory. + +Question: https://leetcode.com/problems/remove-element/ + +""" + + +class Solution: + def removeDuplicates(self, nums: List[int]) -> int: + list = 1 + + for r in range(1, len(nums)): + if nums[r] != nums[r-1]: + nums[list] = nums[r] + list += 1 + + return list \ No newline at end of file diff --git a/14. Questions/leetcode 28 - implement strStr().py b/14. Questions/leetcode 28 - implement strStr().py new file mode 100644 index 0000000..632d895 --- /dev/null +++ b/14. Questions/leetcode 28 - implement strStr().py @@ -0,0 +1,24 @@ +""" +Implement strStr(). + +Given two strings needle and haystack, return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. + +Clarification: + +What should we return when needle is an empty string? This is a great question to ask during an interview. + +For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C's strstr() and Java's indexOf(). + +Question: https://leetcode.com/problems/implement-strstr/ + +""" + +class Solution: + def strStr(self, haystack: str, needle: str) -> int: + if not needle: + return 0 + + for i in range(len(haystack)): + if haystack[i:i+len(needle)] == needle: + return i + return -1 \ No newline at end of file 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 35 - search insert position.py b/14. Questions/leetcode 35 - search insert position.py new file mode 100644 index 0000000..c4d56d7 --- /dev/null +++ b/14. Questions/leetcode 35 - search insert position.py @@ -0,0 +1,28 @@ +""" + +Given a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. + +You must write an algorithm with O(log n) runtime complexity. + +Question: https://leetcode.com/problems/search-insert-position/ + +""" + +class Solution: + def searchInsert(self, nums: List[int], target: int) -> int: + l = 0 + r = len(nums)-1 + + while l <= r: + mid = (l+r)//2 + + if target == nums[mid]: + return mid + + if target > nums[mid]: + l = mid +1 + + else: + r = mid - 1 + + return l \ No newline at end of file diff --git a/14. Questions/leetcode 350 - intersection of two arrays II.py b/14. Questions/leetcode 350 - intersection of two arrays II.py new file mode 100644 index 0000000..d808e2c --- /dev/null +++ b/14. Questions/leetcode 350 - intersection of two arrays II.py @@ -0,0 +1,42 @@ +""" +Given two integer arrays nums1 and nums2, return an array of their intersection. Each element in the result must appear as many times as it shows in both arrays and you may return the result in any order. + + +Question: https://leetcode.com/problems/intersection-of-two-arrays-ii/ + + +""" + +#solution 1 +class Solution: + def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]: + c = Counter(nums1) + output=[] + for n in (nums2): + if c[n] > 0: + output.append(n) + c[n]-=1 + + return (output) + +#solution 2 + +class Solution: + def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]: + i=0 + j=0 + output = [] + nums1.sort() + nums2.sort() + + while i nums2[j]: + j = j+1 + else: + output.append(nums1[i]) + i=i+1 + j=j+1 + + return output 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 53 - maximum subarray.py b/14. Questions/leetcode 53 - maximum subarray.py new file mode 100644 index 0000000..b11ffe5 --- /dev/null +++ b/14. Questions/leetcode 53 - maximum subarray.py @@ -0,0 +1,21 @@ +""" +Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. + +A subarray is a contiguous part of an array. + +Question: https://leetcode.com/problems/maximum-subarray/ + + +""" + +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + maxSub = nums[0] + curSum = 0 + + for n in nums: + if curSum <0: + curSum = 0 + curSum += n + maxSub = max(maxSub, curSum) + return maxSub \ No newline at end of file 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 58 - length of last word.py b/14. Questions/leetcode 58 - length of last word.py new file mode 100644 index 0000000..3f5904a --- /dev/null +++ b/14. Questions/leetcode 58 - length of last word.py @@ -0,0 +1,29 @@ +""" +Given a string s consisting of some words separated by some number of spaces, return the length of the last word in the string. + +A word is a maximal substring consisting of non-space characters only. + +Question: https://leetcode.com/problems/length-of-last-word/ + +""" + +#Solution usinf inbuilt fuctions : +class Solution: + def lengthOfLastWord(self, s: str) -> int: + s = s.strip() + s = s.split(" ") + last = s[len(s)-1] + return (len(last)) + + +#Solution without inbuilt fuctions : +class Solution: + def lengthOfLastWord(self, s: str) -> int: + i, length = len(s)-1, 0 + while s[i] == " ": + i -= 1 + while i >= 0 and s[i] != " ": + length += 1 + i -= 1 + return length + 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 66 - plus one.py b/14. Questions/leetcode 66 - plus one.py new file mode 100644 index 0000000..a4657a6 --- /dev/null +++ b/14. Questions/leetcode 66 - plus one.py @@ -0,0 +1,18 @@ +""" +You are given a large integer represented as an integer array digits, where each digits[i] is the ith digit of the integer. The digits are ordered from most significant to least significant in left-to-right order. The large integer does not contain any leading 0's. + +Increment the large integer by one and return the resulting array of digits. + +Question: https://leetcode.com/problems/plus-one/ + +""" + +class Solution: + def plusOne(self, digits: List[int]) -> List[int]: + n = 0 + for i in range(len(digits)): + n = (n*10)+digits[i] + n = n+1 + m = map(int, str(n)) + return(m) + \ No newline at end of file diff --git a/14. Questions/leetcode 67 - add binary.py b/14. Questions/leetcode 67 - add binary.py new file mode 100644 index 0000000..c6723b6 --- /dev/null +++ b/14. Questions/leetcode 67 - add binary.py @@ -0,0 +1,28 @@ +""" +Given two binary strings a and b, return their sum as a binary string. + +Question: https://leetcode.com/problems/add-binary/ + +""" + +class Solution: + def addBinary(self, a: str, b: str) -> str: + result = "" + aCount = len(a) - 1 + bCount = len(b) - 1 + + carry = 0 + + while aCount >= 0 or bCount >= 0: + totalSum = carry + if aCount >= 0: + totalSum += int(a[aCount]) + aCount -= 1 + if bCount >= 0: + totalSum += int(b[bCount]) + bCount -= 1 + result = str(totalSum % 2) + result + carry = totalSum // 2 + if carry > 0: + result = str(1) + result + return result \ No newline at end of file diff --git a/14. Questions/leetcode 69 - sqrt(x).py b/14. Questions/leetcode 69 - sqrt(x).py new file mode 100644 index 0000000..1e70278 --- /dev/null +++ b/14. Questions/leetcode 69 - sqrt(x).py @@ -0,0 +1,37 @@ +""" + +Given a non-negative integer x, compute and return the square root of x. + +Since the return type is an integer, the decimal digits are truncated, and only the integer part of the result is returned. + +Note: You are not allowed to use any built-in exponent function or operator, such as pow(x, 0.5) or x ** 0.5. + +Question : https://leetcode.com/problems/sqrtx/ + +""" + +# import numpy as np +# class Solution: +# def mySqrt(self, x: int) -> int: +# return int(np.sqrt(x)) + +class Solution: + def mySqrt(self, x: int) -> int: + + start = 0 + end = x + + while start + 1 < end: + mid = start + (end - start) // 2 + + if mid * mid == x: + return mid + elif mid * mid < x: + start = mid + else: + end = mid + + if end * end == x: + return end + + return start \ No newline at end of file diff --git a/14. Questions/leetcode 70 - climbing stairs.py b/14. Questions/leetcode 70 - climbing stairs.py new file mode 100644 index 0000000..228028d --- /dev/null +++ b/14. Questions/leetcode 70 - climbing stairs.py @@ -0,0 +1,20 @@ +""" + +You are climbing a staircase. It takes n steps to reach the top. + +Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? + +Question: https://leetcode.com/problems/climbing-stairs/ + +""" + +class Solution: + def climbStairs(self, n: int) -> int: + one, two = 1,1 + + for i in range (n-1): + temp = one + one = one +two + two = temp + + return one \ No newline at end of file diff --git a/14. Questions/leetcode 724 - find pivot index.py b/14. Questions/leetcode 724 - find pivot index.py new file mode 100644 index 0000000..c42f47a --- /dev/null +++ b/14. Questions/leetcode 724 - find pivot index.py @@ -0,0 +1,25 @@ +""" +Given an array of integers nums, calculate the pivot index of this array. + +The pivot index is the index where the sum of all the numbers strictly to the left of the index is equal to the sum of all the numbers strictly to the index's right. + +If the index is on the left edge of the array, then the left sum is 0 because there are no elements to the left. This also applies to the right edge of the array. + +Return the leftmost pivot index. If no such index exists, return -1. + +Question : https://leetcode.com/problems/find-pivot-index/ + + +""" + +class Solution: + def pivotIndex(self, nums: List[int]) -> int: + total = sum(nums) + + leftSum = 0 + for i in range(len(nums)): + rightSum = total - nums[i] - leftSum + if leftSum == rightSum: + return i + leftSum += nums[i] + return -1 \ 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 83 - remove duplicates from sorted list.py b/14. Questions/leetcode 83 - remove duplicates from sorted list.py new file mode 100644 index 0000000..1e0e2bc --- /dev/null +++ b/14. Questions/leetcode 83 - remove duplicates from sorted list.py @@ -0,0 +1,24 @@ +""" +Given the head of a sorted linked list, delete all duplicates such that each element appears only once. Return the linked list sorted as well. + +Question: https://leetcode.com/problems/remove-duplicates-from-sorted-list/ + +""" + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next + +class Solution: + def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]: + cur = head + + while cur: + while cur.next and cur.next.val == cur .val: + cur.next = cur.next.next + cur = cur.next + + return head + \ No newline at end of file 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 88 - merger sort array.py b/14. Questions/leetcode 88 - merger sort array.py new file mode 100644 index 0000000..cd492f3 --- /dev/null +++ b/14. Questions/leetcode 88 - merger sort array.py @@ -0,0 +1,32 @@ +""" +You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, and two integers m and n, representing the number of elements in nums1 and nums2 respectively. + +Merge nums1 and nums2 into a single array sorted in non-decreasing order. + +The final sorted array should not be returned by the function, but instead be stored inside the array nums1. To accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that should be merged, and the last n elements are set to 0 and should be ignored. nums2 has a length of n. + +Question: https://leetcode.com/problems/merge-sorted-array/ + +""" + +class Solution: + def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: + """ + Do not return anything, modify nums1 in-place instead. + """ + last = m + n - 1 + + #merge in reverse order + while m>0 and n>0: + if nums1[m-1] > nums2[n-1]: + nums1[last] = nums1[m-1] + m = m-1 + else: + nums1[last] = nums2[n-1] + n = n-1 + last = last - 1 + + #fill nums1 with leftover nums2 elements + while n>0: + nums1[last] = nums2[n-1] + n, last = n-1, last -1 \ 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/DSA_Cheatsheet.pdf b/DSA_Cheatsheet.pdf new file mode 100644 index 0000000..624ae5d Binary files /dev/null and b/DSA_Cheatsheet.pdf differ 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/readme.md b/readme.md index f3301df..f5318ec 100644 --- a/readme.md +++ b/readme.md @@ -15,7 +15,7 @@ All the essential resources and template code needed to understand and practice - [Data Structures - Reema Thareja](/01.%20Resources/Books/Data%20Structures%20-%20Reema%20Thareja.pdf) - [competitiveCoding](https://github.com/mihirs16/Data-Structures-and-Algorithms-Python/blob/master/01.%20Resources/Books/competitiveCoding.pdf) 2. [Big-O Cheat Sheet](/01.%20Resources/BigO-cheat-sheet.pdf) -3. [DAA Syllabus](/01.%20Resource/DAA%20Syllabus.pdf) +3. [DAA Syllabus](/01.%20Resources/DAA%20Syllabus.pdf) 4. [Interview Cheat sheet](/01.%20Resources/Interview%20cheatsheet.pdf) 5. [Master Plan](/01.%20Resources/Master%20Plan.pdf) 6. [Master the Interview](/01.%20Resources/Master_the_Interview.pdf) 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}`); +});