├── 1.py ├── 10.py ├── 11.py ├── 12.py ├── 13.py ├── 14.py ├── 15.py ├── 16.py ├── 17.py ├── 18.py ├── 19.py ├── 2.py ├── 20.py ├── 21.py ├── 22.py ├── 3.py ├── 4.py ├── 5.py ├── 6.py ├── 7.py ├── 8.py ├── 9.py └── README.md /1.py: -------------------------------------------------------------------------------- 1 | # Two pointer approach : One input, opposite ends 2 | 3 | def fn(arr): 4 | left = ans = 0 5 | right = len(arr) - 1 6 | 7 | while left < right: 8 | # do some logic here with left and right 9 | if CONDITION: 10 | left += 1 11 | else: 12 | right -= 1 13 | 14 | return ans 15 | -------------------------------------------------------------------------------- /10.py: -------------------------------------------------------------------------------- 1 | # Binary Tree Recursive : DFA (recursive) 2 | 3 | def dfs(root): 4 | if not root: 5 | return 6 | 7 | ans = 0 8 | 9 | # do logic 10 | dfs(root.left) 11 | dfs(root.right) 12 | return ans 13 | -------------------------------------------------------------------------------- /11.py: -------------------------------------------------------------------------------- 1 | # Binary Tree DFS : iterative 2 | 3 | def dfs(root): 4 | stack = [root] 5 | ans = 0 6 | 7 | while stack: 8 | node = stack.pop() 9 | # do logic 10 | if node.left: 11 | stack.append(node.left) 12 | if node.right: 13 | stack.append(node.right) 14 | 15 | return ans 16 | -------------------------------------------------------------------------------- /12.py: -------------------------------------------------------------------------------- 1 | # Binary Tree BFS 2 | 3 | from collections import deque 4 | 5 | def fn(root): 6 | queue = deque([root]) 7 | ans = 0 8 | 9 | while queue: 10 | current_length = len(queue) 11 | # do logic for current level 12 | 13 | for _ in range(current_length): 14 | node = queue.popleft() 15 | # do logic 16 | if node.left: 17 | queue.append(node.left) 18 | if node.right: 19 | queue.append(node.right) 20 | 21 | return ans 22 | -------------------------------------------------------------------------------- /13.py: -------------------------------------------------------------------------------- 1 | # Graph DFS : recursive 2 | 3 | def fn(graph): 4 | def dfs(node): 5 | ans = 0 6 | # do some logic 7 | for neighbor in graph[node]: 8 | if neighbor not in seen: 9 | seen.add(neighbor) 10 | ans += dfs(neighbor) 11 | 12 | return ans 13 | 14 | seen = {START_NODE} 15 | return dfs(START_NODE) 16 | -------------------------------------------------------------------------------- /14.py: -------------------------------------------------------------------------------- 1 | # Graph DFS : iterative 2 | def fn(graph): 3 | stack = [START_NODE] 4 | seen = {START_NODE} 5 | ans = 0 6 | 7 | while stack: 8 | node = stack.pop() 9 | # do some logic 10 | for neighbor in graph[node]: 11 | if neighbor not in seen: 12 | seen.add(neighbor) 13 | stack.append(neighbor) 14 | 15 | return ans 16 | -------------------------------------------------------------------------------- /15.py: -------------------------------------------------------------------------------- 1 | # Graph BFS 2 | from collections import deque 3 | 4 | def fn(graph): 5 | queue = deque([START_NODE]) 6 | seen = {START_NODE} 7 | ans = 0 8 | 9 | while queue: 10 | node = queue.popleft() 11 | # do some logic 12 | for neighbor in graph[node]: 13 | if neighbor not in seen: 14 | seen.add(neighbor) 15 | queue.append(neighbor) 16 | 17 | return ans 18 | -------------------------------------------------------------------------------- /16.py: -------------------------------------------------------------------------------- 1 | # Find top K elements 2 | import heapq 3 | 4 | def fn(arr, k): 5 | heap = [] 6 | for num in arr: 7 | # do some logic to push onto heap according to problem's criteria 8 | heapq.heappush(heap, (CRITERIA, num)) 9 | if len(heap) > k: 10 | heapq.heappop(heap) 11 | 12 | return [num for num in heap] 13 | -------------------------------------------------------------------------------- /17.py: -------------------------------------------------------------------------------- 1 | # Binary Search 2 | 3 | def fn(arr, target): 4 | left = 0 5 | right = len(arr) - 1 6 | while left <= right: 7 | mid = (left + right) // 2 8 | if arr[mid] == target: 9 | # do something 10 | return 11 | if arr[mid] > target: 12 | right = mid - 1 13 | else: 14 | left = mid + 1 15 | 16 | # left is the insertion point 17 | return left 18 | -------------------------------------------------------------------------------- /18.py: -------------------------------------------------------------------------------- 1 | # Binary search : duplicate elements 2 | 3 | def fn(arr, target): 4 | left = 0 5 | right = len(arr) 6 | while left < right: 7 | mid = (left + right) // 2 8 | if arr[mid] >= target: 9 | right = mid 10 | else: 11 | left = mid + 1 12 | 13 | return left 14 | -------------------------------------------------------------------------------- /19.py: -------------------------------------------------------------------------------- 1 | # Binary search duplicate elements : right-most 2 | 3 | def fn(arr, target): 4 | left = 0 5 | right = len(arr) 6 | while left < right: 7 | mid = (left + right) // 2 8 | if arr[mid] > target: 9 | right = mid 10 | else: 11 | left = mid + 1 12 | 13 | return left 14 | -------------------------------------------------------------------------------- /2.py: -------------------------------------------------------------------------------- 1 | # Two pointers : exhaust both 2 | 3 | def fn(arr1, arr2): 4 | i = j = ans = 0 5 | 6 | while i < len(arr1) and j < len(arr2): 7 | # do some logic here 8 | if CONDITION: 9 | i += 1 10 | else: 11 | j += 1 12 | 13 | while i < len(arr1): 14 | # do logic 15 | i += 1 16 | 17 | while j < len(arr2): 18 | # do logic 19 | j += 1 20 | 21 | return ans 22 | -------------------------------------------------------------------------------- /20.py: -------------------------------------------------------------------------------- 1 | # Binary search : greedy problem 2 | 3 | def fn(arr): 4 | def check(x): 5 | # this function is implemented depending on the problem 6 | return BOOLEAN 7 | 8 | left = MINIMUM_POSSIBLE_ANSWER 9 | right = MAXIMUM_POSSIBLE_ANSWER 10 | while left <= right: 11 | mid = (left + right) // 2 12 | if check(mid): 13 | right = mid - 1 14 | else: 15 | left = mid + 1 16 | 17 | return left 18 | -------------------------------------------------------------------------------- /21.py: -------------------------------------------------------------------------------- 1 | # Binary search greedy problem : minimum 2 | 3 | def fn(arr): 4 | def check(x): 5 | # this function is implemented depending on the problem 6 | return BOOLEAN 7 | 8 | left = MINIMUM_POSSIBLE_ANSWER 9 | right = MAXIMUM_POSSIBLE_ANSWER 10 | while left <= right: 11 | mid = (left + right) // 2 12 | if check(mid): 13 | left = mid + 1 14 | else: 15 | right = mid - 1 16 | 17 | return right 18 | -------------------------------------------------------------------------------- /22.py: -------------------------------------------------------------------------------- 1 | # DP Top down memoization 2 | 3 | def fn(arr): 4 | def dp(STATE): 5 | if BASE_CASE: 6 | return 0 7 | 8 | if STATE in memo: 9 | return memo[STATE] 10 | 11 | ans = RECURRENCE_RELATION(STATE) 12 | memo[STATE] = ans 13 | return ans 14 | 15 | memo = {} 16 | return dp(STATE_FOR_WHOLE_INPUT) 17 | -------------------------------------------------------------------------------- /3.py: -------------------------------------------------------------------------------- 1 | # Sliding window problem 2 | 3 | def fn(arr): 4 | left = ans = curr = 0 5 | 6 | for right in range(len(arr)): 7 | # do logic here to add arr[right] to curr 8 | 9 | while WINDOW_CONDITION_BROKEN: 10 | # remove arr[left] from curr 11 | left += 1 12 | 13 | # update ans 14 | 15 | return ans 16 | -------------------------------------------------------------------------------- /4.py: -------------------------------------------------------------------------------- 1 | # Prefix sum 2 | 3 | def fn(arr): 4 | prefix = [arr[0]] 5 | for i in range(1, len(arr)): 6 | prefix.append(prefix[-1] + arr[i]) 7 | 8 | return prefix 9 | -------------------------------------------------------------------------------- /5.py: -------------------------------------------------------------------------------- 1 | # Efficient string builder 2 | 3 | # arr is a list of characters 4 | def fn(arr): 5 | ans = [] 6 | for c in arr: 7 | ans.append(c) 8 | 9 | return "".join(ans) 10 | -------------------------------------------------------------------------------- /6.py: -------------------------------------------------------------------------------- 1 | # Fast and slow pointer in Linked list 2 | 3 | def fn(head): 4 | slow = head 5 | fast = head 6 | ans = 0 7 | 8 | while fast and fast.next: 9 | # do logic 10 | slow = slow.next 11 | fast = fast.next.next 12 | 13 | return ans 14 | -------------------------------------------------------------------------------- /7.py: -------------------------------------------------------------------------------- 1 | # Reverse a linked list 2 | def fn(head): 3 | curr = head 4 | prev = None 5 | while curr: 6 | next_node = curr.next 7 | curr.next = prev 8 | prev = curr 9 | curr = next_node 10 | 11 | return prev 12 | -------------------------------------------------------------------------------- /8.py: -------------------------------------------------------------------------------- 1 | # Number of sub-arrays fitting a criteria 2 | 3 | from collections import defaultdict 4 | 5 | def fn(arr, k): 6 | counts = defaultdict(int) 7 | counts[0] = 1 8 | ans = curr = 0 9 | 10 | for num in arr: 11 | # do logic to change curr 12 | ans += counts[curr - k] 13 | counts[curr] += 1 14 | 15 | return ans 16 | -------------------------------------------------------------------------------- /9.py: -------------------------------------------------------------------------------- 1 | # Monotonic increasing stack 2 | 3 | def fn(arr): 4 | stack = [] 5 | ans = 0 6 | 7 | for num in arr: 8 | # for monotonic decreasing, just flip the > to < 9 | while stack and stack[-1] > num: 10 | # do logic 11 | stack.pop() 12 | stack.append(num) 13 | 14 | return ans 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code-Prodigy 2 | A collection of most asked concepts in coding interviews and coding templates for practice 3 | 4 | | S. No. | Problem | 5 | |--------|---------| 6 | | 1 | [Two pointer: one input, opposite ends](https://github.com/MainakRepositor/Code-Prodigy/blob/master/1.py) | 7 | | 2 | [Two pointers: two input, exhaust both](https://github.com/MainakRepositor/Code-Prodigy/blob/master/2.py) | 8 | | 3 | [Sliding window problem](https://github.com/MainakRepositor/Code-Prodigy/blob/master/3.py) | 9 | | 4 | [Prefix sum](https://github.com/MainakRepositor/Code-Prodigy/blob/master/4.py) | 10 | | 5 | [Efficient string building](https://github.com/MainakRepositor/Code-Prodigy/blob/master/5.py) | 11 | | 6 | [Linked List : fast and slow pointer](https://github.com/MainakRepositor/Code-Prodigy/blob/master/6.py) | 12 | | 7 | [Reverse a linked list](https://github.com/MainakRepositor/Code-Prodigy/blob/master/7.py) | 13 | | 8 | [Number of subarray](https://github.com/MainakRepositor/Code-Prodigy/blob/master/8.py) | 14 | | 9 | [Monotonic increasing stock](https://github.com/MainakRepositor/Code-Prodigy/blob/master/9.py) | 15 | | 10 | [Binary Tree DFS (recursive)](https://github.com/MainakRepositor/Code-Prodigy/blob/master/10.py) | 16 | | 11 | [Binary Tree DFS (iterative)](https://github.com/MainakRepositor/Code-Prodigy/blob/master/11.py) | 17 | | 12 | [Binary Tree BFS](https://github.com/MainakRepositor/Code-Prodigy/blob/master/12.py) | 18 | | 13 | [Graph DFS (recursive)](https://github.com/MainakRepositor/Code-Prodigy/blob/master/13.py) | 19 | | 14 | [Graph DFS (iterative)](https://github.com/MainakRepositor/Code-Prodigy/blob/master/14.py) | 20 | | 15 | [Graph BFS](https://github.com/MainakRepositor/Code-Prodigy/blob/master/15.py) | 21 | | 16 | [Top K elements with heap](https://github.com/MainakRepositor/Code-Prodigy/blob/master/16.py) | 22 | | 17 | [Binary Search](https://github.com/MainakRepositor/Code-Prodigy/blob/master/17.py) | 23 | | 18 | [Binary Search : duplicate elements, left-most insertion point](https://github.com/MainakRepositor/Code-Prodigy/blob/master/18.py) | 24 | | 19 | [Binary Search : duplicate elements, right-most insertion point](https://github.com/MainakRepositor/Code-Prodigy/blob/master/19.py) | 25 | | 20 | [Binary Search : greedy problems - maximum](https://github.com/MainakRepositor/Code-Prodigy/blob/master/20.py) | 26 | | 21 | [Binary Search : greedy problems - minimum](https://github.com/MainakRepositor/Code-Prodigy/blob/master/21.py) | 27 | | 22 | [Dynamic programming: top-down memoization](https://github.com/MainakRepositor/Code-Prodigy/blob/master/22.py) | 28 | --------------------------------------------------------------------------------