├── General ├── Sliding Window.pdf ├── Big O Categorization.pdf ├── Steps for Solving Coding Challenges.pdf ├── Divide and Conquer.md ├── Steps for Solving Coding Challenges.md ├── Solving Strategies.md └── Tail Recursion.md ├── 6. Binary Trees ├── Learning Material │ ├── images │ │ ├── bfs.png │ │ └── dfs.png │ ├── 1. Tree Traversals │ │ ├── In-order.md │ │ ├── Pre-order.md │ │ ├── Binary Tree Guide.md │ │ ├── Post-order.md │ │ ├── Depth First Search.md │ │ ├── Breadth First Search.md │ │ └── Binary Tree Class Code.py │ └── 2. Heaps - Priority Queues │ │ ├── Insertion (Sift Up).md │ │ ├── Priority Queue.py │ │ ├── Deletion (Sift Down).md │ │ └── Heaps.md ├── 3. Right Side View of Tree │ ├── Right Side View of Tree.pdf │ ├── right-side-view-of-tree-dfs.py │ └── right-side-view-of-tree-bfs.py ├── 4. Count Complete Tree Nodes │ ├── Count Complete Tree Nodes.pdf │ ├── count-complete-tree-nodes-brute-force-bfs.py │ ├── count-complete-tree-nodes-brute-force-dfs.py │ └── count-complete-tree-nodes-optimal.py ├── 2. Level Order of a Binary Tree │ ├── Level Order of Binary Tree.pdf │ └── level-order-of-binary-tree.py ├── 5. Validate Binary Search Tree │ ├── Validate Binary Search Tree.pdf │ ├── validate-binary-search-tree-brute-force.py │ └── validate-binary-search-tree-optimal.py └── 1. Maximum Depth of a Binary Tree │ ├── Maximum Depth of Binary Tree.pdf │ ├── maximum-depth-of-a-binary-tree-brute-force.py │ └── maximum-depth-of-a-binary-tree-optimal.py ├── 8. Graphs ├── 2. Course Schedule │ ├── Course Schedule.pdf │ └── course-schedule.py ├── 3. Network Delay Time │ ├── Network Delay Time.pdf │ └── network-delay-time-dynamic-programming.py └── 1. Time Needed to Inform All Employees │ ├── Time Needed to Inform All Employees.pdf │ └── time-needed-to-inform-all-employees.py ├── 2. Strings ├── 3. Valid Palindrome │ ├── Valid Palindrome.pdf │ ├── valid-palindrome-optimal.py │ └── valid-palindrome-brute-force.py ├── 1. Backspace String Compare │ ├── Backspace String Compare.pdf │ ├── backspace-string-compare-brute-force.py │ └── backspace-string-compare-optimal.py ├── 4. Valid Palindrome II - Almost Palindrome │ ├── Valid Palindrome II - Almost Palindrome.pdf │ ├── valid-palindrome-II-brute-force.py │ └── valid-palindrome-II-optimal.py ├── 2. Longest Substring without Repeating Characters │ ├── Longest Substring without Repeating Characters.pdf │ ├── longest-substring-without-repeating-characters-brute-force.py │ └── longest-substring-without-repeating-characters-optimal.py └── Identify Palindrome Techniques.md ├── 7. 2D Arrays ├── 2. Rotting Oranges │ ├── Rotting Oranges.pdf │ └── rotting-oranges.py ├── 3. Walls and Gates │ ├── Walls and Gates.pdf │ └── walls-and-gates.py └── 1. Number of Islands │ ├── Number of Islands.pdf │ └── number-of-islands.py ├── 9. Dynamic Programming ├── 1. Staircase │ └── Staircase.pdf └── 2. Knight Probability in Chessboard │ └── Knight Probability in Chessboard.pdf ├── 1. Arrays ├── 3. Trapping Rain Water │ ├── Trapping Rain Water.pdf │ ├── trapping-rain-water-brute-force.py │ └── trapping-rain-water-optimal.py ├── 2. Container with Most Water │ ├── Container with Most Water.pdf │ ├── container-with-most-water-optimal.py │ └── container-with-most-water-brute-force.py └── 1. Two Sum │ ├── two-sum-optimal.py │ └── two-sum-brute-force.py ├── 4. Stacks + Queues ├── 1. Valid Parentheses │ ├── Valid Parentheses.pdf │ └── valid-parentheses.py ├── 3. Implement Queues using Stacks │ ├── Implement Queues using Stacks.pdf │ └── implement-queues-using-stacks.py └── 2. Minimum Remove to Make Valid Parentheses │ ├── Minimum Remove to Make Vaild Parentheses.pdf │ ├── minimum-remove-to-make-valid-parentheses-optimal.py │ └── minimum-remove-to-make-valid-parentheses-brute-force.py ├── 3. Linked Lists ├── 1. Reverse a Linked List │ ├── Reverse a Linked List.pdf │ ├── reverse-a-linked-list-optimal.py │ └── reverse-a-linked-list-brute-force.py ├── 4. Linked List Cycle (I and II) │ ├── Linked List Cycle (I and II).pdf │ ├── linked-list-cycle-I.py │ └── linked-list-cycle-II.py ├── 3. Merge a Multi-level Doubly Linked List │ ├── Merge Multi-level Doubly Linked List.pdf │ └── merge-multi-level-doubly-linked-list.py └── 2. Reverse Linked Lists II - M, N Reversals │ ├── Reversed Linked Lists II_ M, N Reversals.pdf │ └── reverse-linked-lists-II-m-n-reversals.py ├── 5. Recursion + Sortings ├── 1. Kth Largest Element in an Array │ ├── Kth Largest Element in an Array.pdf │ ├── kth-largest-element-in-an-array-brute-force.py │ └── kth-largest-element-in-an-array-optimal.py ├── 2. Find First and Last Position of Element in Sorted Array │ ├── Find First and Last Position of Element in Sorted Array.pdf │ ├── find-first-and-last-position-of-element-in-sorted-array-iterative.py │ └── find-first-and-last-position-of-element-in-sorted-array-recursive.py └── Learning Material │ ├── 1. Sorting + Searching.md │ ├── Hoarse's QuickSelect Algorithm.md │ ├── Binary Search.md │ ├── Insertion Sort.md │ ├── Selection Sort.md │ └── Bubble Sort.md └── README.md /General/Sliding Window.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/General/Sliding Window.pdf -------------------------------------------------------------------------------- /General/Big O Categorization.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/General/Big O Categorization.pdf -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/images/bfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/6. Binary Trees/Learning Material/images/bfs.png -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/images/dfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/6. Binary Trees/Learning Material/images/dfs.png -------------------------------------------------------------------------------- /8. Graphs/2. Course Schedule/Course Schedule.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/8. Graphs/2. Course Schedule/Course Schedule.pdf -------------------------------------------------------------------------------- /General/Steps for Solving Coding Challenges.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/General/Steps for Solving Coding Challenges.pdf -------------------------------------------------------------------------------- /2. Strings/3. Valid Palindrome/Valid Palindrome.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/2. Strings/3. Valid Palindrome/Valid Palindrome.pdf -------------------------------------------------------------------------------- /7. 2D Arrays/2. Rotting Oranges/Rotting Oranges.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/7. 2D Arrays/2. Rotting Oranges/Rotting Oranges.pdf -------------------------------------------------------------------------------- /7. 2D Arrays/3. Walls and Gates/Walls and Gates.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/7. 2D Arrays/3. Walls and Gates/Walls and Gates.pdf -------------------------------------------------------------------------------- /9. Dynamic Programming/1. Staircase/Staircase.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/9. Dynamic Programming/1. Staircase/Staircase.pdf -------------------------------------------------------------------------------- /1. Arrays/3. Trapping Rain Water/Trapping Rain Water.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/1. Arrays/3. Trapping Rain Water/Trapping Rain Water.pdf -------------------------------------------------------------------------------- /7. 2D Arrays/1. Number of Islands/Number of Islands.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/7. 2D Arrays/1. Number of Islands/Number of Islands.pdf -------------------------------------------------------------------------------- /8. Graphs/3. Network Delay Time/Network Delay Time.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/8. Graphs/3. Network Delay Time/Network Delay Time.pdf -------------------------------------------------------------------------------- /4. Stacks + Queues/1. Valid Parentheses/Valid Parentheses.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/4. Stacks + Queues/1. Valid Parentheses/Valid Parentheses.pdf -------------------------------------------------------------------------------- /3. Linked Lists/1. Reverse a Linked List/Reverse a Linked List.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/3. Linked Lists/1. Reverse a Linked List/Reverse a Linked List.pdf -------------------------------------------------------------------------------- /1. Arrays/2. Container with Most Water/Container with Most Water.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/1. Arrays/2. Container with Most Water/Container with Most Water.pdf -------------------------------------------------------------------------------- /2. Strings/1. Backspace String Compare/Backspace String Compare.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/2. Strings/1. Backspace String Compare/Backspace String Compare.pdf -------------------------------------------------------------------------------- /6. Binary Trees/3. Right Side View of Tree/Right Side View of Tree.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/6. Binary Trees/3. Right Side View of Tree/Right Side View of Tree.pdf -------------------------------------------------------------------------------- /6. Binary Trees/4. Count Complete Tree Nodes/Count Complete Tree Nodes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/6. Binary Trees/4. Count Complete Tree Nodes/Count Complete Tree Nodes.pdf -------------------------------------------------------------------------------- /6. Binary Trees/2. Level Order of a Binary Tree/Level Order of Binary Tree.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/6. Binary Trees/2. Level Order of a Binary Tree/Level Order of Binary Tree.pdf -------------------------------------------------------------------------------- /6. Binary Trees/5. Validate Binary Search Tree/Validate Binary Search Tree.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/6. Binary Trees/5. Validate Binary Search Tree/Validate Binary Search Tree.pdf -------------------------------------------------------------------------------- /2. Strings/3. Valid Palindrome/valid-palindrome-optimal.py: -------------------------------------------------------------------------------- 1 | import re 2 | def isPalindrome(self, s): 3 | """ 4 | :type s: str 5 | :rtype: bool 6 | """ 7 | s = re.sub(r'[^a-zA-Z0-9]', '', s.lower()) 8 | return s == s[::-1] -------------------------------------------------------------------------------- /3. Linked Lists/4. Linked List Cycle (I and II)/Linked List Cycle (I and II).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/3. Linked Lists/4. Linked List Cycle (I and II)/Linked List Cycle (I and II).pdf -------------------------------------------------------------------------------- /6. Binary Trees/1. Maximum Depth of a Binary Tree/Maximum Depth of Binary Tree.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/6. Binary Trees/1. Maximum Depth of a Binary Tree/Maximum Depth of Binary Tree.pdf -------------------------------------------------------------------------------- /4. Stacks + Queues/3. Implement Queues using Stacks/Implement Queues using Stacks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/4. Stacks + Queues/3. Implement Queues using Stacks/Implement Queues using Stacks.pdf -------------------------------------------------------------------------------- /8. Graphs/1. Time Needed to Inform All Employees/Time Needed to Inform All Employees.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/8. Graphs/1. Time Needed to Inform All Employees/Time Needed to Inform All Employees.pdf -------------------------------------------------------------------------------- /5. Recursion + Sortings/1. Kth Largest Element in an Array/Kth Largest Element in an Array.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/5. Recursion + Sortings/1. Kth Largest Element in an Array/Kth Largest Element in an Array.pdf -------------------------------------------------------------------------------- /9. Dynamic Programming/2. Knight Probability in Chessboard/Knight Probability in Chessboard.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/9. Dynamic Programming/2. Knight Probability in Chessboard/Knight Probability in Chessboard.pdf -------------------------------------------------------------------------------- /General/Divide and Conquer.md: -------------------------------------------------------------------------------- 1 | # Divide and Conquer 2 | ## General Steps 3 | 1. Multi-branched recursion (splits the data into multiple parts) 4 | 2. Breaks problem into multiple sub-problems 5 | 3. Combines solutions of sub problems into the solution for original problem -------------------------------------------------------------------------------- /2. Strings/4. Valid Palindrome II - Almost Palindrome/Valid Palindrome II - Almost Palindrome.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/2. Strings/4. Valid Palindrome II - Almost Palindrome/Valid Palindrome II - Almost Palindrome.pdf -------------------------------------------------------------------------------- /3. Linked Lists/3. Merge a Multi-level Doubly Linked List/Merge Multi-level Doubly Linked List.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/3. Linked Lists/3. Merge a Multi-level Doubly Linked List/Merge Multi-level Doubly Linked List.pdf -------------------------------------------------------------------------------- /3. Linked Lists/2. Reverse Linked Lists II - M, N Reversals/Reversed Linked Lists II_ M, N Reversals.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/3. Linked Lists/2. Reverse Linked Lists II - M, N Reversals/Reversed Linked Lists II_ M, N Reversals.pdf -------------------------------------------------------------------------------- /4. Stacks + Queues/2. Minimum Remove to Make Valid Parentheses/Minimum Remove to Make Vaild Parentheses.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/4. Stacks + Queues/2. Minimum Remove to Make Valid Parentheses/Minimum Remove to Make Vaild Parentheses.pdf -------------------------------------------------------------------------------- /2. Strings/2. Longest Substring without Repeating Characters/Longest Substring without Repeating Characters.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/2. Strings/2. Longest Substring without Repeating Characters/Longest Substring without Repeating Characters.pdf -------------------------------------------------------------------------------- /General/Steps for Solving Coding Challenges.md: -------------------------------------------------------------------------------- 1 | # Steps for Solving Coding Challenges 2 | ## Intro 3 | 1. Verify Constraints 4 | 2. Create Testcases 5 | ## Brute Force + Optimal 6 | 1. Brainstorming & Pattern Observations 7 | 2. Pseudocode 8 | 3. Code 9 | 4. Run testcases against code 10 | 5. Analyze time + space complexity 11 | 12 | -------------------------------------------------------------------------------- /2. Strings/3. Valid Palindrome/valid-palindrome-brute-force.py: -------------------------------------------------------------------------------- 1 | import re 2 | def isPalindrome(self, s): 3 | """ 4 | :type s: str 5 | :rtype: bool 6 | """ 7 | s = re.sub(r'[^a-zA-Z0-9]', '', s.lower()) 8 | for i in range(len(s)/2): 9 | if s[i] != s[len(s)-1-i]: 10 | return False 11 | return True -------------------------------------------------------------------------------- /2. Strings/Identify Palindrome Techniques.md: -------------------------------------------------------------------------------- 1 | ## Identify Palindrome Techniques: 2 | 1. Initialize left and right pointers at first and last index and traverse inwards until center to see if chars match 3 | 2. Initialize left and right pointers at center and traverse outwards to see if chars match 4 | 3. Flip given string and check if it matches given string -------------------------------------------------------------------------------- /5. Recursion + Sortings/2. Find First and Last Position of Element in Sorted Array/Find First and Last Position of Element in Sorted Array.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandhya-veludandi/master-the-coding-interview/HEAD/5. Recursion + Sortings/2. Find First and Last Position of Element in Sorted Array/Find First and Last Position of Element in Sorted Array.pdf -------------------------------------------------------------------------------- /2. Strings/1. Backspace String Compare/backspace-string-compare-brute-force.py: -------------------------------------------------------------------------------- 1 | def resultString(self, s): 2 | result = [] 3 | i = 0 4 | while i < len(s): 5 | if s[i] == '#': 6 | if i > 0 and len(result) > 0: 7 | result.pop() 8 | else: 9 | result.append(s[i]) 10 | i += 1 11 | return result -------------------------------------------------------------------------------- /1. Arrays/2. Container with Most Water/container-with-most-water-optimal.py: -------------------------------------------------------------------------------- 1 | def maxArea(self, height): 2 | """ 3 | :type height: List[int] 4 | :rtype: int 5 | """ 6 | maxArea = 0 7 | a_index = 0 8 | b_index = len(height)-1 9 | while a_index != b_index: 10 | a = height[a_index] 11 | b = height[b_index] 12 | newArea = min(a, b)*(b_index-a_index) 13 | maxArea = max(maxArea, newArea) 14 | if a < b: 15 | a_index += 1 16 | else: 17 | b_index -= 1 18 | return maxArea -------------------------------------------------------------------------------- /3. Linked Lists/1. Reverse a Linked List/reverse-a-linked-list-optimal.py: -------------------------------------------------------------------------------- 1 | class ListNode(object): 2 | def __init__(self, val=0, next=None): 3 | self.val = val 4 | self.next = next 5 | 6 | class Solution(object): 7 | def reverseList(self, head): 8 | """ 9 | :type head: ListNode 10 | :rtype: ListNode 11 | """ 12 | prev = None 13 | curr = head 14 | while(curr): 15 | temp = curr.next 16 | curr.next = prev 17 | prev = curr 18 | curr = temp 19 | return prev -------------------------------------------------------------------------------- /1. Arrays/2. Container with Most Water/container-with-most-water-brute-force.py: -------------------------------------------------------------------------------- 1 | def maxArea(self, height): 2 | """ 3 | :type height: List[int] 4 | :rtype: int 5 | """ 6 | maxArea = 0 7 | for i in range(len(height)-1): 8 | curr_height = height[i] 9 | j = i + 1 10 | while j in range(len(height)): 11 | other_height = height[j] 12 | length = min(curr_height, other_height) 13 | width = j - i 14 | newArea = length*width 15 | maxArea = max(maxArea, newArea) 16 | j += 1 17 | return maxArea -------------------------------------------------------------------------------- /3. Linked Lists/4. Linked List Cycle (I and II)/linked-list-cycle-I.py: -------------------------------------------------------------------------------- 1 | class ListNode(object): 2 | def __init__(self, val=0, next=None): 3 | self.val = val 4 | self.next = next 5 | 6 | class Solution(object): 7 | def hasCycle(self, head): 8 | """ 9 | :type head: ListNode 10 | :rtype: bool 11 | """ 12 | curr = head 13 | prev = head 14 | while curr != None and curr.next != None: 15 | curr = curr.next.next 16 | prev = prev.next 17 | if curr != None and curr == prev: 18 | return True 19 | return False -------------------------------------------------------------------------------- /1. Arrays/1. Two Sum/two-sum-optimal.py: -------------------------------------------------------------------------------- 1 | def twoSum(self, nums, target): 2 | """ 3 | :type nums: List[int] 4 | :type target: int 5 | :rtype: List[int] 6 | """ 7 | #Hashmap solution 8 | #Hashmap will contain previously calculated ntfs 9 | hashmap = {} 10 | for i in range(len(nums)): 11 | curr_num = nums[i] 12 | numToFind = target - curr_num 13 | #if curr_num in hashmap, return the indices 14 | if curr_num in hashmap: 15 | return [i, hashmap[curr_num]] 16 | #otherwise, add the new ntf to the hashmap 17 | hashmap[numToFind] = i 18 | return None -------------------------------------------------------------------------------- /4. Stacks + Queues/1. Valid Parentheses/valid-parentheses.py: -------------------------------------------------------------------------------- 1 | def isValid(self, s): 2 | """ 3 | :type s: str 4 | :rtype: bool 5 | """ 6 | if len(s) % 2 == 1: return False 7 | 8 | stack = [] 9 | valid = { 10 | ')': '(', 11 | ']': '[', 12 | '}': '{' 13 | } 14 | for c in s: 15 | if c not in valid: 16 | stack.append(c) 17 | elif stack != [] and valid[c] == stack[-1]: 18 | stack.pop() 19 | else: 20 | return False 21 | return stack == [] -------------------------------------------------------------------------------- /2. Strings/4. Valid Palindrome II - Almost Palindrome/valid-palindrome-II-brute-force.py: -------------------------------------------------------------------------------- 1 | import re 2 | def validPalindrome(self, s): 3 | """ 4 | :type s: str 5 | :rtype: bool 6 | """ 7 | s = re.sub(r'[^a-zA-Z0-9]', '', s.lower()) 8 | if s == s[::-1]: 9 | return True 10 | for i in range(len(s)/2): 11 | if s[i] != s[len(s)-1-i]: 12 | #add two possible palindromes 13 | #one without i char 14 | s1 = s[:i]+s[i+1:] 15 | #one without len(s)-1-i char 16 | s2 = s[:len(s)-1-i]+s[len(s)-i:] 17 | 18 | return s1 == s1[::-1] or s2 == s2[::-1] -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/1. Tree Traversals/In-order.md: -------------------------------------------------------------------------------- 1 | # DFS In-order Traversal 2 | ## Order 3 | left, root, right 4 | ## Example 5 | ``` 6 | 9 7 | 4 20 8 | 1 6 15 170 9 | 10 | Visited Order: 11 | [1, 4, 6, 9, 15, 20, 170] 12 | ``` 13 | 14 | ## Code 15 | ```Python 16 | def traverseInOrder(self, node, list): 17 | if node != None: 18 | if node.left: 19 | self.traverseInOrder(node.left, list) 20 | list.append(node.val) 21 | if node.right: 22 | self.traverseInOrder(node.right, list) 23 | return list 24 | 25 | def dfsInOrder(self): 26 | return self.traverseInOrder(self.getRoot(), []) 27 | ``` 28 | -------------------------------------------------------------------------------- /2. Strings/2. Longest Substring without Repeating Characters/longest-substring-without-repeating-characters-brute-force.py: -------------------------------------------------------------------------------- 1 | def longestSubstringWithoutRepeats(s): 2 | """ 3 | :type s: str 4 | :rtype: int 5 | """ 6 | curr_index = 0 7 | maxLength = 0 8 | chars = {} 9 | while curr_index < len(s): 10 | if s[curr_index] not in chars: 11 | chars[s[curr_index]] = curr_index 12 | else: 13 | curr_index = chars[s[curr_index]]+1 14 | chars = {} 15 | chars[s[curr_index]] = curr_index 16 | maxLength = max(maxLength, len(chars)) 17 | curr_index += 1 18 | return maxLength -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/1. Tree Traversals/Pre-order.md: -------------------------------------------------------------------------------- 1 | # DFS Pre-order Traversal 2 | ## Order 3 | root, left, right 4 | ## Example 5 | ``` 6 | 9 7 | 4 20 8 | 1 6 15 170 9 | 10 | Visited Order: 11 | [9, 4, 1, 6, 20, 15, 170] 12 | ``` 13 | 14 | ## Code 15 | ```Python 16 | def traversePreOrder(self, node, list): 17 | if node != None: 18 | list.append(node.val) 19 | if node.left: 20 | self.traversePreOrder(node.left, list) 21 | if node.right: 22 | self.traversePreOrder(node.right, list) 23 | return list 24 | 25 | def dfsPreOrder(self): 26 | return self.traversePreOrder(self.getRoot(), []) 27 | ``` 28 | -------------------------------------------------------------------------------- /2. Strings/4. Valid Palindrome II - Almost Palindrome/valid-palindrome-II-optimal.py: -------------------------------------------------------------------------------- 1 | import re 2 | def validPalindrome(self, s): 3 | """ 4 | :type s: str 5 | :rtype: bool 6 | """ 7 | s = re.sub(r'[^a-zA-Z0-9]', '', s.lower()) 8 | if s == s[::-1]: 9 | return True 10 | i = 0 11 | while i < len(s)/2+1: 12 | if s[i] != s[len(s)-1-i]: 13 | #two possible palindromes 14 | #one with i char and without len(s)-1-i 15 | s1 = s[i:len(s)-1-i] 16 | #one with len(s)-1-i char and without i 17 | s2 = s[i+1:len(s)-i] 18 | return s1 == s1[::-1] or s2 == s2[::-1] 19 | i += 1 -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/1. Tree Traversals/Binary Tree Guide.md: -------------------------------------------------------------------------------- 1 | # Binary Tree Guide 2 | ## Traversals 3 | * bfs 4 | * dfs 5 | * pre order 6 | * in order 7 | * post order 8 | ## Questions to Ask: 9 | * need to traverse tree? 10 | * bfs: node looking for closer to root rather than leaf nodes (bc bfs travels one by one level) 11 | * dfs: node looking for closer to leaf nodes rather than root (bc follows all the children nodes) 12 | * do we care about diff traversals? care about order in which value is visited? 13 | * pre order: value, left, right 14 | * in order: left, value, right 15 | * post order: left, right, value 16 | -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/1. Tree Traversals/Post-order.md: -------------------------------------------------------------------------------- 1 | # DFS Post-order Traversal 2 | ## Order 3 | left, right, root 4 | 5 | ## Example 6 | ``` 7 | 9 8 | 4 20 9 | 1 6 15 170 10 | 11 | Visited Order: 12 | [1, 6, 4, 15, 170, 20, 9] 13 | ``` 14 | 15 | ## Code 16 | ```Python 17 | def traversePostOrder(self, node, list): 18 | if node != None: 19 | if node.left: 20 | self.traversePostOrder(node.left, list) 21 | if node.right: 22 | self.traversePostOrder(node.right, list) 23 | list.append(node.val) 24 | return list 25 | 26 | def dfsPostOrder(self): 27 | return self.traversePostOrder(self.getRoot(), []) 28 | ``` 29 | -------------------------------------------------------------------------------- /6. Binary Trees/1. Maximum Depth of a Binary Tree/maximum-depth-of-a-binary-tree-brute-force.py: -------------------------------------------------------------------------------- 1 | class TreeNode(object): 2 | def __init__(self, val=0, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | class Solution(object): 8 | def maxDepth(self, root): 9 | """ 10 | :type root: TreeNode 11 | :rtype: int 12 | """ 13 | if root == None: 14 | return 0 15 | 16 | left = 1 + self.maxDepth(root.left) 17 | right = 1 + self.maxDepth(root.right) 18 | if left < right: 19 | return right 20 | else: 21 | return left -------------------------------------------------------------------------------- /5. Recursion + Sortings/Learning Material/1. Sorting + Searching.md: -------------------------------------------------------------------------------- 1 | # Sorting + Searching 2 | When sort an array, have a lot of knowledge at each position: 3 | `[1, 2, 3, 4, 5, 6]`: at position 3 (number 4), then anything before position 3 is less than 4 and greater than 3 is more than 4 4 | ## Important 5 | * trade-offs between time + space complexity 6 | * which types of data does it best/worst sort on? 7 | * random 8 | * nearly sorted 9 | * reversed 10 | * few unique (many values that are the same) 11 | ## Sorts 12 | ### Elementary 13 | 1. Bubble Sort 14 | 2. Selection Sort 15 | 3. Insertion Sort 16 | ### Complex 17 | 1. Merge Sort 18 | 2. Quick Sort 19 | ## Searching 20 | 1. Binary Search -------------------------------------------------------------------------------- /6. Binary Trees/1. Maximum Depth of a Binary Tree/maximum-depth-of-a-binary-tree-optimal.py: -------------------------------------------------------------------------------- 1 | class TreeNode(object): 2 | def __init__(self, val=0, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | class Solution(object): 8 | def maxDepthHelper(self, root, count): 9 | if root == None: 10 | return count 11 | count += 1 12 | return max(self.maxDepthHelper(root.left, count), self.maxDepthHelper(root.right, count)) 13 | 14 | def maxDepth(self, root): 15 | """ 16 | :type root: TreeNode 17 | :rtype: int 18 | """ 19 | return self.maxDepthHelper(root, 0) -------------------------------------------------------------------------------- /2. Strings/2. Longest Substring without Repeating Characters/longest-substring-without-repeating-characters-optimal.py: -------------------------------------------------------------------------------- 1 | def longestSubstringWithoutRepeats(s): 2 | """ 3 | :type s: str 4 | :rtype: int 5 | """ 6 | chars = {} 7 | left = 0 8 | right = 0 9 | maxLength = 0 10 | while right < len(s): 11 | curr_char = s[right] 12 | prevSeenChar = -1 13 | if curr_char in chars: 14 | prevSeenChar = chars[curr_char] 15 | if prevSeenChar >= left: 16 | prevSeenChar += 1 17 | left = prevSeenChar 18 | chars[curr_char] = right 19 | maxLength = max(right-left+1, maxLength) 20 | right += 1 21 | return maxLength -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/1. Tree Traversals/Depth First Search.md: -------------------------------------------------------------------------------- 1 | # Depth First Search (DFS) 2 | Logic: visit all the children node first (classic example of search in tree, traverse thru left then right branch of node) 3 | 4 | 5 | 6 | ## Example: 7 | ``` 8 | 101 9 | 33 105 10 | ``` 11 | 12 | ## 3 Ways to Implement DFS: 13 | The order title refers to which order the root node comes in 14 | 1. Pre-order 15 | 16 | root, left, right: 17 | 101, 33, 105 18 | 19 | 2. In-order 20 | 21 | left , root, right 22 | 33, 101, 105 23 | 24 | 3. Post-order 25 | 26 | left, right , root 27 | 33, 105, 101 28 | 29 | Space Complexity: max tree depth / height -------------------------------------------------------------------------------- /3. Linked Lists/1. Reverse a Linked List/reverse-a-linked-list-brute-force.py: -------------------------------------------------------------------------------- 1 | class ListNode(object): 2 | def __init__(self, val=0, next=None): 3 | self.val = val 4 | self.next = next 5 | 6 | class Solution(object): 7 | def reverseList(self, head): 8 | """ 9 | :type head: ListNode 10 | :rtype: ListNode 11 | """ 12 | if(head == None or head.next == None): 13 | return head 14 | #create new list 15 | newHead = None 16 | #create a new node and add it to the to the front of the list 17 | while head is not None: 18 | newNode = ListNode(val=head.val, next=newHead) 19 | newHead = newNode 20 | head = head.next 21 | return newHead -------------------------------------------------------------------------------- /5. Recursion + Sortings/Learning Material/Hoarse's QuickSelect Algorithm.md: -------------------------------------------------------------------------------- 1 | # Hoarse's QuickSelect Algorithm 2 | Used to find the kth smallest element in unordered list. 3 | ``` 4 | Given: [5, 3, 1, 6, 4, 2] and k = 4 5 | Final Answer with Quick Sort: [1, 2, 3, 4, 5, 6] → 4 6 | ``` 7 | Logic: since we don’t care about sorting all elements, only sort on one half of the branch where we know k will be 8 | 9 | ## kth smallest 10 | [[1], 2, [5, 6, 4, 3]] 11 | partition = 2 12 | k = 4, sort only on the right branch 13 | ``` 14 | if k < partition: 15 | sort on left branch 16 | elif k > partition: 17 | sort on right branch 18 | else: 19 | return arr[partition] 20 | ``` 21 | ## kth largest 22 | Logic: simply change the k value so that it uses the same logic as kth smallest 23 | `k = len(arr) - k` 24 | -------------------------------------------------------------------------------- /3. Linked Lists/4. Linked List Cycle (I and II)/linked-list-cycle-II.py: -------------------------------------------------------------------------------- 1 | class ListNode(object): 2 | def __init__(self, val=0, next=None): 3 | self.val = val 4 | self.next = next 5 | 6 | class Solution(object): 7 | def detectCycle(self, head): 8 | """ 9 | :type head: ListNode 10 | :rtype: ListNode 11 | """ 12 | curr = head 13 | prev = head 14 | while curr != None and curr.next != None: 15 | curr = curr.next.next 16 | prev = prev.next 17 | if curr != None and curr == prev: 18 | start = head 19 | while start != curr: 20 | start = start.next 21 | curr = curr.next 22 | return start 23 | return None -------------------------------------------------------------------------------- /4. Stacks + Queues/2. Minimum Remove to Make Valid Parentheses/minimum-remove-to-make-valid-parentheses-optimal.py: -------------------------------------------------------------------------------- 1 | import re 2 | def minRemoveToMakeValid(self, s): 3 | """ 4 | :type s: str 5 | :rtype: str 6 | """ 7 | stackIndices = [] 8 | s = list(s) 9 | print(s) 10 | i = 0 11 | while i < len(s): 12 | #if we have close parens match 13 | if stackIndices != [] and s[i] == ')' and s[stackIndices[-1]] == '(': 14 | stackIndices.pop() 15 | elif stackIndices == [] and s[i] == ')': 16 | del s[i] 17 | i -= 1 18 | elif s[i] == '(' or s[i] == ')': 19 | stackIndices.append(i) 20 | i += 1 21 | 22 | while stackIndices != []: 23 | idx = stackIndices.pop() 24 | del s[idx] 25 | return "".join(s) -------------------------------------------------------------------------------- /6. Binary Trees/3. Right Side View of Tree/right-side-view-of-tree-dfs.py: -------------------------------------------------------------------------------- 1 | class TreeNode(object): 2 | def __init__(self, val=0, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | class Solution(object): 8 | def helper(self, node, list, height): 9 | if node == None: 10 | return list 11 | height += 1 12 | if height - 1 == len(list): 13 | list.append(node.val) 14 | 15 | if node.right: 16 | self.helper(node.right, list, height) 17 | 18 | if node.left: 19 | self.helper(node.left, list, height) 20 | 21 | def rightSideView(self, root): 22 | """ 23 | :type root: TreeNode 24 | :rtype: List[int] 25 | """ 26 | return self.helper(root, [], 0) -------------------------------------------------------------------------------- /1. Arrays/3. Trapping Rain Water/trapping-rain-water-brute-force.py: -------------------------------------------------------------------------------- 1 | def trap(self, height): 2 | """ 3 | :type height: List[int] 4 | :rtype: int 5 | """ 6 | total_water_amt = 0 7 | p = 0 8 | while p < len(height): 9 | #search for the max to the left of p 10 | maxL = p 11 | maxR = p 12 | i = p-1 13 | while i >= 0: 14 | if (height[i] > height[maxL]): 15 | maxL = i 16 | i -= 1 17 | j = p+1 18 | while j < len(height): 19 | if(height[j] > height[maxR]): 20 | maxR = j 21 | j += 1 22 | 23 | water_amt = min(height[maxL], height[maxR]) - height[p] 24 | if water_amt > 0: 25 | total_water_amt += water_amt 26 | p += 1 27 | return total_water_amt -------------------------------------------------------------------------------- /5. Recursion + Sortings/2. Find First and Last Position of Element in Sorted Array/find-first-and-last-position-of-element-in-sorted-array-iterative.py: -------------------------------------------------------------------------------- 1 | def binarySearch(self, nums, left, right, target, ranges, prevMid): 2 | if nums == []: 3 | return [-1, -1] 4 | initialPos = self.binarySearch(nums, 0, len(nums)-1, target); 5 | if initialPos == -1: return [-1, -1]; 6 | lowPos = initialPos 7 | highPos = initialPos 8 | tempLeft = None 9 | tempRight = None 10 | while lowPos != -1: 11 | #save the last time target was found 12 | tempLeft = lowPos 13 | lowPos = self.binarySearch(nums, 0, lowPos - 1, target) 14 | 15 | while highPos != -1: 16 | tempRight = highPos 17 | highPos = self.binarySearch(nums, highPos + 1, len(nums)-1, target) 18 | 19 | return [tempLeft, tempRight] -------------------------------------------------------------------------------- /7. 2D Arrays/3. Walls and Gates/walls-and-gates.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | directions = [[-1, 0], [0, 1], [1, 0], [0, -1]] 3 | def wallsAndGates(self, a, n, m): 4 | for row in range(n): 5 | for col in range(m): 6 | if a[row][col] == 0: 7 | self.dfs(row, col, a, 0) 8 | return a 9 | 10 | def dfs(self, row, col, grid, steps): 11 | steps += 1 12 | for direction in self.directions: 13 | row1 = row + direction[0] 14 | col1 = col + direction[1] 15 | if row1 < 0 or row1 >= len(grid) or col1 < 0 or col1 >= len(grid[0]) or grid[row1][col1] <= 0 or steps > grid[row1][col1]: 16 | continue 17 | else: 18 | grid[row1][col1] = min(steps, grid[row1][col1]) 19 | self.dfs(row1, col1, grid, steps) -------------------------------------------------------------------------------- /1. Arrays/1. Two Sum/two-sum-brute-force.py: -------------------------------------------------------------------------------- 1 | def twoSum(self, nums, target): 2 | """ 3 | :type nums: List[int] 4 | :type target: int 5 | :rtype: List[int] 6 | """ 7 | results = [] 8 | #Iterate thru all numbers except the last one in the outer for loop 9 | for i in range(len(nums)-1): 10 | #Pointer 1 11 | num = nums[i] 12 | #Based on pointer1's number, we're trying to find the number that will 13 | #add up to the target: numToFind = target - pointer1 14 | numToFind = target - num 15 | #Pointer 2 16 | j = i + 1 17 | #Iterate through the rest of the numbers 18 | while j in range(len(nums)): 19 | if nums[j] == numToFind: 20 | results.append(i) 21 | results.append(j) 22 | return results 23 | j += 1 24 | return None -------------------------------------------------------------------------------- /General/Solving Strategies.md: -------------------------------------------------------------------------------- 1 | # Solving Strategies 2 | ## Iterative 3 | ### Data Structures 4 | 1. Arrays 5 | 2. Strings 6 | 3. Linked Lists 7 | 4. Stacks + Queues 8 | ### Strategies 9 | #### Pointers 10 | Note: pointers can begin anywhere in array (usually at first or last index) 11 | * Basic: pointers for outer and inner for loop (usually O(n^2)) 12 | * Shifting Pointers: 13 | * 2 pointers at first and last index, conditionally move either one inward (usually O(n)) 14 | * Skipping Pointers: 15 | * pointers skip over certain indices depending on condition 16 | #### Hashmaps 17 | Note: used to store 2 pieces information (key and value) 18 | ## Recursion 19 | ### Data Structures 20 | 1. 2d Arrays 21 | 2. Binary Trees 22 | 3. Heaps 23 | 4. Graphs 24 | ### Algorithmic Approaches 25 | 1. Sorting 26 | 2. Greedy Method 27 | 3. Divide & Conquer 28 | 4. Dynamic Programming 29 | 5. Backtracking 30 | 31 | -------------------------------------------------------------------------------- /6. Binary Trees/4. Count Complete Tree Nodes/count-complete-tree-nodes-brute-force-bfs.py: -------------------------------------------------------------------------------- 1 | class TreeNode(object): 2 | def __init__(self, val=0, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | class Solution(object): 8 | def countNodes(self, root): 9 | """ 10 | :type root: TreeNode 11 | :rtype: int 12 | """ 13 | if root == None: return 0 14 | queue = [] 15 | curr = root 16 | queue.append(curr) 17 | orderOfNodesList = [] 18 | while queue != []: 19 | curr = queue[0] 20 | orderOfNodesList.append(curr) 21 | queue = queue[1:] 22 | if curr.left: 23 | queue.append(curr.left) 24 | if curr.right != None: 25 | queue.append(curr.right) 26 | return len(orderOfNodesList) -------------------------------------------------------------------------------- /4. Stacks + Queues/2. Minimum Remove to Make Valid Parentheses/minimum-remove-to-make-valid-parentheses-brute-force.py: -------------------------------------------------------------------------------- 1 | import re 2 | def minRemoveToMakeValid(self, s): 3 | """ 4 | :type s: str 5 | :rtype: str 6 | """ 7 | stackParens = [] 8 | stackIndices = [] 9 | for i in range(len(s)): 10 | char = s[i] 11 | #if we have close parens match 12 | if stackParens != [] and char == ')' and stackParens[-1] == '(': 13 | stackParens.pop() 14 | stackIndices.pop() 15 | elif char == '(' or char == ')': 16 | stackParens.append(char) 17 | stackIndices.append(i) 18 | #remove the parens using stackIndices 19 | arr1=[] 20 | for i in range(len(s)): 21 | arr1.append(i) 22 | new = filter(lambda i: i not in stackIndices, arr1) 23 | new_str = "" 24 | for i in new: 25 | new_str += s[i] 26 | return new_str -------------------------------------------------------------------------------- /6. Binary Trees/4. Count Complete Tree Nodes/count-complete-tree-nodes-brute-force-dfs.py: -------------------------------------------------------------------------------- 1 | class TreeNode(object): 2 | def __init__(self, val=0, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | class Solution(object): 8 | def countNodesHelper(self, root, count): 9 | if root == None: 10 | return 0 11 | else: 12 | count += 1 13 | leftSide = 0 14 | rightSide = 0 15 | if root.left != None: 16 | leftSide = self.countNodesHelper(root.left, 0) 17 | if root.right != None: 18 | rightSide = self.countNodesHelper(root.right, 0) 19 | count += (leftSide + rightSide) 20 | return count 21 | def countNodes(self, root): 22 | """ 23 | :type root: TreeNode 24 | :rtype: int 25 | """ 26 | return self.countNodesHelper(root, 0) -------------------------------------------------------------------------------- /6. Binary Trees/5. Validate Binary Search Tree/validate-binary-search-tree-brute-force.py: -------------------------------------------------------------------------------- 1 | class TreeNode(object): 2 | def __init__(self, val=0, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | class Solution(object): 8 | def inOrderTraversal(self, root, list): 9 | if root != None: 10 | if root.left: 11 | self.inOrderTraversal(root.left, list) 12 | list.append(root.val) 13 | if root.right: 14 | self.inOrderTraversal(root.right, list) 15 | return list 16 | def isValidBST(self, root): 17 | """ 18 | :type root: TreeNode 19 | :rtype: bool 20 | """ 21 | treeList = self.inOrderTraversal(root, []) 22 | tmpList = set(treeList) 23 | sortedList = sorted(treeList) 24 | noDuplicates = len(tmpList) == len(sortedList) 25 | return noDuplicates and sortedList == treeList -------------------------------------------------------------------------------- /1. Arrays/3. Trapping Rain Water/trapping-rain-water-optimal.py: -------------------------------------------------------------------------------- 1 | def trap(self, height): 2 | """ 3 | :type height: List[int] 4 | :rtype: int 5 | """ 6 | total_water_amt = 0 7 | pL = 0 8 | pR = len(height)-1 9 | maxL = 0 10 | maxR = len(height)-1 11 | while(pL != pR): 12 | #where the left side has the shortest height 13 | if height[pL] <= height[pR]: 14 | #calculate water amt if true 15 | if height[maxL] > height[pL]: 16 | total_water_amt += height[maxL] - height[pL] 17 | #update max 18 | else: 19 | maxL = pL 20 | pL += 1 21 | #where the right side has the shortest height 22 | else: 23 | #calculate water amt if true 24 | if height[maxR] > height[pR]: 25 | total_water_amt += height[maxR] - height[pR] 26 | #update max 27 | else: 28 | maxR = pR 29 | pR -= 1 30 | return total_water_amt -------------------------------------------------------------------------------- /3. Linked Lists/3. Merge a Multi-level Doubly Linked List/merge-multi-level-doubly-linked-list.py: -------------------------------------------------------------------------------- 1 | class Node(object): 2 | def __init__(self, val, prev, next, child): 3 | self.val = val 4 | self.prev = prev 5 | self.next = next 6 | self.child = child 7 | 8 | class Solution(object): 9 | def flatten(self, head): 10 | """ 11 | :type head: Node 12 | :rtype: Node 13 | """ 14 | curr = head 15 | while curr != None: 16 | print(curr.val) 17 | if curr.child != None: 18 | temp = curr.next 19 | curr.next = curr.child 20 | curr.child = None 21 | curr.next.prev = curr 22 | tail = curr 23 | while tail != None: 24 | if tail.next == None: 25 | break 26 | tail = tail.next 27 | tail.next = temp 28 | if temp != None: 29 | temp.prev = tail 30 | curr = curr.next 31 | 32 | return head -------------------------------------------------------------------------------- /5. Recursion + Sortings/1. Kth Largest Element in an Array/kth-largest-element-in-an-array-brute-force.py: -------------------------------------------------------------------------------- 1 | def partition(self, arr, low, high): 2 | #holds the place of where the pivot should be 3 | i = low 4 | #scans and compares #s against pivot 5 | j = low 6 | #pivot is rightmost element 7 | pivot = arr[high] 8 | while j < high: 9 | if arr[j] < arr[high]: 10 | if i != j: 11 | arr[i], arr[j] = arr[j], arr[i] 12 | i += 1 13 | j += 1 14 | else: 15 | j += 1 16 | arr[i], arr[high] = pivot, arr[i] 17 | return i 18 | 19 | def quickSort(self, arr, low, high, k): 20 | if low < high: 21 | partition = self.partition(arr, low, high) 22 | if k == len(arr)-partition: 23 | return arr[-k] 24 | self.quickSort(arr, low, partition-1, k) 25 | self.quickSort(arr, partition+1, high, k) 26 | return arr[-k] 27 | 28 | def findKthLargest(self, arr, k): 29 | """ 30 | :type nums: List[int] 31 | :type k: int 32 | :rtype: int 33 | """ 34 | return self.quickSort(arr, 0, len(arr)-1, k) -------------------------------------------------------------------------------- /8. Graphs/3. Network Delay Time/network-delay-time-dynamic-programming.py: -------------------------------------------------------------------------------- 1 | import sys 2 | class Solution(object): 3 | def networkDelayTime(self, times, n, k): 4 | """ 5 | :type times: List[List[int]] 6 | :type n: int 7 | :type k: int 8 | :rtype: int 9 | """ 10 | distance = {} 11 | k = k - 1 12 | 13 | for i in range(n): 14 | distance[i] = sys.maxint 15 | 16 | vertex = k 17 | distance[k] = 0 18 | 19 | for i in range(n): 20 | count = 0 21 | for time in times: 22 | src = time[0] - 1 23 | dest = time[1] - 1 24 | wt = time[2] 25 | 26 | if distance[src] == sys.maxint: 27 | continue 28 | else: 29 | if distance[src] + wt < distance[dest]: 30 | distance[dest] = distance[src] + wt 31 | count += 1 32 | if count == 0: 33 | break 34 | 35 | if sys.maxint in distance.values(): 36 | return -1 37 | 38 | return max(distance.values()) -------------------------------------------------------------------------------- /6. Binary Trees/3. Right Side View of Tree/right-side-view-of-tree-bfs.py: -------------------------------------------------------------------------------- 1 | class TreeNode(object): 2 | def __init__(self, val=0, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | class Solution(object): 8 | def rightSideView(self, root): 9 | """ 10 | :type root: TreeNode 11 | :rtype: List[int] 12 | """ 13 | if root == None: return [] 14 | curr = root 15 | queue = [] 16 | queue.append(curr) 17 | tempList = [] 18 | rightNodes = [] 19 | length = 1 20 | count = 0 21 | while queue != []: 22 | curr = queue[0] 23 | tempList.append(curr.val) 24 | count += 1 25 | queue = queue[1:] 26 | 27 | if curr.left: 28 | queue.append(curr.left) 29 | if curr.right: 30 | queue.append(curr.right) 31 | 32 | if length == count: 33 | rightNodes.append(tempList[-1]) 34 | tempList = [] 35 | count = 0 36 | length = len(queue) 37 | 38 | return rightNodes -------------------------------------------------------------------------------- /3. Linked Lists/2. Reverse Linked Lists II - M, N Reversals/reverse-linked-lists-II-m-n-reversals.py: -------------------------------------------------------------------------------- 1 | class ListNode(object): 2 | def __init__(self, val=0, next=None): 3 | self.val = val 4 | self.next = next 5 | 6 | class Solution(object): 7 | def reverseBetween(self, head, left, right): 8 | if head == None or head.next == None: 9 | return head 10 | count = 1 11 | big_prev = None 12 | tail = None 13 | prev = None 14 | curr = head 15 | while(curr): 16 | if left <= count and count <= right: 17 | if(count == left): 18 | tail = curr 19 | temp = curr.next 20 | curr.next = prev 21 | prev = curr 22 | curr = temp 23 | if count == right: 24 | tail.next = temp 25 | if big_prev != None: 26 | big_prev.next = prev 27 | return head 28 | else: 29 | return prev 30 | 31 | else: 32 | big_prev = curr 33 | curr = curr.next 34 | count += 1 -------------------------------------------------------------------------------- /8. Graphs/2. Course Schedule/course-schedule.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def canFinish(self, numCourses, prerequisites): 3 | """ 4 | :type numCourses: int 5 | :type prerequisites: List[List[int]] 6 | :rtype: bool 7 | """ 8 | 9 | adj_list = [] 10 | inDegree = {} 11 | seen = {} 12 | 13 | for i in range(numCourses): 14 | adj_list.append([]) 15 | inDegree[i] = 0 16 | 17 | for p in prerequisites: 18 | course = p[0] 19 | prereq = p[1] 20 | adj_list[prereq].append(course) 21 | inDegree[course] = inDegree[course] + 1 22 | 23 | while len(inDegree) > 0: 24 | # search for where inDegree[i] == 0 25 | count = len(inDegree) 26 | for node in inDegree: 27 | if inDegree[node] == 0: 28 | for child in adj_list[node]: 29 | inDegree[child] = inDegree[child] - 1 30 | inDegree.pop(node) 31 | break 32 | count = count - 1 33 | if count == 0: 34 | return False 35 | return True -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/1. Tree Traversals/Breadth First Search.md: -------------------------------------------------------------------------------- 1 | # Breadth First Search (BFS) 2 | Logic: start at root node → go thru nodes on same level 3 | 4 | * uses a lot of memory because 5 | * for every level @ every node, need to store the node’s children 6 | * use queue data structure to store node’s children: Space: O(n) 7 | * Downside: tree wide → queue become very large 8 | ## Code 9 | ```Python 10 | def breadthFirstSearch(self): 11 | curr = self.getRoot() 12 | orderOfNodesList = [] 13 | #track children for every level 14 | queue = [] 15 | #add the root to queue 16 | queue.append(curr) 17 | #while there are nodes to be seen in the tree 18 | while queue != []: 19 | #take the first node 20 | curr = queue[0] 21 | #remove it from the queue 22 | queue = queue[1:] 23 | #add the node seen to the list 24 | orderOfNodesList.append(curr.val) 25 | #check if the node has children 26 | if curr.left: 27 | queue.append(curr.left) 28 | if curr.right: 29 | queue.append(curr.right) 30 | print("bfsList: ", orderOfNodesList) 31 | return orderOfNodesList 32 | ``` -------------------------------------------------------------------------------- /6. Binary Trees/2. Level Order of a Binary Tree/level-order-of-binary-tree.py: -------------------------------------------------------------------------------- 1 | class TreeNode(object): 2 | def __init__(self, val=0, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | class Solution(object): 8 | def levelOrder(self, root): 9 | """ 10 | :type root: TreeNode 11 | :rtype: List[List[int]] 12 | """ 13 | if root == None: 14 | return [] 15 | curr = root 16 | queue = [] 17 | queue.append(curr) 18 | tempList = [] 19 | levelOrderOfNodes = [] 20 | length = 1 21 | count = 0 22 | while queue != []: 23 | curr = queue[0] 24 | tempList.append(curr.val) 25 | count += 1 26 | queue = queue[1:] 27 | 28 | if curr.left: 29 | queue.append(curr.left) 30 | if curr.right: 31 | queue.append(curr.right) 32 | 33 | if length == count: 34 | levelOrderOfNodes.append(tempList) 35 | tempList = [] 36 | count = 0 37 | length = len(queue) 38 | 39 | return levelOrderOfNodes -------------------------------------------------------------------------------- /5. Recursion + Sortings/1. Kth Largest Element in an Array/kth-largest-element-in-an-array-optimal.py: -------------------------------------------------------------------------------- 1 | def partition(self, arr, low, high): 2 | #holds the place of where the pivot should be 3 | i = low 4 | #scans and compares #s against pivot 5 | j = low 6 | #pivot is rightmost element 7 | pivot = arr[high] 8 | while j < high: 9 | if arr[j] < arr[high]: 10 | if i != j: 11 | arr[i], arr[j] = arr[j], arr[i] 12 | i += 1 13 | j += 1 14 | else: 15 | j += 1 16 | arr[i], arr[high] = pivot, arr[i] 17 | return i 18 | 19 | def quickSelect(self, arr, low, high, k): 20 | if low < high: 21 | partition = self.partition(arr, low, high) 22 | if k == partition: 23 | return arr[k] 24 | elif k > partition: 25 | return self.quickSelect(arr, partition+1, high, k) 26 | else: 27 | return self.quickSelect(arr, low, partition-1, k) 28 | return arr[k] 29 | 30 | 31 | def findKthLargest(self, arr, k): 32 | """ 33 | :type nums: List[int] 34 | :type k: int 35 | :rtype: int 36 | """ 37 | indexToFind = len(arr)-k 38 | return self.quickSelect(arr, 0, len(arr)-1, indexToFind) -------------------------------------------------------------------------------- /5. Recursion + Sortings/Learning Material/Binary Search.md: -------------------------------------------------------------------------------- 1 | # Binary Search 2 | Time: O(logn) → spend time searching thru half of array 3 | ## Iterative 4 | Space: O(1) 5 | ``` 6 | def search(self, nums, target): 7 | """ 8 | :type nums: List[int] 9 | :type target: int 10 | :rtype: int 11 | """ 12 | left = 0 13 | right = len(nums)-1 14 | while left <= right: 15 | mid = (left+right)/2 16 | if target == nums[mid]: 17 | return mid 18 | elif target < nums[mid]: 19 | right = mid -1 20 | else: 21 | left = mid + 1 22 | return -1 23 | ``` 24 | ## Recursive 25 | Space: O(n) 26 | ``` 27 | def binarySearch(self, nums, left, right, target): 28 | if left <= right: 29 | mid = (right+left)/2 30 | if target == nums[mid]: 31 | return mid 32 | elif target < nums[mid]: 33 | return self.binarySearch(nums, left, mid-1, target) 34 | else: 35 | return self.binarySearch(nums, mid+1, right, target) 36 | return -1 37 | 38 | def search(self, nums, target): 39 | """ 40 | :type nums: List[int] 41 | :type target: int 42 | :rtype: int 43 | """ 44 | return self.binarySearch(nums, 0, len(nums)-1, target) 45 | ``` 46 | -------------------------------------------------------------------------------- /General/Tail Recursion.md: -------------------------------------------------------------------------------- 1 | ## Regular Recursion 2 | ```JavaScript 3 | function recFactorial(x) { 4 | if(x <= 1) { 5 | return 1; 6 | } 7 | return x * recFactorial(x - 1); 8 | } 9 | ``` 10 | 11 | ## Call Stack Space: O(n) 12 | ```JavaScript 13 | recFactorial(4); 14 | 4 * recFactorial(3); 15 | 4 * (3 * recFactorial(2)); 16 | 4 * (3 * (2 * recFactorial(1))); 17 | 4 * (3 * (2 * 1)); 18 | ``` 19 | 20 | * Time: O(n) 21 | * Space: O(n) because all the calls to the function must wait on an answer (have to calculate x*blah blah): `return x * recFactorial(x -1)`, for factorial 4 there were in total 4 calls to the function (4 recursive stacks) 22 | 23 | ## Tail Recursion 24 | ```JavaScript 25 | function tailFactorial(x, totalSoFar = 1) { 26 | if (x === 0) { 27 | return totalSoFar; 28 | } 29 | return tailFactorial(x - 1, totalSoFar * x); 30 | } 31 | ``` 32 | 33 | ## Call Stack Space: O(1) 34 | ```JavaScript 35 | tailFactorial(4); 36 | tailFactorial(4, 1); 37 | tailFactorial(3, 4); 38 | tailFactorial(2, 12); 39 | tailFactorial(1, 24); 40 | tailFactorial(0, 24); 41 | ``` 42 | 43 | * Time: O(n) 44 | * Space: O(1) because we are no longer waiting on an answer (no waiting on x * blah blah calculation): `return tailFactorial(x - 1, totalSoFar * x)` 45 | * Engine compiler dependent: tail recursion O(1) space won’t occur 46 | -------------------------------------------------------------------------------- /6. Binary Trees/5. Validate Binary Search Tree/validate-binary-search-tree-optimal.py: -------------------------------------------------------------------------------- 1 | import sys 2 | class TreeNode(object): 3 | def __init__(self, val=0, left=None, right=None): 4 | self.val = val 5 | self.left = left 6 | self.right = right 7 | 8 | class Solution(object): 9 | def isValidBSTHelper(self, root, left, right): 10 | if root == None: 11 | return True 12 | # check that the node is within the current bounds otherwise return false 13 | if left >= root.val or root.val >= right: 14 | return False 15 | if root.left == None and root.right == None: 16 | return True 17 | 18 | leftSide = True 19 | rightSide = True 20 | if root.left != None: 21 | # if going left, update the right most value to the root value 22 | leftSide = self.isValidBSTHelper(root.left, left, root.val) 23 | if not leftSide: return False 24 | if root.right != None: 25 | rightSide = self.isValidBSTHelper(root.right, root.val, right) 26 | if not rightSide: return False 27 | return True 28 | 29 | def isValidBST(self, root): 30 | """ 31 | :type root: TreeNode 32 | :rtype: bool 33 | """ 34 | return self.isValidBSTHelper(root, ~sys.maxsize, sys.maxsize) -------------------------------------------------------------------------------- /5. Recursion + Sortings/Learning Material/Insertion Sort.md: -------------------------------------------------------------------------------- 1 | # Insertion Sort 2 | ## Sort: 6 5 3 1 8 7 2 4 3 | ``` 4 | Logic: 5 | * numbers are divided into sorted (left) and unsorted (right) parts. 6 | * first item in list is always considered sorted 7 | * take the first element in the unordeded part and move it from right to left 8 | ``` 9 | 1 iteration thru whole array: 10 | ``` 11 | 6 | 5 3 1 8 7 2 4 (swap 5 and 6) 12 | ``` 13 | 2 iter: 14 | ``` 15 | 5 6 | 3 1 8 7 2 4 (swap 3 and 6, swap 3 and 5) 16 | ... 17 | 3 5 6 | 1 8 7 2 4 18 | ``` 19 | 8 iter: 20 | ``` 21 | 1 2 3 4 5 6 7 | 8 22 | 1 2 3 4 5 6 7 8 | 23 | ``` 24 | Patterns: as move down array, the extra included item is sorted among the already sorted items 25 | ## Time + Space Complexity: 26 | * Time: O(n^2) 27 | * Space: O(1) 28 | ## Best Case: 29 | List is almost or is sorted and small data sets: O(n) 30 | ## Code 31 | ```Python 32 | def insertionSort(arr): 33 | """ 34 | :type arr: list 35 | :rtype: list 36 | """ 37 | for i in range(1, len(arr)): 38 | j = i 39 | while j > 0: 40 | # if previous element is larger than current: like 3 2 41 | if arr[j] < arr[j-1]: 42 | # swap 43 | temp = arr[j] 44 | arr[j] = arr[j-1] 45 | arr[j-1] = temp 46 | j -= 1 47 | 48 | 49 | return arr 50 | ``` -------------------------------------------------------------------------------- /5. Recursion + Sortings/Learning Material/Selection Sort.md: -------------------------------------------------------------------------------- 1 | # Selection Sort 2 | ## Sort: 8 5 2 6 9 3 1 4 0 7 3 | ``` 4 | Logic: 2 pointers 5 | * first ptr tracks the min so far and compares it with second ptr (min) 6 | * second ptr scans the rest of the list for the smallest number (scanner). 7 | * if scanner < min: 8 | min = scanner. 9 | * at end of the list, swap minimum number with the current position to be sorted. 10 | * at each iteration, next min # is placed in the right position. 11 | ``` 12 | 1 iteration thru whole array: 13 | ``` 14 | 8 5 2 6 9 3 1 4 0 7 (0 and 8 swap) 15 | ``` 16 | 2 iter: 17 | ``` 18 | 0 | 5 2 6 9 3 1 4 8 7 (1 and 5 swap) 19 | ``` 20 | 8 iter: 21 | ``` 22 | 1 2 3 4 5 6 7 | 8 23 | ``` 24 | Patterns: At each iteration, the min # is searched and swapped with the next unsorted index 25 | 26 | ## Time + Space Complexity: 27 | * Time: O(n^2) 28 | * Space: O(1) 29 | 30 | ## Code 31 | ```Python 32 | def selectionSort(arr): 33 | """ 34 | :type arr: list 35 | :rtype: list 36 | """ 37 | for i in range(len(arr)-1): 38 | comparison = arr[i] 39 | temp = arr[i] 40 | index = i + 1 41 | for j in range(i + 1, len(arr)): 42 | scanner = arr[j] 43 | if scanner < comparison: 44 | comparison = scanner 45 | index = j 46 | arr[i] = comparison 47 | arr[index] = temp 48 | 49 | return arr 50 | ``` -------------------------------------------------------------------------------- /8. Graphs/1. Time Needed to Inform All Employees/time-needed-to-inform-all-employees.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def numOfMinutes(self, n, headID, manager, informTime): 3 | """ 4 | :type n: int 5 | :type headID: int 6 | :type manager: List[int] 7 | :type informTime: List[int] 8 | :rtype: int 9 | """ 10 | max_time = 0 11 | adj_list = [] 12 | seen = {} 13 | for i in range(n): 14 | adj_list.append([]) 15 | seen[i] = False 16 | 17 | seen[headID] = True 18 | for emp_id in range(n): 19 | if emp_id != headID: 20 | adj_list[manager[emp_id]].append(emp_id) 21 | 22 | for neighbor in adj_list[headID]: 23 | new_time = self.dfs(neighbor, adj_list, informTime, informTime[headID], seen) 24 | max_time = max(max_time, new_time) 25 | 26 | return max_time 27 | 28 | def dfs(self, vertex, adj_list, informTime, new_time, seen): 29 | if informTime[vertex] == 0: 30 | return new_time 31 | seen[vertex] = True 32 | new_time += informTime[vertex] 33 | time = 0 34 | for neighbor in adj_list[vertex]: 35 | if not seen[neighbor]: 36 | time = max(time, self.dfs(neighbor, adj_list, informTime, new_time, seen)) 37 | return time -------------------------------------------------------------------------------- /4. Stacks + Queues/3. Implement Queues using Stacks/implement-queues-using-stacks.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | class MyQueue(object): 3 | 4 | def __init__(self): 5 | self.elements = deque() 6 | self.save = deque() 7 | 8 | def push(self, x): 9 | """ 10 | :type x: int 11 | :rtype: None 12 | """ 13 | self.elements.append(x) 14 | 15 | 16 | def pop(self): 17 | """ 18 | :rtype: int 19 | """ 20 | while len(self.elements) > 0: 21 | self.save.append(self.elements.pop()) 22 | result = self.save.pop() 23 | while len(self.save) > 0: 24 | self.elements.append(self.save.pop()) 25 | return result 26 | 27 | 28 | def peek(self): 29 | """ 30 | :rtype: int 31 | """ 32 | while len(self.elements) > 0: 33 | self.save.append(self.elements.pop()) 34 | result = self.save.pop() 35 | self.save.append(result) 36 | while len(self.save) > 0: 37 | self.elements.append(self.save.pop()) 38 | return result 39 | 40 | 41 | def empty(self): 42 | """ 43 | :rtype: bool 44 | """ 45 | return len(self.elements) == 0 46 | 47 | 48 | # Your MyQueue object will be instantiated and called as such: 49 | # obj = MyQueue() 50 | # obj.push(x) 51 | # param_2 = obj.pop() 52 | # param_3 = obj.peek() 53 | # param_4 = obj.empty() -------------------------------------------------------------------------------- /7. 2D Arrays/1. Number of Islands/number-of-islands.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def numIslands(self, grid): 3 | """ 4 | :type grid: List[List[str]] 5 | :rtype: int 6 | """ 7 | num_of_islands = 0 8 | queue = [] 9 | # Perform sequential search to find 1's, and pass row + col into bfs 10 | for row in range(len(grid)): 11 | for col in range(len(grid[0])): 12 | if grid[row][col] == "1": 13 | queue.append([row, col]) 14 | self.bfs(grid, queue) 15 | num_of_islands += 1 16 | queue = [] 17 | return num_of_islands 18 | 19 | def bfs(self, grid, queue): 20 | # up right down left 21 | directions = [[-1, 0], [0, 1], [1, 0], [0, -1]] 22 | 23 | while queue != []: 24 | row = queue[0][0] 25 | col = queue[0][1] 26 | grid[row][col] = "2" 27 | queue = queue[1:] 28 | for direction in directions: 29 | row1 = row + direction[0] 30 | col1 = col + direction[1] 31 | # check if the direction is out of bounds or visited 32 | if row1 < 0 or row1 >= len(grid) or col1 < 0 or col1 >= len(grid[0]) or grid[row1][col1] == "0" or grid[row1][col1] == "2": 33 | continue 34 | else: 35 | grid[row1][col1] = "2" 36 | queue.append([row1, col1]) -------------------------------------------------------------------------------- /5. Recursion + Sortings/Learning Material/Bubble Sort.md: -------------------------------------------------------------------------------- 1 | # Bubble Sort 2 | ## Sort: 6 5 3 1 8 7 2 4 3 | ``` 4 | Logic: sliding window between 2 elements (swap if curr < prev) 5 | while list not sorted: 6 | if prev element < curr element: 7 | move sliding window 8 | else: 9 | swap prev and curr elements 10 | ``` 11 | ## Example: 12 | 1 iteration thru whole array: 13 | ``` 14 | 6 5 3 1 8 7 2 4 (swap 6 and 5) 15 | 5 6 3 1 8 7 2 4 (swap 6 and 3) 16 | 5 3 6 1 8 7 2 4 (swap 6 and 1) 17 | 5 3 1 6 8 7 2 4 (keep 6 and 8) 18 | 5 3 1 6 8 7 2 4 (swap 8 and 7) 19 | 5 3 1 6 7 8 2 4 (swap 8 and 2) 20 | 5 3 1 6 7 2 8 4 (swap 8 and 4) 21 | 5 3 1 6 7 2 4 | 8 (8 is correctly sorted) 22 | ``` 23 | 2 iter: 24 | ``` 25 | ... 26 | 3 1 5 6 2 4 | 7 8 (7 is correctly sorted) 27 | ... 28 | 8 iter: 29 | | 1 2 3 4 5 6 7 8 (1 is correctly sorted) 30 | ``` 31 | Patterns: The highest unsorted number (highest number not at end of array) will be continuously swapped until it reaches the end. 32 | ## Time + Space Complexity: 33 | * Time: O(n^2) 34 | * Space: O(1) 35 | ## Best Case: 36 | O(n): continuously comparing between 2 elements 37 | Code 38 | ```Python 39 | def bubbleSort(arr): 40 | """ 41 | :type arr: list 42 | :rtype: list 43 | """ 44 | bubble = len(arr) 45 | for i in range(bubble-1): 46 | for j in range(0, bubble-1): 47 | # j and j + 1 48 | if arr[j] > arr[j+1]: 49 | # swap them 50 | temp = arr[j] 51 | arr[j] = arr[j+1] 52 | arr[j+1] = temp 53 | bubble -= 1 54 | return arr 55 | ``` -------------------------------------------------------------------------------- /7. 2D Arrays/2. Rotting Oranges/rotting-oranges.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def orangesRotting(self, grid): 3 | """ 4 | :type grid: List[List[int]] 5 | :rtype: int 6 | """ 7 | 8 | directions = [[-1, 0], [0, 1], [1, 0], [0, -1]] 9 | queue = [] 10 | num_of_min = 0 11 | size = 0 12 | num_of_fresh_oranges = 0 13 | for row in range(len(grid)): 14 | for col in range(len(grid[0])): 15 | if grid[row][col] == 2: 16 | queue.append([row, col]) 17 | size += 1 18 | elif grid[row][col] == 1: 19 | num_of_fresh_oranges += 1 20 | 21 | while queue != []: 22 | row = queue[0][0] 23 | col = queue[0][1] 24 | queue = queue[1:] 25 | size -= 1 26 | for direction in directions: 27 | row1 = row + direction[0] 28 | col1 = col + direction[1] 29 | if row1 < 0 or row1 >= len(grid) or col1 < 0 or col1 >= len(grid[0]) or grid[row1][col1] != 1: 30 | continue 31 | else: 32 | grid[row1][col1] = 2 33 | num_of_fresh_oranges -= 1 34 | queue.append([row1, col1]) 35 | if size == 0: 36 | num_of_min += 1 37 | size = len(queue) 38 | 39 | 40 | if num_of_fresh_oranges > 0: 41 | return -1 42 | 43 | if num_of_min == 0: 44 | return 0 45 | return num_of_min - 1 -------------------------------------------------------------------------------- /6. Binary Trees/4. Count Complete Tree Nodes/count-complete-tree-nodes-optimal.py: -------------------------------------------------------------------------------- 1 | class TreeNode(object): 2 | def __init__(self, val=0, left=None, right=None): 3 | self.val = val 4 | self.left = left 5 | self.right = right 6 | 7 | class Solution(object): 8 | def maxHeight(self, root): 9 | if root == None: 10 | return 0 11 | leftHeight = 1 + self.maxHeight(root.left) 12 | rightHeight = 1 + self.maxHeight(root.right) 13 | return max(leftHeight, rightHeight) 14 | 15 | def countNodesHelper(self, root, h, currHeight, numNodes): 16 | if root == None: 17 | return numNodes 18 | 19 | if root.left == None: 20 | numNodes += 1 21 | return numNodes 22 | else: 23 | left = self.maxHeight(root.left) 24 | right = self.maxHeight(root.right) 25 | if right >= left: 26 | numNodes += pow(2, h-1-currHeight) 27 | currHeight+=1 28 | return self.countNodesHelper(root.right, h, currHeight, numNodes) 29 | else: 30 | currHeight+=1 31 | return self.countNodesHelper(root.left, h, currHeight, numNodes) 32 | 33 | 34 | def countNodes(self, root): 35 | """ 36 | :type root: TreeNode 37 | :rtype: int 38 | """ 39 | if root == None: 40 | return 0 41 | h = self.maxHeight(root) 42 | numNodes = pow(2, h-1)-1 43 | currHeight = 1 44 | numNodes = self.countNodesHelper(root, h, currHeight, numNodes) 45 | return numNodes 46 | -------------------------------------------------------------------------------- /2. Strings/1. Backspace String Compare/backspace-string-compare-optimal.py: -------------------------------------------------------------------------------- 1 | def backspaceCompare(self, s, t): 2 | """ 3 | :type s: str 4 | :type t: str 5 | :rtype: bool 6 | """ 7 | p1 = len(s) - 1 8 | p2 = len(t) - 1 9 | stepS = 0 10 | stepT = 0 11 | 12 | while p1 >= 0 or p2 >= 0: 13 | #as long as p1 is not negative 14 | while p1 >= 0: 15 | #if find # then move on to the next char, and increase stepS 16 | if s[p1] == "#": 17 | p1 -= 1 18 | stepS +=1 19 | #if there are stepS (chars to skip) then move on to next char and decrease the number of stepS to skip 20 | elif stepS > 0: 21 | p1 -= 1 22 | stepS -= 1 23 | #if there are no chars to skip, (no #'s or no chars before #'s), then break 24 | else: 25 | break 26 | 27 | while p2 >= 0: 28 | if t[p2] == "#": 29 | p2 -= 1 30 | stepT +=1 31 | elif stepT > 0: 32 | p2 -= 1 33 | stepT -= 1 34 | else: 35 | break 36 | 37 | #if both indices are negative, then return true 38 | #if both indices ended but one is negative and the other is not, then return false 39 | if p1 < 0: return p2 < 0 40 | if p2 < 0: return p1 < 0 41 | #if the chars are not #'s or chars before #'s and do not equal each other, return false 42 | if s[p1] != t[p2]: return False 43 | #if the characters are equal, then check the rest of the string 44 | p1 -= 1 45 | p2 -= 1 46 | 47 | return True -------------------------------------------------------------------------------- /5. Recursion + Sortings/2. Find First and Last Position of Element in Sorted Array/find-first-and-last-position-of-element-in-sorted-array-recursive.py: -------------------------------------------------------------------------------- 1 | def binarySearch(self, nums, left, right, target, ranges, prevMid): 2 | if left <= right: 3 | mid = (right+left)/2 4 | if target == nums[mid]: 5 | if mid < ranges[0] or ranges[0] == -1: 6 | ranges[0] = mid 7 | if ranges[1] < mid: 8 | ranges[1] = mid 9 | 10 | if prevMid != -1: 11 | #right 12 | if prevMid < mid: 13 | return self.binarySearch(nums, mid+1, right, target, ranges, mid) 14 | else: 15 | return self.binarySearch(nums, left, mid-1, target, ranges, mid) 16 | else: 17 | self.binarySearch(nums, left, mid-1, target, ranges, mid) 18 | self.binarySearch(nums, mid+1, right, target, ranges, mid) 19 | 20 | elif target < nums[mid]: 21 | return self.binarySearch(nums, left, mid-1, target, ranges, prevMid) 22 | else: 23 | return self.binarySearch(nums, mid+1, right, target, ranges, prevMid) 24 | return ranges 25 | def searchRange(self, nums, target): 26 | """ 27 | :type nums: List[int] 28 | :type target: int 29 | :rtype: List[int] 30 | """ 31 | prevMid = -1 32 | ranges = [-1, -1] 33 | 34 | if nums == []: 35 | return ranges 36 | if len(nums) == 1: 37 | if nums[0] == target: 38 | return [0, 0] 39 | else: 40 | ranges 41 | if target < nums[0] or nums[-1] < target: 42 | return ranges 43 | 44 | return self.binarySearch(nums, 0, len(nums)-1,target, ranges, prevMid) -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/1. Tree Traversals/Binary Tree Class Code.py: -------------------------------------------------------------------------------- 1 | class Node: 2 | def __init__(self, val): 3 | self.left = None 4 | self.right= None 5 | self.val = val 6 | 7 | class Tree: 8 | def __init__(self): 9 | self.root = None 10 | 11 | def getRoot(self): 12 | return self.root 13 | 14 | def add(self, val): 15 | if self.root is None: 16 | self.root = Node(val) 17 | else: 18 | self._add(val, self.root) 19 | 20 | def _add(self, val, node): 21 | if val < node.val: 22 | if node.left is not None: 23 | self._add(val, node.left) 24 | else: 25 | node.left = Node(val) 26 | else: 27 | if node.right is not None: 28 | self._add(val, node.right) 29 | else: 30 | node.right = Node(val) 31 | 32 | def find(self, val): 33 | if self.root is not None: 34 | return self._find(val, self.root) 35 | else: 36 | return None 37 | 38 | def _find(self, val, node): 39 | if val == node.val: 40 | return node 41 | elif (val < node.val and node.left is not None): 42 | return self._find(val, node.left) 43 | elif (val > node.val and node.right is not None): 44 | return self._find(val, node.r) 45 | 46 | def deleteTree(self): 47 | # garbage collector will do this for us. 48 | self.root = None 49 | 50 | def printTree(self): 51 | if self.root is not None: 52 | self._printTree(self.root) 53 | 54 | def _printTree(self, node): 55 | if node is not None: 56 | self._printTree(node.left) 57 | print(str(node.val) + ' ') 58 | self._printTree(node.right) 59 | 60 | tree = Tree() 61 | tree.add(9) 62 | tree.add(4) 63 | tree.add(6) 64 | tree.add(20) 65 | tree.add(170) 66 | tree.add(15) 67 | tree.add(1) 68 | tree.printTree() 69 | # print(tree.find(3).val) 70 | # print(tree.find(10)) 71 | # tree.deleteTree() 72 | # tree.printTree() -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/2. Heaps - Priority Queues/Insertion (Sift Up).md: -------------------------------------------------------------------------------- 1 | # Insertion (Sift Up) 2 | ## Conceptual 3 | ### Max Heap 4 | ``` 5 | 50 6 | 40 25 7 | 20 35 10 15 8 | ``` 9 | **Insert: 45** 10 | Insert new value into the most left position (b/c heap is complete binary tree) 11 | ``` 12 | 50 13 | 40 25 14 | 20 35 10 15 15 | 45 16 | ``` 17 | * Keep comparing new node (45) to parent 18 | * **20 < 45** 19 | * **Swap** 20 | ``` 21 | 50 22 | 40 25 23 | 45 35 10 15 24 | 20 25 | ``` 26 | * **40 < 45** 27 | * **Swap** 28 | ``` 29 | 50 30 | 45 25 31 | 40 35 10 15 32 | 20 33 | ``` 34 | * **50 > 45** 35 | * Stop 36 | 37 | 38 | ### Min Heap 39 | Instead of swapping when new node is larger than parent node, 40 | swap when NEW node is SMALLER than PARENT 41 | 42 | ## Array Implementation 43 | ``` 44 | [50, 40, 25, 20, 35, 10, 15, 45] 45 | 0 1 2 3 4 5 6 7 46 | ``` 47 | * parent of 45’s index = floor((idx - 1) / 2 ) = floor((8 - 1) / 2) = 3 48 | → swap 20 and 45 49 | * parent of 45’s index = floor((idx - 1) / 2 ) = floor((3 - 1) / 2) = 1 50 | → swap 40 and 45 51 | * parent of 45’s index = floor((idx - 1) / 2 ) = floor((1 - 1) / 2) = 0 52 | → no swap (50 is larger) 53 | 54 | ## Code 55 | ```Python 56 | def push(self, val): 57 | self.heap.append(val) # add new val to bottom of heap 58 | self.siftUp() # sift new val up 59 | return self.size() 60 | 61 | def siftUp(self): 62 | nodeIdx = self.size() - 1 63 | parent = self.parent(nodeIdx) 64 | # MAX heap: while the parent is smaller -> sift up: parent < node 65 | # MIN heap: while the parent is larger -> sift up: parent > node 66 | while(nodeIdx > 0 and self.compare(parent, nodeIdx)): 67 | # switch the parent and current node value 68 | self.swap(self.parent(nodeIdx), nodeIdx) 69 | # move node ptr to parent index 70 | nodeIdx = self.parent(nodeIdx) 71 | parent = self.parent(nodeIdx) 72 | 73 | def parent(self, idx): 74 | return math.floor((idx - 1) / 2) 75 | 76 | def compare(self, i, j): 77 | return self.comparator(self.heap[i], self.heap[j]); 78 | 79 | def swap(self, i, j): 80 | temp = self.heap[i]; 81 | self.heap[i] = self.heap[j]; 82 | self.heap[j] = temp; 83 | ``` -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/2. Heaps - Priority Queues/Priority Queue.py: -------------------------------------------------------------------------------- 1 | import math 2 | class PriorityQueue: 3 | def __init__(self, comparator): 4 | self.heap = [] 5 | self.comparator = comparator 6 | 7 | def size(self): 8 | return len(self.heap) 9 | 10 | def isEmpty(self): 11 | return self.size() == 0 12 | 13 | def peek(self): 14 | if not self.isEmpty(): 15 | return self.heap[0] 16 | return None 17 | 18 | def push(self, val): 19 | self.heap.append(val) # add new val to bottom of heap 20 | self.siftUp() # sift new val up 21 | return self.size() 22 | 23 | def siftUp(self): 24 | nodeIdx = self.size() - 1 25 | parent = self.parent(nodeIdx) 26 | # MAX heap: while the parent is smaller -> sift up: parent < node 27 | # MIN heap: while the parent is larger -> sift up: parent > node 28 | while(nodeIdx > 0 and self.compare(parent, nodeIdx)): 29 | # switch the parent and current node value 30 | self.swap(self.parent(nodeIdx), nodeIdx) 31 | # move node ptr to parent index 32 | nodeIdx = self.parent(nodeIdx) 33 | parent = self.parent(nodeIdx) 34 | 35 | def pop(self): 36 | top = self.heap[0] # save the min/max value 37 | # put the last element into the top position 38 | self.heap[0] = self.heap[self.size() - 1] 39 | # remove the repeat element from the last position 40 | self.heap.pop(self.size() - 1) 41 | # sift the new top value down to get the new min/max 42 | self.siftDown() 43 | return top # return the original min/max value 44 | 45 | def siftDown(self): 46 | nodeIdx = 0 47 | while nodeIdx < self.size(): 48 | # choose min/max b/w left and right child 49 | childIdx = self.siftDownCompare(nodeIdx) 50 | # compare nodeIdx with the min/max child 51 | if childIdx != -1 and self.compare(nodeIdx, childIdx): 52 | # swap if 53 | # MAX: node < child -> child larger so should be on top 54 | # MIN: node > child -> child smaller so should be on top 55 | self.swap(nodeIdx, childIdx) 56 | nodeIdx = childIdx 57 | else: 58 | break 59 | 60 | def parent(self, idx): 61 | return math.floor((idx - 1) / 2) 62 | 63 | def leftChild(self, idx): 64 | return 2 * idx + 1 65 | 66 | def rightChild(self, idx): 67 | return 2 * idx + 2 68 | 69 | def swap(self, i, j): 70 | temp = self.heap[i]; 71 | self.heap[i] = self.heap[j]; 72 | self.heap[j] = temp; 73 | 74 | def compare(self, i, j): 75 | return self.comparator(self.heap[i], self.heap[j]); 76 | 77 | def siftDownCompare(self, idx): 78 | isMax = self.comparator(1, 2) 79 | leftChildIdx = self.leftChild(idx) 80 | rightChildIdx = self.rightChild(idx) 81 | if leftChildIdx >= self.size(): 82 | return -1 83 | elif leftChildIdx < self.size() and rightChildIdx >= self.size(): 84 | return leftChildIdx 85 | elif rightChildIdx < self.size() and leftChildIdx >= self.size(): 86 | return rightChildIdx 87 | if isMax: 88 | if self.heap[leftChildIdx] > self.heap[rightChildIdx]: 89 | return leftChildIdx 90 | else: 91 | return rightChildIdx 92 | else: 93 | if self.heap[leftChildIdx] < self.heap[rightChildIdx]: 94 | return leftChildIdx 95 | else: 96 | return rightChildIdx 97 | # MAX heap: swap node w/ max(left child, right child) 98 | # MIN heap: swap node w/ min(left child, right child) 99 | 100 | def printHeap(self): 101 | if self.heap is not None: 102 | for i in range(len(self.heap)): 103 | print(i, " element: ", self.heap[i], " ") 104 | 105 | def maxComparator(a, b): 106 | return a < b 107 | def minComparator(a, b): 108 | return a > b 109 | 110 | heap = PriorityQueue(maxComparator) 111 | heap.push(50) 112 | heap.push(40) 113 | heap.push(25) 114 | heap.push(20) 115 | heap.push(35) 116 | heap.push(10) 117 | heap.push(15) 118 | heap.push(45) 119 | heap.pop() 120 | heap.printHeap() -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/2. Heaps - Priority Queues/Deletion (Sift Down).md: -------------------------------------------------------------------------------- 1 | # Deletion (Sift Down) 2 | ## Conceptual 3 | ### Max Heap 4 | * Removal deletion, retrieval, return root value (greatest value) 5 | * Restructure heap so max value at root and so tree is complete binary tree 6 | * Take last node and place it in the root node and sift value down 7 | ## Example 8 | ``` 9 | 75 10 | 50 25 11 | 45 35 10 15 12 | 20 40 13 | ``` 14 | * save 75 into variable, then get rid of 40 15 | * swap 75 and 40 variable 16 | * set 45’s right child to null 17 | ``` 18 | 40 19 | 50 25 20 | 45 35 10 15 21 | 20 22 | ``` 23 | * max(left child, right child) = max(50, 25) = 50 24 | * 50 > 40 25 | * swap 50 and 40 26 | ``` 27 | 50 28 | 40 25 29 | 45 35 10 15 30 | 20 31 | ``` 32 | * max(left child, right child) = max(45, 35) = 45 33 | * 45 > 40 34 | * swap 45 and 40 35 | ``` 36 | 50 37 | 45 25 38 | 40 35 10 15 39 | 20 40 | ``` 41 | * max(left child, null) = 20 42 | * 20 < 40 43 | * stop 44 | ### Min Heap 45 | * instead of max use mix() 46 | * swap only if child less than parent 47 | ## Array Implementation 48 | ``` 49 | [75, 50, 25, 45, 35, 10, 15, 20, 40] 50 | 0 1 2 3 4 5 6 7 8 51 | 52 | 75 53 | 50 25 54 | 45 35 10 15 55 | 20 40 56 | ``` 57 | * save 75 into variable, then get rid of 40 return_value = heap[0] 58 | * swap 75 and 40 variable 59 | * set 45’s right child to null 60 | ``` 61 | [40, 50, 25, 45, 35, 10, 15, 20] 62 | 0 1 2 3 4 5 6 7 63 | 64 | 40 65 | 50 25 66 | 45 35 10 15 67 | 20 68 | 69 | left child idx = 2*idx + 1 = 0 + 1 = 1 70 | right child idx = 2*idx + 2 = 2 71 | max(left child, right child) = max(50, 25) = 50 72 | ``` 73 | * 50 > 40 74 | * swap 50 and 40 75 | ``` 76 | [50, 40, 25, 45, 35, 10, 15, 20] 77 | 0 1 2 3 4 5 6 7 78 | 79 | 50 80 | 40 25 81 | 45 35 10 15 82 | 20 83 | ``` 84 | ... and so on 85 | ## Code 86 | ```Python 87 | def pop(self): 88 | top = self.heap[0] # save the min/max value 89 | # put the last element into the top position 90 | self.heap[0] = self.heap[self.size() - 1] 91 | # remove the repeat element from the last position 92 | self.heap.pop(self.size() - 1) 93 | # sift the new top value down to get the new min/max 94 | self.siftDown() 95 | return top # return the original min/max value 96 | 97 | def siftDown(self): 98 | nodeIdx = 0 99 | while nodeIdx < self.size(): 100 | # choose min/max b/w left and right child 101 | childIdx = self.siftDownCompare(nodeIdx) 102 | # compare nodeIdx with the min/max child 103 | if childIdx != -1 and self.compare(nodeIdx, childIdx): 104 | # swap if 105 | # MAX: node < child -> child larger so should be on top 106 | # MIN: node > child -> child smaller so should be on top 107 | self.swap(nodeIdx, childIdx) 108 | nodeIdx = childIdx 109 | else: 110 | break 111 | 112 | def siftDownCompare(self, idx): 113 | isMax = self.comparator(1, 2) 114 | leftChildIdx = self.leftChild(idx) 115 | rightChildIdx = self.rightChild(idx) 116 | if leftChildIdx >= self.size(): 117 | return -1 118 | elif leftChildIdx < self.size() and rightChildIdx >= self.size(): 119 | return leftChildIdx 120 | elif rightChildIdx < self.size() and leftChildIdx >= self.size(): 121 | return rightChildIdx 122 | if isMax: 123 | if self.heap[leftChildIdx] > self.heap[rightChildIdx]: 124 | return leftChildIdx 125 | else: 126 | return rightChildIdx 127 | else: 128 | if self.heap[leftChildIdx] < self.heap[rightChildIdx]: 129 | return leftChildIdx 130 | else: 131 | return rightChildIdx 132 | # MAX heap: swap node w/ max(left child, right child) 133 | # MIN heap: swap node w/ min(left child, right child) 134 | 135 | def leftChild(self, idx): 136 | return 2 * idx + 1 137 | 138 | def rightChild(self, idx): 139 | return 2 * idx + 2 140 | 141 | def swap(self, i, j): 142 | temp = self.heap[i]; 143 | self.heap[i] = self.heap[j]; 144 | self.heap[j] = temp; 145 | 146 | def compare(self, i, j): 147 | return self.comparator(self.heap[i], self.heap[j]); 148 | ``` -------------------------------------------------------------------------------- /6. Binary Trees/Learning Material/2. Heaps - Priority Queues/Heaps.md: -------------------------------------------------------------------------------- 1 | # Heaps / Priority Queues 2 | ## About 3 | ### What are heaps? 4 | * data structure that represents a COMPLETE (2nd to last level is full) binary tree 5 | * max heap: root larger than children nodes in tree (rest of children nodes not in max order) 6 | * min heap: root smallest than children nodes in tree (rest of children nodes not in min order) 7 | 8 | ### Indices 9 | * parent: floor((idx-1) / 2) 10 | * left child: 2*idx + 1 11 | * right child: 2*idx + 2 12 | 13 | ### Time Complexity 14 | * Creation: O(n) 15 | * Insertion: O(logn) [base → root (height of tree → logn)] 16 | * Deletion: O(logn) [root → base (height of tree → logn)] 17 | 18 | ### Important Methods 19 | * Insertion (Sift Up) 20 | * Deletion (Sift Down) 21 | 22 | ## Code (Max Heap) 23 | ```Python 24 | import math 25 | class PriorityQueue: 26 | def __init__(self, comparator): 27 | self.heap = [] 28 | self.comparator = comparator 29 | 30 | def size(self): 31 | return len(self.heap) 32 | 33 | def isEmpty(self): 34 | return self.size() == 0 35 | 36 | def peek(self): 37 | if not self.isEmpty(): 38 | return self.heap[0] 39 | return None 40 | 41 | def push(self, val): 42 | self.heap.append(val) # add new val to bottom of heap 43 | self.siftUp() # sift new val up 44 | return self.size() 45 | 46 | def siftUp(self): 47 | nodeIdx = self.size() - 1 48 | parent = self.parent(nodeIdx) 49 | # MAX heap: while the parent is smaller -> sift up: parent < node 50 | # MIN heap: while the parent is larger -> sift up: parent > node 51 | while(nodeIdx > 0 and self.compare(parent, nodeIdx)): 52 | # switch the parent and current node value 53 | self.swap(self.parent(nodeIdx), nodeIdx) 54 | # move node ptr to parent index 55 | nodeIdx = self.parent(nodeIdx) 56 | parent = self.parent(nodeIdx) 57 | 58 | def pop(self): 59 | top = self.heap[0] # save the min/max value 60 | # put the last element into the top position 61 | self.heap[0] = self.heap[self.size() - 1] 62 | # remove the repeat element from the last position 63 | self.heap.pop(self.size() - 1) 64 | # sift the new top value down to get the new min/max 65 | self.siftDown() 66 | return top # return the original min/max value 67 | 68 | def siftDown(self): 69 | nodeIdx = 0 70 | while nodeIdx < self.size(): 71 | # choose min/max b/w left and right child 72 | childIdx = self.siftDownCompare(nodeIdx) 73 | # compare nodeIdx with the min/max child 74 | if childIdx != -1 and self.compare(nodeIdx, childIdx): 75 | # swap if 76 | # MAX: node < child -> child larger so should be on top 77 | # MIN: node > child -> child smaller so should be on top 78 | self.swap(nodeIdx, childIdx) 79 | nodeIdx = childIdx 80 | else: 81 | break 82 | 83 | def parent(self, idx): 84 | return math.floor((idx - 1) / 2) 85 | 86 | def leftChild(self, idx): 87 | return 2 * idx + 1 88 | 89 | def rightChild(self, idx): 90 | return 2 * idx + 2 91 | 92 | def swap(self, i, j): 93 | temp = self.heap[i]; 94 | self.heap[i] = self.heap[j]; 95 | self.heap[j] = temp; 96 | 97 | def compare(self, i, j): 98 | return self.comparator(self.heap[i], self.heap[j]); 99 | 100 | def siftDownCompare(self, idx): 101 | isMax = self.comparator(1, 2) 102 | leftChildIdx = self.leftChild(idx) 103 | rightChildIdx = self.rightChild(idx) 104 | if leftChildIdx >= self.size(): 105 | return -1 106 | elif leftChildIdx < self.size() and rightChildIdx >= self.size(): 107 | return leftChildIdx 108 | elif rightChildIdx < self.size() and leftChildIdx >= self.size(): 109 | return rightChildIdx 110 | if isMax: 111 | if self.heap[leftChildIdx] > self.heap[rightChildIdx]: 112 | return leftChildIdx 113 | else: 114 | return rightChildIdx 115 | else: 116 | if self.heap[leftChildIdx] < self.heap[rightChildIdx]: 117 | return leftChildIdx 118 | else: 119 | return rightChildIdx 120 | # MAX heap: swap node w/ max(left child, right child) 121 | # MIN heap: swap node w/ min(left child, right child) 122 | 123 | def printHeap(self): 124 | if self.heap is not None: 125 | for i in range(len(self.heap)): 126 | print(i, " element: ", self.heap[i], " ") 127 | 128 | def maxComparator(a, b): 129 | return a < b 130 | def minComparator(a, b): 131 | return a > b 132 | 133 | heap = PriorityQueue(maxComparator) 134 | heap.push(50) 135 | heap.push(40) 136 | heap.push(25) 137 | heap.push(20) 138 | heap.push(35) 139 | heap.push(10) 140 | heap.push(15) 141 | heap.push(45) 142 | heap.pop() 143 | heap.printHeap() 144 | ``` 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Master the Coding Interview: Big Tech (FAANG) Interviews 2 | This repository contains step by step processes and Python solutions to the LeetCode problems reviewed in [Zero To Mastery](https://zerotomastery.io/)'s Udemy course [Master the Coding Interview: Big Tech (FAANG) Interviews](https://www.udemy.com/share/103J2K3@qe9lgUOC5jQCWRWTmPywBQSm1RqY-0fV8O-u23o5D34spyB7ZPocOVDee9aeSwy1/). 3 | 4 | Throughout this repo are some Data Strucutres and Algorithms review notes and coding interview techniques. Check out [this repository](https://github.com/sandhya-veludandi/tech-flashcards) to review Data Structures and Algorithms flashcards. 5 | 6 | | Status | Category | Problem | Difficulty | Solution Folder | 7 | | ------ | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 8 | | ✅ | Arrays | [Two Sum](https://leetcode.com/problems/two-sum/) | Easy | [Two Sum Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/1.%20Arrays/1.%20Two%20Sum) | 9 | | ✅ | Arrays | [Container with Most Water](https://leetcode.com/problems/container-with-most-water/) | Medium | [Container with Most Water Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/1.%20Arrays/2.%20Container%20with%20Most%20Water) | 10 | | ✅ | Arrays | [Trapping Rain Water](https://leetcode.com/problems/trapping-rain-water/) | Hard | [Trapping Rain Water Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/1.%20Arrays/3.%20Trapping%20Rain%20Water) | 11 | | ✅ | Strings | [Backspace String Compare](https://leetcode.com/problems/backspace-string-compare/) | Easy | [Backspace String Compare Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/2.%20Strings/1.%20Backspace%20String%20Compare) | 12 | | ✅ | Strings | [Longest Substring without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/) | Medium | [Longest Substring without Repeating Characters Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/2.%20Strings/2.%20Longest%20Substring%20without%20Repeating%20Characters) | 13 | | ✅ | Strings | [Valid Palindrome](https://leetcode.com/problems/valid-palindrome/) | Easy | [Valid Palindrome Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/2.%20Strings/3.%20Valid%20Palindrome) | 14 | | ✅ | Strings | [Valid Palindrome II](https://leetcode.com/problems/valid-palindrome-ii/) | Easy | [Valid Palindrome II Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/2.%20Strings/4.%20Valid%20Palindrome%20II%20-%20Almost%20Palindrome) | 15 | | ✅ | Linked Lists | [Reverse a Linked List](https://leetcode.com/problems/reverse-linked-list/) | Easy | [Reverse a Linked List Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/3.%20Linked%20Lists/1.%20Reverse%20a%20Linked%20List) | 16 | | ✅ | Linked Lists | [Reverse a Linked List II](https://leetcode.com/problems/reverse-linked-list-ii/) | Medium | [Reverse a Linked List II Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/3.%20Linked%20Lists/2.%20Reverse%20Linked%20Lists%20II%20-%20M%2C%20N%20Reversals) | 17 | | ✅ | Linked Lists | [Flatten a Multilevel Doubly Linked List](https://leetcode.com/problems/flatten-a-multilevel-doubly-linked-list/) | Medium | [Flatten a Multilevel Doubly Linked List Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/3.%20Linked%20Lists/3.%20Merge%20a%20Multi-level%20Doubly%20Linked%20List) | 18 | | ✅ | Linked Lists | [Linked List Cycle I](https://leetcode.com/problems/linked-list-cycle/) | Easy | [Linked List Cycle I Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/3.%20Linked%20Lists/4.%20Linked%20List%20Cycle%20(I%20and%20II)) | 19 | | ✅ | Linked Lists | [Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii/) | Medium | [Linked List Cycle II Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/3.%20Linked%20Lists/4.%20Linked%20List%20Cycle%20(I%20and%20II)) | 20 | | ✅ | Stacks + Queues | [Valid Parentheses](https://leetcode.com/problems/valid-parentheses/) | Easy | [Valid Parentheses Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/4.%20Stacks%20%2B%20Queues/1.%20Valid%20Parentheses) | 21 | | ✅ | Stacks + Queues | [Minimum Remove to Make Valid Parentheses](https://leetcode.com/problems/minimum-remove-to-make-valid-parentheses/) | Medium | [Minimum Remove to Make Valid Parentheses Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/4.%20Stacks%20%2B%20Queues/2.%20Minimum%20Remove%20to%20Make%20Valid%20Parentheses) | 22 | | ✅ | Stacks + Queues | [Implement Queue using Stacks](https://leetcode.com/problems/implement-queue-using-stacks/) | Easy | [Implement Queue using Stacks Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/4.%20Stacks%20%2B%20Queues/3.%20Implement%20Queues%20using%20Stacks) | 23 | | ✅ | Recursion + Sortings | [Kth Largest Element in an Array](https://leetcode.com/problems/kth-largest-element-in-an-array/) | Medium | [Kth Largest Element in an Array Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/5.%20Recursion%20%2B%20Sortings/1.%20Kth%20Largest%20Element%20in%20an%20Array) | 24 | | ✅ | Recursion + Sortings | [Find First and Last Position of Element in Sorted Array](https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/) | Medium | [Find First and Last Position of Element in Sorted Array Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/5.%20Recursion%20%2B%20Sortings/2.%20Find%20First%20and%20Last%20Position%20of%20Element%20in%20Sorted%20Array) | 25 | | ✅ | Binary Trees | [Maximum Depth of a Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) | Easy | [Maximum Depth of a Binary Tree Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/6.%20Binary%20Trees/1.%20Maximum%20Depth%20of%20a%20Binary%20Tree) | 26 | | ✅ | Binary Trees | [Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/) | Medium | [Binary Tree Level Order Traversal Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/6.%20Binary%20Trees/2.%20Level%20Order%20of%20a%20Binary%20Tree) | 27 | | ✅ | Binary Trees | [Binary Tree Right Side View](https://leetcode.com/problems/binary-tree-right-side-view/) | Medium | [Binary Tree Right Side View Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/6.%20Binary%20Trees/3.%20Right%20Side%20View%20of%20Tree) | 28 | | ✅ | Binary Trees | [Count Complete Tree Nodes](https://leetcode.com/problems/count-complete-tree-nodes/) | Medium | [Count Complete Tree Nodes Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/6.%20Binary%20Trees/4.%20Count%20Complete%20Tree%20Nodes) | 29 | | ✅ | Binary Trees | [Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree/) | Medium | [Validate Binary Search Tree Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/6.%20Binary%20Trees/5.%20Validate%20Binary%20Search%20Tree) | 30 | | ✅ | 2D Arrays | [Number of Islands](https://leetcode.com/problems/number-of-islands/) | Medium | [Number of Islands Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/7.%202D%20Arrays/1.%20Number%20of%20Islands) | 31 | | ✅ | 2D Arrays | [Rotting Oranges](https://leetcode.com/problems/rotting-oranges/) | Medium | [Rotting Oranges Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/7.%202D%20Arrays/2.%20Rotting%20Oranges) | 32 | | ✅ | 2D Arrays | [LC Walls and Gates](https://leetcode.com/problems/walls-and-gates/) or [Coding Ninjas Walls and Gates](https://www.codingninjas.com/codestudio/problems/walls-and-gates_1092887) | Medium | [Walls and Gates Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/7.%202D%20Arrays/3.%20Walls%20and%20Gates) | 33 | | ✅ | Graphs | [Time Needed to Inform All Employees](https://leetcode.com/problems/time-needed-to-inform-all-employees/) | Medium | [Time Needed to Inform All Employees Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/8.%20Graphs/1.%20Time%20Needed%20to%20Inform%20All%20Employees) | 34 | | ✅ | Graphs | [Course Schedule](https://leetcode.com/problems/course-schedule/) | Medium | [Course Schedule Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/8.%20Graphs/2.%20Course%20Schedule) | 35 | | ✅ | Graphs | [Network Delay Time](https://leetcode.com/problems/network-delay-time/) | Medium | [Network Delay Time Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/8.%20Graphs/3.%20Network%20Delay%20Time) | 36 | | ✅ | Dynamic Programming | [Min Cost Climbing Stairs](https://leetcode.com/problems/min-cost-climbing-stairs/) | Easy | [Min Cost Climbing Stairs Solution](https://github.com/sandhya-veludandi/master-the-coding-interview/tree/main/9.%20Dynamic%20Programming/1.%20Staircase) | 37 | | ⚒️ | Dynamic Programming | [Knight Probability in Chessboard](https://leetcode.com/problems/knight-probability-in-chessboard/) | Medium | in progress | 38 | | ⚒️ | Backtracking | [Sudoku Solver](https://leetcode.com/problems/sudoku-solver/) | Hard | in progress | 39 | | ⚒️ | Interface Design | Monarchy | None | in progress | 40 | | ⚒️ | Tries | [Implement Prefix Trie](https://leetcode.com/problems/implement-trie-prefix-tree/) | Medium | in progress | 41 | --------------------------------------------------------------------------------