├── Leetcode Problems ├── Easy │ ├── 1-Two-Sum.py │ ├── 1025-Divisor-Game.py │ ├── 104-Maximum-Depth-of-Binary-Tree.py │ ├── 1051-Height-Checker.py │ ├── 1089-Duplicate-Zeros.py │ ├── 1108-Defanging-an-IP-Address.py │ ├── 1119-Remove-Vowels-from-a-String.py │ ├── 118-Pascal's-Triangle.py │ ├── 1207-Unique-Number-of-Occurrences.py │ ├── 121-Best-Time-to-Buy-and-Sell-Stock.py │ ├── 125-Valid-Palindrome.py │ ├── 1275-Find-Winner-on-a-Tic-Tac-Toe-Game.py │ ├── 1290-Convert-Binary-Number-in-a-Linked-List-to-Integer.py │ ├── 1295-Find-Numbers-with-Even-Number-of-Digits.py │ ├── 1299-Replace-Elements-with-Greatest-Element-on-Right-Side.py │ ├── 13-Roman-to-Integer.py │ ├── 1332-Remove-Palindromic-Subsequences.py │ ├── 1346-Check-If-N-and-Its-Double-Exist.py │ ├── 1365-How-Many-Numbers-Are-Smaller-Than-the-Current-Number.py │ ├── 1370-Increasing-Decreasing-String.py │ ├── 14-Longest-Common-Prefix.py │ ├── 1413-Minimum-Value-to-Get-Positive-Step-by-Step-Sum.py │ ├── 1431-Kids-With-the-Greatest-Number-of-Candies.py │ ├── 144-Binary-Tree-Preorder-Traversal.py │ ├── 145-Binary-Tree-Postorder-Traversal.py │ ├── 1470-Shuffle-the-Array.py │ ├── 1480-Running-Sum-of-1d-Array.py │ ├── 1512-Number-of-Good-Pairs.py │ ├── 1523-Count-Odd-Numbers-in-an-Interval-Range.py │ ├── 1528-Shuffle-String.py │ ├── 1603-Design-Parking-System.py │ ├── 1629-Slowest-Key.py │ ├── 167-Two-Sum-II-Input-Array-Is-Sorted.py │ ├── 1672-Richest-Customer-Wealth.py │ ├── 169-Majority-Element.py │ ├── 1710-Maximum-Units-on-a-Truck.py │ ├── 1768-Merge-Strings-Alternately.py │ ├── 1812-Determine-Color-of-a-Chessboard-Square.py │ ├── 1920-Build-Array-from-Permutation.py │ ├── 1929-Concatenation-of-Array.py │ ├── 20-Valid-Parentheses.py │ ├── 2011-Final-Value-of-Variable-After-Performing-Operations.py │ ├── 206-Reverse-Linked-List.py │ ├── 2068-Check-Whether-Two-Strings-are-Almost-Equivalent.py │ ├── 21-Merge-Two-Sorted-Lists.py │ ├── 2114-Maximum-Number-of-Words-Found-in-Sentences.py │ ├── 217-Contains-Duplicate.py │ ├── 2206-Divide-Array-Into-Equal-Pairs.py │ ├── 2235-Add-Two-Integers.py │ ├── 2248-Intersection-of-Multiple-Arrays.py │ ├── 225-Implement-Stack-using-Queues.py │ ├── 2283-Check-if-Number-Has-Equal-Digit-Count-and-Digit-Value.py │ ├── 234-Palindrome-Linked-List.py │ ├── 242-Valid-Anagram.py │ ├── 26-Remove-Duplicates-from-Sorted-Array.py │ ├── 2620-Counter.js │ ├── 2665-Counter-II.js │ ├── 2667-Create-Hello-World-Function.js │ ├── 27-Remove-Element.py │ ├── 2704-To-Be-Or-Not-To-Be.js │ ├── 278-First-Bad-Version.py │ ├── 283-Move-Zeros.py │ ├── 326-Power-of-Three.py │ ├── 338-Counting-Bits.py │ ├── 344-Reverse-String.py │ ├── 346-Moving-Average-from-Data-Stream.py │ ├── 349-Intersection-of-Two-Arrays.py │ ├── 35-Search-Insert-Position.py │ ├── 359-Logger-Rate-Limiter.py │ ├── 383-Ransom-Note.py │ ├── 387-First-Unique-Character-in-a-String.py │ ├── 408-Valid-Word-Abbreviation.py │ ├── 412-Fizz-Buzz.py │ ├── 414-Third-Maximum-Number.py │ ├── 448-Find-All-Numbers-Disappeared-in-an-Array.py │ ├── 459-Repeated-Substring-Pattern.py │ ├── 485-Max-Consecutive-Ones.py │ ├── 509-Fibonacci-Number.py │ ├── 53-Maximum-Subarray.py │ ├── 557-Reverse-Words-in-a-String-III.py │ ├── 595-Big-Countries.sql │ ├── 680-Valid-Palindrome-II.py │ ├── 70-Climbing-Stairs.py │ ├── 704-Binary.py │ ├── 706-Design-HashMap.py │ ├── 724-Find-Pivot-Index.py │ ├── 771-Jewels-and-Stones.py │ ├── 867-Transpose-Matrix.py │ ├── 88-Merge-Sorted-Array.py │ ├── 9-Palindrome-Number.py │ ├── 905-Sort-Array-By-Parity.py │ ├── 94-Binary-Tree-Inorder-Traversal.py │ ├── 941-Valid-Mountain-Array.py │ └── 977-Squares-of-a-Sorted-Array.py ├── Hard │ ├── 10-Regular-Expression-Matching.py │ └── 44-Wildcard-Matching.py └── Medium │ ├── 102-Binary-Tree-Level-Order-Traversal.py │ ├── 1249-Minimum-Remove-to-Make-Valid-Parentheses.py │ ├── 146-LRU-Cache.py │ ├── 151-Reverse-Words-in-a-String.py │ ├── 189-Rotate-Array.py │ ├── 2-Add-Two-Numbers.py │ ├── 200-Number-of-Islands.py │ ├── 3-Longest-Substring-Without-Repeating-Characters.py │ ├── 423-Reconstruct-Original-Digits-from-English.py │ ├── 487-Max-Consecutive-Ones-II.py │ ├── 498-Diagonal-Traverse.py │ ├── 5-Longest-Palindromic-Substring.py │ ├── 56-Merge-Intervals.py │ ├── 622-Design-Circular-Queue.py │ └── 811-Subdomain-Visit-Count.py ├── Practice Concepts ├── Data Structures │ ├── CircularQ.py │ ├── Queue.py │ ├── dequeue.py │ ├── hash-table.py │ ├── priority_q.py │ ├── singly-linked-list.py │ └── stacks.py ├── Dynamic Programming │ ├── fw.py │ ├── lcs.py │ └── rk.py ├── Graphs │ ├── adj-list.py │ ├── adj-mat.py │ ├── bfs.py │ ├── dfs.py │ └── scc.py ├── Greedy Algorithms │ ├── dijkstra.py │ ├── ffa.py │ ├── huffman.py │ ├── kruskal.py │ └── prim.py ├── Search │ ├── binary-search.py │ └── linear-search.py ├── Sorting │ ├── bubble-sort.py │ ├── bucket-sort.py │ ├── counting-sort.py │ ├── heap-sort.py │ ├── insertion-sort.py │ ├── merge-sort.py │ ├── quick-sort.py │ ├── radix-sort.py │ └── selection-sort.py └── Trees │ ├── balanced-binary-tree.py │ ├── binary-search-tree.py │ ├── binary-tree.py │ ├── complete-binary-tree.py │ ├── full-binary-tree.py │ ├── perfect-binary-tree.py │ └── tree-traverse.py ├── README.md ├── Resources ├── Animations │ ├── Bubble-sort.gif │ ├── CLL.png │ ├── DLL.png │ ├── Insertion-Sort.gif │ ├── Merge-Sort.gif │ ├── PUSH-POP.png │ ├── Selection-Sort.gif │ ├── binary.gif │ ├── bst.png │ ├── bucket.webp │ ├── cb1.png │ ├── cb2.png │ ├── cb3.png │ ├── cb4.png │ ├── cb5.png │ ├── counting-sort.gif │ ├── dgen.png │ ├── enq-dq.png │ ├── full-binary-tree.png │ ├── graph.png │ ├── h(x).png │ ├── heapsort.gif │ ├── in-order-traversal.gif │ ├── linear.gif │ ├── linked-list-complexity.png │ ├── linked-list.png │ ├── min-max-heap.png │ ├── node-edge.png │ ├── perfect-binary-tree.png │ ├── post-order-traversal.gif │ ├── pre-order-traversal.gif │ ├── quicksort.gif │ ├── radix-sort.gif │ ├── skew.png │ └── strongly-connected.png └── Books │ ├── Data Structure and Algorithmic Thinking with Python Data Structure and Algorithmic Puzzles.pdf │ ├── Data Structures and Algorithms Made Easy_ Data Structures and Algorithmic Puzzles.pdf │ ├── Grokking Algorithms.pdf │ └── Introduction to Algorithms, Third Edition.pdf └── extras ├── Arrays and Strings ├── LargestNumberAtLeastTwiceOthers.py ├── PivotIndex.py ├── PlusOne.py └── README.md ├── Basics ├── Big-O Notation.jpeg ├── Omega Notation.jpeg ├── README.md └── Theta Notation.jpeg ├── Binary Tree └── README.md ├── Graphs └── README.md ├── Recursion and Backtracking ├── HackerRank │ ├── PowerSum.py │ └── RecursiveDigitSum.py ├── LeetCode │ ├── MergeTwoSortedLists.py │ └── ReverseString.py └── README.md ├── Search Algorithms ├── BinaySearch.py └── SequentialSearch.py └── Sorting Algorithms ├── BubbleSort.py └── SelectionSort.py /Leetcode Problems/Easy/1-Two-Sum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. 3 | 4 | You may assume that each input would have exactly one solution, and you may not use the same element twice. 5 | 6 | You can return the answer in any order. 7 | ''' 8 | 9 | class Solution: 10 | def twoSum(self, nums: List[int], target: int) -> List[int]: 11 | result = {} 12 | for i in range(len(nums)): 13 | if(target - nums[i] in result): 14 | return [result[target - nums[i]], i] 15 | else: 16 | result[nums[i]] = i 17 | return [] -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1025-Divisor-Game.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Alice and Bob take turns playing a game, with Alice starting first. 3 | 4 | Initially, there is a number n on the chalkboard. On each player's turn, that player makes a move consisting of: 5 | 6 | Choosing any x with 0 < x < n and n % x == 0. 7 | Replacing the number n on the chalkboard with n - x. 8 | Also, if a player cannot make a move, they lose the game. 9 | 10 | Return true if and only if Alice wins the game, assuming both players play optimally. 11 | ''' 12 | 13 | class Solution: 14 | def divisorGame(self, n: int) -> bool: 15 | return n % 2 == 0 16 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/104-Maximum-Depth-of-Binary-Tree.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the root of a binary tree, return its maximum depth. 3 | 4 | A binary tree's maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 5 | ''' 6 | 7 | # Definition for a binary tree node. 8 | # class TreeNode: 9 | # def __init__(self, val=0, left=None, right=None): 10 | # self.val = val 11 | # self.left = left 12 | # self.right = right 13 | class Solution: 14 | def maxDepth(self, root: Optional[TreeNode]) -> int: 15 | 16 | # Recursion 17 | if root is None: 18 | return 0 19 | else: 20 | left_depth = self.maxDepth(root.left) 21 | right_depth = self.maxDepth(root.right) 22 | return max(left_depth, right_depth) + 1 23 | 24 | # Iteration 25 | ''' 26 | stack = [] 27 | if root is not None: 28 | stack.append((1, root)) 29 | depth = 0 30 | while stack != []: 31 | current_dep, root = stack.pop() 32 | if root is not None: 33 | depth = max(depth, current_dep) 34 | stack.append((current_dep + 1, root.left)) 35 | stack.append((current_dep + 1, root.right)) 36 | return depth 37 | ''' -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1051-Height-Checker.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def heightChecker(self, heights: List[int]) -> int: 3 | ans = 0 4 | expected = sorted(heights) 5 | 6 | for i in range(len(expected)): 7 | if expected[i] != heights[i]: 8 | ans += 1 9 | return ans -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1089-Duplicate-Zeros.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def duplicateZeros(self, arr: List[int]) -> None: 3 | """ 4 | Do not return anything, modify arr in-place instead. 5 | """ 6 | temp = [] 7 | 8 | for i in range(len(arr)): 9 | if(arr[i] == 0): 10 | temp.append(0) 11 | temp.append(0) 12 | else: 13 | temp.append(arr[i]) 14 | 15 | arr[i] = temp[i] -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1108-Defanging-an-IP-Address.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a valid (IPv4) IP address, return a defanged version of that IP address. 3 | 4 | A defanged IP address replaces every period "." with "[.]". 5 | ''' 6 | 7 | class Solution(object): 8 | def defangIPaddr(self, address): 9 | """ 10 | :type address: str 11 | :rtype: str 12 | """ 13 | addr = list(address) 14 | output = "" 15 | for i in range(len(addr)): 16 | if(addr[i] == '.'): 17 | addr[i] = '[.]' 18 | return output.join(addr) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1119-Remove-Vowels-from-a-String.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string s, remove the vowels 'a', 'e', 'i', 'o', and 'u' from it, and return the new string. 3 | ''' 4 | 5 | class Solution(object): 6 | def removeVowels(self, s): 7 | """ 8 | :type s: str 9 | :rtype: str 10 | """ 11 | final = "" 12 | 13 | for ch in s: 14 | if ch not in ('a', 'e', 'i', 'o', 'u'): 15 | final += ch 16 | 17 | return final -------------------------------------------------------------------------------- /Leetcode Problems/Easy/118-Pascal's-Triangle.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an integer numRows, return the first numRows of Pascal's triangle. 3 | 4 | In Pascal's triangle, each number is the sum of the two numbers directly above it as shown 5 | ''' 6 | 7 | class Solution: 8 | def generate(self, numRows: int) -> List[List[int]]: 9 | output = [] 10 | if numRows < 1: 11 | return output 12 | 13 | for i in range(numRows): 14 | output.append([]) 15 | for j in range(i + 1): 16 | if j == 0 or j == i: 17 | output[i].append(1) 18 | else: 19 | output[i].append(output[i - 1][j - 1] + output[i - 1][j]) 20 | return output -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1207-Unique-Number-of-Occurrences.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array of integers arr, return true if the number of occurrences of each value in the array is unique, or false otherwise. 3 | ''' 4 | 5 | class Solution: 6 | def uniqueOccurrences(self, arr: List[int]) -> bool: 7 | countDict = Counter(arr) 8 | numCount = set() 9 | for x in countDict.values(): 10 | if x in numCount: 11 | return False 12 | else: 13 | numCount.add(x) 14 | return True -------------------------------------------------------------------------------- /Leetcode Problems/Easy/121-Best-Time-to-Buy-and-Sell-Stock.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProfit(self, prices: List[int]) -> int: 3 | if len(prices) == 0: 4 | return 0 5 | maxProfit = 0 6 | minPrice = prices[0] 7 | for p in prices[1:]: 8 | if p < minPrice: 9 | minPrice = p 10 | elif maxProfit < p - minPrice: 11 | maxProfit = p - minPrice 12 | return maxProfit 13 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/125-Valid-Palindrome.py: -------------------------------------------------------------------------------- 1 | ''' 2 | A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers. 3 | 4 | Given a string s, return true if it is a palindrome, or false otherwise. 5 | ''' 6 | 7 | class Solution: 8 | def isPalindrome(self, s: str) -> bool: 9 | x = ''.join(e for e in s if e.isalnum()) 10 | x = x.lower() 11 | if(x == x[::-1]): 12 | return True 13 | else: 14 | return False 15 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1275-Find-Winner-on-a-Tic-Tac-Toe-Game.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Tic-tac-toe is played by two players A and B on a 3 x 3 grid. The rules of Tic-Tac-Toe are: 3 | 4 | Players take turns placing characters into empty squares ' '. 5 | The first player A always places 'X' characters, while the second player B always places 'O' characters. 6 | 'X' and 'O' characters are always placed into empty squares, never on filled ones. 7 | The game ends when there are three of the same (non-empty) character filling any row, column, or diagonal. 8 | The game also ends if all squares are non-empty. 9 | No more moves can be played if the game is over. 10 | Given a 2D integer array moves where moves[i] = [rowi, coli] indicates that the ith move will be played on grid[rowi][coli]. return the winner of the game if it exists (A or B). In case the game ends in a draw return "Draw". If there are still movements to play return "Pending". 11 | 12 | You can assume that moves is valid (i.e., it follows the rules of Tic-Tac-Toe), the grid is initially empty, and A will play first. 13 | 14 | ''' 15 | 16 | class Solution: 17 | def tictactoe(self, moves: List[List[int]]) -> str: 18 | winningMoves = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]] 19 | array = [] 20 | l1 = len(moves) 21 | l2 = len(winningMoves) 22 | for i in moves: 23 | array.append(3*i[0] + i[1]) 24 | A = array[0:l1:2] 25 | B = array[1:l1:2] 26 | B.sort() 27 | A.sort() 28 | for winningMoves in winningMoves: 29 | if all([i in A for i in winningMoves]): 30 | return 'A' 31 | elif all([i in B for i in winningMoves]): 32 | return 'B' 33 | if l1 == 9: 34 | return "Draw" 35 | else: 36 | return "Pending" 37 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1290-Convert-Binary-Number-in-a-Linked-List-to-Integer.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given head which is a reference node to a singly-linked list. The value of each node in the linked list is either 0 or 1. The linked list holds the binary representation of a number. 3 | 4 | Return the decimal value of the number in the linked list. 5 | 6 | The most significant bit is at the head of the linked list. 7 | ''' 8 | 9 | # Definition for singly-linked list. 10 | # class ListNode: 11 | # def __init__(self, val=0, next=None): 12 | # self.val = val 13 | # self.next = next 14 | class Solution: 15 | def getDecimalValue(self, head: ListNode) -> int: 16 | result = 0 17 | 18 | while head: 19 | result = result * 2 + head.val 20 | head = head.next 21 | 22 | return result -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1295-Find-Numbers-with-Even-Number-of-Digits.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findNumbers(self, nums: List[int]) -> int: 3 | temp = [] 4 | count = 0 5 | 6 | for num in nums: 7 | temp = [int(i) for i in str(num)] 8 | if(len(temp) % 2 == 0): 9 | count += 1 10 | temp.clear() 11 | 12 | return count -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1299-Replace-Elements-with-Greatest-Element-on-Right-Side.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def replaceElements(self, arr: List[int]) -> List[int]: 3 | for i in range(len(arr)): 4 | nextMax = max(arr[i:len(arr)]) 5 | arr[i] = nextMax 6 | del arr[0] 7 | arr.append(-1) 8 | return arr -------------------------------------------------------------------------------- /Leetcode Problems/Easy/13-Roman-to-Integer.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a roman numeral, convert it to an integer. 3 | ''' 4 | 5 | class Solution: 6 | def romanToInt(self, s: str) -> int: 7 | 8 | # Map the symbols to the integer values 9 | symbolMap = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} 10 | 11 | strLen = len(s) 12 | 13 | result = symbolMap[s[strLen - 1]] 14 | 15 | # Move from right to left 16 | for i in range(strLen - 2, -1, -1): 17 | 18 | if(symbolMap[s[i]] >= symbolMap[s[i + 1]]): 19 | result += symbolMap[s[i]] 20 | else: 21 | result -= symbolMap[s[i]] 22 | 23 | return result -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1332-Remove-Palindromic-Subsequences.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given a string s consisting only of letters 'a' and 'b'. In a single step you can remove one palindromic subsequence from s. 3 | 4 | Return the minimum number of steps to make the given string empty. 5 | 6 | A string is a subsequence of a given string if it is generated by deleting some characters of a given string without changing its order. Note that a subsequence does not necessarily need to be contiguous. 7 | 8 | A string is called palindrome if is one that reads the same backward as well as forward. 9 | ''' 10 | 11 | class Solution: 12 | def removePalindromeSub(self, s: str) -> int: 13 | if(s == ""): 14 | return 0 15 | elif(s == s[::-1]): 16 | return 1 17 | else: 18 | return 2 -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1346-Check-If-N-and-Its-Double-Exist.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def checkIfExist(self, arr: List[int]) -> bool: 3 | for i in range(len(arr)): 4 | for j in (arr[:i] + arr[i+1:]): 5 | if(2*arr[i] == j): 6 | return True 7 | return False -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1365-How-Many-Numbers-Are-Smaller-Than-the-Current-Number.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the array nums, for each nums[i] find out how many numbers in the array are smaller than it. That is, for each nums[i] you have to count the number of valid j's such that j != i and nums[j] < nums[i]. 3 | 4 | Return the answer in an array. 5 | ''' 6 | 7 | class Solution(object): 8 | def smallerNumbersThanCurrent(self, nums): 9 | """ 10 | :type nums: List[int] 11 | :rtype: List[int] 12 | """ 13 | output = [] 14 | checkLessNum = 0 15 | for i in range(len(nums)): 16 | for j in range(len(nums)): 17 | if(nums[i] - nums[j] > 0): 18 | checkLessNum += 1 19 | output.append(checkLessNum) 20 | checkLessNum = 0 21 | return output 22 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1370-Increasing-Decreasing-String.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given a string s. Reorder the string using the following algorithm: 3 | 4 | Pick the smallest character from s and append it to the result. 5 | Pick the smallest character from s which is greater than the last appended character to the result and append it. 6 | Repeat step 2 until you cannot pick more characters. 7 | Pick the largest character from s and append it to the result. 8 | Pick the largest character from s which is smaller than the last appended character to the result and append it. 9 | Repeat step 5 until you cannot pick more characters. 10 | Repeat the steps from 1 to 6 until you pick all characters from s. 11 | In each step, If the smallest or the largest character appears more than once you can choose any occurrence and append it to the result. 12 | 13 | Return the result string after sorting s with this algorithm. 14 | ''' 15 | class Solution: 16 | def sortString(self, s: str) -> str: 17 | s = list(s) 18 | result = [] 19 | while s: 20 | temp = list(set(s)) 21 | temp.sort(key=lambda c: ord(c)) 22 | for i in temp: 23 | result.append(i) 24 | s.remove(i) 25 | temp = list(set(s)) 26 | temp.sort(key=lambda c: ord(c), reverse=True) 27 | for i in temp: 28 | result.append(i) 29 | s.remove(i) 30 | return ''.join(result) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/14-Longest-Common-Prefix.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Write a function to find the longest common prefix string amongst an array of strings. 3 | 4 | If there is no common prefix, return an empty string "". 5 | ''' 6 | 7 | class Solution: 8 | def longestCommonPrefix(self, strs: List[str]) -> str: 9 | 10 | output = "" 11 | 12 | if strs is None or len(strs) == 0: 13 | return output 14 | 15 | minLength = len(strs[0]) 16 | for i in range(1, len(strs)): 17 | minLength = min(minLength, len(strs[i])) 18 | 19 | for i in range(0, minLength): 20 | # Get the current character from the first string 21 | current = strs[0][i] 22 | 23 | # Check if this character is found in all other strings or not 24 | for j in range(0, len(strs)): 25 | if strs[j][i] != current: 26 | return output 27 | output += current 28 | return output 29 | 30 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1413-Minimum-Value-to-Get-Positive-Step-by-Step-Sum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array of integers nums, you start with an initial positive value startValue. 3 | 4 | In each iteration, you calculate the step by step sum of startValue plus elements in nums (from left to right). 5 | 6 | Return the minimum positive value of startValue such that the step by step sum is never less than 1. 7 | 8 | ''' 9 | 10 | class Solution(object): 11 | def minStartValue(self, nums): 12 | """ 13 | :type nums: List[int] 14 | :rtype: int 15 | """ 16 | min_n=0 17 | sum_n=0 18 | for i in nums: 19 | sum_n+=i 20 | min_n=min(sum_n,min_n) 21 | return 1-min_njb -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1431-Kids-With-the-Greatest-Number-of-Candies.py: -------------------------------------------------------------------------------- 1 | ''' 2 | There are n kids with candies. You are given an integer array candies, where each candies[i] represents the number of candies the ith kid has, and an integer extraCandies, denoting the number of extra candies that you have. 3 | 4 | Return a boolean array result of length n, where result[i] is true if, after giving the ith kid all the extraCandies, they will have the greatest number of candies among all the kids, or false otherwise. 5 | 6 | Note that multiple kids can have the greatest number of candies. 7 | ''' 8 | 9 | class Solution: 10 | def kidsWithCandies(self, candies: List[int], extraCandies: int) -> List[bool]: 11 | output = [] 12 | for i in range(len(candies)): 13 | if(candies[i]+extraCandies >= max(candies)): 14 | output.append(True) 15 | else: 16 | output.append(False) 17 | return output -------------------------------------------------------------------------------- /Leetcode Problems/Easy/144-Binary-Tree-Preorder-Traversal.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the root of a binary tree, return the preorder traversal of its nodes' values. 3 | ''' 4 | 5 | # Definition for a binary tree node. 6 | # class TreeNode: 7 | # def __init__(self, val=0, left=None, right=None): 8 | # self.val = val 9 | # self.left = left 10 | # self.right = right 11 | class Solution: 12 | def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]: 13 | # One liner - recursive 14 | # return [root.val] + self.preorderTraversal(root.left) + self.preorderTraversal(root.right) if root else [] 15 | 16 | # Iteration Method 17 | if root is None: 18 | return [] 19 | stack, output = [root, ], [] 20 | 21 | while stack: 22 | root = stack.pop() 23 | if root is not None: 24 | output.append(root.val) 25 | if root.right is not None: 26 | stack.append(root.right) 27 | if root.left is not None: 28 | stack.append(root.left) 29 | return output -------------------------------------------------------------------------------- /Leetcode Problems/Easy/145-Binary-Tree-Postorder-Traversal.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the root of a binary tree, return the postorder traversal of its nodes' values. 3 | ''' 4 | 5 | # Definition for a binary tree node. 6 | # class TreeNode: 7 | # def __init__(self, val=0, left=None, right=None): 8 | # self.val = val 9 | # self.left = left 10 | # self.right = right 11 | class Solution: 12 | def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]: 13 | # One Liner 14 | return self.postorderTraversal(root.left) + self. postorderTraversal(root.right) + [root.val] if root else [] 15 | 16 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1470-Shuffle-the-Array.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the array nums consisting of 2n elements in the form [x1,x2,...,xn,y1,y2,...,yn]. 3 | 4 | Return the array in the form [x1,y1,x2,y2,...,xn,yn]. 5 | ''' 6 | 7 | class Solution: 8 | def shuffle(self, nums: List[int], n: int) -> List[int]: 9 | final = [] 10 | for i in range(n): 11 | final.append(nums[i]) 12 | final.append(nums[n+i]) 13 | return final -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1480-Running-Sum-of-1d-Array.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array nums. We define a running sum of an array as runningSum[i] = sum(nums[0]…nums[i]). 3 | 4 | Return the running sum of nums. 5 | ''' 6 | class Solution: 7 | def runningSum(self, nums: List[int]) -> List[int]: 8 | ans = [] 9 | tmp = 0 10 | for i in range(len(nums)): 11 | tmp += nums[i] 12 | ans.append(tmp) 13 | 14 | return ans -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1512-Number-of-Good-Pairs.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numIdenticalPairs(self, nums: List[int]) -> int: 3 | count = 0 4 | checked = defaultdict(list) 5 | 6 | for i, num in enumerate(nums): 7 | if num in checked: 8 | count += len(checked[num]) 9 | checked[num].append(i) 10 | 11 | return count -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1523-Count-Odd-Numbers-in-an-Interval-Range.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given two non-negative integers low and high. Return the count of odd numbers between low and high (inclusive). 3 | ''' 4 | 5 | class Solution: 6 | def countOdds(self, low: int, high: int) -> int: 7 | if(low%2 == 0 and high%2 == 0): 8 | return high//2 - low//2 9 | else: 10 | return (high - low)//2 + 1 -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1528-Shuffle-String.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given a string s and an integer array indices of the same length. The string s will be shuffled such that the character at the ith position moves to indices[i] in the shuffled string. 3 | 4 | Return the shuffled string. 5 | ''' 6 | class Solution(object): 7 | def restoreString(self, s, indices): 8 | """ 9 | :type s: str 10 | :type indices: List[int] 11 | :rtype: str 12 | """ 13 | 14 | result = list(s) 15 | for i in range(len(indices)): 16 | result[indices[i]] = s[i] 17 | return "".join(result) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1603-Design-Parking-System.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Design a parking system for a parking lot. The parking lot has three kinds of parking spaces: big, medium, and small, with a fixed number of slots for each size. 3 | 4 | Implement the ParkingSystem class: 5 | 6 | ParkingSystem(int big, int medium, int small) Initializes object of the ParkingSystem class. The number of slots for each parking space are given as part of the constructor. 7 | bool addCar(int carType) Checks whether there is a parking space of carType for the car that wants to get into the parking lot. carType can be of three kinds: big, medium, or small, which are represented by 1, 2, and 3 respectively. A car can only park in a parking space of its carType. If there is no space available, return false, else park the car in that size space and return true. 8 | ''' 9 | 10 | class ParkingSystem: 11 | 12 | def __init__(self, big: int, medium: int, small: int): 13 | self.space = {1: big, 2: medium, 3: small} 14 | 15 | def addCar(self, carType: int) -> bool: 16 | if(self.space[carType] == 0): 17 | return False 18 | else: 19 | self.space[carType] -= 1 20 | return True 21 | 22 | 23 | # Your ParkingSystem object will be instantiated and called as such: 24 | # obj = ParkingSystem(big, medium, small) 25 | # param_1 = obj.addCar(carType) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1629-Slowest-Key.py: -------------------------------------------------------------------------------- 1 | ''' 2 | A newly designed keypad was tested, where a tester pressed a sequence of n keys, one at a time. 3 | 4 | You are given a string keysPressed of length n, where keysPressed[i] was the ith key pressed in the testing sequence, and a sorted list releaseTimes, where releaseTimes[i] was the time the ith key was released. Both arrays are 0-indexed. The 0th key was pressed at the time 0, and every subsequent key was pressed at the exact time the previous key was released. 5 | 6 | The tester wants to know the key of the keypress that had the longest duration. The ith keypress had a duration of releaseTimes[i] - releaseTimes[i - 1], and the 0th keypress had a duration of releaseTimes[0]. 7 | 8 | Note that the same key could have been pressed multiple times during the test, and these multiple presses of the same key may not have had the same duration. 9 | 10 | Return the key of the keypress that had the longest duration. If there are multiple such keypresses, return the lexicographically largest key of the keypresses. 11 | ''' 12 | 13 | class Solution: 14 | def slowestKey(self, releaseTimes: List[int], keysPressed: str) -> str: 15 | maxKeyPress = releaseTimes[0] 16 | outKey = '' 17 | keyDur = 0 18 | for i in range(len(keysPressed)): 19 | 20 | if(i == 0): 21 | outKey = keysPressed[0] 22 | continue 23 | 24 | keyDur = releaseTimes[i] - releaseTimes[i - 1] 25 | if(keyDur > maxKeyPress): 26 | maxKeyPress = keyDur 27 | outKey = keysPressed[i] 28 | 29 | if(keyDur == maxKeyPress): 30 | if(keysPressed[i] > outKey): 31 | outKey = keysPressed[i] 32 | 33 | return outKey -------------------------------------------------------------------------------- /Leetcode Problems/Easy/167-Two-Sum-II-Input-Array-Is-Sorted.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def twoSum(self, numbers: List[int], target: int) -> List[int]: 3 | start = 0 4 | end = len(numbers) - 1 5 | 6 | while start <= end: 7 | summation = numbers[start] + numbers[end] 8 | 9 | if(summation == target): 10 | return [start + 1, end + 1] 11 | elif(summation < target): 12 | start += 1 13 | else: 14 | end -= 1 15 | 16 | return [-1, -1] -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1672-Richest-Customer-Wealth.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given an m x n integer grid accounts where accounts[i][j] is the amount of money the i​​​​​​​​​​​th​​​​ customer has in the j​​​​​​​​​​​th​​​​ bank. Return the wealth that the richest customer has. 3 | 4 | A customer's wealth is the amount of money they have in all their bank accounts. The richest customer is the customer that has the maximum wealth. 5 | ''' 6 | 7 | class Solution: 8 | def maximumWealth(self, accounts: List[List[int]]) -> int: 9 | current, maxW = 0, 0 10 | for account in accounts: 11 | for i in account: 12 | current += i 13 | maxW = max(maxW, current) 14 | current = 0 15 | return maxW -------------------------------------------------------------------------------- /Leetcode Problems/Easy/169-Majority-Element.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array nums of size n, return the majority element. 3 | 4 | The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array. 5 | ''' 6 | class Solution: 7 | def majorityElement(self, nums: List[int]) -> int: 8 | counter = Counter(nums) 9 | for key in counter: 10 | if counter[key] > len(nums)//2: 11 | return key -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1710-Maximum-Units-on-a-Truck.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are assigned to put some amount of boxes onto one truck. You are given a 2D array boxTypes, where boxTypes[i] = [numberOfBoxesi, numberOfUnitsPerBoxi]: 3 | 4 | numberOfBoxesi is the number of boxes of type i. 5 | numberOfUnitsPerBoxi is the number of units in each box of the type i. 6 | You are also given an integer truckSize, which is the maximum number of boxes that can be put on the truck. You can choose any boxes to put on the truck as long as the number of boxes does not exceed truckSize. 7 | 8 | Return the maximum total number of units that can be put on the truck. 9 | ''' 10 | 11 | class Solution: 12 | def maximumUnits(self, boxTypes: List[List[int]], truckSize: int) -> int: 13 | boxTypes.sort(key=lambda x: x[1], reverse = True) 14 | boxCount = 0 15 | output = 0 16 | for i in range(len(boxTypes)): 17 | if(boxCount + boxTypes[i][0] < truckSize): 18 | output += (boxTypes[i][0] * boxTypes[i][1]) 19 | boxCount += boxTypes[i][0] 20 | else: 21 | totalToBeUsed = truckSize - boxCount 22 | output += (totalToBeUsed * boxTypes[i][1]) 23 | break 24 | return output -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1768-Merge-Strings-Alternately.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given two strings word1 and word2. Merge the strings by adding letters in alternating order, starting with word1. If a string is longer than the other, append the additional letters onto the end of the merged string. 3 | 4 | Return the merged string. 5 | 6 | Example 1: 7 | 8 | Input: word1 = "abc", word2 = "pqr" 9 | Output: "apbqcr" 10 | Explanation: The merged string will be merged as so: 11 | word1: a b c 12 | word2: p q r 13 | merged: a p b q c r 14 | Example 2: 15 | 16 | Input: word1 = "ab", word2 = "pqrs" 17 | Output: "apbqrs" 18 | Explanation: Notice that as word2 is longer, "rs" is appended to the end. 19 | word1: a b 20 | word2: p q r s 21 | merged: a p b q r s 22 | Example 3: 23 | 24 | Input: word1 = "abcd", word2 = "pq" 25 | Output: "apbqcd" 26 | Explanation: Notice that as word1 is longer, "cd" is appended to the end. 27 | word1: a b c d 28 | word2: p q 29 | merged: a p b q c d 30 | 31 | 32 | Constraints: 33 | 34 | 1 <= word1.length, word2.length <= 100 35 | word1 and word2 consist of lowercase English letters. 36 | 37 | ''' 38 | 39 | class Solution: 40 | def mergeAlternately(self, word1: str, word2: str) -> str: 41 | merged_list = [] 42 | 43 | min_len = min(len(word1), len(word2)) 44 | 45 | for i in range(min_len): 46 | merged_list.append(word1[i]) 47 | merged_list.append(word2[i]) 48 | 49 | merged_list.append(word1[min_len:]) 50 | merged_list.append(word2[min_len:]) 51 | 52 | return ''.join(merged_list) 53 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1812-Determine-Color-of-a-Chessboard-Square.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given coordinates, a string that represents the coordinates of a square of the chessboard. 3 | Return true if the square is white, and false if the square is black. 4 | The coordinate will always represent a valid chessboard square. The coordinate will always have the letter first, and the number second. 5 | ''' 6 | 7 | class Solution: 8 | def squareIsWhite(self, coordinates: str) -> bool: 9 | ''' 10 | - Black: Odd numbers for a,c,e,g; Even numbers for b,d,f,h - FALSE 11 | - Else TRUE 12 | ''' 13 | l1 = ['a', 'c', 'e', 'g'] 14 | l2 = ['b', 'd', 'f', 'h'] 15 | 16 | if(coordinates[0] in l1): 17 | if(int(coordinates[1]) % 2 == 0): 18 | return True 19 | else: 20 | return False 21 | else: 22 | if(int(coordinates[1]) % 2 == 0): 23 | return False 24 | else: 25 | return True 26 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1920-Build-Array-from-Permutation.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a zero-based permutation nums (0-indexed), build an array ans of the same length where ans[i] = nums[nums[i]] for each 0 <= i < nums.length and return it. 3 | 4 | A zero-based permutation nums is an array of distinct integers from 0 to nums.length - 1 (inclusive). 5 | ''' 6 | class Solution: 7 | def buildArray(self, nums: List[int]) -> List[int]: 8 | ans = [] 9 | 10 | for i in range(len(nums)): 11 | ans.append(nums[nums[i]]) 12 | 13 | return ans -------------------------------------------------------------------------------- /Leetcode Problems/Easy/1929-Concatenation-of-Array.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an integer array nums of length n, you want to create an array ans of length 2n where ans[i] == nums[i] and ans[i + n] == nums[i] for 0 <= i < n (0-indexed). 3 | 4 | Specifically, ans is the concatenation of two nums arrays. 5 | 6 | Return the array ans. 7 | 8 | ''' 9 | 10 | class Solution: 11 | def getConcatenation(self, nums: List[int]) -> List[int]: 12 | return (nums + nums) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/20-Valid-Parentheses.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. 3 | 4 | An input string is valid if: 5 | 6 | Open brackets must be closed by the same type of brackets. 7 | Open brackets must be closed in the correct order. 8 | Every close bracket has a corresponding open bracket of the same type. 9 | ''' 10 | 11 | class Solution: 12 | def isValid(self, s: str) -> bool: 13 | if len(s) % 2 != 0: 14 | return False 15 | dict = {'(' : ')', '[' : ']', '{' : '}'} 16 | stack = [] 17 | 18 | for i in s: 19 | if i in dict.keys(): 20 | stack.append(i) 21 | else: 22 | if stack == []: 23 | return False 24 | a = stack.pop() 25 | if i != dict[a]: 26 | return False 27 | 28 | return stack == [] -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2011-Final-Value-of-Variable-After-Performing-Operations.py: -------------------------------------------------------------------------------- 1 | ''' 2 | There is a programming language with only four operations and one variable X: 3 | 4 | ++X and X++ increments the value of the variable X by 1. 5 | --X and X-- decrements the value of the variable X by 1. 6 | Initially, the value of X is 0. 7 | 8 | Given an array of strings operations containing a list of operations, return the final value of X after performing all the operations. 9 | ''' 10 | 11 | class Solution: 12 | def finalValueAfterOperations(self, operations: List[str]) -> int: 13 | ans = 0 14 | for operation in operations: 15 | if(operation == "++X" or operation == "X++"): 16 | ans += 1 17 | else: 18 | ans -= 1 19 | return ans -------------------------------------------------------------------------------- /Leetcode Problems/Easy/206-Reverse-Linked-List.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the head of a singly linked list, reverse the list, and return the reversed list. 3 | ''' 4 | 5 | # Definition for singly-linked list. 6 | # class ListNode: 7 | # def __init__(self, val=0, next=None): 8 | # self.val = val 9 | # self.next = next 10 | class Solution: 11 | def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: 12 | next = None 13 | while head: 14 | head.next, head, next = next, head.next, head 15 | return next -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2068-Check-Whether-Two-Strings-are-Almost-Equivalent.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Two strings word1 and word2 are considered almost equivalent if the differences between the frequencies of each letter from 'a' to 'z' between word1 and word2 is at most 3. 3 | 4 | Given two strings word1 and word2, each of length n, return true if word1 and word2 are almost equivalent, or false otherwise. 5 | 6 | The frequency of a letter x is the number of times it occurs in the string. 7 | ''' 8 | 9 | class Solution: 10 | def checkAlmostEquivalent(self, word1: str, word2: str) -> bool: 11 | c1, c2 = Counter(word1), Counter(word2) 12 | values = ((c1-c2)|(c2-c1)).values() 13 | return max(values, default=0) < 4 14 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/21-Merge-Two-Sorted-Lists.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given the heads of two sorted linked lists list1 and list2. 3 | 4 | Merge the two lists in a one sorted list. The list should be made by splicing together the nodes of the first two lists. 5 | 6 | Return the head of the merged linked list. 7 | ''' 8 | 9 | # Definition for singly-linked list. 10 | # class ListNode: 11 | # def __init__(self, val=0, next=None): 12 | # self.val = val 13 | # self.next = next 14 | class Solution: 15 | def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: 16 | 17 | if list1 is None: 18 | return list2 19 | if list2 is None: 20 | return list1 21 | 22 | if(list1.val < list2.val): 23 | tem = head = ListNode(list1.val) 24 | list1 = list1.next 25 | else: 26 | tem = head = ListNode(list2.val) 27 | list2 = list2.next 28 | 29 | while list1 is not None and list2 is not None: 30 | if(list1.val < list2.val): 31 | tem.next = ListNode(list1.val) 32 | list1 = list1.next 33 | else: 34 | tem.next = ListNode(list2.val) 35 | list2 = list2.next 36 | tem = tem.next 37 | 38 | while list1 is not None: 39 | tem.next = ListNode(list1.val) 40 | list1 = list1.next 41 | tem = tem.next 42 | 43 | while list2 is not None: 44 | tem.next = ListNode(list2.val) 45 | list2 = list2.next 46 | tem = tem.next 47 | 48 | return head 49 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2114-Maximum-Number-of-Words-Found-in-Sentences.py: -------------------------------------------------------------------------------- 1 | ''' 2 | A sentence is a list of words that are separated by a single space with no leading or trailing spaces. 3 | 4 | You are given an array of strings sentences, where each sentences[i] represents a single sentence. 5 | 6 | Return the maximum number of words that appear in a single sentence. 7 | ''' 8 | 9 | class Solution: 10 | def mostWordsFound(self, sentences: List[str]) -> int: 11 | maxW = 0 12 | 13 | for sentence in sentences: 14 | temp = len(sentence.split()) 15 | 16 | if(temp > maxW): 17 | maxW = temp 18 | 19 | return maxW -------------------------------------------------------------------------------- /Leetcode Problems/Easy/217-Contains-Duplicate.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct. 3 | 4 | ''' 5 | 6 | class Solution: 7 | def containsDuplicate(self, nums: List[int]) -> bool: 8 | nums.sort() 9 | for i in range(len(nums) - 1): 10 | if(nums[i] == nums[i+1]): 11 | return True 12 | return False -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2206-Divide-Array-Into-Equal-Pairs.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given an integer array nums consisting of 2 * n integers. 3 | 4 | You need to divide nums into n pairs such that: 5 | 6 | Each element belongs to exactly one pair. 7 | The elements present in a pair are equal. 8 | Return true if nums can be divided into n pairs, otherwise return false. 9 | ''' 10 | 11 | class Solution: 12 | def divideArray(self, nums: List[int]) -> bool: 13 | for i in range(len(nums)): 14 | numOcc = nums.count(nums[i]) 15 | if(numOcc % 2 != 0): 16 | return False 17 | return True 18 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2235-Add-Two-Integers.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given two integers num1 and num2, return the sum of the two integers. 3 | ''' 4 | 5 | class Solution: 6 | def sum(self, num1: int, num2: int) -> int: 7 | return num1 + num2 -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2248-Intersection-of-Multiple-Arrays.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a 2D integer array nums where nums[i] is a non-empty array of distinct positive integers, return the list of integers that are present in each array of nums sorted in ascending order. 3 | ''' 4 | class Solution: 5 | def intersection(self, nums: List[List[int]]) -> List[int]: 6 | result = set(i for i in range(1001)) 7 | for num in nums: 8 | result &= set(num) 9 | return sorted(list(result)) 10 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/225-Implement-Stack-using-Queues.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 3 | Implement a last-in-first-out (LIFO) stack using only two queues. The implemented stack should support all the functions of a normal stack (push, top, pop, and empty). 4 | 5 | Implement the MyStack class: 6 | 7 | void push(int x) Pushes element x to the top of the stack. 8 | int pop() Removes the element on the top of the stack and returns it. 9 | int top() Returns the element on the top of the stack. 10 | boolean empty() Returns true if the stack is empty, false otherwise. 11 | Notes: 12 | 13 | You must use only standard operations of a queue, which means that only push to back, peek/pop from front, size and is empty operations are valid. 14 | Depending on your language, the queue may not be supported natively. You may simulate a queue using a list or deque (double-ended queue) as long as you use only a queue's standard operations. 15 | 16 | 17 | Example 1: 18 | 19 | Input 20 | ["MyStack", "push", "push", "top", "pop", "empty"] 21 | [[], [1], [2], [], [], []] 22 | Output 23 | [null, null, null, 2, 2, false] 24 | 25 | Explanation 26 | MyStack myStack = new MyStack(); 27 | myStack.push(1); 28 | myStack.push(2); 29 | myStack.top(); // return 2 30 | myStack.pop(); // return 2 31 | myStack.empty(); // return False 32 | 33 | 34 | Constraints: 35 | 36 | 1 <= x <= 9 37 | At most 100 calls will be made to push, pop, top, and empty. 38 | All the calls to pop and top are valid. 39 | 40 | ''' 41 | 42 | from collections import deque 43 | 44 | class MyStack: 45 | 46 | def __init__(self): 47 | self.stack = deque() 48 | 49 | 50 | def push(self, x: int) -> None: 51 | self.stack.append(x) 52 | 53 | 54 | def pop(self) -> int: 55 | if not self.empty(): 56 | return self.stack.pop() 57 | raise IndexError('pop from empty stack') 58 | 59 | 60 | def top(self) -> int: 61 | if not self.empty(): 62 | return self.stack[-1] 63 | raise IndexError('top from empty stack') 64 | 65 | 66 | def empty(self) -> bool: 67 | return len(self.stack) == 0 68 | 69 | 70 | 71 | # Your MyStack object will be instantiated and called as such: 72 | # obj = MyStack() 73 | # obj.push(x) 74 | # param_2 = obj.pop() 75 | # param_3 = obj.top() 76 | # param_4 = obj.empty() -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2283-Check-if-Number-Has-Equal-Digit-Count-and-Digit-Value.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given a 0-indexed string num of length n consisting of digits. 3 | 4 | Return true if for every index i in the range 0 <= i < n, the digit i occurs num[i] times in num, otherwise return false. 5 | ''' 6 | 7 | class Solution: 8 | def digitCount(self, num: str) -> bool: 9 | c = Counter(num) 10 | for i in range(len(num)): 11 | if c[str(i)] == int(num[i]): 12 | continue 13 | else: 14 | return False 15 | return True -------------------------------------------------------------------------------- /Leetcode Problems/Easy/234-Palindrome-Linked-List.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the head of a singly linked list, return true if it is a palindrome or false otherwise. 3 | ''' 4 | 5 | # Definition for singly-linked list. 6 | # class ListNode: 7 | # def __init__(self, val=0, next=None): 8 | # self.val = val 9 | # self.next = next 10 | class Solution: 11 | def isPalindrome(self, head: Optional[ListNode]) -> bool: 12 | output = [] 13 | current = head 14 | while current is not None: 15 | output.append(current.val) 16 | current = current.next 17 | return output == output[::-1] -------------------------------------------------------------------------------- /Leetcode Problems/Easy/242-Valid-Anagram.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given two strings s and t, return true if t is an anagram of s, and false otherwise. 3 | 4 | An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once. 5 | ''' 6 | 7 | class Solution: 8 | def isAnagram(self, s: str, t: str) -> bool: 9 | s = Counter(s) 10 | t = Counter(t) 11 | 12 | if(s == t): 13 | return True 14 | else: 15 | return False -------------------------------------------------------------------------------- /Leetcode Problems/Easy/26-Remove-Duplicates-from-Sorted-Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def removeDuplicates(self, nums: List[int]) -> int: 3 | if len(nums) == 0: 4 | return 0 5 | if len(nums) == 1: 6 | return 1 7 | 8 | j = 1 9 | for i in range(1, len(nums)): 10 | if nums[i] != nums[i-1]: 11 | nums[j] = nums[i] 12 | j += 1 13 | 14 | for delete_index in range(i, j-1, -1): 15 | del nums[delete_index] 16 | 17 | return j -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2620-Counter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Given an integer n, return a counter function. This counter function initially returns n and then returns 1 more than the previous value every subsequent time it is called (n, n + 1, n + 2, etc). 4 | * 5 | * Example 1: 6 | * 7 | * Input: 8 | * n = 10 9 | * ["call","call","call"] 10 | * Output: [10,11,12] 11 | * Explanation: 12 | * counter() = 10 // The first time counter() is called, it returns n. 13 | * counter() = 11 // Returns 1 more than the previous time. 14 | * counter() = 12 // Returns 1 more than the previous time. 15 | * 16 | * Example 2: 17 | * 18 | * Input: 19 | * n = -2 20 | * ["call","call","call","call","call"] 21 | * Output: [-2,-1,0,1,2] 22 | * Explanation: counter() initially returns -2. Then increases after each sebsequent call. 23 | * 24 | * Constraints: 25 | * 26 | * -1000 <= n <= 1000 27 | * 0 <= calls.length <= 1000 28 | * calls[i] === "call" 29 | * 30 | */ 31 | 32 | /** 33 | * @param {number} n 34 | * @return {Function} counter 35 | */ 36 | var createCounter = function (n) { 37 | let count = n; 38 | return function () { 39 | return count++; 40 | }; 41 | }; 42 | 43 | /** 44 | * const counter = createCounter(10) 45 | * counter() // 10 46 | * counter() // 11 47 | * counter() // 12 48 | */ 49 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2665-Counter-II.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Write a function createCounter. It should accept an initial integer init. 3 | * It should return an object with three functions. 4 | * 5 | * The three functions are: 6 | * 7 | * increment() increases the current value by 1 and then returns it. 8 | * decrement() reduces the current value by 1 and then returns it. 9 | * reset() sets the current value to init and then returns it. 10 | * 11 | * Example 1: 12 | * 13 | * Input: init = 5, calls = ["increment","reset","decrement"] 14 | * Output: [6,5,4] 15 | * Explanation: 16 | * const counter = createCounter(5); 17 | * counter.increment(); // 6 18 | * counter.reset(); // 5 19 | * counter.decrement(); // 4 20 | * 21 | * Example 2: 22 | * 23 | * Input: init = 0, calls = ["increment","increment","decrement","reset","reset"] 24 | * Output: [1,2,1,0,0] 25 | * Explanation: 26 | * const counter = createCounter(0); 27 | * counter.increment(); // 1 28 | * counter.increment(); // 2 29 | * counter.decrement(); // 1 30 | * counter.reset(); // 0 31 | * counter.reset(); // 0 32 | * 33 | */ 34 | 35 | /** 36 | * @param {integer} init 37 | * @return { increment: Function, decrement: Function, reset: Function } 38 | */ 39 | var createCounter = function (init) { 40 | let count = init; 41 | 42 | return { 43 | increment: function () { 44 | return ++count; 45 | }, 46 | decrement: function () { 47 | return --count; 48 | }, 49 | reset: function () { 50 | count = init; 51 | return count; 52 | }, 53 | }; 54 | }; 55 | 56 | /** 57 | * const counter = createCounter(5) 58 | * counter.increment(); // 6 59 | * counter.reset(); // 5 60 | * counter.decrement(); // 4 61 | */ 62 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2667-Create-Hello-World-Function.js: -------------------------------------------------------------------------------- 1 | // Write a function createHelloWorld. It should return a new function that always returns "Hello World". 2 | 3 | // Example 1: 4 | 5 | // Input: args = [] 6 | // Output: "Hello World" 7 | // Explanation: 8 | // const f = createHelloWorld(); 9 | // f(); // "Hello World" 10 | 11 | // The function returned by createHelloWorld should always return "Hello World". 12 | // Example 2: 13 | 14 | // Input: args = [{},null,42] 15 | // Output: "Hello World" 16 | // Explanation: 17 | // const f = createHelloWorld(); 18 | // f({}, null, 42); // "Hello World" 19 | 20 | // Any arguments could be passed to the function but it should still always return "Hello World". 21 | 22 | // Constraints: 23 | 24 | // 0 <= args.length <= 10 25 | 26 | /** 27 | * @return {Function} 28 | */ 29 | var createHelloWorld = function () { 30 | return function (...args) { 31 | return "Hello World"; 32 | }; 33 | }; 34 | 35 | // Test case 36 | const f = createHelloWorld(); 37 | f(); // "Hello World" 38 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/27-Remove-Element.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def removeElement(self, nums: List[int], val: int) -> int: 3 | count = 0 4 | 5 | for i in range(len(nums)): 6 | if(nums[i] != val): 7 | nums[count] = nums[i] 8 | count += 1 9 | 10 | return count -------------------------------------------------------------------------------- /Leetcode Problems/Easy/2704-To-Be-Or-Not-To-Be.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Write a function expect that helps developers test their code. It should take in any value val and return an object with the following two functions. 4 | * 5 | * toBe(val) accepts another value and returns true if the two values === each other. If they are not equal, it should throw an error "Not Equal". 6 | * notToBe(val) accepts another value and returns true if the two values !== each other. If they are equal, it should throw an error "Equal". 7 | * 8 | * Example 1: 9 | * 10 | * Input: func = () => expect(5).toBe(5) 11 | * Output: {"value": true} 12 | * Explanation: 5 === 5 so this expression returns true. 13 | * 14 | * Example 2: 15 | * 16 | * Input: func = () => expect(5).toBe(null) 17 | * Output: {"error": "Not Equal"} 18 | * Explanation: 5 !== null so this expression throw the error "Not Equal". 19 | * 20 | * Example 3: 21 | * 22 | * Input: func = () => expect(5).notToBe(null) 23 | * Output: {"value": true} 24 | * Explanation: 5 !== null so this expression returns true. 25 | * 26 | */ 27 | 28 | /** 29 | * @param {string} val 30 | * @return {Object} 31 | */ 32 | var expect = function (val) { 33 | return { 34 | toBe: function (val2) { 35 | if (val === val2) { 36 | return true; 37 | } else { 38 | throw new Error("Not Equal"); 39 | } 40 | }, 41 | notToBe: function (val2) { 42 | if (val !== val2) { 43 | return true; 44 | } else { 45 | throw new Error("Equal"); 46 | } 47 | }, 48 | }; 49 | }; 50 | 51 | /** 52 | * expect(5).toBe(5); // true 53 | * expect(5).notToBe(5); // throws "Equal" 54 | */ 55 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/278-First-Bad-Version.py: -------------------------------------------------------------------------------- 1 | # Use of Binary + Pivots 2 | # The isBadVersion API is already defined for you. 3 | # def isBadVersion(version: int) -> int: 4 | 5 | class Solution: 6 | def firstBadVersion(self, n: int) -> int: 7 | start = 1 8 | end = n 9 | 10 | while start <= end: 11 | middle = (start + end) // 2 12 | if(isBadVersion(middle)): 13 | result = middle 14 | end = middle - 1 15 | else: 16 | start = middle + 1 17 | 18 | return result -------------------------------------------------------------------------------- /Leetcode Problems/Easy/283-Move-Zeros.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def moveZeroes(self, nums: List[int]) -> None: 3 | """ 4 | Do not return anything, modify nums in-place instead. 5 | """ 6 | for i in range(len(nums))[::-1]: 7 | if(nums[i] == 0): 8 | nums.append(nums[i]) 9 | nums.pop(i) 10 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/326-Power-of-Three.py: -------------------------------------------------------------------------------- 1 | import math 2 | class Solution: 3 | def isPowerOfThree(self, n: int) -> bool: 4 | if n <= 0: 5 | return False 6 | ans = math.log(n, 3) 7 | return math.fabs(ans - round(ans)) < 0.0000000001 -------------------------------------------------------------------------------- /Leetcode Problems/Easy/338-Counting-Bits.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an integer n, return an array ans of length n + 1 such that for each i (0 <= i <= n), ans[i] is the number of 1's in the binary representation of i. 3 | ''' 4 | 5 | class Solution: 6 | def countBits(self, n: int) -> List[int]: 7 | ''' 8 | 1. Loop till n 9 | 2. Convert to binary 10 | 3. extract the value 11 | 4. Count number of 1s 12 | ''' 13 | output = [] 14 | temp = [] 15 | 16 | for i in range(n + 1): 17 | x = str(bin(i)) 18 | x = x[2:len(x)] 19 | temp.append(x) 20 | 21 | for i in range(len(temp)): 22 | y = 0 23 | for j in range(len(temp[i])): 24 | if temp[i][j] == '1': 25 | y += 1 26 | output.append(y) 27 | 28 | return output 29 | 30 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/344-Reverse-String.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reverseString(self, s: List[str]) -> None: 3 | """ 4 | Do not return anything, modify s in-place instead. 5 | """ 6 | start = 0 7 | end = len(s) -1 8 | 9 | while start < end: 10 | s[start], s[end] = s[end], s[start] 11 | start += 1 12 | end -= 1 -------------------------------------------------------------------------------- /Leetcode Problems/Easy/346-Moving-Average-from-Data-Stream.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window. 3 | 4 | Implement the MovingAverage class: 5 | 6 | MovingAverage(int size) Initializes the object with the size of the window size. 7 | double next(int val) Returns the moving average of the last size values of the stream. 8 | ''' 9 | 10 | class MovingAverage: 11 | 12 | def __init__(self, size: int): 13 | self.queue = [] 14 | self.movingAvg = 0 15 | self.size = size 16 | self.count = 0 17 | self.total = 0 18 | 19 | def next(self, val: int) -> float: 20 | if(len(self.queue) < self.size): 21 | self.queue.append(val) 22 | self.count += 1 23 | self.total += val 24 | self.movingAvg = (self.total) / self.count 25 | return self.movingAvg 26 | 27 | else: 28 | self.total -= self.queue[0] 29 | self.queue.pop(0) 30 | self.queue.append(val) 31 | self.total += val 32 | self.movingAvg = (self.total) / self.size 33 | return self.movingAvg 34 | 35 | 36 | 37 | 38 | # Your MovingAverage object will be instantiated and called as such: 39 | # obj = MovingAverage(size) 40 | # param_1 = obj.next(val) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/349-Intersection-of-Two-Arrays.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given two integer arrays nums1 and nums2, return an array of their intersection. Each element in the result must be unique and you may return the result in any order. 3 | ''' 4 | 5 | class Solution: 6 | def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]: 7 | nums1 = set(nums1) 8 | nums2 = set(nums2) 9 | output = [] 10 | 11 | if len(nums1) > len(nums2): 12 | for i in nums2: 13 | if i in nums1 and i not in output: 14 | output.append(i) 15 | else: 16 | for i in nums1: 17 | if i in nums2 and i not in output: 18 | output.append(i) 19 | return output 20 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/35-Search-Insert-Position.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def searchInsert(self, nums: List[int], target: int) -> int: 3 | start = 0 4 | end = len(nums) - 1 5 | 6 | while(start <= end): 7 | middle = (start + end) // 2 8 | 9 | if(nums[middle] == target): 10 | return middle 11 | elif(nums[middle] < target): 12 | start = middle + 1 13 | else: 14 | end = middle - 1 15 | 16 | return start -------------------------------------------------------------------------------- /Leetcode Problems/Easy/359-Logger-Rate-Limiter.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Design a logger system that receives a stream of messages along with their timestamps. Each unique message should only be printed at most every 10 seconds (i.e. a message printed at timestamp t will prevent other identical messages from being printed until timestamp t + 10). 3 | 4 | All messages will come in chronological order. Several messages may arrive at the same timestamp. 5 | 6 | Implement the Logger class: 7 | 8 | Logger() Initializes the logger object. 9 | bool shouldPrintMessage(int timestamp, string message) Returns true if the message should be printed in the given timestamp, otherwise returns false. 10 | ''' 11 | 12 | class Logger: 13 | 14 | def __init__(self): 15 | self.hash = {} 16 | 17 | def shouldPrintMessage(self, timestamp: int, message: str) -> bool: 18 | if(message not in self.hash or self.hash[message] + 10 <= timestamp): 19 | self.hash[message] = timestamp 20 | return True 21 | return False 22 | 23 | 24 | 25 | # Your Logger object will be instantiated and called as such: 26 | # obj = Logger() 27 | # param_1 = obj.shouldPrintMessage(timestamp,message) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/383-Ransom-Note.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given two strings ransomNote and magazine, return true if ransomNote can be constructed by using the letters from magazine and false otherwise. 3 | 4 | Each letter in magazine can only be used once in ransomNote. 5 | ''' 6 | 7 | class Solution: 8 | def canConstruct(self, ransomNote: str, magazine: str) -> bool: 9 | count1 = Counter(ransomNote) 10 | count2 = Counter(magazine) 11 | return all(count1[c] <= count2[c] for c in string.ascii_lowercase) 12 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/387-First-Unique-Character-in-a-String.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string s, find the first non-repeating character in it and return its index. If it does not exist, return -1. 3 | ''' 4 | 5 | class Solution: 6 | def firstUniqChar(self, s: str) -> int: 7 | sDic = Counter(s) 8 | for i in range(len(s)): 9 | if sDic[s[i]] == 1: 10 | return i 11 | return -1 12 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/408-Valid-Word-Abbreviation.py: -------------------------------------------------------------------------------- 1 | ''' 2 | A string can be abbreviated by replacing any number of non-adjacent, non-empty substrings with their lengths. The lengths should not have leading zeros. 3 | 4 | For example, a string such as "substitution" could be abbreviated as (but not limited to): 5 | 6 | "s10n" ("s ubstitutio n") 7 | "sub4u4" ("sub stit u tion") 8 | "12" ("substitution") 9 | "su3i1u2on" ("su bst i t u ti on") 10 | "substitution" (no substrings replaced) 11 | The following are not valid abbreviations: 12 | 13 | "s55n" ("s ubsti tutio n", the replaced substrings are adjacent) 14 | "s010n" (has leading zeros) 15 | "s0ubstitution" (replaces an empty substring) 16 | Given a string word and an abbreviation abbr, return whether the string matches the given abbreviation. 17 | 18 | A substring is a contiguous non-empty sequence of characters within a string. 19 | ''' 20 | 21 | class Solution: 22 | def validWordAbbreviation(self, word: str, abbr: str) -> bool: 23 | w = 0 24 | a = 0 25 | while w < len(word) and a < len(abbr): 26 | if abbr[a].isdigit() and abbr[a] != '0': 27 | e = a 28 | while e < len(abbr) and abbr[e].isdigit(): 29 | e += 1 30 | num = int(abbr[a:e]) 31 | a = e 32 | w += num 33 | else: 34 | if word[w] != abbr[a]: 35 | return False 36 | w += 1 37 | a += 1 38 | return w == len(word) and a == len(abbr) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/412-Fizz-Buzz.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an integer n, return a string array answer (1-indexed) where: 3 | 4 | answer[i] == "FizzBuzz" if i is divisible by 3 and 5. 5 | answer[i] == "Fizz" if i is divisible by 3. 6 | answer[i] == "Buzz" if i is divisible by 5. 7 | answer[i] == i (as a string) if none of the above conditions are true. 8 | ''' 9 | 10 | class Solution: 11 | def fizzBuzz(self, n: int) -> List[str]: 12 | answer = [] 13 | for i in range(1, n + 1): 14 | if((i % 3 == 0) and (i % 5 == 0)): 15 | answer.append("FizzBuzz") 16 | continue 17 | elif(i % 3 == 0): 18 | answer.append("Fizz") 19 | continue 20 | elif(i % 5 == 0): 21 | answer.append("Buzz") 22 | continue 23 | else: 24 | answer.append(str(i)) 25 | return answer 26 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/414-Third-Maximum-Number.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def thirdMax(self, nums: List[int]) -> int: 3 | nums = set(nums) 4 | maxV = max(nums) 5 | 6 | if(len(nums) < 3): 7 | return maxV 8 | 9 | nums.remove(maxV) 10 | nums.remove(max(nums)) 11 | return max(nums) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/448-Find-All-Numbers-Disappeared-in-an-Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findDisappearedNumbers(self, nums: List[int]) -> List[int]: 3 | length = len(nums) 4 | exp = set(range(1, length + 1)) 5 | 6 | for num in nums: 7 | if(num in exp): 8 | exp.remove(num) 9 | 10 | return exp -------------------------------------------------------------------------------- /Leetcode Problems/Easy/459-Repeated-Substring-Pattern.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string s, check if it can be constructed by taking a substring of it and appending multiple copies of the substring together. 3 | ''' 4 | 5 | class Solution: 6 | def repeatedSubstringPattern(self, s: str) -> bool: 7 | for i in range(1, len(s)//2+1): 8 | if len(s) % i == 0: 9 | if all(s[j]==s[j-i] for j in range(i, len(s))): 10 | return True 11 | 12 | return False -------------------------------------------------------------------------------- /Leetcode Problems/Easy/485-Max-Consecutive-Ones.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findMaxConsecutiveOnes(self, nums: List[int]) -> int: 3 | maxC = 0 4 | count = 0 5 | 6 | for i in range(len(nums)): 7 | if(nums[i] == 1): 8 | count += 1 9 | 10 | else: 11 | maxC = max(maxC, count) 12 | count = 0 13 | 14 | return max(maxC, count) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/509-Fibonacci-Number.py: -------------------------------------------------------------------------------- 1 | ''' 2 | The Fibonacci numbers, commonly denoted F(n) form a sequence, called the Fibonacci sequence, such that each number is the sum of the two preceding ones, starting from 0 and 1. That is, 3 | F(0) = 0, F(1) = 1 4 | F(n) = F(n - 1) + F(n - 2), for n > 1. 5 | Given n, calculate F(n). 6 | ''' 7 | 8 | class Solution: 9 | def fib(self, n: int) -> int: 10 | output = [0 for x in range(n + 1)] 11 | output[0] = 0 12 | if(n >= 1): 13 | output[1] = 1 14 | for x in range(2, n+1): 15 | output[x] = output[x - 1] + output[x - 2] 16 | return output[-1] 17 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/53-Maximum-Subarray.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. 3 | 4 | A subarray is a contiguous part of an array. 5 | ''' 6 | 7 | class Solution: 8 | def maxSubArray(self, nums: List[int]) -> int: 9 | ans, temp = nums[0], nums[0] 10 | for i in range(1, len(nums)): 11 | temp = max(temp + nums[i], nums[i]) 12 | if(temp > ans): 13 | ans = temp 14 | return ans -------------------------------------------------------------------------------- /Leetcode Problems/Easy/557-Reverse-Words-in-a-String-III.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reverseWords(self, s: str) -> str: 3 | sep = s.split() 4 | ans = [] 5 | for word in sep: 6 | ans.append(word[::-1]) 7 | 8 | return " ".join(ans) -------------------------------------------------------------------------------- /Leetcode Problems/Easy/595-Big-Countries.sql: -------------------------------------------------------------------------------- 1 | # Write your MySQL query statement below 2 | SELECT 3 | name, population, area 4 | FROM 5 | world 6 | WHERE 7 | area >= 3000000 OR population >= 25000000 8 | ; -------------------------------------------------------------------------------- /Leetcode Problems/Easy/680-Valid-Palindrome-II.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string s, return true if the s can be palindrome after deleting at most one character from it. 3 | ''' 4 | class Solution: 5 | def validPalindrome(self, s: str) -> bool: 6 | combList = [] 7 | for i in range(len(s)): 8 | temp = list(s) 9 | temp.pop(i) 10 | temp = ''.join(temp) 11 | combList.append(temp) 12 | 13 | for i in range(len(combList)): 14 | if(combList[i] == combList[i][::-1]): 15 | return True 16 | return False 17 | ''' 18 | i = 0 19 | j = len(s) - 1 20 | 21 | 22 | while i < j: 23 | if s[i] == s[j]: 24 | i += 1 25 | j -= 1 26 | else: 27 | return self.helper(s, i + 1, j) or self.helper(s, i, j - 1) 28 | 29 | 30 | return True 31 | 32 | def helper(self, s, left, right): 33 | 34 | while left < right: 35 | if s[left] == s[right]: 36 | left += 1 37 | right -= 1 38 | else: 39 | return False 40 | 41 | return True 42 | ''' -------------------------------------------------------------------------------- /Leetcode Problems/Easy/70-Climbing-Stairs.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are climbing a staircase. It takes n steps to reach the top. 3 | 4 | Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? 5 | ''' 6 | class Solution: 7 | def climbStairs(self, n: int) -> int: 8 | if(n <= 2): 9 | return n 10 | 11 | output = [0]*(n+1) 12 | output[1] = 1 13 | output[2] = 2 14 | for i in range(3,n+1): 15 | output[i] = output[i-1] + output[i-2] 16 | return output[n] -------------------------------------------------------------------------------- /Leetcode Problems/Easy/704-Binary.py: -------------------------------------------------------------------------------- 1 | ''' 2 | - List is ordered 3 | - Declare 2 pointers - start and end of the list 4 | - Iterate while start <= end 5 | - Get middle value 6 | - Compare values - if it is equal, return index 7 | - If middle < target - move start to middle + 1 8 | - If middle > target - move end to middle - 1 9 | - Else return -1 10 | 11 | Time - O(logn) 12 | ''' 13 | 14 | class Solution: 15 | def search(self, nums: List[int], target: int) -> int: 16 | start = 0 17 | end = len(nums) - 1 18 | 19 | while start <= end: 20 | middle = (start + end) // 2 21 | 22 | if(nums[middle] == target): 23 | return middle 24 | elif(nums[middle] < target): 25 | start = middle + 1 26 | elif(nums[middle] > target): 27 | end = middle - 1 28 | 29 | return -1 30 | 31 | 32 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/706-Design-HashMap.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Design a HashMap without using any built-in hash table libraries. 3 | 4 | Implement the MyHashMap class: 5 | 6 | MyHashMap() initializes the object with an empty map. 7 | void put(int key, int value) inserts a (key, value) pair into the HashMap. If the key already exists in the map, update the corresponding value. 8 | int get(int key) returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key. 9 | void remove(key) removes the key and its corresponding value if the map contains the mapping for the key. 10 | ''' 11 | 12 | class MyHashMap: 13 | 14 | def __init__(self): 15 | self.hashmap = [-1]*10000000 16 | 17 | def put(self, key: int, value: int) -> None: 18 | self.hashmap[key] = value 19 | 20 | def get(self, key: int) -> int: 21 | return self.hashmap[key] 22 | 23 | def remove(self, key: int) -> None: 24 | self.hashmap[key] = -1 25 | 26 | 27 | 28 | # Your MyHashMap object will be instantiated and called as such: 29 | # obj = MyHashMap() 30 | # obj.put(key,value) 31 | # param_2 = obj.get(key) 32 | # obj.remove(key) 33 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/724-Find-Pivot-Index.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array of integers nums, calculate the pivot index of this array. 3 | 4 | The pivot index is the index where the sum of all the numbers strictly to the left of the index is equal to the sum of all the numbers strictly to the index's right. 5 | 6 | If the index is on the left edge of the array, then the left sum is 0 because there are no elements to the left. This also applies to the right edge of the array. 7 | 8 | Return the leftmost pivot index. If no such index exists, return -1. 9 | ''' 10 | 11 | class Solution: 12 | def pivotIndex(self, nums: List[int]) -> int: 13 | summ = sum(nums) 14 | prefix = 0 15 | 16 | for i, num in enumerate(nums): 17 | if prefix == summ - prefix - num: 18 | return i 19 | prefix += num 20 | 21 | return -1 22 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/771-Jewels-and-Stones.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You're given strings jewels representing the types of stones that are jewels, and stones representing the stones you have. Each character in stones is a type of stone you have. You want to know how many of the stones you have are also jewels. 3 | 4 | Letters are case sensitive, so "a" is considered a different type of stone from "A". 5 | ''' 6 | 7 | class Solution(object): 8 | def numJewelsInStones(self, jewels, stones): 9 | """ 10 | :type jewels: str 11 | :type stones: str 12 | :rtype: int 13 | """ 14 | count = 0 15 | hash_set = set(jewels) 16 | for jewel in stones: 17 | if jewel in hash_set: 18 | count += 1 19 | return count -------------------------------------------------------------------------------- /Leetcode Problems/Easy/867-Transpose-Matrix.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a 2D integer array matrix, return the transpose of matrix. 3 | 4 | The transpose of a matrix is the matrix flipped over its main diagonal, switching the matrix's row and column indices. 5 | ''' 6 | 7 | class Solution: 8 | def transpose(self, matrix: List[List[int]]) -> List[List[int]]: 9 | output = [[0 for i in range(0, len(matrix))] for j in range(0, len(matrix[0]))] 10 | 11 | for i in range(0, len(matrix)): 12 | for j in range(0, len(matrix[0])): 13 | output[j][i] = matrix[i][j] 14 | 15 | return output 16 | -------------------------------------------------------------------------------- /Leetcode Problems/Easy/88-Merge-Sorted-Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: 3 | """ 4 | Do not return anything, modify nums1 in-place instead. 5 | """ 6 | final = m + n - 1 7 | first = m - 1 8 | second = n - 1 9 | while first >= 0 and second >= 0: 10 | if(nums1[first] > nums2[second]): 11 | nums1[final] = nums1[first] 12 | first -= 1 13 | final -= 1 14 | else: 15 | nums1[final] = nums2[second] 16 | second -= 1 17 | final -= 1 18 | if first < 0: 19 | nums1[:final+1] = nums2[:second+1] 20 | else: 21 | nums1[:final+1] = nums1[:first+1] -------------------------------------------------------------------------------- /Leetcode Problems/Easy/9-Palindrome-Number.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an integer x, return true if x is palindrome integer. 3 | 4 | An integer is a palindrome when it reads the same backward as forward. 5 | ''' 6 | # First solution 7 | class Solution: 8 | def isPalindrome(self, x: int) -> bool: 9 | convInt = str(x) 10 | revInt = convInt[::-1] 11 | if(convInt == revInt): 12 | return True 13 | else: 14 | return False 15 | 16 | # Second solution 17 | class Solution: 18 | def isPalindrome(self, x: int) -> bool: 19 | if x < 0: 20 | return False 21 | 22 | number = x 23 | reverse = 0 24 | 25 | while number: 26 | reverse = reverse * 10 + number % 10 27 | number //= 10 28 | 29 | return x == reverse -------------------------------------------------------------------------------- /Leetcode Problems/Easy/905-Sort-Array-By-Parity.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def sortArrayByParity(self, nums: List[int]) -> List[int]: 3 | even = [] 4 | odd = [] 5 | for i in range(len(nums)): 6 | if(nums[i] % 2 != 0): 7 | odd.append(nums[i]) 8 | else: 9 | even.append(nums[i]) 10 | return even + odd -------------------------------------------------------------------------------- /Leetcode Problems/Easy/94-Binary-Tree-Inorder-Traversal.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the root of a binary tree, return the inorder traversal of its nodes' values. 3 | ''' 4 | 5 | # Definition for a binary tree node. 6 | # class TreeNode: 7 | # def __init__(self, val=0, left=None, right=None): 8 | # self.val = val 9 | # self.left = left 10 | # self.right = right 11 | class Solution: 12 | def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]: 13 | output = [] 14 | 15 | def inorder_fn(tree): 16 | if tree: 17 | inorder_fn(tree.left) 18 | output.append(tree.val) 19 | inorder_fn(tree.right) 20 | 21 | inorder_fn(root) 22 | 23 | return output -------------------------------------------------------------------------------- /Leetcode Problems/Easy/941-Valid-Mountain-Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def validMountainArray(self, arr: List[int]) -> bool: 3 | if(len(arr) < 3): 4 | return False 5 | 6 | prev = None 7 | max_index = None 8 | for i, num in enumerate(arr): 9 | if prev != None and num <= prev: 10 | break 11 | 12 | prev = num 13 | max_index = i 14 | 15 | 16 | if max_index == 0 or max_index == len(arr) - 1: 17 | return False 18 | 19 | for i, num in enumerate(arr[max_index + 1:]): 20 | if num >= prev: 21 | print (num, prev) 22 | return False 23 | 24 | prev = num 25 | 26 | return True -------------------------------------------------------------------------------- /Leetcode Problems/Easy/977-Squares-of-a-Sorted-Array.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Approach: Use 2 pointers for O(N) complexity 3 | The array given is sorted, which is why we use 2 pointers for the negative portion 4 | as well as the positive portion of the array (since negative squares -> positive) 5 | The left pointer goes through the negative portion, and the right pointer goes through 6 | the positive portion. If the absolute value is lesser in comparison, that value is then 7 | squared and put in the result list. 8 | ''' 9 | 10 | class Solution: 11 | def sortedSquares(self, nums: List[int]) -> List[int]: 12 | result = [0] * (len(nums)) 13 | left = 0 14 | right = len(nums) - 1 15 | for i in range(len(nums) - 1, -1, -1): 16 | if(abs(nums[left]) < abs(nums[right])): 17 | sq = nums[right] 18 | right = right - 1 19 | else: 20 | sq = nums[left] 21 | left = left + 1 22 | result[i] = sq * sq 23 | 24 | return result -------------------------------------------------------------------------------- /Leetcode Problems/Hard/10-Regular-Expression-Matching.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an input string s and a pattern p, implement regular expression matching with support for '.' and '*' where: 3 | 4 | '.' Matches any single character.​​​​ 5 | '*' Matches zero or more of the preceding element. 6 | The matching should cover the entire input string (not partial). 7 | ''' 8 | 9 | class Solution: 10 | def isMatch(self, s: str, p: str) -> bool: 11 | p = r"{}".format(p) 12 | p = re.compile(p) 13 | if p.fullmatch(s): 14 | return True 15 | else: 16 | return False -------------------------------------------------------------------------------- /Leetcode Problems/Hard/44-Wildcard-Matching.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*' where: 3 | 4 | '?' Matches any single character. 5 | '*' Matches any sequence of characters (including the empty sequence). 6 | The matching should cover the entire input string (not partial). 7 | ''' 8 | 9 | class Solution: 10 | def isMatch(self, s: str, p: str) -> bool: 11 | m = len(s) 12 | n = len(p) 13 | 14 | dp = [[False for j in range(n + 1)] for i in range(m + 1)] 15 | 16 | dp[0][0] = True 17 | 18 | for j in range(1, n + 1): 19 | if p[j - 1] == '*': 20 | dp[0][j] = dp[0][j - 1] 21 | 22 | for i in range(1, m + 1): 23 | for j in range(1, n + 1): 24 | if p[j - 1] == '*': 25 | dp[i][j] = dp[i - 1][j] or dp[i][j - 1] 26 | else: 27 | if s[i - 1] == p[j - 1] or p[j - 1] == '?': 28 | dp[i][j] = dp[i - 1][j - 1] 29 | 30 | return dp[m][n] 31 | -------------------------------------------------------------------------------- /Leetcode Problems/Medium/102-Binary-Tree-Level-Order-Traversal.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the root of a binary tree, return the level order traversal of its nodes' values. (i.e., from left to right, level by level). 3 | ''' 4 | 5 | # Definition for a binary tree node. 6 | # class TreeNode: 7 | # def __init__(self, val=0, left=None, right=None): 8 | # self.val = val 9 | # self.left = left 10 | # self.right = right 11 | class Solution: 12 | def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: 13 | levels = [] 14 | if not root: 15 | return levels 16 | 17 | def bfs(node, level): 18 | if len(levels) == level: 19 | levels.append([]) 20 | 21 | levels[level].append(node.val) 22 | 23 | if node.left: 24 | bfs(node.left, level + 1) 25 | if node.right: 26 | bfs(node.right, level + 1) 27 | 28 | bfs(root, 0) 29 | return levels -------------------------------------------------------------------------------- /Leetcode Problems/Medium/1249-Minimum-Remove-to-Make-Valid-Parentheses.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string s of '(' , ')' and lowercase English characters. 3 | 4 | Your task is to remove the minimum number of parentheses ( '(' or ')', in any positions ) so that the resulting parentheses string is valid and return any valid string. 5 | 6 | ''' 7 | 8 | class Solution: 9 | def minRemoveToMakeValid(self, s: str) -> str: 10 | stack = [] 11 | indexRemove = set() 12 | i = 0 13 | result = '' 14 | 15 | for c in s: 16 | if c == '(': 17 | stack.append(i) 18 | elif c == ')': 19 | if len(stack) == 0: 20 | indexRemove.add(i) 21 | else: 22 | stack.pop() 23 | i += 1 24 | 25 | indexRemove = indexRemove.union(stack) 26 | for i in range(len(s)): 27 | if i not in indexRemove: 28 | result += s[i] 29 | 30 | return result -------------------------------------------------------------------------------- /Leetcode Problems/Medium/146-LRU-Cache.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Design a data structure that follows the constraints of a Least Recently Used (LRU) cache. 3 | 4 | Implement the LRUCache class: 5 | 6 | LRUCache(int capacity) Initialize the LRU cache with positive size capacity. 7 | int get(int key) Return the value of the key if the key exists, otherwise return -1. 8 | void put(int key, int value) Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key. 9 | The functions get and put must each run in O(1) average time complexity. 10 | ''' 11 | 12 | from collections import deque 13 | 14 | class LRUCache: 15 | 16 | def __init__(self, capacity: int): 17 | self.capacity = capacity 18 | self.dict = {} 19 | self.cache = deque() 20 | 21 | def get(self, key: int) -> int: 22 | if key in self.dict.keys(): 23 | self.put(key, self.dict[key]) 24 | return self.dict[key] 25 | else: 26 | return -1 27 | 28 | def put(self, key: int, value: int) -> None: 29 | if key in self.dict.keys(): 30 | self.dict[key] = value 31 | self.cache.remove(key) 32 | self.cache.append(key) 33 | else: 34 | if len(self.dict) == self.capacity: 35 | keytoremove = self.cache[0] 36 | self.cache.remove(keytoremove) 37 | del(self.dict[keytoremove]) 38 | 39 | self.cache.append(key) 40 | self.dict[key] = value 41 | 42 | 43 | # Your LRUCache object will be instantiated and called as such: 44 | # obj = LRUCache(capacity) 45 | # param_1 = obj.get(key) 46 | # obj.put(key,value) -------------------------------------------------------------------------------- /Leetcode Problems/Medium/151-Reverse-Words-in-a-String.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an input string s, reverse the order of the words. 3 | 4 | A word is defined as a sequence of non-space characters. The words in s will be separated by at least one space. 5 | 6 | Return a string of the words in reverse order concatenated by a single space. 7 | 8 | Note that s may contain leading or trailing spaces or multiple spaces between two words. The returned string should only have a single space separating the words. Do not include any extra spaces. 9 | 10 | ''' 11 | 12 | class Solution: 13 | def reverseWords(self, s: str) -> str: 14 | outputList = [] 15 | s = s.split(' ') 16 | print(s) 17 | for word in s[::-1]: 18 | if word == '': 19 | continue 20 | else: 21 | outputList.append(word) 22 | output = ' '.join(outputList) 23 | return output 24 | 25 | -------------------------------------------------------------------------------- /Leetcode Problems/Medium/189-Rotate-Array.py: -------------------------------------------------------------------------------- 1 | 2 | ''' 3 | Given an array, rotate the array to the right by k steps, where k is non-negative. 4 | ''' 5 | class Solution: 6 | def rotate(self, nums: List[int], k: int) -> None: 7 | """ 8 | Do not return anything, modify nums in-place instead. 9 | """ 10 | right = len(nums) - 1 11 | for i in range(len(nums) - 1, (len(nums) - 1) - k, -1): 12 | nums.insert(0, nums[right]) 13 | nums.pop() 14 | -------------------------------------------------------------------------------- /Leetcode Problems/Medium/2-Add-Two-Numbers.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list. 3 | 4 | You may assume the two numbers do not contain any leading zero, except the number 0 itself. 5 | ''' 6 | 7 | # Definition for singly-linked list. 8 | # class ListNode: 9 | # def __init__(self, val=0, next=None): 10 | # self.val = val 11 | # self.next = next 12 | class Solution: 13 | def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]: 14 | list1 = [] 15 | list2 = [] 16 | while True: 17 | list1.append(str(l1.val)) 18 | if(l1.next is None): 19 | break 20 | l1 = l1.next 21 | 22 | while True: 23 | list2.append(str(l2.val)) 24 | if(l2.next is None): 25 | break 26 | l2 = l2.next 27 | 28 | list1 = list1[::-1] 29 | list2 = list2[::-1] 30 | num1 = int("".join(list1)) 31 | num2 = int("".join(list2)) 32 | 33 | sumOut = num1 + num2 34 | sumOut = list(map(int, str(sumOut))) 35 | sumOut = sumOut[::-1] 36 | 37 | curr = ListNode(sumOut[0]) 38 | head = curr 39 | 40 | # iterating over output list 41 | for i in sumOut[1:]: 42 | temp = ListNode(i) 43 | curr.next = temp 44 | curr = temp 45 | 46 | return head -------------------------------------------------------------------------------- /Leetcode Problems/Medium/200-Number-of-Islands.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an m x n 2D binary grid grid which represents a map of '1's (land) and '0's (water), return the number of islands. 3 | 4 | An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. 5 | ''' 6 | 7 | class Solution: 8 | def numIslands(self, grid: List[List[str]]) -> int: 9 | if not grid: return 0 10 | row = len(grid) 11 | col = len(grid[0]) 12 | visited = set() 13 | count = 0 14 | directions=[(-1,0),(0,1),(1,0),(0,-1)] 15 | def findIsland(x,y): 16 | for dx, dy in directions: 17 | nx,ny = x+dx, y+dy 18 | if(0 <= nx < row and 0 <= ny < col and grid[nx][ny]=='1' and (nx,ny) not in visited): 19 | visited.add((nx,ny)) 20 | findIsland(nx,ny) 21 | 22 | for x in range(row): 23 | for y in range(col): 24 | if grid[x][y] == '1' and (x,y) not in visited: 25 | count +=1 26 | visited.add((x,y)) 27 | findIsland(x,y) 28 | return count -------------------------------------------------------------------------------- /Leetcode Problems/Medium/3-Longest-Substring-Without-Repeating-Characters.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string s, find the length of the longest substring without repeating characters. 3 | ''' 4 | 5 | class Solution: 6 | def lengthOfLongestSubstring(self, s: str) -> int: 7 | start = 0 8 | end = 0 9 | uniqueVal = set() 10 | maxLen = 0 11 | 12 | if s == "": 13 | return 0 14 | 15 | while end < len(s): 16 | if(s[end] not in uniqueVal): 17 | uniqueVal.add(s[end]) 18 | end += 1 19 | maxLen = max(maxLen, len(uniqueVal)) 20 | else: 21 | uniqueVal.remove(s[start]) 22 | start += 1 23 | 24 | return maxLen -------------------------------------------------------------------------------- /Leetcode Problems/Medium/423-Reconstruct-Original-Digits-from-English.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string s containing an out-of-order English representation of digits 0-9, return the digits in ascending order. 3 | ''' 4 | 5 | class Solution: 6 | def originalDigits(self, s: str) -> str: 7 | c = Counter(s) 8 | 9 | res = [0] * 10 10 | 11 | res[0] = c['z'] 12 | res[2] = c['w'] 13 | res[4] = c['u'] 14 | res[6] = c['x'] 15 | res[8] = c['g'] 16 | res[1] = c['o'] - res[0] - res[2] - res[4] 17 | res[3] = c['h'] - res[8] 18 | res[5] = c['f'] - res[4] 19 | res[7] = c['s'] - res[6] 20 | res[9] = c['i'] - res[5] - res[6] - res[8] 21 | 22 | output = [] 23 | 24 | for i in range(10): 25 | output.append(str(i) * res[i]) 26 | 27 | return "".join(output) -------------------------------------------------------------------------------- /Leetcode Problems/Medium/487-Max-Consecutive-Ones-II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findMaxConsecutiveOnes(self, nums: List[int]) -> int: 3 | result, prev, curr = 0, 0, 0 4 | 5 | for num in nums: 6 | if num == 0: 7 | result = max(result, prev+curr+1) 8 | prev, curr = curr, 0 9 | else: 10 | curr += 1 11 | 12 | return min(max(result, prev+curr+1), len(nums)) -------------------------------------------------------------------------------- /Leetcode Problems/Medium/498-Diagonal-Traverse.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an m x n matrix mat, return an array of all the elements of the array in a diagonal order. 3 | ''' 4 | 5 | class Solution(object): 6 | def findDiagonalOrder(self, mat): 7 | """ 8 | :type mat: List[List[int]] 9 | :rtype: List[int] 10 | """ 11 | if(len(mat) == 0 or len(mat[0]) == 0): 12 | return [] 13 | 14 | column = len(mat) 15 | row = len(mat[0]) 16 | numbers = row * column 17 | output = [] 18 | m = 0 19 | n = 0 20 | flag = True 21 | 22 | for i in range(numbers): 23 | output.append(mat[m][n]) 24 | 25 | if flag: 26 | m-=1 27 | n+=1 28 | 29 | else: 30 | m+=1 31 | n-=1 32 | 33 | if m >= column: 34 | m-=1 35 | n+=2 36 | flag=True 37 | 38 | elif n >= row: 39 | m+=2 40 | n-=1 41 | flag=False 42 | 43 | if m<0: 44 | m=0 45 | flag=False 46 | 47 | elif n<0: 48 | n=0 49 | flag=True 50 | 51 | return output -------------------------------------------------------------------------------- /Leetcode Problems/Medium/5-Longest-Palindromic-Substring.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string s, return the longest palindromic substring in s. 3 | ''' 4 | 5 | class Solution: 6 | def longestPalindrome(self, s: str) -> str: 7 | ''' 8 | # Time Limit Exceeded 9 | output = '' 10 | for i in range(len(s)): 11 | temp = '' 12 | for letter in s: 13 | temp = temp + letter 14 | if(temp == temp[::-1]): 15 | if(len(temp) > len(output)): 16 | output = temp 17 | s = list(s) 18 | s.pop(0) 19 | s = ''.join(s) 20 | print(s) 21 | 22 | return output 23 | ''' 24 | 25 | longest = '' 26 | def findLongest(s, l, r): 27 | while l>=0 and r len(longest): longest = s1 35 | 36 | s2 = findLongest(s, i, i+1) 37 | if len(s2) > len(longest): longest = s2 38 | 39 | return longest -------------------------------------------------------------------------------- /Leetcode Problems/Medium/56-Merge-Intervals.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input. 3 | ''' 4 | 5 | class Solution: 6 | def merge(self, intervals: List[List[int]]) -> List[List[int]]: 7 | if len(intervals) == 0: 8 | return [] 9 | sorted_intervals = sorted(intervals, key = lambda x: x[0]) 10 | res = [sorted_intervals[0]] 11 | for interval in sorted_intervals[1:]: 12 | if interval[0] <= res[-1][1]: 13 | res[-1][1] = max(interval[1], res[-1][1]) 14 | else: 15 | res.append(interval) 16 | return res -------------------------------------------------------------------------------- /Leetcode Problems/Medium/622-Design-Circular-Queue.py: -------------------------------------------------------------------------------- 1 | class MyCircularQueue(object): 2 | 3 | def __init__(self, k): 4 | """ 5 | :type k: int 6 | """ 7 | self.queue = [0] * k 8 | self.head = 0 9 | self.count = 0 10 | self.size = k 11 | 12 | def enQueue(self, value): 13 | """ 14 | :type value: int 15 | :rtype: bool 16 | """ 17 | if(self.count == self.size): 18 | return False 19 | self.queue[(self.head + self.count) % self.size] = value 20 | self.count += 1 21 | return True 22 | 23 | def deQueue(self): 24 | """ 25 | :rtype: bool 26 | """ 27 | if(self.count == 0): 28 | return False 29 | self.head = (self.head + 1) % self.size 30 | self.count -= 1 31 | return True 32 | 33 | def Front(self): 34 | """ 35 | :rtype: int 36 | """ 37 | if(self.count == 0): 38 | return -1 39 | return self.queue[self.head] 40 | 41 | 42 | def Rear(self): 43 | """ 44 | :rtype: int 45 | """ 46 | if(self.count == 0): 47 | return -1 48 | return self.queue[(self.head + self.count - 1) % self.size] 49 | 50 | 51 | def isEmpty(self): 52 | """ 53 | :rtype: bool 54 | """ 55 | return self.count == 0 56 | 57 | 58 | def isFull(self): 59 | """ 60 | :rtype: bool 61 | """ 62 | return self.count == self.size 63 | 64 | 65 | # Your MyCircularQueue object will be instantiated and called as such: 66 | # obj = MyCircularQueue(k) 67 | # param_1 = obj.enQueue(value) 68 | # param_2 = obj.deQueue() 69 | # param_3 = obj.Front() 70 | # param_4 = obj.Rear() 71 | # param_5 = obj.isEmpty() 72 | # param_6 = obj.isFull() -------------------------------------------------------------------------------- /Leetcode Problems/Medium/811-Subdomain-Visit-Count.py: -------------------------------------------------------------------------------- 1 | ''' 2 | A website domain "discuss.leetcode.com" consists of various subdomains. At the top level, we have "com", at the next level, we have "leetcode.com" and at the lowest level, "discuss.leetcode.com". When we visit a domain like "discuss.leetcode.com", we will also visit the parent domains "leetcode.com" and "com" implicitly. 3 | 4 | A count-paired domain is a domain that has one of the two formats "rep d1.d2.d3" or "rep d1.d2" where rep is the number of visits to the domain and d1.d2.d3 is the domain itself. 5 | 6 | For example, "9001 discuss.leetcode.com" is a count-paired domain that indicates that discuss.leetcode.com was visited 9001 times. 7 | Given an array of count-paired domains cpdomains, return an array of the count-paired domains of each subdomain in the input. You may return the answer in any order. 8 | ''' 9 | 10 | class Solution: 11 | def subdomainVisits(self, cpdomains: List[str]) -> List[str]: 12 | cnt = collections.Counter() 13 | for dom in cpdomains: 14 | count, domain = dom.split(" ") 15 | count = int(count) 16 | cnt[domain] += count 17 | for j, k in enumerate(domain): 18 | if k == '.': 19 | cnt[domain[j + 1 : ]] += count 20 | return [str(count) + " " + domain for domain, count in cnt.items()] -------------------------------------------------------------------------------- /Practice Concepts/Data Structures/CircularQ.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Circular Q 2 | 3 | class CircularQ(): 4 | 5 | def __init__(self, capacity): 6 | self.queue = [None] * capacity 7 | self.capacity = capacity 8 | self.front = 0 9 | self.rear = -1 10 | self.size = 0 11 | 12 | def enqueue(self, value): 13 | if self.size == self.capacity: 14 | raise OverflowError('Queue is full') 15 | self.rear = (self.rear + 1) % self.capacity 16 | self.queue[self.rear] = value 17 | self.size += 1 18 | 19 | def dequeue(self): 20 | if self.isEmpty(): 21 | raise IndexError('Queue is empty') 22 | value = self.queue[self.front] 23 | self.front = (self.front + 1) % self.capacity 24 | self.size -= 1 25 | return value 26 | 27 | def isEmpty(self): 28 | return self.size == 0 29 | 30 | def front(self): 31 | if not self.isEmpty(): 32 | return self.queue[self.front] 33 | raise IndexError('Queue is empty') 34 | 35 | def rear(self): 36 | if not self.isEmpty(): 37 | return self.queue[self.rear] 38 | raise IndexError('Queue is empty') 39 | 40 | # Test Cases 41 | queue = CircularQ(3) 42 | queue.enqueue(1) 43 | queue.enqueue(2) 44 | queue.enqueue(3) 45 | assert queue.front() == 1 46 | assert queue.rear() == 3 47 | assert queue.dequeue() == 1 48 | assert queue.front() == 2 49 | assert queue.rear() == 3 50 | assert queue.dequeue() == 2 51 | assert queue.front() == 3 52 | assert queue.rear() == 3 53 | assert queue.dequeue() == 3 54 | assert queue.isEmpty() == True -------------------------------------------------------------------------------- /Practice Concepts/Data Structures/Queue.py: -------------------------------------------------------------------------------- 1 | # Python implementation of a simple queue 2 | 3 | from collections import deque 4 | 5 | class Queue: 6 | 7 | def __init__(self): 8 | self.queue = deque() 9 | 10 | def enqueue(self, value): 11 | self.queue.append(value) 12 | 13 | def dequeue(self): 14 | if not self.isEmpty(): 15 | return self.queue.popleft() # Remove and return the first element 16 | raise IndexError('Queue is empty') 17 | 18 | def isEmpty(self): 19 | return len(self.queue) == 0 20 | 21 | def front(self): 22 | if not self.isEmpty(): 23 | return self.queue[0] # Return the FRONT of the queue without removing it 24 | raise IndexError('Queue is empty') 25 | 26 | def rear(self): 27 | if not self.isEmpty(): 28 | return self.queue[-1] # Return the REAR of the queue without removing it 29 | raise IndexError('Queue is empty') 30 | 31 | # Test Cases 32 | queue = Queue() 33 | queue.enqueue(1) 34 | queue.enqueue(2) 35 | queue.enqueue(3) 36 | assert queue.front() == 1 37 | assert queue.rear() == 3 38 | assert queue.dequeue() == 1 39 | assert queue.front() == 2 40 | assert queue.rear() == 3 41 | assert queue.dequeue() == 2 42 | assert queue.front() == 3 43 | assert queue.rear() == 3 44 | assert queue.dequeue() == 3 45 | assert queue.isEmpty() == True 46 | -------------------------------------------------------------------------------- /Practice Concepts/Data Structures/dequeue.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | class Deque: 4 | def __init__(self): 5 | self.deque = deque() 6 | 7 | def enqueue_front(self, item): 8 | self.deque.appendleft(item) # Add item to the front 9 | 10 | def enqueue_rear(self, item): 11 | self.deque.append(item) # Add item to the rear 12 | 13 | def dequeue_front(self): 14 | if not self.is_empty(): 15 | return self.deque.popleft() # Remove and return the front item 16 | raise IndexError("Dequeue from an empty deque") 17 | 18 | def dequeue_rear(self): 19 | if not self.is_empty(): 20 | return self.deque.pop() # Remove and return the rear item 21 | raise IndexError("Dequeue from an empty deque") 22 | 23 | def is_empty(self): 24 | return len(self.deque) == 0 25 | 26 | def size(self): 27 | return len(self.deque) 28 | 29 | # Test cases 30 | deque = Deque() 31 | deque.enqueue_front(10) 32 | deque.enqueue_front(20) 33 | deque.enqueue_rear(30) 34 | assert deque.dequeue_front() == 20 35 | assert deque.dequeue_rear() == 30 36 | assert deque.size() == 1 37 | assert deque.is_empty() == False 38 | assert deque.dequeue_front() == 10 39 | assert deque.is_empty() == True 40 | assert deque.size() == 0 41 | -------------------------------------------------------------------------------- /Practice Concepts/Data Structures/hash-table.py: -------------------------------------------------------------------------------- 1 | # Python implementation of a basic hash table. 2 | 3 | hashTable = [[],] * 10 4 | 5 | def primeCheck(n): 6 | if n == 1 or n == 0: 7 | return 0 8 | for i in range(2, n//2): 9 | if n % 1 == 0: 10 | return 0 11 | return 1 12 | 13 | def primeGet(n): 14 | if n % 2 == 0: 15 | n += 1 16 | while not primeCheck(n): 17 | n += 2 18 | return n 19 | 20 | def hashFn(key): 21 | capacity = primeGet(10) 22 | return key % capacity 23 | 24 | def insertData(key, data): 25 | index = hashFn(key) 26 | hashTable[index] = [key, data] 27 | 28 | def removeData(key): 29 | index = hashFn(key) 30 | hashTable[index] = 0 31 | 32 | insertData(123, "test1") 33 | insertData(432, "test2") 34 | insertData(213, "test3") 35 | insertData(654, "test4") 36 | 37 | print(hashTable) 38 | 39 | removeData(123) 40 | 41 | print(hashTable) 42 | -------------------------------------------------------------------------------- /Practice Concepts/Data Structures/priority_q.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | 3 | class PriorityQueue: 4 | def __init__(self): 5 | self.queue = [] 6 | 7 | def enqueue(self, item): 8 | heapq.heappush(self.queue, item) # Push item while maintaining heap order 9 | 10 | def dequeue(self): 11 | if not self.is_empty(): 12 | return heapq.heappop(self.queue) # Remove and return the smallest item 13 | raise IndexError("Dequeue from an empty queue") 14 | 15 | def is_empty(self): 16 | return len(self.queue) == 0 17 | 18 | def size(self): 19 | return len(self.queue) 20 | 21 | def front(self): 22 | if not self.is_empty(): 23 | return self.queue[0] 24 | raise IndexError("Front from an empty queue") 25 | 26 | def rear(self): 27 | if not self.is_empty(): 28 | return self.queue[-1] 29 | raise IndexError("Rear from an empty queue") 30 | 31 | # Test Cases 32 | queue = PriorityQueue() 33 | queue.enqueue(30) 34 | queue.enqueue(10) 35 | queue.enqueue(20) 36 | assert queue.front() == 10 37 | assert queue.rear() == 20 38 | assert queue.dequeue() == 10 39 | assert queue.front() == 20 40 | assert queue.rear() == 30 41 | assert queue.dequeue() == 20 42 | assert queue.front() == 30 43 | assert queue.rear() == 30 44 | assert queue.dequeue() == 30 45 | assert queue.is_empty() == True 46 | -------------------------------------------------------------------------------- /Practice Concepts/Data Structures/singly-linked-list.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Singly Linked List and its operations 2 | 3 | class Node: 4 | # Create a node 5 | def __init__(self, item): 6 | self.item = item 7 | self.next = None 8 | 9 | class LinkedList: 10 | def __init__(self): 11 | self.head = None 12 | 13 | # Insert: Beginning 14 | def insertBeg(self, newItem): 15 | newNode = Node(newItem) 16 | newNode.next = self.head 17 | self.head = newNode 18 | 19 | # Insert: End 20 | def insertEnd(self, newItem): 21 | newNode = Node(newItem) 22 | if self.head is None: 23 | self.head = newNode 24 | return 25 | last = self.head 26 | while(last.next): 27 | last = last.next 28 | last.next = newNode 29 | 30 | # Insert: After a node 31 | def insertAfterNode(self, prevNode, newItem): 32 | if prevNode is None: 33 | print('The given previous node must be in the Linked List') 34 | return 35 | newNode = Node(newItem) 36 | newNode.next = prevNode.next 37 | prevNode.next = newNode 38 | 39 | # Deleting a node 40 | def deleteNode(self, position): 41 | if self.head is None: 42 | return 43 | 44 | temp = self.head 45 | 46 | if position == 0: 47 | self.head = temp.next 48 | temp = None 49 | return 50 | 51 | for i in range(position - 1): 52 | temp = temp.next 53 | if temp is None: 54 | break 55 | 56 | if temp is None: 57 | return 58 | 59 | if temp.next is None: 60 | return 61 | 62 | next = temp.next.next 63 | temp.next = None 64 | temp.next = next 65 | 66 | # Search for an element 67 | def search(self, key): 68 | current = self.head 69 | 70 | while current is not None: 71 | if current.item == key: 72 | return True 73 | current = current.next 74 | return False 75 | 76 | # Sort Linked List 77 | def sort(self, head): 78 | current = head 79 | index = Node(None) 80 | 81 | if head is None: 82 | return 83 | 84 | else: 85 | while current is not None: 86 | index = current.next 87 | 88 | while index is not None: 89 | if current.item > index.item: 90 | current.item, index.item = index.item, current.item 91 | index = index.next 92 | 93 | current = current.next 94 | 95 | # Print the linked list 96 | def printList(self): 97 | temp = self.head 98 | while (temp): 99 | print(str(temp.item) + " ", end="") 100 | temp = temp.next 101 | 102 | # Driver code 103 | if __name__ == '__main__': 104 | linkedList = LinkedList() 105 | 106 | # Assign Data 107 | linkedList.head = Node(1) 108 | second = Node(2) 109 | third = Node(3) 110 | 111 | # Connect the nodes 112 | linkedList.head.next = second 113 | second.next = third 114 | 115 | # Print the Linked List 116 | while linkedList.head != None: 117 | print(linkedList.head.item, end=' ') 118 | linkedList.head = linkedList.head.next 119 | 120 | llist = LinkedList() 121 | llist.insertEnd(1) 122 | llist.insertBeg(2) 123 | llist.insertBeg(3) 124 | llist.insertEnd(4) 125 | llist.insertAfterNode(llist.head.next, 5) 126 | 127 | print('Linked List:') 128 | llist.printList() 129 | 130 | print("\nAfter deleting an element:") 131 | llist.deleteNode(3) 132 | llist.printList() 133 | 134 | print() 135 | item_to_find = 3 136 | if llist.search(item_to_find): 137 | print(str(item_to_find) + " is found") 138 | else: 139 | print(str(item_to_find) + " is not found") 140 | 141 | llist.sort(llist.head) 142 | print("Sorted List: ") 143 | llist.printList() -------------------------------------------------------------------------------- /Practice Concepts/Data Structures/stacks.py: -------------------------------------------------------------------------------- 1 | # Python implementations of stacks - List-based implementation and Deque-based implementation 2 | 3 | class ListBasedStack: 4 | def __init__(self): 5 | self.stack = [] 6 | 7 | def push(self, item): 8 | self.stack.append(item) 9 | 10 | def pop(self): 11 | if not self.is_empty(): 12 | return self.stack.pop() 13 | raise IndexError("pop from empty stack") 14 | 15 | def peek(self): 16 | if not self.is_empty(): 17 | return self.stack[-1] 18 | raise IndexError("peek from empty stack") 19 | 20 | def is_empty(self): 21 | return len(self.stack) == 0 22 | 23 | 24 | from collections import deque 25 | 26 | class DequeBasedStack: 27 | def __init__(self): 28 | self.stack = deque() 29 | 30 | def push(self, item): 31 | self.stack.append(item) 32 | 33 | def pop(self): 34 | if not self.is_empty(): 35 | return self.stack.pop() 36 | raise IndexError("pop from empty stack") 37 | 38 | def peek(self): 39 | if not self.is_empty(): 40 | return self.stack[-1] 41 | raise IndexError("peek from empty stack") 42 | 43 | def is_empty(self): 44 | return len(self.stack) == 0 45 | 46 | # Test cases 47 | stack = ListBasedStack() 48 | stack.push(1) 49 | stack.push(2) 50 | stack.push(3) 51 | assert stack.peek() == 3 52 | assert stack.pop() == 3 53 | assert stack.peek() == 2 54 | assert stack.pop() == 2 55 | assert stack.peek() == 1 56 | assert stack.pop() == 1 57 | assert stack.is_empty() == True 58 | 59 | stack = DequeBasedStack() 60 | stack.push(1) 61 | stack.push(2) 62 | stack.push(3) 63 | assert stack.peek() == 3 64 | assert stack.pop() == 3 65 | assert stack.peek() == 2 66 | assert stack.pop() == 2 67 | assert stack.peek() == 1 68 | assert stack.pop() == 1 69 | assert stack.is_empty() == True -------------------------------------------------------------------------------- /Practice Concepts/Dynamic Programming/fw.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Floyd Warshall Algorithm 2 | 3 | # The number of vertices 4 | nV = 4 5 | INF = 999 6 | 7 | # Algorithm implementation 8 | def floyd_warshall(G): 9 | distance = list(map(lambda i: list(map(lambda j: j, i)), G)) 10 | 11 | # Adding vertices individually 12 | for k in range(nV): 13 | for i in range(nV): 14 | for j in range(nV): 15 | distance[i][j] = min(distance[i][j], distance[i][k] + distance[k][j]) 16 | print_solution(distance) 17 | 18 | # Printing the solution 19 | def print_solution(distance): 20 | for i in range(nV): 21 | for j in range(nV): 22 | if(distance[i][j] == INF): 23 | print("INF", end=" ") 24 | else: 25 | print(distance[i][j], end=" ") 26 | print(" ") 27 | 28 | # Driver Code 29 | G = [[0, 3, INF, 5], 30 | [2, 0, INF, 4], 31 | [INF, 1, 0, INF], 32 | [INF, INF, 2, 0]] 33 | floyd_warshall(G) -------------------------------------------------------------------------------- /Practice Concepts/Dynamic Programming/lcs.py: -------------------------------------------------------------------------------- 1 | # Python implementation of the Longest Common Subsequence Algorithm 2 | 3 | # Function to find lcs_algo 4 | def lcs_algo(S1, S2, m, n): 5 | L = [[0 for x in range(n+1)] for x in range(m+1)] 6 | 7 | # Building the mtrix in bottom-up way 8 | for i in range(m+1): 9 | for j in range(n+1): 10 | if i == 0 or j == 0: 11 | L[i][j] = 0 12 | elif S1[i-1] == S2[j-1]: 13 | L[i][j] = L[i-1][j-1] + 1 14 | else: 15 | L[i][j] = max(L[i-1][j], L[i][j-1]) 16 | 17 | index = L[m][n] 18 | 19 | lcs_algo = [""] * (index+1) 20 | lcs_algo[index] = "" 21 | 22 | i = m 23 | j = n 24 | while i > 0 and j > 0: 25 | 26 | if S1[i-1] == S2[j-1]: 27 | lcs_algo[index-1] = S1[i-1] 28 | i -= 1 29 | j -= 1 30 | index -= 1 31 | 32 | elif L[i-1][j] > L[i][j-1]: 33 | i -= 1 34 | else: 35 | j -= 1 36 | 37 | # Printing the sub sequences 38 | print("S1 : " + S1 + "\nS2 : " + S2) 39 | print("LCS: " + "".join(lcs_algo)) 40 | 41 | # Driver Code 42 | S1 = "ACADB" 43 | S2 = "CBDA" 44 | m = len(S1) 45 | n = len(S2) 46 | lcs_algo(S1, S2, m, n) -------------------------------------------------------------------------------- /Practice Concepts/Dynamic Programming/rk.py: -------------------------------------------------------------------------------- 1 | # Python implementation to Rabin Karp Algorithm 2 | 3 | d = 10 4 | 5 | def search(pattern, text, q): 6 | m = len(pattern) 7 | n = len(text) 8 | p = 0 9 | t = 0 10 | h = 1 11 | i = 0 12 | j = 0 13 | 14 | for i in range(m-1): 15 | h = (h*d) % q 16 | 17 | # Calculate hash value for pattern and text 18 | for i in range(m): 19 | p = (d*p + ord(pattern[i])) % q 20 | t = (d*t + ord(text[i])) % q 21 | 22 | # Find the match 23 | for i in range(n-m+1): 24 | if p == t: 25 | for j in range(m): 26 | if text[i+j] != pattern[j]: 27 | break 28 | 29 | j += 1 30 | if j == m: 31 | print("Pattern is found at position: " + str(i+1)) 32 | 33 | if i < n-m: 34 | t = (d*(t-ord(text[i])*h) + ord(text[i+m])) % q 35 | 36 | if t < 0: 37 | t = t+q 38 | 39 | # Driver Code 40 | text = "ABCCDDAEFG" 41 | pattern = "CDD" 42 | q = 13 43 | search(pattern, text, q) -------------------------------------------------------------------------------- /Practice Concepts/Graphs/adj-list.py: -------------------------------------------------------------------------------- 1 | # Adjacency List representation in Python 2 | 3 | class AdjNode: 4 | def __init__(self, value): 5 | self.vertex = value 6 | self.next = None 7 | 8 | 9 | class Graph: 10 | def __init__(self, num): 11 | self.V = num 12 | self.graph = [None] * self.V 13 | 14 | # Add edges 15 | def add_edge(self, s, d): 16 | node = AdjNode(d) 17 | node.next = self.graph[s] 18 | self.graph[s] = node 19 | 20 | node = AdjNode(s) 21 | node.next = self.graph[d] 22 | self.graph[d] = node 23 | 24 | # Print the graph 25 | def print_agraph(self): 26 | for i in range(self.V): 27 | print("Vertex " + str(i) + ":", end="") 28 | temp = self.graph[i] 29 | while temp: 30 | print(" -> {}".format(temp.vertex), end="") 31 | temp = temp.next 32 | print(" \n") 33 | 34 | 35 | if __name__ == "__main__": 36 | V = 5 37 | 38 | # Create graph and edges 39 | graph = Graph(V) 40 | graph.add_edge(0, 1) 41 | graph.add_edge(0, 2) 42 | graph.add_edge(0, 3) 43 | graph.add_edge(1, 2) 44 | 45 | graph.print_agraph() -------------------------------------------------------------------------------- /Practice Concepts/Graphs/adj-mat.py: -------------------------------------------------------------------------------- 1 | # Adjacency Matrix representation in Python 2 | 3 | 4 | class Graph(object): 5 | 6 | # Initialize the matrix 7 | def __init__(self, size): 8 | self.adjMatrix = [] 9 | for i in range(size): 10 | self.adjMatrix.append([0 for i in range(size)]) 11 | self.size = size 12 | 13 | # Add edges 14 | def add_edge(self, v1, v2): 15 | if v1 == v2: 16 | print("Same vertex %d and %d" % (v1, v2)) 17 | self.adjMatrix[v1][v2] = 1 18 | self.adjMatrix[v2][v1] = 1 19 | 20 | # Remove edges 21 | def remove_edge(self, v1, v2): 22 | if self.adjMatrix[v1][v2] == 0: 23 | print("No edge between %d and %d" % (v1, v2)) 24 | return 25 | self.adjMatrix[v1][v2] = 0 26 | self.adjMatrix[v2][v1] = 0 27 | 28 | def __len__(self): 29 | return self.size 30 | 31 | # Print the matrix 32 | def print_matrix(self): 33 | for row in self.adjMatrix: 34 | for val in row: 35 | print('{:4}'.format(val)), 36 | print 37 | 38 | 39 | def main(): 40 | g = Graph(5) 41 | g.add_edge(0, 1) 42 | g.add_edge(0, 2) 43 | g.add_edge(1, 2) 44 | g.add_edge(2, 0) 45 | g.add_edge(2, 3) 46 | 47 | g.print_matrix() 48 | 49 | 50 | if __name__ == '__main__': 51 | main() -------------------------------------------------------------------------------- /Practice Concepts/Graphs/bfs.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Breadth-First Search 2 | 3 | import collections 4 | 5 | def bfs(graph, root): 6 | 7 | visited, queue = set(), collections.deque([root]) 8 | visited.add(root) 9 | 10 | while queue: 11 | 12 | # Dequeue a vertex from queue 13 | vertex = queue.popleft() 14 | print(str(vertex) + " ", end="") 15 | 16 | # If not visited, mark it as visited, and enqueue it 17 | for neighbour in graph[vertex]: 18 | if neighbour not in visited: 19 | visited.add(neighbour) 20 | queue.append(neighbour) 21 | 22 | 23 | if __name__ == '__main__': 24 | graph = {0: [1, 2], 1: [2], 2: [3], 3: [1, 2]} 25 | print("Breadth First Traversal: ") 26 | bfs(graph, 0) -------------------------------------------------------------------------------- /Practice Concepts/Graphs/dfs.py: -------------------------------------------------------------------------------- 1 | # Python implementation of the DFS Algorithm 2 | 3 | def dfs(graph, start, visited=None): 4 | if visited is None: 5 | visited = set() 6 | visited.add(start) 7 | 8 | print(start) 9 | 10 | for next in graph[start] - visited: 11 | dfs(graph, next, visited) 12 | return visited 13 | 14 | # Driver Code 15 | graph = {'0': set(['1', '2']), 16 | '1': set(['0', '3', '4']), 17 | '2': set(['0']), 18 | '3': set(['1']), 19 | '4': set(['2', '3'])} 20 | 21 | dfs(graph, '0') -------------------------------------------------------------------------------- /Practice Concepts/Graphs/scc.py: -------------------------------------------------------------------------------- 1 | # Python implementation to find Strongly Connected Components 2 | 3 | from collections import defaultdict 4 | 5 | class Graph: 6 | def __init__(self, vertex): 7 | self.V = vertex 8 | self.graph = defaultdict(list) 9 | 10 | # Add edge to the graph 11 | def add_edge(self, s, d): 12 | self.graph[s].append(d) 13 | 14 | # DFS 15 | def dfs(self, d, visitedVertex): 16 | visitedVertex[d] = True 17 | print(d, end=' ') 18 | for i in self.graph[d]: 19 | if not visitedVertex[i]: 20 | self.dfs(i, visitedVertex) 21 | 22 | def fill_order(self, d, visitedVertex, stack): 23 | visitedVertex[d] = True 24 | for i in self.graph[d]: 25 | if not visitedVertex[i]: 26 | self.fill_order(i, visitedVertex, stack) 27 | stack = stack.append(d) 28 | 29 | # transpose the matrix 30 | def transpose(self): 31 | g = Graph(self.V) 32 | 33 | for i in self.graph: 34 | for j in self.graph[i]: 35 | g.add_edge(j, i) 36 | return g 37 | 38 | # Print stongly connected components 39 | def print_scc(self): 40 | stack = [] 41 | visitedVertex = [False] * (self.V) 42 | 43 | for i in range(self.V): 44 | if not visitedVertex[i]: 45 | self.fill_order(i, visitedVertex, stack) 46 | 47 | gr = self.transpose() 48 | 49 | visitedVertex = [False] * (self.V) 50 | 51 | while stack: 52 | i = stack.pop() 53 | if not visitedVertex[i]: 54 | gr.dfs(i, visitedVertex) 55 | print("") 56 | 57 | 58 | g = Graph(8) 59 | g.add_edge(0, 1) 60 | g.add_edge(1, 2) 61 | g.add_edge(2, 3) 62 | g.add_edge(2, 4) 63 | g.add_edge(3, 0) 64 | g.add_edge(4, 5) 65 | g.add_edge(5, 6) 66 | g.add_edge(6, 4) 67 | g.add_edge(6, 7) 68 | 69 | print("Strongly Connected Components:") 70 | g.print_scc() -------------------------------------------------------------------------------- /Practice Concepts/Greedy Algorithms/dijkstra.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Dijkstra's Algorithm 2 | 3 | import sys 4 | vertices = [[0, 0, 1, 1, 0, 0, 0], 5 | [0, 0, 1, 0, 0, 1, 0], 6 | [1, 1, 0, 1, 1, 0, 0], 7 | [1, 0, 1, 0, 0, 0, 1], 8 | [0, 0, 1, 0, 0, 1, 0], 9 | [0, 1, 0, 0, 1, 0, 1], 10 | [0, 0, 0, 1, 0, 1, 0]] 11 | 12 | edges = [[0, 0, 1, 2, 0, 0, 0], 13 | [0, 0, 2, 0, 0, 3, 0], 14 | [1, 2, 0, 1, 3, 0, 0], 15 | [2, 0, 1, 0, 0, 0, 1], 16 | [0, 0, 3, 0, 0, 2, 0], 17 | [0, 3, 0, 0, 2, 0, 1], 18 | [0, 0, 0, 1, 0, 1, 0]] 19 | 20 | # Find which vertex is to be visited next 21 | def to_be_visited(): 22 | global visited_and_distance 23 | v = -10 24 | for index in range(num_of_vertices): 25 | if visited_and_distance[index][0] == 0 \ 26 | and (v < 0 or visited_and_distance[index][1] <= 27 | visited_and_distance[v][1]): 28 | v = index 29 | return v 30 | 31 | 32 | num_of_vertices = len(vertices[0]) 33 | 34 | visited_and_distance = [[0, 0]] 35 | for i in range(num_of_vertices-1): 36 | visited_and_distance.append([0, sys.maxsize]) 37 | 38 | for vertex in range(num_of_vertices): 39 | 40 | # Find next vertex to be visited 41 | to_visit = to_be_visited() 42 | for neighbor_index in range(num_of_vertices): 43 | 44 | # Updating new distances 45 | if vertices[to_visit][neighbor_index] == 1 and \ 46 | visited_and_distance[neighbor_index][0] == 0: 47 | new_distance = visited_and_distance[to_visit][1] \ 48 | + edges[to_visit][neighbor_index] 49 | if visited_and_distance[neighbor_index][1] > new_distance: 50 | visited_and_distance[neighbor_index][1] = new_distance 51 | 52 | visited_and_distance[to_visit][0] = 1 53 | 54 | i = 0 55 | 56 | # Printing the distance 57 | for distance in visited_and_distance: 58 | print("Distance of ", chr(ord('a') + i), 59 | " from source vertex: ", distance[1]) 60 | i = i + 1 -------------------------------------------------------------------------------- /Practice Concepts/Greedy Algorithms/ffa.py: -------------------------------------------------------------------------------- 1 | # Python implementation of the Ford Fulkerson Algorithm 2 | 3 | from collections import defaultdict 4 | 5 | class Graph: 6 | 7 | def __init__(self, graph): 8 | self.graph = graph 9 | self.row = len(graph) 10 | 11 | # BFS - searching algorithm 12 | def BFS(self, s, t, parent): 13 | 14 | visited = [False] * (self.row) 15 | queue = [] 16 | 17 | queue.append(s) 18 | visited[s] = True 19 | 20 | while queue: 21 | 22 | u = queue.pop(0) 23 | 24 | for ind, val in enumerate(self.graph[u]): 25 | if visited[ind] == False and val > 0: 26 | queue.append(ind) 27 | visited[ind] = True 28 | parent[ind] = u 29 | 30 | return True if visited[t] else False 31 | 32 | # Applying fordfulkerson algorithm 33 | def ford_fulkerson(self, source, sink): 34 | parent = [-1] * (self.row) 35 | max_flow = 0 36 | 37 | while self.BFS(source, sink, parent): 38 | 39 | path_flow = float("Inf") 40 | s = sink 41 | while(s != source): 42 | path_flow = min(path_flow, self.graph[parent[s]][s]) 43 | s = parent[s] 44 | 45 | # Adding the path flows 46 | max_flow += path_flow 47 | 48 | # Updating the residual values of edges 49 | v = sink 50 | while(v != source): 51 | u = parent[v] 52 | self.graph[u][v] -= path_flow 53 | self.graph[v][u] += path_flow 54 | v = parent[v] 55 | 56 | return max_flow 57 | 58 | # Driver Code 59 | graph = [[0, 8, 0, 0, 3, 0], 60 | [0, 0, 9, 0, 0, 0], 61 | [0, 0, 0, 0, 7, 2], 62 | [0, 0, 0, 0, 0, 5], 63 | [0, 0, 7, 4, 0, 0], 64 | [0, 0, 0, 0, 0, 0]] 65 | 66 | g = Graph(graph) 67 | 68 | source = 0 69 | sink = 5 70 | 71 | print("Max Flow: %d " % g.ford_fulkerson(source, sink)) -------------------------------------------------------------------------------- /Practice Concepts/Greedy Algorithms/huffman.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Huffman Coding 2 | 3 | string = 'BCAADDDCCACACAC' 4 | 5 | 6 | # Creating tree nodes 7 | class NodeTree(object): 8 | 9 | def __init__(self, left=None, right=None): 10 | self.left = left 11 | self.right = right 12 | 13 | def children(self): 14 | return (self.left, self.right) 15 | 16 | def nodes(self): 17 | return (self.left, self.right) 18 | 19 | def __str__(self): 20 | return '%s_%s' % (self.left, self.right) 21 | 22 | 23 | # Main function implementing huffman coding 24 | def huffman_code_tree(node, left=True, binString=''): 25 | if type(node) is str: 26 | return {node: binString} 27 | (l, r) = node.children() 28 | d = dict() 29 | d.update(huffman_code_tree(l, True, binString + '0')) 30 | d.update(huffman_code_tree(r, False, binString + '1')) 31 | return d 32 | 33 | 34 | # Calculating frequency 35 | freq = {} 36 | for c in string: 37 | if c in freq: 38 | freq[c] += 1 39 | else: 40 | freq[c] = 1 41 | 42 | freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) 43 | 44 | nodes = freq 45 | 46 | while len(nodes) > 1: 47 | (key1, c1) = nodes[-1] 48 | (key2, c2) = nodes[-2] 49 | nodes = nodes[:-2] 50 | node = NodeTree(key1, key2) 51 | nodes.append((node, c1 + c2)) 52 | 53 | nodes = sorted(nodes, key=lambda x: x[1], reverse=True) 54 | 55 | huffmanCode = huffman_code_tree(nodes[0][0]) 56 | 57 | print(' Char | Huffman code ') 58 | print('----------------------') 59 | for (char, frequency) in freq: 60 | print(' %-4r |%12s' % (char, huffmanCode[char])) -------------------------------------------------------------------------------- /Practice Concepts/Greedy Algorithms/kruskal.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Kruskal's Algorithm 2 | 3 | class Graph: 4 | def __init__(self, vertices): 5 | self.V = vertices 6 | self.graph = [] 7 | 8 | def add_edge(self, u, v, w): 9 | self.graph.append([u, v, w]) 10 | 11 | # Search function 12 | 13 | def find(self, parent, i): 14 | if parent[i] == i: 15 | return i 16 | return self.find(parent, parent[i]) 17 | 18 | def apply_union(self, parent, rank, x, y): 19 | xroot = self.find(parent, x) 20 | yroot = self.find(parent, y) 21 | if rank[xroot] < rank[yroot]: 22 | parent[xroot] = yroot 23 | elif rank[xroot] > rank[yroot]: 24 | parent[yroot] = xroot 25 | else: 26 | parent[yroot] = xroot 27 | rank[xroot] += 1 28 | 29 | # Applying Kruskal algorithm 30 | def kruskal_algo(self): 31 | result = [] 32 | i, e = 0, 0 33 | self.graph = sorted(self.graph, key=lambda item: item[2]) 34 | parent = [] 35 | rank = [] 36 | for node in range(self.V): 37 | parent.append(node) 38 | rank.append(0) 39 | while e < self.V - 1: 40 | u, v, w = self.graph[i] 41 | i = i + 1 42 | x = self.find(parent, u) 43 | y = self.find(parent, v) 44 | if x != y: 45 | e = e + 1 46 | result.append([u, v, w]) 47 | self.apply_union(parent, rank, x, y) 48 | for u, v, weight in result: 49 | print("%d - %d: %d" % (u, v, weight)) 50 | 51 | 52 | g = Graph(6) 53 | g.add_edge(0, 1, 4) 54 | g.add_edge(0, 2, 4) 55 | g.add_edge(1, 2, 2) 56 | g.add_edge(1, 0, 4) 57 | g.add_edge(2, 0, 4) 58 | g.add_edge(2, 1, 2) 59 | g.add_edge(2, 3, 3) 60 | g.add_edge(2, 5, 2) 61 | g.add_edge(2, 4, 4) 62 | g.add_edge(3, 2, 3) 63 | g.add_edge(3, 4, 3) 64 | g.add_edge(4, 2, 4) 65 | g.add_edge(4, 3, 3) 66 | g.add_edge(5, 2, 2) 67 | g.add_edge(5, 4, 3) 68 | g.kruskal_algo() -------------------------------------------------------------------------------- /Practice Concepts/Greedy Algorithms/prim.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Prim's Algorithm 2 | 3 | INF = 9999999 4 | # number of vertices in graph 5 | V = 5 6 | # create a 2d array of size 5x5 7 | # for adjacency matrix to represent graph 8 | G = [[0, 9, 75, 0, 0], 9 | [9, 0, 95, 19, 42], 10 | [75, 95, 0, 51, 66], 11 | [0, 19, 51, 0, 31], 12 | [0, 42, 66, 31, 0]] 13 | # create a array to track selected vertex 14 | # selected will become true otherwise false 15 | selected = [0, 0, 0, 0, 0] 16 | # set number of edge to 0 17 | no_edge = 0 18 | # the number of egde in minimum spanning tree will be 19 | # always less than(V - 1), where V is number of vertices in 20 | # graph 21 | # choose 0th vertex and make it true 22 | selected[0] = True 23 | # print for edge and weight 24 | print("Edge : Weight\n") 25 | while (no_edge < V - 1): 26 | # For every vertex in the set S, find the all adjacent vertices 27 | #, calculate the distance from the vertex selected at step 1. 28 | # if the vertex is already in the set S, discard it otherwise 29 | # choose another vertex nearest to selected vertex at step 1. 30 | minimum = INF 31 | x = 0 32 | y = 0 33 | for i in range(V): 34 | if selected[i]: 35 | for j in range(V): 36 | if ((not selected[j]) and G[i][j]): 37 | # not in selected and there is an edge 38 | if minimum > G[i][j]: 39 | minimum = G[i][j] 40 | x = i 41 | y = j 42 | print(str(x) + "-" + str(y) + ":" + str(G[x][y])) 43 | selected[y] = True 44 | no_edge += 1 -------------------------------------------------------------------------------- /Practice Concepts/Search/binary-search.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Binary Search Algorithm 2 | 3 | def binarySearch(array, x, low, high): 4 | 5 | if high >= low: 6 | 7 | mid = low + (high - low) // 2 8 | 9 | # If found at mid, then return it 10 | if array[mid] == x: 11 | return mid 12 | 13 | # Search the left half 14 | elif array[mid] > x: 15 | return binarySearch(array, x, low, mid-1) 16 | 17 | # Search the right half 18 | else: 19 | return binarySearch(array, x, mid + 1, high) 20 | 21 | else: 22 | return -1 23 | 24 | 25 | array = [3, 4, 5, 6, 7, 8, 9] 26 | x = 4 27 | 28 | result = binarySearch(array, x, 0, len(array)-1) 29 | 30 | if result != -1: 31 | print("Element is present at index " + str(result)) 32 | else: 33 | print("Not found") -------------------------------------------------------------------------------- /Practice Concepts/Search/linear-search.py: -------------------------------------------------------------------------------- 1 | # Pythonn implementation of Linear Search Algorithm 2 | 3 | def linearSearch(array, x): 4 | for i in range(len(array)): 5 | if(array[i] == x): 6 | return i 7 | return -1 8 | 9 | # Driver Code 10 | array = [2, 4, 0, 1, 9] 11 | x = 1 12 | result = linearSearch(array, x) 13 | if(result == -1): 14 | print("Element not found") 15 | else: 16 | print("Element found at index: ", result) -------------------------------------------------------------------------------- /Practice Concepts/Sorting/bubble-sort.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Bubble Sort algorithm 2 | 3 | def bubbleSort(inputArr): 4 | # Do not go through if array is sorted 5 | swapped = False 6 | 7 | # Outer Loop - for checking all the elements 8 | for i in range(len(inputArr) - 1): 9 | # Inner Loop - for swapping 10 | for j in range(0, len(inputArr) - i - 1): 11 | if(inputArr[j] > inputArr[j + 1]): 12 | swapped = True 13 | inputArr[j], inputArr[j + 1] = inputArr[j + 1], inputArr[j] 14 | 15 | if not swapped: 16 | # Exit the main loop if no swap was needed to be made 17 | return 18 | 19 | inputArr = [5, 10, 4, 2, 3, 18, 15, 22] 20 | bubbleSort(inputArr) 21 | for k in range(len(inputArr)): 22 | print(inputArr[k]) -------------------------------------------------------------------------------- /Practice Concepts/Sorting/bucket-sort.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Bucket Sort Algorithm 2 | 3 | def bucketSort(array): 4 | bucket = [] 5 | 6 | # Create empty buckets 7 | for i in range(len(array)): 8 | bucket.append([]) 9 | 10 | # Insert elements into their respective buckets 11 | for j in array: 12 | index_b = int(10 * j) 13 | bucket[index_b].append(j) 14 | 15 | # Sort the elements of each bucket 16 | for i in range(len(array)): 17 | bucket[i] = sorted(bucket[i]) 18 | 19 | # Get the sorted elements 20 | k = 0 21 | for i in range(len(array)): 22 | for j in range(len(bucket[i])): 23 | array[k] = bucket[i][j] 24 | k += 1 25 | return array 26 | 27 | 28 | array = [.42, .32, .33, .52, .37, .47, .51, .51] 29 | print("Sorted Array in descending order is") 30 | print(bucketSort(array)) -------------------------------------------------------------------------------- /Practice Concepts/Sorting/counting-sort.py: -------------------------------------------------------------------------------- 1 | # Python implementation for Counting Sort Algorithm 2 | 3 | def countingsort(array): 4 | size = len(array) 5 | output = [0] * size 6 | 7 | # Initialize the count array 8 | count = [0] * 10 9 | 10 | # Store the count of each element in the count array 11 | for i in range(0, size): 12 | count[array[i]] += 1 13 | 14 | # Store the cummulative count 15 | for i in range(1, 10): 16 | count[i] += count[i - 1] 17 | 18 | # Find the index of each element of the original array in count array place the elements in output array 19 | i = size - 1 20 | while i >= 0: 21 | output[count[array[i]] - 1] = array[i] 22 | count[array[i]] -= 1 23 | i -= 1 24 | 25 | # Copy the sorted elements into original array 26 | for i in range(0, size): 27 | array[i] = output[i] 28 | 29 | # Driver Code 30 | data = [4, 2, 2, 8, 3, 3, 1] 31 | countingsort(data) 32 | print("Sorted Array in Ascending Order: ") 33 | print(data) -------------------------------------------------------------------------------- /Practice Concepts/Sorting/heap-sort.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Heap Sort Algorithm 2 | 3 | def heapify(arr, n, i): 4 | # Find largest among root and children 5 | largest = i 6 | l = 2 * i + 1 7 | r = 2 * i + 2 8 | 9 | if l < n and arr[i] < arr[l]: 10 | largest = l 11 | 12 | if r < n and arr[largest] < arr[r]: 13 | largest = r 14 | 15 | # If root is not largest, swap with largest and continue heapifying 16 | if largest != i: 17 | arr[i], arr[largest] = arr[largest], arr[i] 18 | heapify(arr, n, largest) 19 | 20 | 21 | def heapSort(arr): 22 | n = len(arr) 23 | 24 | # Build max heap 25 | for i in range(n//2, -1, -1): 26 | heapify(arr, n, i) 27 | 28 | for i in range(n-1, 0, -1): 29 | # Swap 30 | arr[i], arr[0] = arr[0], arr[i] 31 | 32 | # Heapify root element 33 | heapify(arr, i, 0) 34 | 35 | # Driver Code 36 | arr = [1, 12, 9, 5, 6, 10] 37 | heapSort(arr) 38 | n = len(arr) 39 | print("Sorted array is") 40 | for i in range(n): 41 | print("%d " % arr[i], end='') -------------------------------------------------------------------------------- /Practice Concepts/Sorting/insertion-sort.py: -------------------------------------------------------------------------------- 1 | # Insertion Sort Algorithm 2 | 3 | def insertionSort(arrayToBeSorted): 4 | 5 | # Outer loop - start from the second element in the list 6 | for i in range(1, len(arrayToBeSorted)): 7 | # Element to be sorted 8 | key = arrayToBeSorted[i] 9 | 10 | # Move elements that are greater than the key one place to the right 11 | # Checking for the comparison from right to left 12 | j = i - 1 13 | while j >= 0 and key < arrayToBeSorted[j]: 14 | arrayToBeSorted[j + 1] = arrayToBeSorted[j] 15 | j -= 1 16 | arrayToBeSorted[j + 1] = key 17 | return arrayToBeSorted 18 | 19 | arrayToBeSorted = [10, 8, 12, 19, 6, 2] 20 | print('Original List:', arrayToBeSorted) 21 | print('Sorted List (via Insertion Sort): ', insertionSort(arrayToBeSorted)) 22 | -------------------------------------------------------------------------------- /Practice Concepts/Sorting/merge-sort.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Merge Sort algorithm 2 | 3 | def mergeSort(inputArr): 4 | if(len(inputArr)) > 1: 5 | 6 | # Point of division for the array into subarrays 7 | r = len(inputArr)//2 8 | subA1 = inputArr[:r] 9 | subA2 = inputArr[r:] 10 | 11 | # Recursively divide the array until only single elements are left, and sort them 12 | mergeSort(subA1) 13 | mergeSort(subA2) 14 | 15 | i = j = k = 0 16 | 17 | # Until we reach the end of either of the sub arrays, pick the smaller amongst the 2 and place in array 18 | while i < len(subA1) and j < len(subA2): 19 | if(subA1[i] < subA2[j]): 20 | inputArr[k] = subA1[i] 21 | i += 1 22 | else: 23 | inputArr[k] = subA2[j] 24 | j += 1 25 | k += 1 26 | 27 | # Place remaining elements in the output array 28 | while i < len(subA1): 29 | inputArr[k] = subA1[i] 30 | i += 1 31 | k += 1 32 | 33 | while j < len(subA2): 34 | inputArr[k] = subA2[j] 35 | j += 1 36 | k += 1 37 | 38 | # Driver code 39 | inputArr = [5, 10, 4, 2, 3, 18, 15, 22] 40 | mergeSort(inputArr) 41 | for l in range(len(inputArr)): 42 | print(inputArr[l]) -------------------------------------------------------------------------------- /Practice Concepts/Sorting/quick-sort.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Quicksort algorithm 2 | 3 | # Quicksort algorithm 4 | def quicksort(array, low, high): 5 | if low < high: 6 | pv = divAcon(array, low, high) 7 | 8 | # Left of Pivot 9 | quicksort(array, low, pv - 1) 10 | 11 | # Right of Pivot 12 | quicksort(array, pv + 1, high) 13 | 14 | # Divide and Conquer algorithm 15 | def divAcon(array, low, high): 16 | # Rightmost element 17 | pivot = array[high] 18 | 19 | # Second pointer 20 | i = low - 1 21 | 22 | for j in range(low, high): 23 | if array[j] <= pivot: 24 | i = i + 1 25 | array[i], array[j] = array[j], array[i] 26 | # swap the pivot element with the greater element specified by i 27 | array[i + 1], array[high] = array[high], array[i + 1] 28 | 29 | return i + 1 # this is where the partition is done 30 | 31 | # Driver code 32 | data = [8, 7, 2, 1, 0, 9, 6] 33 | print("Unsorted Array") 34 | print(data) 35 | 36 | size = len(data) 37 | 38 | quicksort(data, 0, size - 1) 39 | 40 | print('Sorted Array in Ascending Order:') 41 | print(data) -------------------------------------------------------------------------------- /Practice Concepts/Sorting/radix-sort.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Radix Sort Algorithm 2 | 3 | # Using Counting Sort to sort the elements on the basis of significant places 4 | def countingsort(array, place): 5 | size = len(array) 6 | output = [0] * size 7 | count = [0] * 10 8 | 9 | # Calculate the count of elements 10 | for i in range(0, size): 11 | index = array[i] // place 12 | count[index % 10] += 1 13 | 14 | # Calculate the cumulative count 15 | for i in range(1, 10): 16 | count[i] += count[i - 1] 17 | 18 | # Place the elements in sorted order 19 | i = size - 1 20 | while i >= 0: 21 | index = array[i] // place 22 | output[count[index % 10] - 1] = array[i] 23 | count[index % 10] -= 1 24 | i -= 1 25 | 26 | for i in range(0, size): 27 | array[i] = output[i] 28 | 29 | # Radix Sort 30 | def radixsort(array): 31 | # Get maximum element 32 | max_element = max(array) 33 | 34 | # Apply counting sort to sort elements based on place value. 35 | place = 1 36 | while max_element // place > 0: 37 | countingsort(array, place) 38 | place *= 10 39 | 40 | # Driver Code 41 | data = [121, 432, 564, 23, 1, 45, 788] 42 | radixsort(data) 43 | print(data) -------------------------------------------------------------------------------- /Practice Concepts/Sorting/selection-sort.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Selection Sort algorithm 2 | 3 | def selectionSort(inputArr): 4 | 5 | # Outer Loop to traverse through all array elements 6 | for i in range(len(inputArr)): 7 | # Set the current value index as the minimum index 8 | index_of_min = i 9 | 10 | # Inner Loop to find the index of minimum value 11 | for j in range(i + 1, len(inputArr)): 12 | if(inputArr[index_of_min] > inputArr[j]): 13 | index_of_min = j 14 | 15 | inputArr[i], inputArr[index_of_min] = inputArr[index_of_min], inputArr[i] 16 | 17 | inputArr = [5, 10, 4, 2, 3, 18, 15, 22] 18 | selectionSort(inputArr) 19 | for k in range(len(inputArr)): 20 | print(inputArr[k]) -------------------------------------------------------------------------------- /Practice Concepts/Trees/balanced-binary-tree.py: -------------------------------------------------------------------------------- 1 | # Python implementation for checking if balanced binary tree 2 | 3 | class Node: 4 | def __init__(self, data): 5 | self.data = data 6 | self.left = None 7 | self.right = None 8 | 9 | class Height: 10 | def __init__(self): 11 | self.height = 0 12 | 13 | def isHeightBalanced(root, height): 14 | left_height = Height() 15 | right_height = Height() 16 | 17 | if root is None: 18 | return True 19 | 20 | l = isHeightBalanced(root.left, left_height) 21 | r = isHeightBalanced(root.right, right_height) 22 | 23 | height.height = max(left_height.height, right_height.height) + 1 24 | 25 | if abs(left_height.height - right_height.height) <= 1: 26 | return l and r 27 | 28 | return False 29 | 30 | 31 | height = Height() 32 | 33 | root = Node(1) 34 | root.left = Node(2) 35 | root.right = Node(3) 36 | root.left.left = Node(4) 37 | root.left.right = Node(5) 38 | 39 | if isHeightBalanced(root, height): 40 | print('The tree is balanced') 41 | else: 42 | print('The tree is not balanced') 43 | -------------------------------------------------------------------------------- /Practice Concepts/Trees/binary-search-tree.py: -------------------------------------------------------------------------------- 1 | # Python implementation of binary search tree operations 2 | 3 | class Node: 4 | def __init__(self, key): 5 | self.left = None 6 | self.right = None 7 | self.key = key 8 | 9 | # Inorder Traversal 10 | def inOrder(root): 11 | if root is not None: 12 | inOrder(root.left) 13 | print(str(root.key) + "->", end=' ') 14 | inOrder(root.right) 15 | 16 | # Insert a node 17 | def insertNode(node, key): 18 | if node is None: 19 | return Node(key) 20 | 21 | if key < Node.key: 22 | node.left = insertNode(node.left, key) 23 | else: 24 | node.right = insertNode(node.right, key) 25 | 26 | return node 27 | 28 | # INORDER SUCCESSOR 29 | def inOS(node): 30 | current = node 31 | while current.left is not None: 32 | current = current.left 33 | return current 34 | 35 | # Delete Node 36 | def delNode(root, key): 37 | if root is None: 38 | return root 39 | 40 | if key < root.key: 41 | root.left = delNode(root.left, key) 42 | elif(key > root.key): 43 | root.right = delNode(root.right, key) 44 | else: 45 | # If the node is with only one child or no child 46 | if root.left is None: 47 | temp = root.right 48 | root = None 49 | return temp 50 | 51 | elif root.right is None: 52 | temp = root.left 53 | root = None 54 | return temp 55 | 56 | # If the node has two children, 57 | # place the inorder successor in position of the node to be deleted 58 | temp = inOS(root.right) 59 | 60 | root.key = temp.key 61 | 62 | # Delete the inorder successor 63 | root.right = delNode(root.right, temp.key) 64 | 65 | return root 66 | 67 | # Driver Code 68 | root = None 69 | root = insertNode(root, 8) 70 | root = insertNode(root, 3) 71 | root = insertNode(root, 1) 72 | root = insertNode(root, 6) 73 | root = insertNode(root, 7) 74 | root = insertNode(root, 10) 75 | root = insertNode(root, 14) 76 | root = insertNode(root, 4) 77 | 78 | print("Inorder traversal: ", end=' ') 79 | inOrder(root) 80 | 81 | print("\nDelete 10") 82 | root = delNode(root, 10) 83 | print("Inorder traversal: ", end=' ') 84 | inOrder(root) -------------------------------------------------------------------------------- /Practice Concepts/Trees/binary-tree.py: -------------------------------------------------------------------------------- 1 | # Python implementation of Binary Tree 2 | 3 | class Node: 4 | def __init__(self, item): 5 | self.left = None 6 | self.right = None 7 | self.val = item 8 | 9 | def inOrder(self): 10 | if self.left: 11 | self.left.inOrder() 12 | print(self.val, end=' ') 13 | if self.right: 14 | self.right.inOrder() 15 | 16 | def preOrder(self): 17 | print(self.val, end=' ') 18 | if self.left: 19 | self.left.preOrder() 20 | if self.right: 21 | self.right.preOrder() 22 | 23 | def postOrder(self): 24 | if self.left: 25 | self.left.postOrder() 26 | if self.right: 27 | self.right.postOrder() 28 | print(self.val, end=' ') 29 | 30 | # Driver Code 31 | root = Node(1) 32 | root.left = Node(2) 33 | root.right = Node(3) 34 | root.left.left = Node(4) 35 | 36 | print("Pre order Traversal: ", end="") 37 | root.preOrder() 38 | print("\nIn order Traversal: ", end="") 39 | root.inOrder() 40 | print("\nPost order Traversal: ", end="") 41 | root.postOrder() 42 | 43 | 44 | -------------------------------------------------------------------------------- /Practice Concepts/Trees/complete-binary-tree.py: -------------------------------------------------------------------------------- 1 | # Python implementation for checking if complete binary tree 2 | 3 | class Node: 4 | def __init__(self, item): 5 | self.left = None 6 | self.right = None 7 | self.item = item 8 | 9 | # Count number of nodes 10 | def numNodes(root): 11 | if root is None: 12 | return 0 13 | return (1 + numNodes(root.left) + numNodes(root.right)) 14 | 15 | # Check whether it is complete binary tree 16 | def isCompleteTree(root, index, numnodes): 17 | if root is None: 18 | return True 19 | 20 | if index >= numnodes: 21 | return False 22 | 23 | return (isCompleteTree(root.left, 2 * index + 1, numnodes) 24 | and isCompleteTree(root.right, 2 * index + 2, numnodes)) 25 | 26 | # Driver code 27 | root = Node(1) 28 | root.left = Node(2) 29 | root.right = Node(3) 30 | root.left.left = Node(4) 31 | root.left.right = Node(5) 32 | root.right.left = Node(6) 33 | 34 | node_count = numNodes(root) 35 | index = 0 36 | 37 | if isCompleteTree(root, index, node_count): 38 | print("The tree is a complete binary tree") 39 | else: 40 | print("The tree is not a complete binary tree") -------------------------------------------------------------------------------- /Practice Concepts/Trees/full-binary-tree.py: -------------------------------------------------------------------------------- 1 | # Python implementation for checking if full binary tree 2 | 3 | class Node: 4 | def __init__(self, item): 5 | self.leftC = None 6 | self.rightC = None 7 | self.item = item 8 | 9 | def isFullBinaryTree(root): 10 | 11 | # Empty Tree 12 | if root is None: 13 | return True 14 | 15 | if root.leftC is None and root.rightC is None: 16 | return True 17 | 18 | if root.leftC is not None and root.rightC is not None: 19 | return isFullBinaryTree(root.leftC) and isFullBinaryTree(root.rightC) 20 | 21 | return False 22 | 23 | # Driver Code 24 | root = Node(1) 25 | root.rightChild = Node(3) 26 | root.leftChild = Node(2) 27 | root.leftChild.leftChild = Node(4) 28 | root.leftChild.rightChild = Node(5) 29 | root.leftChild.rightChild.leftChild = Node(6) 30 | root.leftChild.rightChild.rightChild = Node(7) 31 | 32 | if(isFullBinaryTree(root)): 33 | print("The tree is a full binary tree") 34 | else: 35 | print("The tree is not a full binary tree") -------------------------------------------------------------------------------- /Practice Concepts/Trees/perfect-binary-tree.py: -------------------------------------------------------------------------------- 1 | # Python implementation for checking if perfect binary tree 2 | 3 | class Node: 4 | def __init__(self, item): 5 | self.left = None 6 | self.right = None 7 | self.key = item 8 | 9 | # Depth Calculation 10 | def depth(node): 11 | d = 0 12 | while node is not None: 13 | d += 1 14 | node = node.left 15 | return d 16 | 17 | # Check is perfect binary tree 18 | def isPerfectBinaryTree(root, d, level = 0): 19 | if root is None: 20 | return True 21 | 22 | if(root.left is None and root.right is None): 23 | return (d == level + 1) 24 | 25 | if(root.left is None or root.right is None): 26 | return False 27 | 28 | return (isPerfectBinaryTree(root.left, d, level + 1) and 29 | isPerfectBinaryTree(root.right, d, level + 1)) 30 | 31 | # Driver code 32 | root = None 33 | root = Node(1) 34 | root.left = Node(2) 35 | root.right = Node(3) 36 | root.left.left = Node(4) 37 | root.left.right = Node(5) 38 | 39 | if (isPerfectBinaryTree(root, depth(root))): 40 | print("The tree is a perfect binary tree") 41 | else: 42 | print("The tree is not a perfect binary tree") 43 | -------------------------------------------------------------------------------- /Practice Concepts/Trees/tree-traverse.py: -------------------------------------------------------------------------------- 1 | # Python implementation of tree traversal 2 | 3 | class Node: 4 | def __init__(self, item): 5 | self.left = None 6 | self.right = None 7 | self.val = item 8 | 9 | def inOrder(root): 10 | 11 | if root: 12 | # Traverse the left subtree 13 | inOrder(root.left) 14 | # Traverse the root 15 | print(str(root.val) + "->", end='') 16 | # Traverse the right subtree 17 | inOrder(root.right) 18 | 19 | def preOrder(root): 20 | if root: 21 | # Traverse the root 22 | print(str(root.val) + "->", end='') 23 | # Traverse the left subtree 24 | preOrder(root.left) 25 | # Traverse the right subtree 26 | preOrder(root.right) 27 | 28 | def postOrder(root): 29 | if root: 30 | # Traverse the left subtree 31 | postOrder(root.left) 32 | # Traverse the right subtree 33 | postOrder(root.right) 34 | # Traverse the root 35 | print(str(root.val) + "->", end='') 36 | 37 | # Driver code 38 | root = Node(1) 39 | root.left = Node(2) 40 | root.right = Node(3) 41 | root.left.left = Node(4) 42 | root.left.right = Node(5) 43 | 44 | print("Inorder traversal ") 45 | inOrder(root) 46 | 47 | print("\nPreorder traversal ") 48 | preOrder(root) 49 | 50 | print("\nPostorder traversal ") 51 | postOrder(root) -------------------------------------------------------------------------------- /Resources/Animations/Bubble-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/Bubble-sort.gif -------------------------------------------------------------------------------- /Resources/Animations/CLL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/CLL.png -------------------------------------------------------------------------------- /Resources/Animations/DLL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/DLL.png -------------------------------------------------------------------------------- /Resources/Animations/Insertion-Sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/Insertion-Sort.gif -------------------------------------------------------------------------------- /Resources/Animations/Merge-Sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/Merge-Sort.gif -------------------------------------------------------------------------------- /Resources/Animations/PUSH-POP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/PUSH-POP.png -------------------------------------------------------------------------------- /Resources/Animations/Selection-Sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/Selection-Sort.gif -------------------------------------------------------------------------------- /Resources/Animations/binary.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/binary.gif -------------------------------------------------------------------------------- /Resources/Animations/bst.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/bst.png -------------------------------------------------------------------------------- /Resources/Animations/bucket.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/bucket.webp -------------------------------------------------------------------------------- /Resources/Animations/cb1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/cb1.png -------------------------------------------------------------------------------- /Resources/Animations/cb2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/cb2.png -------------------------------------------------------------------------------- /Resources/Animations/cb3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/cb3.png -------------------------------------------------------------------------------- /Resources/Animations/cb4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/cb4.png -------------------------------------------------------------------------------- /Resources/Animations/cb5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/cb5.png -------------------------------------------------------------------------------- /Resources/Animations/counting-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/counting-sort.gif -------------------------------------------------------------------------------- /Resources/Animations/dgen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/dgen.png -------------------------------------------------------------------------------- /Resources/Animations/enq-dq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/enq-dq.png -------------------------------------------------------------------------------- /Resources/Animations/full-binary-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/full-binary-tree.png -------------------------------------------------------------------------------- /Resources/Animations/graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/graph.png -------------------------------------------------------------------------------- /Resources/Animations/h(x).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/h(x).png -------------------------------------------------------------------------------- /Resources/Animations/heapsort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/heapsort.gif -------------------------------------------------------------------------------- /Resources/Animations/in-order-traversal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/in-order-traversal.gif -------------------------------------------------------------------------------- /Resources/Animations/linear.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/linear.gif -------------------------------------------------------------------------------- /Resources/Animations/linked-list-complexity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/linked-list-complexity.png -------------------------------------------------------------------------------- /Resources/Animations/linked-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/linked-list.png -------------------------------------------------------------------------------- /Resources/Animations/min-max-heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/min-max-heap.png -------------------------------------------------------------------------------- /Resources/Animations/node-edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/node-edge.png -------------------------------------------------------------------------------- /Resources/Animations/perfect-binary-tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/perfect-binary-tree.png -------------------------------------------------------------------------------- /Resources/Animations/post-order-traversal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/post-order-traversal.gif -------------------------------------------------------------------------------- /Resources/Animations/pre-order-traversal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/pre-order-traversal.gif -------------------------------------------------------------------------------- /Resources/Animations/quicksort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/quicksort.gif -------------------------------------------------------------------------------- /Resources/Animations/radix-sort.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/radix-sort.gif -------------------------------------------------------------------------------- /Resources/Animations/skew.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/skew.png -------------------------------------------------------------------------------- /Resources/Animations/strongly-connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Animations/strongly-connected.png -------------------------------------------------------------------------------- /Resources/Books/Data Structure and Algorithmic Thinking with Python Data Structure and Algorithmic Puzzles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Books/Data Structure and Algorithmic Thinking with Python Data Structure and Algorithmic Puzzles.pdf -------------------------------------------------------------------------------- /Resources/Books/Data Structures and Algorithms Made Easy_ Data Structures and Algorithmic Puzzles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Books/Data Structures and Algorithms Made Easy_ Data Structures and Algorithmic Puzzles.pdf -------------------------------------------------------------------------------- /Resources/Books/Grokking Algorithms.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Books/Grokking Algorithms.pdf -------------------------------------------------------------------------------- /Resources/Books/Introduction to Algorithms, Third Edition.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/Resources/Books/Introduction to Algorithms, Third Edition.pdf -------------------------------------------------------------------------------- /extras/Arrays and Strings/LargestNumberAtLeastTwiceOthers.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given an integer array nums where the largest integer is unique. 3 | Determine whether the largest element in the array is at least twice as much as every other number in the array. 4 | If it is, return the index of the largest element, or return -1 otherwise. 5 | ''' 6 | 7 | def dominantIndex(self, nums: List[int]) -> int: 8 | largest = max(nums) 9 | index = nums.index(largest) 10 | temp = [val*2 for val in nums] 11 | temp.pop(index) 12 | count = 0 13 | for i in range(len(temp)): 14 | if(largest >= temp[i]): 15 | count += 1 16 | if(count == len(temp)): 17 | return index 18 | else: 19 | return -1 -------------------------------------------------------------------------------- /extras/Arrays and Strings/PivotIndex.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array of integers nums, calculate the pivot index of this array. 3 | The pivot index is the index where the sum of all the numbers strictly to the left of the index is equal to the sum of all the numbers strictly to the index's right. 4 | If the index is on the left edge of the array, then the left sum is 0 because there are no elements to the left. 5 | This also applies to the right edge of the array. 6 | Return the leftmost pivot index. If no such index exists, return -1. 7 | ''' 8 | 9 | def pivotIndex(self, nums: List[int]) -> int: 10 | leftSum = 0 11 | rightSum = sum(nums) 12 | for i in range(len(nums)): 13 | rightSum -= nums[i] 14 | if leftSum == rightSum: 15 | return i 16 | leftSum += nums[i] 17 | 18 | return -1 -------------------------------------------------------------------------------- /extras/Arrays and Strings/PlusOne.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given a large integer represented as an integer array digits, 3 | where each digits[i] is the ith digit of the integer. 4 | The digits are ordered from most significant to least significant in left-to-right order. 5 | The large integer does not contain any leading 0's. 6 | Increment the large integer by one and return the resulting array of digits. 7 | ''' 8 | 9 | def plusOne(self, digits: List[int]) -> List[int]: 10 | res = [] 11 | digits = [str(i) for i in digits] 12 | val = ''.join(digits) 13 | val = int(val) 14 | val += 1 15 | res = [int(i) for i in str(val)] 16 | return res -------------------------------------------------------------------------------- /extras/Arrays and Strings/README.md: -------------------------------------------------------------------------------- 1 | # Arrays and Strings 2 | ###### This section covers basic arrays and strings concepts - 3 | 4 | - An **array** is a basic data structure to store a collection of elements sequentially. These elements, however, can be accessed randomly via index values of the elements in arrays. 5 | - Arrays can have one (linear) or more dimensions 6 | - Index values start from 0 7 | - An array has a fixed capacity, need to specify size during intialization - difficult to initialise 8 | - Use of **dynamic arrays** - arrays with variable size 9 | - In a 2D array, the elements are laid out in a rectangular grid, rather than a line 10 | - In some programming languages, multidimensional arrays are represented as one dimensional arrays, and in others, the concept of multidimensional arrays does not exist. 11 | - C++ - 2D arrays are stored as 1D arrays - A[i][j] equals to A[i * N + j] if we defined A as a one dimensional array which also contains M * N elements. 12 | - Java: Two dimensional array is actually a one dimensional array which contains M elements, each of which is an array of N integers. 13 | -------------------------------------------------------------------------------- /extras/Basics/Big-O Notation.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/extras/Basics/Big-O Notation.jpeg -------------------------------------------------------------------------------- /extras/Basics/Omega Notation.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/extras/Basics/Omega Notation.jpeg -------------------------------------------------------------------------------- /extras/Basics/README.md: -------------------------------------------------------------------------------- 1 | # Basics - Introduction 2 | ###### This section covers the basic, underlying concepts of algorithms and data structure, to provide a solid foundation for more complex cases and problems in this domain. 3 | 4 | - **Variables** are placeholders for data (in equations and programming logic) 5 | - These variables take the form of specific data types. **Data types** are a set of data with predefined values - integers, floats, characters, string, boolean, etc 6 | - Data types occupy a set amount of memory units (bytes). There are two types of data types - primitive (system defined) and user defined data types. 7 | - **Primitive data types** - char, int, float, double, bool, etc - provided by the programming language - the number of bits allocated to each data type depends on the programming language, compiler and the operating system. 8 | - **User defined data types** - structures in C and classes in Java - when primitive data types are not enough - gives more flexibility, we can combine primitive types. 9 | - **Data structure** is a way of storing and organising data in a computer - arrays, linked lists, stacks, queues, trees, graphs 10 | - **Linear data structures** - elements accessed in sequential order, but not necessarily stored that way - linked lists, stacks and queues. 11 | - **Non Linear data structures** - elements stored and accessed in a non-linear order - trees and graphs 12 | - **Abstract Data Types** - When we combine data structures with their operations, which involves the declaration of data and operations. 13 | - An **algorithm** is the step by step instructions to solve a given problem. There are multiple algorithms to solve the same problem, and the analysis of these algorithms helps determine the algorithms most efficient in terms of computation time and space consumed. 14 | - The goal of algorithmic analysis is to compare different algorithms in terms of **running time** and **memory**. 15 | - Running time analysis involves determining the increase in processing time as the size of input (number of elements) increases. 16 | - Algorithms are compared by expressing the running time of a given algorithm as a function of the input - independent of factors such as machine capability, programming style. 17 | - Rate of growth is defined as the rate at which the running time increases (with input) 18 | - **Rates of growth** - 19 | ``` n! > 4^n > 2^n > n^2 > nlog(n) > log(n!) > n > 2^logn > log^2(n) > sqrt(logn) > log(logn) > 1 ``` 20 | - **Worst Case**: Defines the input for which the algorithm takes the longest time (slowest) 21 | - **Best Case**: Defines the input for which the algorithm takes the least time (fastest) 22 | - **Average Case**: Provides a prediction about the running of the algorithm - random input 23 | - Upper and lower bounds need to be computed for all the 3 aforementioned cases - need notations to represent these bounds. 24 | - **Big-O Notation** - Gives the tight upper bound for a function. Outputs a function which gives the maximum rate of growth for the input function at larger values of n (input). We usually consider values of input above a given threshold. 25 | - **Omega Notation**: Gives the tight lower bound for a given algorithm. 26 | - **Theta Notation**: Decides whether the upper and lower bounds are the same for a given algorithm. In this case, best case and worst case are the same - average case will also be the same. 27 | - The general focus is on the upper bound of an algorithm - Big-O Notation. 28 | - **Loops:** The running time of a loop is, at most, the running time of the statements inside the loop (including tests) multiplied by the number of iterations 29 | - **Nested Loops:** Analyse from the inside out. Total running time is the product of the sizes of all the loops 30 | - **Consecutive Statements:** Add the time complexities of each statement 31 | - **If-then-else statements:** Worst case running time: the test, plus either the *then* part or the *else* part (whichever is the larger) 32 | - **Logarithmic complexity:** An algorithm is O(logn) if it takes a constant time to cut the problem size by a fraction 33 | - More information + mathematical induction can be found in the [Basics](/Basics) directory (images). 34 | -------------------------------------------------------------------------------- /extras/Basics/Theta Notation.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/extras/Basics/Theta Notation.jpeg -------------------------------------------------------------------------------- /extras/Binary Tree/README.md: -------------------------------------------------------------------------------- 1 | # Binary Trees 2 | ###### This section covers basic binary tree concepts - 3 | 4 | - A **tree** is a data structure that represents hierarchical information. 5 | - Each node has a root node and references to other nodes, which are child nodes. 6 | - Can also be defined as a **directed acyclic graph** -> ``` N Nodes and N - 1 edges ``` 7 | - Each node has at most **2** child nodes 8 | 9 | ## Tree Traversal 10 | - **Pre-order Traversal**: Visit the root first - then traverse the left subtree, then right. 11 | - **In-order Traversal**: Traverse the left subtree, Visit the root, Traverse the right subtree. 12 | - **Post-order Traversal**: Traverse the left subtree, Traverse the right subtree, Visit the root. 13 | - Deletion process of nodes will be post-order. 14 | -------------------------------------------------------------------------------- /extras/Graphs/README.md: -------------------------------------------------------------------------------- 1 | # Graphs 2 | ###### This section covers basic graphs concepts. 3 | 4 | - A graph is a non-linear data structure consisting of vertices and edges. 5 | - **Vertex** is a node in a graph 6 | - **Path** - The sequence of vertices to go through from one vertex to another. 7 | - **Path Length** - The number of edges in a path 8 | - **Cycle** - A path where the starting point and endpoint are the same vertex. 9 | - **Negative Weight Cycle** - In a weighted graph, if the sum of the weights of all edges of a cycle is a negative value. 10 | - **Connectivity** - If there exists at least one path between two vertices, these two vertices are connected. 11 | - **Degree of a Vertex** - The term degree applies to unweighted graphs. The degree of a vertex is the number of edges connecting the vertex. 12 | - **In-Degree** - In-Degree is a concept in directed graphs. If the in-degree of a vertex is d, there are d directional edges incident to the vertex. 13 | - **Out-Degree** - Out-Degree is a concept in directed graphs. If the out-degree of a vertex is d, there are d edges incident from the vertex. 14 | - **Edge** - The connection between two vertices are the edges of the graph. 15 | - **Undirected Graphs** - The edges between any two vertices in an undirected graph do not have a direction, indicating a two-way relationship. 16 | - **Directed Graphs** - The edges between any two vertices in a directed graph are directional. 17 | - **Weighted Graphs** - Each edge in a weighted graph has an associated weight, which can be of any metric. 18 | 19 | ## Disjoint Sets 20 | - Also known as union-find data structure 21 | - Primary objective of disjoint sets is to address the connectivity between the components of a network. 22 | - **Parent Node** - The direct parent node of a vertex (adjacent to it) 23 | - **Root Node** - A node without a parent node - it can be viewed as the parent node of itself. Sometimes referred to as the head node. 24 | - Connections can be direct or indirect 25 | - Use sets (unions) to connect vertices and compare root nodes to check for connectivity 26 | - The find function finds the root node of a given vertex, the union function unions two vertices and makes their root nodes the same. 27 | - Implementation with *Quick Find*: in this case, the time complexity of the find function will be O(1). However, the union function will take more time with the time complexity of O(N). 28 | > - When initializing a union-find constructor, we need to create an array of size N with the values equal to the corresponding array indices; this requires linear time. 29 | > - Each call to find will require O(1) time since we are just accessing an element of the array at the given index. 30 | > - Each call to union will require O(N) time because we need to traverse through the entire array and update the root vertices for all the vertices of the set that is going to be merged into another set. 31 | > - The connected operation takes O(1) time since it involves the two find calls and the equality check operation. 32 | - Implementation with *Quick Union*: compared with the Quick Find implementation, the time complexity of the union function is better. Meanwhile, the find function will take more time in this case. 33 | > - The same as in the quick find implementation, when initializing a union-find constructor, we need to create an array of size N with the values equal to the corresponding array indices; this requires linear time. 34 | > - For the find operation, in the worst-case scenario, we need to traverse every vertex to find the root for the input vertex. The maximum number of operations to get the root vertex would be no more than the tree's height, so it will take O(N) time. 35 | > - The union operation consists of two find operations which (only in the worst-case) will take O(N) time, and two constant time operations, including the equality check and updating the array value at a given index. Therefore, the union operation also costs O(N) in the worst-case. 36 | > - The connected operation also takes O(N) time in the worst-case since it involves two find calls. 37 | - *Union by rank* - The word “rank” means ordering by specific criteria. Previously, for the union function, we always chose the root node of x and set it as the new root node for the other vertex. However, by choosing the parent node based on certain criteria (by rank), we can limit the maximum height of each vertex. 38 | - Rank refers to the height of each vertex - effectively avoid the possibility of connecting all vertices into a straight line. 39 | - -------------------------------------------------------------------------------- /extras/Recursion and Backtracking/HackerRank/PowerSum.py: -------------------------------------------------------------------------------- 1 | import math 2 | import os 3 | import random 4 | import re 5 | import sys 6 | """ 7 | Python program to count number of ways 8 | to express X as sum of N-th power 9 | of unique natural numbers. 10 | """ 11 | # 12 | # Complete the 'powerSum' function below. 13 | # 14 | # The function is expected to return an INTEGER. 15 | # The function accepts following parameters: 16 | # 1. INTEGER X 17 | # 2. INTEGER N 18 | # 19 | c = 0 20 | 21 | def count(X, N, num): 22 | currentValue = (X - pow(num, N)) 23 | if currentValue == 0: 24 | return c + 1 25 | if currentValue < 0: 26 | return 0 27 | 28 | return count(currentValue, N, num + 1) + count(X, N, num + 1) 29 | 30 | def powerSum(X, N): 31 | # Write your code here 32 | return count(X, N, 1) 33 | 34 | 35 | if __name__ == '__main__': 36 | X = int(input().strip()) 37 | N = int(input().strip()) 38 | result = powerSum(X, N) 39 | print(result) 40 | 41 | -------------------------------------------------------------------------------- /extras/Recursion and Backtracking/HackerRank/RecursiveDigitSum.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | 3 | import math 4 | import os 5 | import random 6 | import re 7 | import sys 8 | """ 9 | Need to complete test cases for very large numbers - goes into runtime error 10 | """ 11 | # 12 | # Complete the 'superDigit' function below. 13 | # 14 | # The function is expected to return an INTEGER. 15 | # The function accepts following parameters: 16 | # 1. STRING n 17 | # 2. INTEGER k 18 | # 19 | 20 | def checkSuperDigit(val): 21 | add = 0 22 | for digit in val: 23 | add = add + int(digit) 24 | 25 | if(len(str(add)) == 1): 26 | return add 27 | 28 | else: 29 | val = str(add) 30 | return checkSuperDigit(val) 31 | 32 | def superDigit(n, k): 33 | # Write your code here 34 | concatVal = n * k 35 | return checkSuperDigit(concatVal) 36 | 37 | 38 | if __name__ == '__main__': 39 | first_multiple_input = input().rstrip().split() 40 | n = first_multiple_input[0] 41 | k = int(first_multiple_input[1]) 42 | result = superDigit(n, k) 43 | -------------------------------------------------------------------------------- /extras/Recursion and Backtracking/LeetCode/MergeTwoSortedLists.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aish21/Algorithms-and-Data-Structures/5d44320a70bd01fe9ba06c535b3b4ed3479e5566/extras/Recursion and Backtracking/LeetCode/MergeTwoSortedLists.py -------------------------------------------------------------------------------- /extras/Recursion and Backtracking/LeetCode/ReverseString.py: -------------------------------------------------------------------------------- 1 | def ReverseString(s): 2 | start = 0 3 | end = len(s) - 1 4 | 5 | while(start < end): 6 | temp = s[start] 7 | s[start] = s[end] 8 | s[end] = temp 9 | 10 | start += 1 11 | end -= 1 12 | 13 | print(s) 14 | 15 | userInp = input('Enter String:\n') 16 | ReverseString(list(userInp)) 17 | -------------------------------------------------------------------------------- /extras/Recursion and Backtracking/README.md: -------------------------------------------------------------------------------- 1 | # Recursion 2 | ###### This section covers basic recursion concepts. 3 | 4 | - -------------------------------------------------------------------------------- /extras/Search Algorithms/BinaySearch.py: -------------------------------------------------------------------------------- 1 | """ 2 | > Requires list to be ordered 3 | > Uses divide and conquer approach 4 | > Check half, if element less than half, then must be on the left. 5 | > Continue this process until the element is found 6 | > Two approaches - iterative and recursive 7 | > Time complexity is O(log(n)) 8 | """ 9 | 10 | def BinarySearch_Iterative(list, item): 11 | low = 0 12 | high = len(list) - 1 13 | mid = 0 14 | itemFound = False 15 | 16 | while(low <= high) and not itemFound: 17 | mid = low + (high - low)/2 18 | 19 | if(list[mid] < item): 20 | low = mid + 1 21 | 22 | elif(list[mid] > item): 23 | high = mid - 1 24 | 25 | else: 26 | itemFound = True 27 | return itemFound, mid 28 | 29 | return itemFound 30 | 31 | def BinarySearch_Recursive(list, item, low, high): 32 | itemFound = False 33 | 34 | if(low > high): 35 | return itemFound 36 | mid = low + (high - low)/2 37 | if(list[mid] < item): 38 | BinarySearch_Recursive(list, item, mid + 1, high) 39 | elif(list[mid] > item): 40 | BinarySearch_Recursive(list, item, low, mid - 1) 41 | else: 42 | itemFound = True 43 | return mid, itemFound 44 | 45 | -------------------------------------------------------------------------------- /extras/Search Algorithms/SequentialSearch.py: -------------------------------------------------------------------------------- 1 | """ 2 | > Also known as linear search 3 | > Check for the desired element in sequence until it is found or the 4 | list is exhausted. 5 | > Need not be Ordered. 6 | > Time complexity is O(n) 7 | """ 8 | 9 | def SequentialSearch(list, item): 10 | index = 0 11 | itemFound = False 12 | 13 | while index < len(list) and not itemFound: 14 | if list[index] == item: 15 | itemFound = True 16 | else: 17 | index += 1 18 | 19 | return index, itemFound -------------------------------------------------------------------------------- /extras/Sorting Algorithms/BubbleSort.py: -------------------------------------------------------------------------------- 1 | """ 2 | > Compares a pair of elements in one iteration 3 | > Moves larger to the right 4 | > Sorted grows from right to left 5 | > Worst, Average Case - O(n^2) 6 | > Best case - O(n) 7 | """ 8 | 9 | def BubbleSort(list): 10 | for i in range(len(list) - 1): 11 | for j in range(len(list) - i - 1): 12 | if(list[j] > list[j + 1]): 13 | list[j], list[j + 1] = list[j + 1], list[j] 14 | 15 | return list -------------------------------------------------------------------------------- /extras/Sorting Algorithms/SelectionSort.py: -------------------------------------------------------------------------------- 1 | """ 2 | > Finds the minimum element in the unsorted part of the array that 3 | > Swaps with the first element of the array (unsorted) 4 | > Sorted grows from left to right 5 | > Not stable (space complexity) 6 | > Worst, Average, Best Case - O(n^2) 7 | """ 8 | 9 | def SelectionSort(list): 10 | for i in range(len(list)): 11 | minimumIndex = i 12 | for j in range(i+1, len(list)): 13 | if(list[minimumIndex] > list[j]): 14 | minimumIndex = j 15 | # Swap 16 | list[i], list[minimumIndex] = list[minimumIndex], list[i] 17 | return list 18 | --------------------------------------------------------------------------------