├── Data Bank ├── Coin Change.pdf ├── Hackerrank Project Euler 1 Solution.png ├── Hackerrank Project Euler 15 Solution.png ├── Hackerrank Project Euler 69 Solution.jpg ├── Hackerrank Top Germany.jpg ├── Integer_Partition.pdf ├── Lattice_Paths.pdf ├── Lexicographic_Permutations.pdf ├── LongestCommonSubsequence.pdf ├── Longest_Increasing_Subsequence.pdf ├── MST_Kruskal.pdf ├── MST_Prim.pdf ├── Max_PathSum_Triangle.pdf ├── Max_SubarraySum.pdf ├── Min_PathSum_Matrix.pdf ├── Multiples_of_3_and_5.pdf ├── Number_Spiral_Diagonals.pdf ├── Overview of file.PNG ├── SP_Dijkstra_MinHeap.pdf └── SumOfSubstrings.pdf ├── Data Structures Applications ├── BST.ipynb ├── BST_Find.ipynb └── BST_Find_Index.ipynb ├── Dynamic Programming ├── CoinChange.ipynb ├── IntegerPartition.ipynb ├── Knapsack_01.ipynb ├── LongestCommonSubsequence.ipynb ├── Longest_Common_Substring.ipynb ├── Longest_Increasing_Subsequence.ipynb ├── Max_PathSum_Triangle.ipynb ├── Max_SubarraySum.ipynb ├── Max_SubarraySum_Extended.ipynb ├── MinCoinChange.ipynb ├── Min_PathSum_Matrix.ipynb ├── Min_SubarraySum.ipynb ├── PartitionProblem_SubsetSum.ipynb ├── SubarraySum_DivByK.ipynb ├── SubarraySum_EqualsK.ipynb └── SumOfSubstrings.ipynb ├── Greedy Algorithm ├── Largest_Permutation.ipynb ├── Largest_Permutation.pdf ├── Sherlock_and_The_Beast.ipynb └── Sherlock_and_The_Beast.pdf ├── Linked List ├── Array_to_ListNode.ipynb ├── ListNode.ipynb └── ListNode_to_Array.ipynb ├── Mathematics ├── Euler_Totient_NumList.ipynb ├── Euler_Totient_SingleNum.ipynb ├── Factorization.ipynb ├── Lattice_Paths.ipynb ├── Lexicographic_Permutations.ipynb ├── Multiples_of_3_and_5.ipynb ├── Number_Spiral_Diagonals.ipynb ├── Pascal_Triangle.ipynb ├── PrimeFactorization.ipynb ├── PrimeFactorization_SPF.ipynb ├── PythagoreanTriplets_LessEqualN.ipynb ├── PythagoreanTriplets_Perimeter.ipynb ├── Sieve_All_Primes.ipynb ├── Sieve_SPF.ipynb ├── areCoprimes.ipynb ├── arePermutations.ipynb ├── isPrime.ipynb └── isPrime_Miller_Rabin.ipynb ├── Matrix ├── Diagonal_Traverse.ipynb └── Spiral_Matrix.ipynb ├── README.md ├── Searching and Graph Algorithms ├── BFS.ipynb ├── DFS.ipynb ├── DisjointSet.ipynb ├── Find_AllNodes.ipynb ├── Find_AllPaths_BFS.ipynb ├── Graph_AdjacencyList.ipynb ├── MST_Kruskal.ipynb ├── MST_Prim.ipynb ├── SP_BFS.ipynb ├── SP_Dijkstra_MinHeap.ipynb └── isCycle_DisjointSet.ipynb ├── String Algorithm ├── LCPArray_Kasai.ipynb └── SuffixArray_ManberMyers.ipynb └── Two Pointers - Sliding Window └── LongestSubstring_0RepeatChars.ipynb /Data Bank/Coin Change.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Coin Change.pdf -------------------------------------------------------------------------------- /Data Bank/Hackerrank Project Euler 1 Solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Hackerrank Project Euler 1 Solution.png -------------------------------------------------------------------------------- /Data Bank/Hackerrank Project Euler 15 Solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Hackerrank Project Euler 15 Solution.png -------------------------------------------------------------------------------- /Data Bank/Hackerrank Project Euler 69 Solution.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Hackerrank Project Euler 69 Solution.jpg -------------------------------------------------------------------------------- /Data Bank/Hackerrank Top Germany.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Hackerrank Top Germany.jpg -------------------------------------------------------------------------------- /Data Bank/Integer_Partition.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Integer_Partition.pdf -------------------------------------------------------------------------------- /Data Bank/Lattice_Paths.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Lattice_Paths.pdf -------------------------------------------------------------------------------- /Data Bank/Lexicographic_Permutations.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Lexicographic_Permutations.pdf -------------------------------------------------------------------------------- /Data Bank/LongestCommonSubsequence.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/LongestCommonSubsequence.pdf -------------------------------------------------------------------------------- /Data Bank/Longest_Increasing_Subsequence.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Longest_Increasing_Subsequence.pdf -------------------------------------------------------------------------------- /Data Bank/MST_Kruskal.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/MST_Kruskal.pdf -------------------------------------------------------------------------------- /Data Bank/MST_Prim.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/MST_Prim.pdf -------------------------------------------------------------------------------- /Data Bank/Max_PathSum_Triangle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Max_PathSum_Triangle.pdf -------------------------------------------------------------------------------- /Data Bank/Max_SubarraySum.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Max_SubarraySum.pdf -------------------------------------------------------------------------------- /Data Bank/Min_PathSum_Matrix.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Min_PathSum_Matrix.pdf -------------------------------------------------------------------------------- /Data Bank/Multiples_of_3_and_5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Multiples_of_3_and_5.pdf -------------------------------------------------------------------------------- /Data Bank/Number_Spiral_Diagonals.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Number_Spiral_Diagonals.pdf -------------------------------------------------------------------------------- /Data Bank/Overview of file.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/Overview of file.PNG -------------------------------------------------------------------------------- /Data Bank/SP_Dijkstra_MinHeap.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/SP_Dijkstra_MinHeap.pdf -------------------------------------------------------------------------------- /Data Bank/SumOfSubstrings.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Data Bank/SumOfSubstrings.pdf -------------------------------------------------------------------------------- /Data Structures Applications/BST.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "BST.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Original Binary Search Tree Algorithm\n", 24 | " Time complexity = O(logn)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " sortedList: list\n", 29 | " A sorted list of numbers as the input \n", 30 | " n : integer\n", 31 | " The number to find the index\n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " idx: intger\n", 36 | "\n", 37 | " Examples:\n", 38 | " ---------\n", 39 | " >>> l = [1, 3, 5, 6, 7, 10]\n", 40 | " >>> print(BST(l, 5))\n", 41 | " 2\n", 42 | " >>> print(BST(l, 8))\n", 43 | " Exception: n is not in the list\n", 44 | "\n", 45 | " References:\n", 46 | " https://www.geeksforgeeks.org/binary-search/\n", 47 | "'''\n", 48 | "\n", 49 | "def BST(sortedList, n): \n", 50 | " l, r, arr = 0, len(sortedList)-1, sortedList\n", 51 | "\n", 52 | " while l <= r: \n", 53 | " m = l + (r - l)//2 # Mid \n", 54 | " # Check if n is present at mid \n", 55 | " if arr[m] == n: \n", 56 | " return m \n", 57 | " # If n is greater, ignore left half \n", 58 | " elif arr[m] < n: \n", 59 | " l = m + 1\n", 60 | " # If n is smaller, ignore right half \n", 61 | " else: \n", 62 | " r = m - 1\n", 63 | " \n", 64 | " # If we reach here, then the element was not present \n", 65 | " raise Exception('n is not in the list')" 66 | ], 67 | "execution_count": null, 68 | "outputs": [] 69 | } 70 | ] 71 | } -------------------------------------------------------------------------------- /Data Structures Applications/BST_Find.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "BST_Find.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to check if a number is in a sorted list using Binary Search Tree Algorithm\n", 24 | " Time complexity = O(logn)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " sortedList: list\n", 29 | " A sorted list of numbers as the input \n", 30 | " n : integer\n", 31 | " The number to find\n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " True/False: boolean\n", 36 | "\n", 37 | " Examples:\n", 38 | " ---------\n", 39 | " >>> l = [1, 3, 5, 6, 7, 10]\n", 40 | " >>> print(BST_Find(l,3))\n", 41 | " True\n", 42 | " >>> print(BST_Find(l,8))\n", 43 | " False\n", 44 | "'''\n", 45 | "\n", 46 | "from bisect import bisect_left\n", 47 | "\n", 48 | "def BST_Find(sortedList,n):\n", 49 | " idx = bisect_left(sortedList,n)\n", 50 | " if idx < len(sortedList) and sortedList[idx] == n:\n", 51 | " return True\n", 52 | " else:\n", 53 | " return False" 54 | ], 55 | "execution_count": null, 56 | "outputs": [] 57 | } 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /Data Structures Applications/BST_Find_Index.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "BST_Find_Index.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find the index of a number in a sorted list using Binary Search Tree Algorithm\n", 24 | " Time complexity = O(logn)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " sortedList: list\n", 29 | " A sorted list of numbers as the input \n", 30 | " n : integer\n", 31 | " The number to find the index\n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " idx: intger\n", 36 | "\n", 37 | " Examples:\n", 38 | " ---------\n", 39 | " >>> l = [1, 3, 5, 6, 7, 10]\n", 40 | " >>> print(BST_Find_Index(l,5))\n", 41 | " 2\n", 42 | " >>> print(BST_Find_Index(l,8))\n", 43 | " Exception: n is not in the list\n", 44 | "'''\n", 45 | "\n", 46 | "from bisect import bisect_left\n", 47 | "\n", 48 | "def BST_Find_Index(sortedList,n):\n", 49 | " idx = bisect_left(sortedList,n)\n", 50 | " if idx < len(sortedList) and sortedList[idx] == n:\n", 51 | " return idx\n", 52 | " else:\n", 53 | " raise Exception('n is not in the list')" 54 | ], 55 | "execution_count": null, 56 | "outputs": [] 57 | } 58 | ] 59 | } -------------------------------------------------------------------------------- /Dynamic Programming/CoinChange.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "IntegerPartition.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find how many ways to pay V money using C coins [C1,C2,...,Cn]\n", 24 | " Time complexity = O(C.V)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " V : integer\n", 29 | " Value of money to be paid\n", 30 | " C : list\n", 31 | " All coin types available \n", 32 | " output: 'single' (by default) or 'all', optional\n", 33 | " 2 types of output\n", 34 | "\n", 35 | " Returns:\n", 36 | " --------\n", 37 | " output = 'single': integer\n", 38 | " Number of ways to pay V using C coins\n", 39 | " output = 'all' : list\n", 40 | " All numbers of ways to pay each [1,2,...,V] money using C coins\n", 41 | "\n", 42 | " Examples:\n", 43 | " ---------\n", 44 | " With 4 types of coins C = [8,3,1,2], we can make change for V = 3 in\n", 45 | " 3 ways: {1,1,1}, {1,2} and {3}\n", 46 | "\n", 47 | " >>> C = [8,3,1,2]\n", 48 | " >>> V = 3\n", 49 | " >>> print(CoinChange(V, C))\n", 50 | " 3\n", 51 | "\n", 52 | " To pay 1 money, we have 1 way : {1}\n", 53 | " 2 money, we have 2 ways: {1,1} and {2}\n", 54 | " 3 money, we have 3 ways: {1,1,1}, {1,2} and {3}\n", 55 | " \n", 56 | " >>> C = [8,3,1,2]\n", 57 | " >>> V = 3\n", 58 | " >>> print(CoinChange(V, C, output='all'))\n", 59 | " [1, 1, 2, 3]\n", 60 | "\n", 61 | " References: \n", 62 | " https://blog.dreamshire.com/project-euler-31-solution/\n", 63 | "'''\n", 64 | "\n", 65 | "def CoinChange(V, C, output='single'):\n", 66 | " memo = [1]+[0]*V # Memory for dynamic programming\n", 67 | " \n", 68 | " for coin in C:\n", 69 | " for val in range(coin,V+1):\n", 70 | " memo[val] += memo[val-coin]\n", 71 | " \n", 72 | " # 2 ways of output: 'single' or 'all'\n", 73 | " if output == 'all': return memo\n", 74 | " if output == 'single': return memo[V]" 75 | ], 76 | "execution_count": null, 77 | "outputs": [] 78 | } 79 | ] 80 | } 81 | -------------------------------------------------------------------------------- /Dynamic Programming/IntegerPartition.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "IntegerPartition.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find how many ways to partition number N using [1,2,...N] numbers\n", 24 | " Time complexity = O(n^1.5) \n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " N : integer\n", 29 | " Input number to be partitioned\n", 30 | " output: 'single' (by default) or 'all', optional\n", 31 | " 2 types of output\n", 32 | " \n", 33 | " Returns:\n", 34 | " --------\n", 35 | " output = 'single': integer \n", 36 | " Number of ways to partition number N (by default)\n", 37 | " output = 'all' : list\n", 38 | " All numbers of ways to partition all numbers from 0 to N\n", 39 | "\n", 40 | " Examples:\n", 41 | " ---------\n", 42 | " With 5 types of coins [1, 2, 3, 4, 5], we can make change for N = 5 in 7 ways:\n", 43 | " 5 = 5\n", 44 | " = 4+1\n", 45 | " = 3+2\n", 46 | " = 3+1+1\n", 47 | " = 2+2+1\n", 48 | " = 2+1+1+1\n", 49 | " = 1+1+1+1+1\n", 50 | "\n", 51 | " >>> N = 5\n", 52 | " >>> ways = IntegerPartition(N,output='single')\n", 53 | " >>> print(ways)\n", 54 | " 7\n", 55 | "\n", 56 | " >>> N = 5\n", 57 | " >>> ways = IntegerPartition(N,output='all')\n", 58 | " >>> print(ways)\n", 59 | " [1, 1, 2, 3, 5, 7]\n", 60 | "\n", 61 | " References:\n", 62 | " https://blog.dreamshire.com/project-euler-78-solution/\n", 63 | " https://taskinoor.wordpress.com/2011/11/20/the-relation-between-integer-partition-and-pentagonal-numbers/\n", 64 | " https://en.wikipedia.org/wiki/Partition_%28number_theory%29\n", 65 | "'''\n", 66 | "\n", 67 | "from math import sqrt\n", 68 | "\n", 69 | "def IntegerPartition(N, output='single'):\n", 70 | " # List of generalized pentagonal numbers for generating function\n", 71 | " k = sum([[i*(3*i - 1)//2, i*(3*i - 1)//2 + i] for i in range(1, max(250,int(sqrt(N))))], [])\n", 72 | " \n", 73 | " p = [1] # List to count how many ways to partition number n\n", 74 | " sgn = [1, 1, -1, -1] # List of signs\n", 75 | " n = 0 # Starting number\n", 76 | "\n", 77 | " while n < N: # Expand generating function to calculate p(n)\n", 78 | " n += 1\n", 79 | " px, i = 0, 0\n", 80 | "\n", 81 | " while k[i] <= n:\n", 82 | " px += p[n - k[i]] * sgn[i%4]\n", 83 | " i += 1\n", 84 | "\n", 85 | " p.append(px)\n", 86 | " \n", 87 | " # 2 types of output: 'all' or 'single'\n", 88 | " if output == 'all': return p\n", 89 | " if output == 'single': return p[N] # By default" 90 | ], 91 | "execution_count": null, 92 | "outputs": [] 93 | } 94 | ] 95 | } 96 | -------------------------------------------------------------------------------- /Dynamic Programming/Knapsack_01.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Knapsack_01.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Given a List of Weights associated with their Values, find the Founding Weights and\n", 24 | " Maximum Total Value attained with its Total Weight <= Given Total Weight, \n", 25 | " each Weight is only picked once (0/1 Rule) \n", 26 | "\n", 27 | " Time complexity = O(|weights|*totalWeight) \n", 28 | "\n", 29 | " Parameters:\n", 30 | " -----------\n", 31 | " totalWeight: int\n", 32 | " Total weight that can be reached\n", 33 | " weights : list\n", 34 | " List of weights in ascending order\n", 35 | " values : list\n", 36 | " List of values associated with weights\n", 37 | " output : 'MaxTotalValue' (by default) or 'Weights', optional\n", 38 | " 2 types of output: Maximum Total Value or Founding Weights\n", 39 | "\n", 40 | " Returns:\n", 41 | " --------\n", 42 | " Maximum total value: int\n", 43 | " subset : list\n", 44 | " List of Founding Weights\n", 45 | "\n", 46 | " Examples:\n", 47 | " ---------\n", 48 | " Given an weights array [1, 3, 4, 5] with its values array [1, 4, 5, 7]. \n", 49 | " The maximum total value is 9, which can be attained by the weight 3 and 4.\n", 50 | "\n", 51 | " The dynamic programming matrix looks like this:\n", 52 | " [[0, 1, 1, 1, 1, 1, 1, 1], \n", 53 | " [0, 1, 1, 4, 5, 5, 5, 5], \n", 54 | " [0, 1, 1, 4, 5, 6, 6, 9], \n", 55 | " [0, 1, 1, 4, 5, 7, 8, 9]]\n", 56 | " \n", 57 | " >>> totalWeight = 7\n", 58 | " >>> weights = [1, 3, 4, 5]\n", 59 | " >>> values = [1, 4, 5, 7]\n", 60 | " >>> print(Knapsack_01(totalWeight, weights, values))\n", 61 | " 9\n", 62 | "\n", 63 | " To find what weights constitute the maximum total value 9, the algorithm \n", 64 | " follows the path coordinate like this: (3,7) -> (2,7) -> (1,3) -> (0,0).\n", 65 | "\n", 66 | " >>> print(Knapsack_01(totalWeight, weights, values, output='Weights'))\n", 67 | " [4, 3]\n", 68 | "\n", 69 | " References:\n", 70 | " https://www.youtube.com/watch?v=8LusJS5-AGo\n", 71 | " https://en.wikipedia.org/wiki/Knapsack_problem#0-1_knapsack_problem\n", 72 | "'''\n", 73 | "\n", 74 | "def Knapsack_01(totalWeight, weights, values, output = 'MaxTotalValue'):\n", 75 | " # Warning: Weights must be sorted in ascending order\n", 76 | "\n", 77 | " R, C = len(weights), totalWeight + 1\n", 78 | " dp = [[0 for i in range(C)] for i in range(R)]\n", 79 | "\n", 80 | " count = weights[0] # Cumulative weight\n", 81 | " for c in range(weights[0], C):\n", 82 | " dp[0][c] = values[0]\n", 83 | "\n", 84 | " for r in range(1, R):\n", 85 | " count += weights[r]\n", 86 | " for c in range(1, C):\n", 87 | " if c < weights[r]:\n", 88 | " dp[r][c] = dp[r-1][c]\n", 89 | " elif weights[r] <= c <= count:\n", 90 | " dp[r][c] = max(dp[r-1][c], values[r] + dp[r-1][c - weights[r]])\n", 91 | " elif c > count: \n", 92 | " # Every weight is only picked once, so there's no more value gained\n", 93 | " dp[r][c] = dp[r][c-1]\n", 94 | "\n", 95 | " # There are 2 types of output: 'MaxTotalValue' (by default) or 'Weights'\n", 96 | " if output == 'MaxTotalValue':\n", 97 | " return dp[-1][-1]\n", 98 | "\n", 99 | " # Algorithm to find weights that founded the Maximum Total Value\n", 100 | " elif output == 'Weights':\n", 101 | " r, c = R - 1, C - 1\n", 102 | " subset = []\n", 103 | "\n", 104 | " while True:\n", 105 | " if r == 0 and c == 0:\n", 106 | " return subset\n", 107 | " \n", 108 | " if r > 0 and c > 0:\n", 109 | " if dp[r-1][c] == dp[r][c]:\n", 110 | " r -= 1\n", 111 | " elif dp[r][c-1] == dp[r][c]:\n", 112 | " c -= 1\n", 113 | " else:\n", 114 | " subset.append(weights[r])\n", 115 | " c -= weights[r]\n", 116 | " r -= 1\n", 117 | " continue\n", 118 | "\n", 119 | " if r == 0:\n", 120 | " if dp[r][c-1] == dp[r][c]:\n", 121 | " c -= 1\n", 122 | " else:\n", 123 | " subset.append(weights[r])\n", 124 | " c -= weights[r]\n", 125 | " continue" 126 | ], 127 | "execution_count": null, 128 | "outputs": [] 129 | } 130 | ] 131 | } 132 | -------------------------------------------------------------------------------- /Dynamic Programming/LongestCommonSubsequence.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "LongestCommonSubsequence.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Longest Common Subsequence of 2 lists of string\n", 24 | " Time complexity = O(|L1|.|L2|), |L| is length of string list\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " strList1: list\n", 29 | " The first input string list \n", 30 | " strList2: list\n", 31 | " The second input string list \n", 32 | " output : 'stringList' (default) or 'length', optional\n", 33 | " Type of output: max string list or max length\n", 34 | "\n", 35 | " Returns:\n", 36 | " --------\n", 37 | " output = 'stringList': list\n", 38 | " List of characters of ONLY 1 longest subsequence (there maybe more)\n", 39 | " output = 'length' : int\n", 40 | " Length of longest subsequence \n", 41 | "\n", 42 | " Examples:\n", 43 | " ---------\n", 44 | " T E R R A C E D | T E R R A C E D\n", 45 | " C - - - - - C C C | C 0 0 0 0 0 1 1 1\n", 46 | " R - - R R R R R R | R 0 0 1 1 1 1 1 1\n", 47 | " A - - R R RA RA RA RA | A 0 0 1 1 2 2 2 2\n", 48 | " T T T R R RA RA RA RA | T 1 1 1 1 2 2 2 2\n", 49 | " E T TE TE TE RA RA RAE [RAE] | E 1 2 2 2 2 2 3 3\n", 50 | " R T TE TER TER TER TER [TER] [TER] | R 1 2 3 3 3 3 3 3*\n", 51 | "\n", 52 | " Both 'RAE' and 'TER' are longest subsequences. This algorithm only returns\n", 53 | " 'TER' (right bottom of the table). To return more, please add 2 more neighbors\n", 54 | " of right bottom if they also have the same length.\n", 55 | "\n", 56 | " >>> strList1 = 'T E R R A C E D'.split()\n", 57 | " >>> strList2 = 'C R A T E R'.split()\n", 58 | " >>> LCS = LongestCommonSubsequence(strList1,strList2,output='stringList')\n", 59 | " >>> print(LCS)\n", 60 | " ['T', 'E', 'R']\n", 61 | " >>> maxLength = LongestCommonSubsequence(strList1,strList2,output='length')\n", 62 | " >>> print(maxLength)\n", 63 | " 3\n", 64 | "\n", 65 | " >>> strList1 = list('SHINCHAN')\n", 66 | " >>> strList2 = list('NOHARAAA')\n", 67 | " >>> LCS = LongestCommonSubsequence(strList1,strList2,output='stringList')\n", 68 | " >>> print(LCS)\n", 69 | " ['N', 'H', 'A']\n", 70 | "\n", 71 | " >>> strList1 = '16 27 60 76 123 88 55 94 57'.split()\n", 72 | " >>> strList2 = '27 76 88 0 55 2 94 70 34 42 47'.split()\n", 73 | " >>> LCS = LongestCommonSubsequence(strList1,strList2,output='stringList')\n", 74 | " >>> print(LCS)\n", 75 | " ['27', '76', '88', '55', '94']\n", 76 | "\n", 77 | " References:\n", 78 | " https://en.wikipedia.org/wiki/Longest_common_subsequence_problem\n", 79 | " https://www.geeksforgeeks.org/python-program-for-longest-common-subsequence/\n", 80 | "'''\n", 81 | "\n", 82 | "def LongestCommonSubsequence(strList1, strList2, output='stringList'):\n", 83 | " # Choose the longer length \n", 84 | " L = max(len(strList1),len(strList2)) \n", 85 | " # Dynamic programming memory for lengths\n", 86 | " dp_L = [ [0]*(L+1) for _ in range(L+1)]\n", 87 | " # Dynamic programming memory for strings\n", 88 | " dp_S = [ [[]]*(L+1) for _ in range(L+1)]\n", 89 | "\n", 90 | " for i in range(0,len(strList1)):\n", 91 | " for j in range(0,len(strList2)):\n", 92 | " if strList1[i] == strList2[j]:\n", 93 | " dp_L[i+1][j+1] = dp_L[i][j] + 1\n", 94 | " dp_S[i+1][j+1] = dp_S[i][j] + [strList1[i]]\n", 95 | " else:\n", 96 | " dp_L[i+1][j+1] = max(dp_L[i][j+1],dp_L[i+1][j])\n", 97 | " if dp_L[i][j+1] >= dp_L[i+1][j]: dp_S[i+1][j+1] = dp_S[i][j+1]\n", 98 | " else: dp_S[i+1][j+1] = dp_S[i+1][j]\n", 99 | "\n", 100 | " # 2 ways of output: max string lists or max lengths\n", 101 | " if output == 'stringList': \n", 102 | " # ONLY 1 longest subsequence, modify codes to return more\n", 103 | " return dp_S[len(strList1)][len(strList2)] \n", 104 | " elif output == 'length': \n", 105 | " return dp_L[len(strList1)][len(strList2)]" 106 | ], 107 | "execution_count": null, 108 | "outputs": [] 109 | } 110 | ] 111 | } 112 | -------------------------------------------------------------------------------- /Dynamic Programming/Longest_Common_Substring.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Draft.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "v7CwPh7LozYh" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Longest Common Substring (Factor) of 2 strings\n", 24 | " Time complexity = O(m.n); m = |S1| and n = |S2|\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " s1 : string\n", 29 | " The first input string \n", 30 | " s2 : list\n", 31 | " The second input string list \n", 32 | " output : 'substring' (default) or 'position', optional\n", 33 | " Type of output: common substring or its position\n", 34 | "\n", 35 | " Returns:\n", 36 | " --------\n", 37 | " output = 'substring': string\n", 38 | " Longest common substring\n", 39 | " output = 'position' : int\n", 40 | " Substring's position in s1 and s2\n", 41 | "\n", 42 | " Examples:\n", 43 | " ---------\n", 44 | " >>> s1 = 'helloworld'\n", 45 | " >>> s2 = 'yellomarin'\n", 46 | " >>> LCS = LongestCommonSubstring(s1, s2, output = 'substring')\n", 47 | " >>> print(LCS)\n", 48 | " ello\n", 49 | "\n", 50 | " >>> s1 = 'tabriz'\n", 51 | " >>> s2 = 'torino'\n", 52 | " >>> posS1, posS2 = LongestCommonSubstring(s1, s2, output = 'position')\n", 53 | " >>> print(posS1)\n", 54 | " [3, 4]\n", 55 | " >>> print(posS2)\n", 56 | " [2, 3]\n", 57 | "\n", 58 | " See also:\n", 59 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/LongestCommonSubsequence.ipynb\n", 60 | "\n", 61 | " References:\n", 62 | " https://en.wikipedia.org/wiki/Longest_common_substring_problem#Dynamic_programming\n", 63 | "'''\n", 64 | "\n", 65 | "def LongestCommonSubstring(s1, s2, output='substring'):\n", 66 | " dp = [[0 for i in range(len(s2)+1)] for i in range(len(s1)+1)] \n", 67 | " longest, i_longest, j_longest = 0, 0, 0\n", 68 | "\n", 69 | " # Main algorithm\n", 70 | " for i in range(1, len(s1)+1):\n", 71 | " for j in range(1, len(s2)+1):\n", 72 | " if s1[i-1] == s2[j-1]:\n", 73 | " dp[i][j] = dp[i-1][j-1] + 1\n", 74 | " if dp[i][j] > longest:\n", 75 | " longest = dp[i][j]\n", 76 | " i_longest = i - 1\n", 77 | " j_longest = j - 1\n", 78 | " \n", 79 | " # 2 ways of output: substring or its position\n", 80 | " if output == 'substring':\n", 81 | " return s1[i_longest - longest + 1 : i_longest + 1]\n", 82 | " elif output == 'position':\n", 83 | " pos_s1 = [i_longest - longest + 1, i_longest] \n", 84 | " pos_s2 = [j_longest - longest + 1, j_longest]\n", 85 | " return [pos_s1, pos_s2]" 86 | ], 87 | "execution_count": 9, 88 | "outputs": [] 89 | } 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /Dynamic Programming/Longest_Increasing_Subsequence.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Longest_Increasing_Subsequence.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Longest Increasing/Decreasing Subsequence of an array based on patience sorting\n", 24 | " Time complexity = O(n.log(n))\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " arr : list\n", 29 | " Input array of numbers\n", 30 | " algoType: 'LIS' (by default) or 'LDS', optional\n", 31 | " Algorithm type: Longest Increasing Subsequence (LIS)\n", 32 | " or Longest Decreasing Subsequence (LDS)\n", 33 | "\n", 34 | " Returns:\n", 35 | " --------\n", 36 | " result: tuple\n", 37 | " A tuple of length of LIS, LIS and its indices in input array\n", 38 | " or length of LDS, LDS and its indices in input array\n", 39 | "\n", 40 | " Examples:\n", 41 | " ---------\n", 42 | " Given an array list: \n", 43 | " 2 5 3 7 11 8 10 13 6\n", 44 | " LIS of this array is: \n", 45 | " [2] 5 [3] [7] 11 [8] [10] [13] 6 => 6 elements\n", 46 | " Its position is: \n", 47 | " 0 2 3 5 6 7\n", 48 | "\n", 49 | " >>> arr = [2, 5, 3, 7, 11, 8, 10, 13, 6] \n", 50 | " >>> print(Longest_Increasing_Subsequence(arr))\n", 51 | " (6, [2, 3, 7, 8, 10, 13], [0, 2, 3, 5, 6, 7])\n", 52 | "\n", 53 | " >>> print(Longest_Increasing_Subsequence(arr, algoType='LDS'))\n", 54 | " (3, [11, 8, 6], [4, 5, 8])\n", 55 | "\n", 56 | " References:\n", 57 | " https://www.youtube.com/watch?v=S9oUiVYEq7E\n", 58 | " https://www.youtube.com/watch?v=22s1xxRvy28&feature=youtu.be\n", 59 | " https://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/\n", 60 | "'''\n", 61 | " \n", 62 | "def Longest_Increasing_Subsequence(arr, algoType='LIS'): \n", 63 | " # Convert input for algorithm type: Longest Increasing Subsequence (LIS) or Longest Decreasing Subsequence (LDS)\n", 64 | " if algoType == 'LIS': \n", 65 | " pass\n", 66 | " elif algoType == 'LDS': \n", 67 | " arr = arr[::-1]\n", 68 | "\n", 69 | " # Modified binary search \n", 70 | " def GetCeilIndex(arr, T, l, r, key): \n", 71 | " while r - l > 1: \n", 72 | " m = l + (r - l)//2\n", 73 | " if arr[T[m]] >= key: \n", 74 | " r = m \n", 75 | " else: \n", 76 | " l = m \n", 77 | " return r \n", 78 | "\n", 79 | " # Initialized with 0 \n", 80 | " tailIndices =[0 for i in range(len(arr)+1)] \n", 81 | " # Initialized with -1 \n", 82 | " prevIndices =[-1 for i in range(len(arr)+1)] \n", 83 | " \n", 84 | " # It will always point to empty location \n", 85 | " length = 1 \n", 86 | " for i in range(1, len(arr)): \n", 87 | " if arr[i] < arr[tailIndices[0]]: \n", 88 | " # New smallest value \n", 89 | " tailIndices[0] = i \n", 90 | "\n", 91 | " elif arr[i] >= arr[tailIndices[length-1]]: \n", 92 | " # arr[i] wants to extend largest subsequence \n", 93 | " prevIndices[i] = tailIndices[length-1] \n", 94 | " tailIndices[length] = i \n", 95 | " length += 1\n", 96 | " \n", 97 | " else: \n", 98 | " # arr[i] wants to be a potential condidate of future subsequence \n", 99 | " # It will replace ceil value in tailIndices \n", 100 | " pos = GetCeilIndex(arr, tailIndices, -1, length-1, arr[i]) \n", 101 | " prevIndices[i] = tailIndices[pos-1] \n", 102 | " tailIndices[pos] = i \n", 103 | " \n", 104 | " # Construct Longest Increasing Subsequence and its indices \n", 105 | " if algoType == 'LIS':\n", 106 | " LIS = []\n", 107 | " LIS_idx = []\n", 108 | " i = tailIndices[length-1]\n", 109 | "\n", 110 | " while i >= 0: \n", 111 | " LIS.insert(0,arr[i])\n", 112 | " LIS_idx.insert(0,i)\n", 113 | " i = prevIndices[i] \n", 114 | "\n", 115 | " result = (length, LIS, LIS_idx)\n", 116 | "\n", 117 | " # Construct Longest Decreasing Subsequence and its indices\n", 118 | " elif algoType == 'LDS':\n", 119 | " LDS = []\n", 120 | " LDS_idx = []\n", 121 | " i = tailIndices[length-1]\n", 122 | "\n", 123 | " while i >= 0: \n", 124 | " LDS.append(arr[i])\n", 125 | " LDS_idx.append(len(arr)-1-i)\n", 126 | " i = prevIndices[i] \n", 127 | "\n", 128 | " result = (length, LDS, LDS_idx)\n", 129 | "\n", 130 | " return result" 131 | ], 132 | "execution_count": null, 133 | "outputs": [] 134 | } 135 | ] 136 | } 137 | -------------------------------------------------------------------------------- /Dynamic Programming/Max_PathSum_Triangle.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Max_PathSum_Triangle.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Maximum Path Sum from top to bottom of a Triangle\n", 24 | " Time complexity = O(R), R is number of rows of the triangle\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " tri: list\n", 29 | " Input triangle\n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " maxSum: integer\n", 34 | " Max sum of the path from top to bottom\n", 35 | "\n", 36 | " Examples:\n", 37 | " --------- \n", 38 | " 3 [3]\n", 39 | " 7 5 Max sum path [7] 5 \n", 40 | " 2 4 6 ===========================> 2 [4] 6 \n", 41 | " 8 5 9 3 Max sum = 3 + 7 + 4 + 9 = 23 8 5 [9] 3\n", 42 | "\n", 43 | " 8 [8]\n", 44 | " -4 4 Max sum path -4 [4] \n", 45 | " 2 2 6 ===========================> 2 2 [6] \n", 46 | " 1 1 1 1 Max sum = 8 + 4 + 6 + 1 = 19 1 1 [1] 1\n", 47 | "\n", 48 | " >>> tri = [[3],\n", 49 | " [7,4],\n", 50 | " [2,4,6],\n", 51 | " [8,5,9,3]]\n", 52 | " >>> print(Max_PathSum_Triangle(tri))\n", 53 | " 23\n", 54 | "\n", 55 | " References:\n", 56 | " https://blog.dreamshire.com/solutions/project_euler/project-euler-problem-018-solution/\n", 57 | "'''\n", 58 | "\n", 59 | "from copy import deepcopy\n", 60 | "\n", 61 | "def Max_PathSum_Triangle(tri):\n", 62 | " '''\n", 63 | " This algorithm is to find max path sum.\n", 64 | " For other cases, please modify codes.\n", 65 | " '''\n", 66 | " memo = deepcopy(tri)\n", 67 | "\n", 68 | " for r in range(len(memo)-1-1,-1,-1):\n", 69 | " for c in range(0,len(memo[r])):\n", 70 | " memo[r][c] += max(memo[r+1][c],memo[r+1][c+1])\n", 71 | " \n", 72 | " maxSum = memo[0][0] # Top of the triangle is the accumulative sum\n", 73 | " return maxSum" 74 | ], 75 | "execution_count": null, 76 | "outputs": [] 77 | } 78 | ] 79 | } 80 | -------------------------------------------------------------------------------- /Dynamic Programming/Max_SubarraySum.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Max_SubarraySum.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find maximum subarray sum of an array\n", 24 | " Time complexity = O(n)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " arr: list\n", 29 | " Input array of numbers\n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " best: int\n", 34 | " Maximum subarray sum\n", 35 | "\n", 36 | " Examples:\n", 37 | " --------- \n", 38 | " Given an array: [-1, 2, 3, -4, 5, 10]\n", 39 | " The maximum subarray sum is 16.\n", 40 | " Its position is 1 and 5.\n", 41 | "\n", 42 | " >>> arr = [-1, 2, 3, -4, 5, 10]\n", 43 | " >>> print(Max_SubarraySum(arr))\n", 44 | " 16\n", 45 | "\n", 46 | " >>> arr = [-1, -2, -3, -4, -5, -10]\n", 47 | " >>> print(Max_SubarraySum(arr))\n", 48 | " -1\n", 49 | "\n", 50 | " References:\n", 51 | " https://en.wikipedia.org/wiki/Maximum_subarray_problem\n", 52 | "'''\n", 53 | "\n", 54 | "def Max_SubarraySum(arr):\n", 55 | " curr = best = arr[0] # Current and max subarray sum\n", 56 | " \n", 57 | " for i in arr[1:]:\n", 58 | " # After adding i, if current subarray sum >= previous subarray sum, \n", 59 | " # then new subarray starts at i\n", 60 | " curr = max(i, curr + i) \n", 61 | " # Memoize max subarray sum\n", 62 | " best = max(best, curr)\n", 63 | " \n", 64 | " return best" 65 | ], 66 | "execution_count": null, 67 | "outputs": [] 68 | } 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /Dynamic Programming/Max_SubarraySum_Extended.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Max_SubarraySum_Extended.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find maximum subarray sum of an array and its indices\n", 24 | " Time complexity = O(n)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " arr: list\n", 29 | " Input array of numbers\n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " result: tuple\n", 34 | " A tuple of maximum subarray sum and its position\n", 35 | "\n", 36 | " Examples:\n", 37 | " --------- \n", 38 | " Given an array: [-1, 2, 3, -4, 5, 10]\n", 39 | " The maximum subarray sum is 16.\n", 40 | " Its position is 1 and 5.\n", 41 | "\n", 42 | " >>> arr = [-1, 2, 3, -4, 5, 10]\n", 43 | " >>> print(Max_SubarraySum_Extended(arr))\n", 44 | " (16, 1, 5)\n", 45 | "\n", 46 | " >>> arr = [-1, -2, -3, -4, -5, -10]\n", 47 | " >>> print(Max_SubarraySum_Extended(arr))\n", 48 | " (-1, 0, 0)\n", 49 | "\n", 50 | " References:\n", 51 | " https://en.wikipedia.org/wiki/Maximum_subarray_problem\n", 52 | "'''\n", 53 | "\n", 54 | "def Max_SubarraySum_Extended(arr):\n", 55 | " best_sum = 0 # or: float('-inf')\n", 56 | " best_start = best_end = 0 # or: None\n", 57 | " current_sum = 0\n", 58 | "\n", 59 | " for current_end, x in enumerate(arr):\n", 60 | " if current_sum <= 0:\n", 61 | " # Start a new sequence at the current element\n", 62 | " current_start = current_end\n", 63 | " current_sum = x\n", 64 | " else:\n", 65 | " # Extend the existing sequence with the current element\n", 66 | " current_sum += x\n", 67 | "\n", 68 | " if current_sum > best_sum:\n", 69 | " best_sum = current_sum\n", 70 | " best_start = current_start\n", 71 | " best_end = current_end \n", 72 | "\n", 73 | " if (best_sum, best_start, best_end) == (0, 0, 0):\n", 74 | " best_sum = max(arr)\n", 75 | " best_start = best_end = arr.index(best_sum)\n", 76 | "\n", 77 | " result = (best_sum, best_start, best_end)\n", 78 | " return result" 79 | ], 80 | "execution_count": null, 81 | "outputs": [] 82 | } 83 | ] 84 | } -------------------------------------------------------------------------------- /Dynamic Programming/MinCoinChange.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "MinCoinChange.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find minimum number of coins to pay V money using C coins [C1,C2,...,Cn]\n", 24 | " Time complexity = O(C.V)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " V : integer\n", 29 | " Value of money to be paid\n", 30 | " C : list\n", 31 | " All coin types available \n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " Integer: If it's possible to pay V using C coins\n", 36 | " Inf : if it's impossible to pay V using C coins\n", 37 | "\n", 38 | " Examples:\n", 39 | " ---------\n", 40 | " With 3 types of coins C = [5,1,3], we can make change for V = 11 using \n", 41 | " at least 3 coins: {5}, {5} and {1}\n", 42 | "\n", 43 | " >>> V = 11\n", 44 | " >>> C = [5,1,3]\n", 45 | " >>> print(MinCoinChange(V, C))\n", 46 | " 3\n", 47 | "\n", 48 | " With 3 types of coins C = [5,3,6], there's no way to make change for V = 11\n", 49 | "\n", 50 | " >>> V = 2\n", 51 | " >>> C = [5,3,6]\n", 52 | " >>> print(MinCoinChange(V, C))\n", 53 | " inf\n", 54 | "\n", 55 | " References:\n", 56 | " https://en.wikipedia.org/wiki/Change-making_problem\n", 57 | " https://www.youtube.com/watch?v=NJuKJ8sasGk\n", 58 | " https://www.youtube.com/watch?v=Y0ZqKpToTic&t=379s\n", 59 | "'''\n", 60 | "\n", 61 | "def MinCoinChange(V, C):\n", 62 | " dp = [0] + [float('inf')]*V # Memory for dynamic programming\n", 63 | " \n", 64 | " for coin in C:\n", 65 | " for val in range(coin, V+1):\n", 66 | " dp[val] = min(dp[val], dp[val-coin]+1)\n", 67 | " \n", 68 | " return dp[V]" 69 | ], 70 | "execution_count": null, 71 | "outputs": [] 72 | } 73 | ] 74 | } 75 | -------------------------------------------------------------------------------- /Dynamic Programming/Min_PathSum_Matrix.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Min_PathSum_Matrix.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find min path sum from top-left to right-bottom element of a matrix\n", 24 | " Time complexity = O(R.C); R, C is length of row and column of the matrix\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " m: list\n", 29 | " Input matrix\n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " minCost: integer\n", 34 | " Min cost value\n", 35 | "\n", 36 | " Examples:\n", 37 | " --------- \n", 38 | " For a given matrix: \n", 39 | " 131 673 234 103 18\n", 40 | " 201 96 342 965 150\n", 41 | " 630 803 746 422 111\n", 42 | " 537 699 497 121 956\n", 43 | " 805 732 524 37 331\n", 44 | " Top-Left is 131 and Right-Bottom is 331.\n", 45 | "\n", 46 | " The minimum sum path is: \n", 47 | " [131] 673 234 103 18\n", 48 | " [201] [96] [342] 965 150\n", 49 | " 630 803 [746] [422] 111\n", 50 | " 537 699 497 [121] 956\n", 51 | " 805 732 524 [37] [331]\n", 52 | " -> 131, 201, 96, 342, 746, 422, 121, 37, 331\n", 53 | "\n", 54 | " >>> m = [[131, 673, 234, 103, 18],\n", 55 | " [201, 96, 342, 965, 150],\n", 56 | " [630, 803, 746, 422, 111],\n", 57 | " [537, 699, 497, 121, 956],\n", 58 | " [805, 732, 524, 37, 331]]\n", 59 | " >>> print(Min_PathSum_Matrix(m))\n", 60 | " 2427\n", 61 | "\n", 62 | " References:\n", 63 | " https://www.youtube.com/watch?v=lBRtnuxg-gU\n", 64 | " https://www.geeksforgeeks.org/min-cost-path-dp-6/\n", 65 | "'''\n", 66 | "\n", 67 | "def Min_PathSum_Matrix(m):\n", 68 | " '''\n", 69 | " This algorithm finds MIN VALUE of sum path from TOP-LEFT to RIGHT-BOTTOM using\n", 70 | " DOWN and RIGHT moves.\n", 71 | " For further cases, please modify codes.\n", 72 | " '''\n", 73 | " r, c = len(m), len(m[0])\n", 74 | " dp = [[0]*c for i in range(r)]\n", 75 | " \n", 76 | " # Same value at starting point\n", 77 | " dp[0][0] = m[0][0]\n", 78 | " # Initialize first column of dp matrix\n", 79 | " for i in range(1, r):\n", 80 | " dp[i][0] = dp[i-1][0] + m[i][0]\n", 81 | " # Initialize first row of dp matrix\n", 82 | " for j in range(1, c):\n", 83 | " dp[0][j] = dp[0][j-1] + m[0][j]\n", 84 | " # Construct rest of the dp matrix\n", 85 | " for i in range(1, r):\n", 86 | " for j in range(1, c):\n", 87 | " dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + m[i][j]\n", 88 | " \n", 89 | " minCost = dp[-1][-1]\n", 90 | " return minCost" 91 | ], 92 | "execution_count": null, 93 | "outputs": [] 94 | } 95 | ] 96 | } 97 | -------------------------------------------------------------------------------- /Dynamic Programming/Min_SubarraySum.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Min_SubarraySum.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find minimum subarray sum of an array\n", 24 | " Time complexity = O(n)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " arr: list\n", 29 | " Input array of numbers\n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " result: tuple\n", 34 | " A tuple of minimum subarray sum and its position\n", 35 | "\n", 36 | " Examples:\n", 37 | " --------- \n", 38 | " Given an array: [3, -4, 2, -3, -1, 7, -5]\n", 39 | " The minimum subarray sum is -6.\n", 40 | " Its position is 1 and 4.\n", 41 | "\n", 42 | " >>> arr = [3, -4, 2, -3, -1, 7, -5]\n", 43 | " >>> print(Min_SubarraySum(arr))\n", 44 | " (-6, 1, 4)\n", 45 | "\n", 46 | " >>> arr = [2, 6, 8, 1, 4]\n", 47 | " >>> print(Min_SubarraySum(arr))\n", 48 | " (1, 3, 3)\n", 49 | "\n", 50 | " References:\n", 51 | " https://en.wikipedia.org/wiki/Maximum_subarray_problem\n", 52 | "'''\n", 53 | "\n", 54 | "def Min_SubarraySum(arr):\n", 55 | " best_sum = 0 # or: float('-inf')\n", 56 | " best_start = best_end = 0 # or: None\n", 57 | " current_sum = 0\n", 58 | "\n", 59 | " for current_end, x in enumerate(arr):\n", 60 | " if current_sum >= 0:\n", 61 | " # Start a new sequence at the current element\n", 62 | " current_start = current_end\n", 63 | " current_sum = x\n", 64 | " else:\n", 65 | " # Extend the existing sequence with the current element\n", 66 | " current_sum += x\n", 67 | "\n", 68 | " if current_sum < best_sum:\n", 69 | " best_sum = current_sum\n", 70 | " best_start = current_start\n", 71 | " best_end = current_end \n", 72 | "\n", 73 | " if (best_sum, best_start, best_end) == (0, 0, 0):\n", 74 | " best_sum = min(arr)\n", 75 | " best_start = best_end = arr.index(best_sum)\n", 76 | "\n", 77 | " result = (best_sum, best_start, best_end)\n", 78 | " return result" 79 | ], 80 | "execution_count": null, 81 | "outputs": [] 82 | } 83 | ] 84 | } -------------------------------------------------------------------------------- /Dynamic Programming/PartitionProblem_SubsetSum.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "PartitionProblem_SubsetSum.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Given an array containing only positive integers, find if it can be partitioned \n", 24 | " into two subsets having sum of elements in both subsets is equal. \n", 25 | "\n", 26 | " Time complexity = O(N.T), N, T is length of numbers array and target sum (=sum/2) \n", 27 | "\n", 28 | " Parameters:\n", 29 | " -----------\n", 30 | " nums: list\n", 31 | " List of numbers\n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " True/False\n", 36 | "\n", 37 | " Examples:\n", 38 | " ---------\n", 39 | " 1) Given an array [1, 2, 3, 4], this can be partitioned into 2 subsets having\n", 40 | " equal sum = 5: [1, 4] and [2, 3]. So the target sum is 5.\n", 41 | "\n", 42 | " The dynamic programming matrix looks like this:\n", 43 | " [[0, 1, 1, 1, 1, 1], \n", 44 | " [0, 1, 2, 3, 3, 3], \n", 45 | " [0, 1, 2, 3, 4, 5], \n", 46 | " [0, 0, 0, 0, 0, 0]]\n", 47 | "\n", 48 | " >>> nums = [1, 2, 3, 4]\n", 49 | " >>> print(PartitionProblem_SubsetSum(nums))\n", 50 | " True\n", 51 | "\n", 52 | " 2) Given an array [2,2,3,5], this can't be partitioned into 2 subsets having\n", 53 | " equal sum. So the target sum is (2+2+3+5)/2 = 6.\n", 54 | "\n", 55 | " The dynamic programming matrix looks like this:\n", 56 | " [[0, 0, 2, 2, 2, 2, 2], \n", 57 | " [0, 0, 2, 2, 4, 4, 4], \n", 58 | " [0, 0, 2, 3, 4, 5, 5], \n", 59 | " [0, 0, 2, 3, 4, 5, 5]]\n", 60 | "\n", 61 | " >>> nums = [2,2,3,5]\n", 62 | " >>> print(PartitionProblem_SubsetSum(nums))\n", 63 | " False\n", 64 | "\n", 65 | " References:\n", 66 | " https://en.wikipedia.org/wiki/Knapsack_problem#0-1_knapsack_problem\n", 67 | " https://en.wikipedia.org/wiki/Partition_problem\n", 68 | " https://en.wikipedia.org/wiki/Subset_sum_problem\n", 69 | " https://leetcode.com/problems/partition-equal-subset-sum/discuss/462699/Whiteboard-Editorial.-All-Approaches-explained.\n", 70 | "'''\n", 71 | "\n", 72 | "def PartitionProblem_SubsetSum(nums):\n", 73 | " nums.sort() # Number list must be sorted in ascending order\n", 74 | " \n", 75 | " if sum(nums) % 2 != 0:\n", 76 | " return False\n", 77 | " else:\n", 78 | " tg = sum(nums) // 2 # Target sum\n", 79 | " \n", 80 | " # Modified Knapsack 0/1 Algorithm\n", 81 | " for i in range(len(nums)):\n", 82 | " if nums[i] > tg:\n", 83 | " i -= 1\n", 84 | " break\n", 85 | " R, C = i + 1, tg + 1 # Number of rows and columns for DP matrix\n", 86 | " \n", 87 | " dp = [[0 for i in range(C)] for i in range(R)] # DP matrix\n", 88 | " \n", 89 | " count = nums[0] # Cumulative sum\n", 90 | " for c in range(nums[0], C):\n", 91 | " dp[0][c] = nums[0]\n", 92 | " \n", 93 | " # Original Knapsack 0/1 Algorithm\n", 94 | " for r in range(1, R):\n", 95 | " count += nums[r]\n", 96 | " for c in range(1, C):\n", 97 | " if c < nums[r]:\n", 98 | " dp[r][c] = dp[r-1][c]\n", 99 | " elif nums[r] <= c <= count:\n", 100 | " dp[r][c] = max(dp[r-1][c], nums[r] + dp[r-1][c-nums[r]])\n", 101 | " elif c > count:\n", 102 | " dp[r][c] = dp[r][c-1]\n", 103 | " \n", 104 | " # Modified part to check if numbers can found target sum\n", 105 | " if dp[r][-1] == tg:\n", 106 | " return True\n", 107 | " \n", 108 | " return False" 109 | ], 110 | "execution_count": null, 111 | "outputs": [] 112 | } 113 | ] 114 | } 115 | -------------------------------------------------------------------------------- /Dynamic Programming/SubarraySum_DivByK.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "SubarraySum_DivByK.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Find the number of continuous subarrays of an array whose sum is divisible by k. \n", 24 | " Time complexity = O(n)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " nums: list\n", 29 | " The input array\n", 30 | " k : int\n", 31 | " Given divisor of subarrays\n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " count: int\n", 36 | " The number of subarrays\n", 37 | "\n", 38 | " Examples:\n", 39 | " --------- \n", 40 | " Given an array [4,5,0,-2,-3,1] with given divisor k = 5. \n", 41 | " Subarrays that have sum % 5 = 0 are:\n", 42 | " [5], [5,0], [0], [5,0,-2,-3], [0,-2,-3], [-2,-3], [4,5,0,-2,-3,1].\n", 43 | "\n", 44 | " How the algorithm works?\n", 45 | "\n", 46 | " The array of cumulative sum is [0,4,9,9,7,4,5]\n", 47 | " The array of cumulative sum mod K is [0,4,4,4,2,4,0]\n", 48 | " In the algorithm, turn the array into dictionary of cumulative sum mod K and its frequency:\n", 49 | " memo = {0: 2, 4: 4, 2: 1}\n", 50 | "\n", 51 | " For every cumulative sum (called current sum), if (currSum % k) is in memo, \n", 52 | " then we found subarray(s) having subarraySum % k = 0 from index of \n", 53 | " the sum = currSum - subarraySum to index of currSum.\n", 54 | "\n", 55 | " currSum % k = (currSum - subarraySum) % k\n", 56 | " => subarraySum % k = 0\n", 57 | "\n", 58 | " The number of subarray(s) found is the frequency of the sum = currSum % k.\n", 59 | "\n", 60 | " i = 4 -> currSum = 4 -> currSum % k = 4 not in memo -> ignore\n", 61 | " i = 5 -> currSum = 9 -> currSum % k = 4 in memo -> count = 1, found [5]\n", 62 | " i = 0 -> currSum = 9 -> currSum % k = 4 in memo -> count = 3, found [5,0], [0]\n", 63 | " i = -2 -> currSum = 7 -> currSum % k = 2 not in memo -> ignore\n", 64 | " i = -3 -> currSum = 4 -> currSum % k = 4 in memo -> count = 6, found [5,0,-2,-3], [0,-2,-3], [-2,-3]\n", 65 | " i = 1 -> currSum = 5 -> currSum % k = 0 in memo -> count = 7, found [4,5,0,-2,-3,1].\n", 66 | "\n", 67 | " >>> nums = [4,5,0,-2,-3,1]\n", 68 | " >>> k = 5\n", 69 | " >>> print(SubarraySum_DivByK(nums, k))\n", 70 | " 7\n", 71 | "\n", 72 | " References:\n", 73 | " https://leetcode.com/problems/subarray-sums-divisible-by-k/solution/\n", 74 | "'''\n", 75 | "\n", 76 | "def SubarraySum_DivByK(nums, k):\n", 77 | " from collections import defaultdict\n", 78 | " \n", 79 | " memo = defaultdict(int) # Memoization as: cumulativeSum mod K -> Frequency\n", 80 | " memo[0] = 1\n", 81 | " \n", 82 | " currSum = 0 # Current cumulative sum \n", 83 | " count = 0 # Number of continuous subarrays whose sum is divisible by K\n", 84 | " \n", 85 | " for i in nums:\n", 86 | " currSum += i \n", 87 | " \n", 88 | " # If (currSum % k) is in memo, then we found subarray(s) having subarraySum % k = 0\n", 89 | " # from index of the sum = currSum - subarraySum to index of currSum.\n", 90 | " # currSum % k = (currSum - subarraySum) % k\n", 91 | " # => subarraySum % k = 0\n", 92 | " if currSum % k in memo:\n", 93 | " # The number of subarray(s) found is the frequency of the sum = currSum % k.\n", 94 | " count += memo[currSum % k]\n", 95 | " \n", 96 | " memo[currSum % k] += 1\n", 97 | " \n", 98 | " return count" 99 | ], 100 | "execution_count": null, 101 | "outputs": [] 102 | } 103 | ] 104 | } -------------------------------------------------------------------------------- /Dynamic Programming/SubarraySum_EqualsK.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "SubarraySum_EqualsK.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find the number of continuous subarrays of an array whose sum equals to k. \n", 24 | " Time complexity = O(n) \n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " nums: list\n", 29 | " The input array\n", 30 | " k : int\n", 31 | " Given sum of subarrays\n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " count: int\n", 36 | " The number of subarrays\n", 37 | "\n", 38 | " Examples:\n", 39 | " ---------\n", 40 | " Given an array [3,4,7,2,-3,1,7] with given sum k = 7. \n", 41 | " Subarrays that have sum = 7 are:\n", 42 | " [3,4], [7], [7,2,-3,1], [2,-3,1,7], [7].\n", 43 | "\n", 44 | " How the algorithm works?\n", 45 | "\n", 46 | " The array of cumulative sum is [0,3,7,14,16,13,14,21].\n", 47 | " In the algorithm, turn the array into dictionary of cumulative sum and its frequency:\n", 48 | " memo = {0: 1, 3: 1, 7: 1, 14: 2, 16: 1, 13: 1, 21: 1}\n", 49 | "\n", 50 | " For every cumulative sum (called current sum), if (current sum - k) is in memo, \n", 51 | " then we found subarray(s) having sum = k from index of the sum = current sum - k \n", 52 | " to index of the current sum. \n", 53 | " The number of subarray(s) found is the frequency of the sum = current sum - k.\n", 54 | "\n", 55 | " i = 3 -> currSum = 3 -> currSum - k = -4 not in memo -> ignore\n", 56 | " i = 4 -> currSum = 7 -> currSum - k = 0 in memo -> count = 1, found [3,4]\n", 57 | " i = 7 -> currSum = 14 -> currSum - k = 7 in memo -> count = 2, found [7]\n", 58 | " i = 2 -> currSum = 16 -> currSum - k = 9 not in memo -> ignore\n", 59 | " i = -3 -> currSum = 13 -> currSum - k = 6 not in memo -> ignore\n", 60 | " i = 1 -> currSum = 14 -> currSum - k = 7 in memo -> count = 3, found [7,2,-3,1]\n", 61 | " i = 7 -> currSum = 21 -> currSum - k = 14 in memo -> count = 5, found [2,-3,1,7], [7].\n", 62 | " \n", 63 | " >>> nums = [3,4,7,2,-3,1,7]\n", 64 | " >>> k = 7\n", 65 | " >>> print(SubarraySum_EqualsK(nums, k))\n", 66 | " 5\n", 67 | "\n", 68 | " References:\n", 69 | " https://leetcode.com/problems/subarray-sum-equals-k/solution/\n", 70 | "'''\n", 71 | "\n", 72 | "def SubarraySum_EqualsK(nums, k):\n", 73 | " from collections import defaultdict\n", 74 | " \n", 75 | " memo = defaultdict(int) # Memoization as: Cumulative sum -> Frequency\n", 76 | " memo[0] = 1\n", 77 | " \n", 78 | " currSum = 0 # Current cumulative sum\n", 79 | " count = 0 # Number of continuous subarrays whose sum = k\n", 80 | " \n", 81 | " for i in nums:\n", 82 | " currSum += i\n", 83 | " \n", 84 | " # If (current sum - k) is in memo, then we found subarray(s) having sum = k\n", 85 | " # from index of the sum = current sum - k to index of the current sum.\n", 86 | " # The number of subarray(s) found is the frequency of the sum = current sum - k.\n", 87 | " if currSum - k in memo:\n", 88 | " count += memo[currSum-k]\n", 89 | " \n", 90 | " memo[currSum] += 1\n", 91 | " \n", 92 | " return count" 93 | ], 94 | "execution_count": null, 95 | "outputs": [] 96 | } 97 | ] 98 | } -------------------------------------------------------------------------------- /Dynamic Programming/SumOfSubstrings.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "SumOfSubstrings.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Sum of all Substrings of an number string\n", 24 | " Time complexity = O(|s|)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " s: string\n", 29 | " Input number string\n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " An integer sum of of all number substrings \n", 34 | "\n", 35 | " Examples:\n", 36 | " --------- \n", 37 | " The sub-strings of 123 are 1, 2, 3, 12, 23, 123 which sums to 164\n", 38 | "\n", 39 | " >>> t = SumOfSubstrings('123')\n", 40 | " >>> print(t)\n", 41 | " 164\n", 42 | "\n", 43 | " References:\n", 44 | " https://www.youtube.com/watch?v=kXS66eP0T6s&list=PLVFrD1dmDdvdw9vOgm3-uyP5qbBWLYx9a&index=3\n", 45 | " https://www.geeksforgeeks.org/sum-of-all-substrings-of-a-string-representing-a-number/\n", 46 | "'''\n", 47 | "\n", 48 | "def SumOfSubstrings(s):\n", 49 | " dp = [0]*len(s)\n", 50 | " dp[0] = int(s[0])\n", 51 | " \n", 52 | " for i in range(1,len(s)):\n", 53 | " # If mod(10^9+7) is required, then add in\n", 54 | " dp[i] = (i+1)*int(s[i]) + 10*dp[i-1]\n", 55 | " \n", 56 | " return sum(dp)" 57 | ], 58 | "execution_count": null, 59 | "outputs": [] 60 | } 61 | ] 62 | } -------------------------------------------------------------------------------- /Greedy Algorithm/Largest_Permutation.ipynb: -------------------------------------------------------------------------------- 1 | {"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Largest_Permutation.ipynb","provenance":[],"collapsed_sections":[]},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"code","metadata":{"id":"UbI2xrdV4fTi"},"source":["from collections import defaultdict\n","\n","'''\n","NOTE:\n","- Time complexity = O(n)\n","- The trick is to use dictionary to store {value:index} of the array, \n","so we can access index faster\n","'''\n","\n","# Complete the largestPermutation function below.\n","def largestPermutation(k, arr):\n"," # Create a dictionary to store values and indices of arr\n"," # This will reduce much time to take index of a value\n"," # {value1:index1, value2:index2, ..., valueN:indexN}\n"," dict = defaultdict(int)\n","\n"," for i in range(0,len(arr)):\n"," dict[arr[i]] = i\n","\n"," # Check each value in arr to see if we can swap\n"," for j in range(0,len(arr)):\n"," # Extract index of max value in arr[j:len(arr)]\n"," # Max value = len(arr)-j \n"," # Time = O(1) instead of O(n) by using max(arr[j:len(arr)])\n"," idx = dict[len(arr)-j]\n","\n"," if k > 0 and j != idx:\n"," # Update new indices of 2 swapped values\n"," dict[len(arr)-j] = j\n"," dict[arr[j]] = idx\n"," # Swap 2 values\n"," arr[j],arr[idx] = arr[idx],arr[j]\n"," # Lose 1 swap after that\n"," k -= 1\n","\n"," # If there's no swap allowed anymore\n"," elif k <= 0:\n"," break\n","\n"," return arr\n"," \n","if __name__ == '__main__':\n"," nk = input().split()\n"," n = int(nk[0])\n"," k = int(nk[1])\n","\n"," arr = list(map(int, input().rstrip().split()))\n","\n"," result = largestPermutation(k, arr)\n"," print(' '.join(map(str, result)))\n"," "],"execution_count":null,"outputs":[]}]} 2 | -------------------------------------------------------------------------------- /Greedy Algorithm/Largest_Permutation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Greedy Algorithm/Largest_Permutation.pdf -------------------------------------------------------------------------------- /Greedy Algorithm/Sherlock_and_The_Beast.ipynb: -------------------------------------------------------------------------------- 1 | {"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Sherlock_and_The_Beast.ipynb","provenance":[],"collapsed_sections":[]},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"code","metadata":{"id":"UbI2xrdV4fTi"},"source":["def decentNumber(n):\n"," if n%5 == 0 and n%3 == 0:\n"," return int('5'*n)\n","\n"," elif n%3 == 0:\n"," return int('5'*n)\n"," \n"," # If no match above, then n-digit-result is composed by\n"," # (3*b) digits of 5 and (5*a) digits of 3\n"," for a in range(0,n//5+1):\n"," if n - 5*a >= 0:\n"," if (n - 5*a)%3 == 0:\n"," b = int((n - 5*a)/3)\n"," return int('5'*(3*b) + '3'*(5*a))\n"," \n"," return -1\n","\n","if __name__ == '__main__':\n"," t = int(input().strip())\n","\n"," for t_itr in range(t):\n"," n = int(input().strip())\n"," print(decentNumber(n))"],"execution_count":null,"outputs":[]}]} 2 | -------------------------------------------------------------------------------- /Greedy Algorithm/Sherlock_and_The_Beast.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leduckhai/Awesome-Competitive-Programming/f17270caaf59a26eebaa9acf99b04d5d6562b95a/Greedy Algorithm/Sherlock_and_The_Beast.pdf -------------------------------------------------------------------------------- /Linked List/Array_to_ListNode.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [] 7 | }, 8 | "kernelspec": { 9 | "name": "python3", 10 | "display_name": "Python 3" 11 | }, 12 | "language_info": { 13 | "name": "python" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "code", 19 | "source": [ 20 | "'''\n", 21 | " Function to convert Array to ListNode\n", 22 | "\n", 23 | " Parameters:\n", 24 | " -----------\n", 25 | " root : ListNode\n", 26 | " ListNode object\n", 27 | "\n", 28 | " Examples:\n", 29 | " ---------\n", 30 | " >>> arr = [0, 1, 2]\n", 31 | " >>> root = Array_to_ListNode(arr)\n", 32 | " >>> print(root.val, root.next.val, root.next.next.val)\n", 33 | " 0 1 2\n", 34 | "'''\n", 35 | "\n", 36 | "class ListNode:\n", 37 | " def __init__(self, val=0, next=None):\n", 38 | " self.val = val\n", 39 | " self.next = next\n", 40 | "\n", 41 | "def Array_to_ListNode(arr):\n", 42 | " root = ListNode()\n", 43 | " curr = root\n", 44 | "\n", 45 | " for i in range(0, len(arr)):\n", 46 | " curr.val = arr[i]\n", 47 | " if i < len(arr)-1:\n", 48 | " curr.next = ListNode()\n", 49 | " curr = curr.next\n", 50 | "\n", 51 | " return root" 52 | ], 53 | "metadata": { 54 | "id": "GBzvaIlHHaWM" 55 | }, 56 | "execution_count": 10, 57 | "outputs": [] 58 | } 59 | ] 60 | } -------------------------------------------------------------------------------- /Linked List/ListNode.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [] 7 | }, 8 | "kernelspec": { 9 | "name": "python3", 10 | "display_name": "Python 3" 11 | }, 12 | "language_info": { 13 | "name": "python" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "code", 19 | "source": [ 20 | "'''\n", 21 | " Function to define a singly-linked list using \"Node class\"\n", 22 | "\n", 23 | " Parameters:\n", 24 | " -----------\n", 25 | " val : integer\n", 26 | " Value of the node\n", 27 | " next: None or ListNode\n", 28 | " None or another node\n", 29 | "\n", 30 | " Examples:\n", 31 | " ---------\n", 32 | " >>> root = ListNode()\n", 33 | " >>> root.val = 1\n", 34 | " >>> root.next = ListNode()\n", 35 | " >>> print(root)\n", 36 | " <__main__.ListNode object at 0x7d6c1624a5f0>\n", 37 | "\n", 38 | " >>> print(root.val)\n", 39 | " 1\n", 40 | "\n", 41 | " >>> print(root.next.val)\n", 42 | " 0\n", 43 | "'''\n", 44 | "\n", 45 | "class ListNode:\n", 46 | " def __init__(self, val=0, next=None):\n", 47 | " self.val = val\n", 48 | " self.next = next" 49 | ], 50 | "metadata": { 51 | "id": "GBzvaIlHHaWM" 52 | }, 53 | "execution_count": 2, 54 | "outputs": [] 55 | } 56 | ] 57 | } -------------------------------------------------------------------------------- /Linked List/ListNode_to_Array.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [] 7 | }, 8 | "kernelspec": { 9 | "name": "python3", 10 | "display_name": "Python 3" 11 | }, 12 | "language_info": { 13 | "name": "python" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "code", 19 | "source": [ 20 | "'''\n", 21 | " Function to convert ListNode to Array\n", 22 | "\n", 23 | " Parameters:\n", 24 | " -----------\n", 25 | " root : ListNode\n", 26 | " ListNode object\n", 27 | "\n", 28 | " Examples:\n", 29 | " ---------\n", 30 | " >>> root = ListNode(0)\n", 31 | " >>> root.next = ListNode(1)\n", 32 | " >>> root.next.next = ListNode(2)\n", 33 | " >>> print(ListNode_to_Array(root))\n", 34 | " [0, 1, 2]\n", 35 | "'''\n", 36 | "\n", 37 | "class ListNode:\n", 38 | " def __init__(self, val=0, next=None):\n", 39 | " self.val = val\n", 40 | " self.next = next\n", 41 | "\n", 42 | "def ListNode_to_Array(root):\n", 43 | " curr = root\n", 44 | " arr = []\n", 45 | "\n", 46 | " while curr:\n", 47 | " arr.append(curr.val)\n", 48 | " curr = curr.next\n", 49 | "\n", 50 | " return arr" 51 | ], 52 | "metadata": { 53 | "id": "GBzvaIlHHaWM" 54 | }, 55 | "execution_count": 7, 56 | "outputs": [] 57 | } 58 | ] 59 | } -------------------------------------------------------------------------------- /Mathematics/Euler_Totient_NumList.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "asdf.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find ALL numbers of coprimes less than n based on Euler totient function\n", 24 | " Time complexity = O((l) + m.loglogm + l.(logm + k)); \n", 25 | " k is the number of prime factors of n,\n", 26 | " m is max value of the input number list\n", 27 | " l is length of the input number list\n", 28 | "\n", 29 | " Parameters:\n", 30 | " -----------\n", 31 | " NumList: list\n", 32 | " Input integer number list\n", 33 | " max_n : integer, optional\n", 34 | " Max value of the input number list \n", 35 | "\n", 36 | " Returns:\n", 37 | " --------\n", 38 | " phi_list: list\n", 39 | " All values of phi (all numbers of coprimes less than n)\n", 40 | "\n", 41 | " Examples:\n", 42 | " ---------\n", 43 | " >>> # Common use with the input list [1,2,...,10]\n", 44 | " >>> print(Euler_Totient_NumList(list(range(1,11))))\n", 45 | " [1, 1, 2, 2, 4, 2, 6, 4, 6, 4]\n", 46 | "\n", 47 | " >>> # Faster runtime with known max value of the list\n", 48 | " >>> print(Euler_Totient_NumList(list(range(1,11)),10))\n", 49 | " [1, 1, 2, 2, 4, 2, 6, 4, 6, 4]\n", 50 | "\n", 51 | " >>> # Also works with random integer numbers\n", 52 | " >>> print(Euler_Totient_NumList([3,1,7,4,8]))\n", 53 | " [2, 1, 6, 2, 4]\n", 54 | "\n", 55 | " See also:\n", 56 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Sieve_SPF.ipynb \n", 57 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PrimeFactorization_SPF.ipynb\n", 58 | "\n", 59 | " Reference: \n", 60 | " https://en.wikipedia.org/wiki/Euler%27s_totient_function#Euler's_product_formula\n", 61 | " https://cp-algorithms.com/algebra/phi-function.html\n", 62 | "'''\n", 63 | "\n", 64 | "def Euler_Totient_NumList(NumList, max_n=-1):\n", 65 | " '''\n", 66 | " Function to find SPF (Smallest Prime Factor) for all numbers < N\n", 67 | " Time complexity = O(nloglogn)\n", 68 | " See also: https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Sieve_SPF.ipynb\n", 69 | " '''\n", 70 | "\n", 71 | " from math import ceil, sqrt\n", 72 | "\n", 73 | " def Sieve_SPF(N):\n", 74 | " # Stores smallest prime factor for every number\n", 75 | " SPFs = [0]*N\n", 76 | " SPFs[1] = 1\n", 77 | "\n", 78 | " for i in range(2, N):\n", 79 | " # Mark smallest prime factor for every number to be itself\n", 80 | " SPFs[i] = i\n", 81 | "\n", 82 | " # Separately marking spf for every even number as 2\n", 83 | " for i in range(4, N, 2):\n", 84 | " SPFs[i] = 2\n", 85 | "\n", 86 | " for i in range(3, ceil(sqrt(N))):\n", 87 | " # Check if i is prime\n", 88 | " if (SPFs[i] == i):\n", 89 | " # Mark SPFs for all numbers divisible by i\n", 90 | " for j in range(i * i, N, i):\n", 91 | " # Mark SPFs[j] if it is not previously marked\n", 92 | " if (SPFs[j] == j):\n", 93 | " SPFs[j] = i \n", 94 | "\n", 95 | " return SPFs\n", 96 | "\n", 97 | " '''\n", 98 | " Function to return prime factorization by dividing by SPF at every step\n", 99 | " Time complexity = O(log n)\n", 100 | " See also: https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PrimeFactorization_SPF.ipynb\n", 101 | " '''\n", 102 | "\n", 103 | " def PrimeFactorization_SPF(x,SPFs):\n", 104 | " PFs = set() # Set of all prime factors of x\n", 105 | " while (x != 1):\n", 106 | " PFs.add(SPFs[x])\n", 107 | " x = x // SPFs[x]\n", 108 | " return PFs\n", 109 | "\n", 110 | " # Core function\n", 111 | " if max_n == -1: max_n = max(NumList) # Time = O(l); O(1) if max_n is known\n", 112 | " \n", 113 | " SPFs = Sieve_SPF(max_n+1)\n", 114 | "\n", 115 | " phi_list = []\n", 116 | "\n", 117 | " for n in NumList:\n", 118 | " PFs = PrimeFactorization_SPF(n,SPFs)\n", 119 | " phi = n \n", 120 | " for p in PFs:\n", 121 | " phi *= (1-1/p)\n", 122 | "\n", 123 | " phi_list.append(int(phi))\n", 124 | "\n", 125 | " return phi_list" 126 | ], 127 | "execution_count": null, 128 | "outputs": [] 129 | } 130 | ] 131 | } 132 | -------------------------------------------------------------------------------- /Mathematics/Euler_Totient_SingleNum.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Euler_Totient_SingleNum.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find the number of coprimes less than n based on Euler totient function\n", 24 | " Time complexity = O(sqrt(n) + k); \n", 25 | " n is the input number\n", 26 | " k is the number of prime factors of n\n", 27 | "\n", 28 | " Parameters:\n", 29 | " -----------\n", 30 | " n: integer\n", 31 | " The input positive number \n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " phi: integer\n", 36 | " Phi value of n (the number of coprimes < n)\n", 37 | "\n", 38 | " Examples:\n", 39 | " ---------\n", 40 | " >>> n_cp = Euler_Totient_SingleNum(11)\n", 41 | " >>> print(n_cp) \n", 42 | " 10\n", 43 | "\n", 44 | " See also:\n", 45 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Euler_Totient_NumList.ipynb \n", 46 | "\n", 47 | " Reference: \n", 48 | " https://en.wikipedia.org/wiki/Euler%27s_totient_function#Euler's_product_formula\n", 49 | " https://cp-algorithms.com/algebra/phi-function.html\n", 50 | "'''\n", 51 | "\n", 52 | "def Euler_Totient_SingleNum(n):\n", 53 | " '''\n", 54 | " Function to find all prime factors of a positive integer\n", 55 | " Time complexity = O(sqrt(n))\n", 56 | "\n", 57 | " See also:\n", 58 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PrimeFactorization.ipynb\n", 59 | " '''\n", 60 | "\n", 61 | " def PrimeFactorization(n):\n", 62 | " factors = []\n", 63 | " d = 2\n", 64 | "\n", 65 | " while n > 1:\n", 66 | " \n", 67 | " while n % d == 0:\n", 68 | " if d not in factors:\n", 69 | " factors.append(d)\n", 70 | " n /= d\n", 71 | "\n", 72 | " d += 1\n", 73 | "\n", 74 | " if d*d > n:\n", 75 | " if n > 1: \n", 76 | " factors.append(int(n))\n", 77 | " break\n", 78 | "\n", 79 | " return factors\n", 80 | "\n", 81 | " # Core function\n", 82 | " PFs = PrimeFactorization(n) # All prime factors of n\n", 83 | " phi = n \n", 84 | "\n", 85 | " for p in PFs:\n", 86 | " phi *= (1-1/p)\n", 87 | "\n", 88 | " return int(phi)" 89 | ], 90 | "execution_count": null, 91 | "outputs": [] 92 | } 93 | ] 94 | } -------------------------------------------------------------------------------- /Mathematics/Factorization.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "adsf.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find all factors of an integer\n", 24 | " Time complexity = O(sqrt(n))\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " n: integer\n", 29 | " Input number \n", 30 | " \n", 31 | " Returns:\n", 32 | " --------\n", 33 | " factors: list\n", 34 | " All factors of the number n\n", 35 | "\n", 36 | " Examples:\n", 37 | " ---------\n", 38 | " >>> factors = Factorization(10)\n", 39 | " >>> print(factors)\n", 40 | " [1, 10, 2, 5]\n", 41 | "\n", 42 | " See also:\n", 43 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PrimeFactorization.ipynb\n", 44 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PrimeFactorization_SPF.ipynb\n", 45 | "'''\n", 46 | "\n", 47 | "def Factorization(n):\n", 48 | " factors = []\n", 49 | "\n", 50 | " for div in range(1, int(n**0.5) + 1):\n", 51 | " if n % div == 0:\n", 52 | " factors.append(div)\n", 53 | "\n", 54 | " other = n // div\n", 55 | " if other != div:\n", 56 | " factors.append(other)\n", 57 | "\n", 58 | " return factors" 59 | ], 60 | "execution_count": null, 61 | "outputs": [] 62 | } 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /Mathematics/Lattice_Paths.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Lattice_Paths.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "from math import factorial as f\n", 23 | "\n", 24 | "def Lattice_Paths(n,m):\n", 25 | " res = f(n+m)//(f(n)*f(m)) # (n+m)C(n) or (n+m)C(m)\n", 26 | " return res%(10**9+7)\n", 27 | "\n", 28 | "if __name__ == '__main__':\n", 29 | " for _ in range(int(input())):\n", 30 | " nm = list(map(int,input().split()))\n", 31 | " n,m = nm\n", 32 | " print(Lattice_Paths(n,m))" 33 | ], 34 | "execution_count": null, 35 | "outputs": [] 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /Mathematics/Lexicographic_Permutations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "adsf.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find n-th Lexicographic Permutation of a very long word\n", 24 | " Time complexity = O(n) \n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " word: string\n", 29 | " Input word to find permutation \n", 30 | " n : integer\n", 31 | " Order of Lexicographic Permutation\n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " word_perm: string\n", 36 | " n-th permutated word\n", 37 | "\n", 38 | " Examples:\n", 39 | " ---------\n", 40 | " The Lexicographic Permutations of 'abc' are:\n", 41 | " 'abc', 'acb', 'bac', 'bca', 'cab', 'cba'\n", 42 | " 1 2 3 4 5 6 (= 3!)\n", 43 | "\n", 44 | " >>> word = 'abc'\n", 45 | " >>> word_perm = Lexicographic_Permutations(word,4)\n", 46 | " >>> print(word_perm)\n", 47 | " bca\n", 48 | "'''\n", 49 | "\n", 50 | "from math import factorial as f\n", 51 | "\n", 52 | "def Lexicographic_Permutations(word,n): \n", 53 | " n -= 1 # First order of permutation is 1, not 0\n", 54 | " queue = sorted(word)\n", 55 | " word_perm = ''\n", 56 | " i = 1\n", 57 | "\n", 58 | " while queue:\n", 59 | " pos = n//f(len(word)-i)\n", 60 | " word_perm += queue.pop(pos)\n", 61 | " n -= pos*f(len(word)-i)\n", 62 | " i += 1\n", 63 | " \n", 64 | " return word_perm" 65 | ], 66 | "execution_count": null, 67 | "outputs": [] 68 | } 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /Mathematics/Multiples_of_3_and_5.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Multiples of 3 and 5.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "def SumOfMultiples(n):\n", 23 | " n = n - 1\n", 24 | " \n", 25 | " sum_of_3 = 3*(n//3)*(1+n//3)//2\n", 26 | " sum_of_5 = 5*(n//5)*(1+n//5)//2\n", 27 | " sum_of_15 = 15*(n//15)*(1+n//15)//2\n", 28 | " \n", 29 | " sum = int(sum_of_3 + sum_of_5 - sum_of_15)\n", 30 | " \n", 31 | " return sum\n", 32 | "\n", 33 | "if __name__ == '__main__':\n", 34 | " t = int(input())\n", 35 | " \n", 36 | " for _ in range(t):\n", 37 | " n = int(input())\n", 38 | " print(SumOfMultiples(n))" 39 | ], 40 | "execution_count": null, 41 | "outputs": [] 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /Mathematics/Number_Spiral_Diagonals.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Number_Spiral_Diagonals.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "# Faster solution instead of Brute-force method O(n)\n", 23 | "# Time complexity = O(1)\n", 24 | "def Number_Spiral_Diagonals(n):\n", 25 | " N = (n+1)//2 # Number of numbers from 1 to n\n", 26 | " \n", 27 | " sum1 = n*(n+1)*(n+2)//6 - 3*N*(1+n)//2 + 3*N\n", 28 | " sum2 = n*(n+1)*(n+2)//6 - 2*N*(1+n)//2 + 2*N\n", 29 | " sum3 = n*(n+1)*(n+2)//6 - 1*N*(1+n)//2 + 1*N\n", 30 | " sum4 = n*(n+1)*(n+2)//6\n", 31 | " sum = sum1 + sum2 + sum3 + sum4 - 3\n", 32 | " \n", 33 | " return sum%(10**9+7)\n", 34 | "\n", 35 | "if __name__ == '__main__':\n", 36 | " for _ in range(int(input())):\n", 37 | " n = int(input())\n", 38 | " print(Number_Spiral_Diagonals(n))" 39 | ], 40 | "execution_count": null, 41 | "outputs": [] 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /Mathematics/Pascal_Triangle.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "adsf.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to create Pascal Triangle, used to calculate multiple large-number combinations\n", 24 | " Time complexity = O(n^2)\n", 25 | " Space complexity = O((n+1)(n+2)/2)\n", 26 | "\n", 27 | " Parameters:\n", 28 | " -----------\n", 29 | " N: integer\n", 30 | " Size of Pascal Triangle\n", 31 | " \n", 32 | " Returns:\n", 33 | " --------\n", 34 | " t: list\n", 35 | " All rows of Pascal Triangle\n", 36 | "\n", 37 | " Examples:\n", 38 | " ---------\n", 39 | " For N = 4:\n", 40 | " 1 n = 0 0C0\n", 41 | " 1 1 n = 1 1C0 1C1\n", 42 | " 1 2 1 n = 2 2C0 2C1 2C2 \n", 43 | " 1 3 3 1 n = 3 3C0 3C1 3C2 3C3\n", 44 | " 1 4 6 4 1 n = 4 4C0 4C1 4C2 4C3 4C4\n", 45 | "\n", 46 | " >>> t = Pascal_Triangle(4)\n", 47 | " >>> print(t)\n", 48 | " [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]]\n", 49 | "\n", 50 | " References: \n", 51 | " https://www.hackerrank.com/challenges/ncr-table/editorial\n", 52 | "'''\n", 53 | "\n", 54 | "def Pascal_Triangle(N):\n", 55 | " t = [] # Full triangle\n", 56 | "\n", 57 | " for i in range(0,N+1):\n", 58 | " r = [0]*(i+1) # Row i of triangle t\n", 59 | " t.append(r)\n", 60 | "\n", 61 | " for j in range(0,len(r)):\n", 62 | " if j == 0 or j == i: # nC0 = nCn = 1\n", 63 | " t[i][j] = 1\n", 64 | " else:\n", 65 | " t[i][j] = t[i-1][j-1] + t[i-1][j]\n", 66 | "\n", 67 | " return t" 68 | ], 69 | "execution_count": null, 70 | "outputs": [] 71 | } 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /Mathematics/PrimeFactorization.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "PrimeFactorization.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find all prime factors of a positive integer\n", 24 | " Time complexity = O(sqrt(n))\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " n: integer\n", 29 | " The input positive number\n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " factors: list\n", 34 | " All prime factors of the input number\n", 35 | "\n", 36 | " Examples:\n", 37 | " >>> factors = PrimeFactorization(45)\n", 38 | " >>> print(factors)\n", 39 | " [3, 5]\n", 40 | "\n", 41 | " See also:\n", 42 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PrimeFactorization_SPF.ipynb\n", 43 | "'''\n", 44 | "\n", 45 | "def PrimeFactorization(n):\n", 46 | " factors = []\n", 47 | " d = 2\n", 48 | "\n", 49 | " while n > 1:\n", 50 | " \n", 51 | " while n % d == 0:\n", 52 | " if d not in factors:\n", 53 | " factors.append(d)\n", 54 | " n /= d\n", 55 | "\n", 56 | " d += 1\n", 57 | "\n", 58 | " if d*d > n:\n", 59 | " if n > 1: \n", 60 | " factors.append(int(n))\n", 61 | " break\n", 62 | "\n", 63 | " return factors" 64 | ], 65 | "execution_count": null, 66 | "outputs": [] 67 | } 68 | ] 69 | } -------------------------------------------------------------------------------- /Mathematics/PrimeFactorization_SPF.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "PrimeFactorization_SPF.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to return prime factorization by dividing by SPF at every step\n", 24 | " Time complexity = O(log n) \n", 25 | " \n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " x : integer\n", 29 | " Input number \n", 30 | " SPFs: list\n", 31 | " All Smallest Prime Factors from 0 to x \n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " PFs: set\n", 36 | " All prime factors of the number x\n", 37 | "\n", 38 | " Examples:\n", 39 | " ---------\n", 40 | " >>> # In case we already calculated all Smallest Prime Factors from 0 to x\n", 41 | " >>> SPFs = [0, 1, 2, 3, 2, 5, 2, 7, 2, 3]\n", 42 | " >>> print(PrimeFactorization_SPF(4,SPFs))\n", 43 | " {2}\n", 44 | "\n", 45 | " >>> # In case we didn't calculate all Smallest Prime Factors from 0 to x\n", 46 | " >>> SPFs = Sieve_SPF(10)\n", 47 | " >>> print(SPFs)\n", 48 | " [0, 1, 2, 3, 2, 5, 2, 7, 2, 3]\n", 49 | " >>> print(PrimeFactorization_SPF(4,SPFs))\n", 50 | " {2}\n", 51 | "\n", 52 | " See also:\n", 53 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Sieve_SPF.ipynb\n", 54 | "\n", 55 | " References: \n", 56 | " https://www.geeksforgeeks.org/prime-factorization-using-sieve-olog-n-multiple-queries/\n", 57 | "'''\n", 58 | "\n", 59 | "def PrimeFactorization_SPF(x,SPFs):\n", 60 | " PFs = set() # Set of all prime factors of x\n", 61 | " while (x != 1):\n", 62 | " PFs.add(SPFs[x])\n", 63 | " x = x // SPFs[x]\n", 64 | " return PFs " 65 | ], 66 | "execution_count": null, 67 | "outputs": [] 68 | } 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /Mathematics/PythagoreanTriplets_LessEqualN.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "PythagoreanTriplets_LessEqualN.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to generate all Pythagorean Triplets <= N\n", 24 | " Time complexity = O(N.log(N))\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " N: int\n", 29 | " Input number\n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " triplets: list\n", 34 | " List of Pythagorean Triplet tuples\n", 35 | "\n", 36 | " Examples:\n", 37 | " ---------\n", 38 | " Every element in triplets must be <= N\n", 39 | "\n", 40 | " >>> N = 20\n", 41 | " >>> triplets = PythagoreanTriplets_LessEqualN(N)\n", 42 | " >>> print(triplets)\n", 43 | " [(3, 4, 5), (6, 8, 10), (9, 12, 15), (12, 16, 20), (5, 12, 13), (15, 8, 17)]\n", 44 | "\n", 45 | " References:\n", 46 | " https://codereview.stackexchange.com/questions/250855/efficiently-find-all-the-pythagorean-triplets-where-all-numbers-less-than-1000\n", 47 | " https://en.wikipedia.org/wiki/Pythagorean_triple#Generating_a_triple\n", 48 | "'''\n", 49 | "\n", 50 | "from math import sqrt, gcd\n", 51 | "\n", 52 | "def PythagoreanTriplets_LessEqualN(N):\n", 53 | " triplets = []\n", 54 | "\n", 55 | " for m in range(0, int(sqrt(N-1))+1):\n", 56 | " for n in range(1+m%2, min(m, int(sqrt(N-m**2))+1), 2):\n", 57 | " if gcd(m, n) > 1:\n", 58 | " continue\n", 59 | "\n", 60 | " a = m**2 - n**2\n", 61 | " b = 2*m*n\n", 62 | " c = m**2 + n**2\n", 63 | "\n", 64 | " for k in range(1, N//c+1):\n", 65 | " triplets.append((k*a,k*b,k*c))\n", 66 | " \n", 67 | " return triplets" 68 | ], 69 | "execution_count": null, 70 | "outputs": [] 71 | } 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /Mathematics/PythagoreanTriplets_Perimeter.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "PythagoreanTriplets_Perimeter.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Pythagorean Triplets having perimeter (or sum) P\n", 24 | " Time complexity = O(P)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " P: int\n", 29 | " Input perimeter \n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " triplets: set\n", 34 | " A set of all Pythagorean Triplet tuples having perimeter P\n", 35 | "\n", 36 | " Examples:\n", 37 | " ---------\n", 38 | " >>> P = 120\n", 39 | " >>> triplets = PythagoreanTriplets_Perimeter(P)\n", 40 | " >>> print(triplets)\n", 41 | " {(24, 45, 51), (20, 48, 52), (30, 40, 50)}\n", 42 | "\n", 43 | " >>> P = 11\n", 44 | " >>> triplets = PythagoreanTriplets_Perimeter(P)\n", 45 | " >>> print(triplets)\n", 46 | " set()\n", 47 | "\n", 48 | " References:\n", 49 | " https://www.geeksforgeeks.org/pythagorean-triplet-with-given-sum-using-single-loop/?ref=lbp\n", 50 | "'''\n", 51 | "\n", 52 | "def PythagoreanTriplets_Perimeter(P):\n", 53 | " triplets = set()\n", 54 | " \n", 55 | " for a in range(1, P):\n", 56 | " b = (P**2 - 2*P*a)//(2*P - 2*a)\n", 57 | " c = P - a - b\n", 58 | " \n", 59 | " if a**2 + b**2 == c**2 and b > 0 and c > 0:\n", 60 | " triplets.add(tuple(sorted([a,b,c])))\n", 61 | " \n", 62 | " return triplets" 63 | ], 64 | "execution_count": null, 65 | "outputs": [] 66 | } 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /Mathematics/Sieve_All_Primes.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "adsf.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find all primes < n using \"Sieve Method\"\n", 24 | " Time complexity = O(sqrt(n))\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " n: integer\n", 29 | " Input positive number \n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " primes: list\n", 34 | " All prime numbers < n\n", 35 | "\n", 36 | " Examples:\n", 37 | " ---------\n", 38 | " >>> primes = Sieve_All_Primes(11)\n", 39 | " >>> print(primes)\n", 40 | " [2, 3, 5, 7]\n", 41 | "'''\n", 42 | "\n", 43 | "def Sieve_All_Primes(n):\n", 44 | " sieve = [True] * n\n", 45 | " for i in range(3,int(n**0.5)+1,2):\n", 46 | " if sieve[i]:\n", 47 | " sieve[i*i::2*i]=[False]*((n-i*i-1)//(2*i)+1)\n", 48 | " \n", 49 | " # Output the list of all primes\n", 50 | " primes = [2] + [i for i in range(3,n,2) if sieve[i]]\n", 51 | " return primes" 52 | ], 53 | "execution_count": null, 54 | "outputs": [] 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /Mathematics/Sieve_SPF.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "asdf.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find SPF (Smallest Prime Factor) for all numbers < N\n", 24 | " Time complexity = O(nloglogn) \n", 25 | " \n", 26 | " Parameters:\n", 27 | " N: integer\n", 28 | "\n", 29 | " Returns:\n", 30 | " SPFs: list\n", 31 | " All Smallest Prime Factors of all numbers from 0 to N-1\n", 32 | "\n", 33 | " Examples:\n", 34 | " >>> SPFs = Sieve_SPF(10)\n", 35 | " >>> print(SPFs)\n", 36 | " [0, 1, 2, 3, 2, 5, 2, 7, 2, 3]\n", 37 | "\n", 38 | " See also:\n", 39 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PrimeFactorization_SPF.ipynb\n", 40 | " \n", 41 | " References: \n", 42 | " https://www.geeksforgeeks.org/prime-factorization-using-sieve-olog-n-multiple-queries/\n", 43 | "'''\n", 44 | "\n", 45 | "from math import ceil, sqrt\n", 46 | "\n", 47 | "def Sieve_SPF(N):\n", 48 | " # Stores smallest prime factor for every number\n", 49 | " SPFs = [0]*N\n", 50 | " SPFs[1] = 1\n", 51 | "\n", 52 | " for i in range(2, N):\n", 53 | " # Mark smallest prime factor for every number to be itself\n", 54 | " SPFs[i] = i\n", 55 | "\n", 56 | " # Separately marking spf for every even number as 2\n", 57 | " for i in range(4, N, 2):\n", 58 | " SPFs[i] = 2\n", 59 | "\n", 60 | " for i in range(3, ceil(sqrt(N))):\n", 61 | " # Check if i is prime\n", 62 | " if (SPFs[i] == i):\n", 63 | " # Mark SPFs for all numbers divisible by i\n", 64 | " for j in range(i * i, N, i):\n", 65 | " # Mark SPFs[j] if it is not previously marked\n", 66 | " if (SPFs[j] == j):\n", 67 | " SPFs[j] = i \n", 68 | "\n", 69 | " return SPFs" 70 | ], 71 | "execution_count": null, 72 | "outputs": [] 73 | } 74 | ] 75 | } 76 | -------------------------------------------------------------------------------- /Mathematics/areCoprimes.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "asdf.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to check if two numbers are coprime\n", 24 | " Time complexity = O(log a.b)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " a: integer\n", 29 | " First input number \n", 30 | " b: integer\n", 31 | " Second input number\n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " True/False: boolean\n", 36 | "\n", 37 | " References: \n", 38 | " https://stackoverflow.com/questions/39678984/efficiently-check-if-two-numbers-are-co-primes-relatively-primes/39679114#39679114\n", 39 | "'''\n", 40 | "\n", 41 | "import math\n", 42 | "\n", 43 | "def areCoprimes(a,b):\n", 44 | " return math.gcd(a,b) == 1" 45 | ], 46 | "execution_count": null, 47 | "outputs": [] 48 | } 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /Mathematics/arePermutations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Draft.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "v7CwPh7LozYh" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to check if 2 numbers/strings are permutations\n", 24 | " Time complexity = O(n.logn), n = max(|a|,|b|)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " a: integer or string\n", 29 | " First input \n", 30 | " b: integer or string\n", 31 | " Second input\n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " True/False: boolean\n", 36 | "\n", 37 | " Examples:\n", 38 | " ---------\n", 39 | " >>> a = 'AEF'\n", 40 | " >>> b = 'FEAF'\n", 41 | " >>> print(arePermutations(a,b)) \n", 42 | " False\n", 43 | "\n", 44 | " >>> a = 1432\n", 45 | " >>> b = 4312\n", 46 | " >>> print(arePermutations(a,b))\n", 47 | " True\n", 48 | "'''\n", 49 | "\n", 50 | "def arePermutations(a,b):\n", 51 | " # Decompose input into a sorted list of characters\n", 52 | " la, lb = sorted(str(a)), sorted(str(b)) \n", 53 | "\n", 54 | " if la == lb:\n", 55 | " return True\n", 56 | " else:\n", 57 | " return False" 58 | ], 59 | "execution_count": 1, 60 | "outputs": [] 61 | } 62 | ] 63 | } 64 | -------------------------------------------------------------------------------- /Mathematics/isPrime.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "isPrime.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to check if a number is prime using \"Common Method\"\n", 24 | " Time complexity = O(sqrt(n))\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " n: integer\n", 29 | " Input number \n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " True/False: boolean\n", 34 | "\n", 35 | "'''\n", 36 | "\n", 37 | "def isPrime(n):\n", 38 | " if n == 2 or n == 3: return True\n", 39 | " if n%2 == 0 or n < 2: return False\n", 40 | " for i in range(3, int(n**0.5)+1, 2): # Only odd numbers\n", 41 | " if n%i == 0:\n", 42 | " return False \n", 43 | "\n", 44 | " return True" 45 | ], 46 | "execution_count": null, 47 | "outputs": [] 48 | } 49 | ] 50 | } -------------------------------------------------------------------------------- /Mathematics/isPrime_Miller_Rabin.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "asdf.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to check if a number is prime based on Miller-Rabin probabilistic test\n", 24 | " Time complexity = O(k.(logn)^3)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " n: integer\n", 29 | " Input number to be checked\n", 30 | " k: integer, optional\n", 31 | " Constant adjusted to balance accuracy/speed (default: k = 3)\n", 32 | " Highly recommend to try multiple k to get best outcome \n", 33 | "\n", 34 | " Returns:\n", 35 | " --------\n", 36 | " PFs: set\n", 37 | " All prime factors of the number x\n", 38 | "\n", 39 | " Examples:\n", 40 | " ---------\n", 41 | " >>> n = 11\n", 42 | " >>> print(isPrime_Miller_Rabin(n, k=3)) \n", 43 | " True\n", 44 | "\n", 45 | " >>> # Experiment to find best 'k'\n", 46 | " >>> primes = Sieve_All_Primes(10**5)\n", 47 | " >>> for n in primes:\n", 48 | " >>> if isPrime(n) != isPrime_Miller_Rabin(n, k=3):\n", 49 | " >>> print('k=3 cannot assure the accuracy, please adjust k')\n", 50 | "\n", 51 | " See also:\n", 52 | " https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/isPrime.ipynb\n", 53 | "\n", 54 | " References:\n", 55 | " Theory: https://en.wikipedia.org/wiki/Miller-Rabin_primality_test\n", 56 | " Source codes: https://en.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Primality_Testing\n", 57 | "'''\n", 58 | "\n", 59 | "import random\n", 60 | "import math\n", 61 | "\n", 62 | "def isPrime_Miller_Rabin(n, k=3):\n", 63 | " # Adjust \"k\" to trade-off speed/accuraccy\n", 64 | " if n < 6: # Assuming n >= 0 in all cases... shortcut small cases here\n", 65 | " return [False, False, True, True, False, True][n]\n", 66 | " elif n & 1 == 0: # Should be faster than n % 2\n", 67 | " return False\n", 68 | " else:\n", 69 | " s, d = 0, n - 1\n", 70 | " while d & 1 == 0:\n", 71 | " s, d = s + 1, d >> 1\n", 72 | " # Use random.randint(2, n-2) for very large numbers\n", 73 | " for a in random.sample(range(2, min(n - 2, math.inf)), min(n - 4, k)):\n", 74 | " x = pow(a, d, n)\n", 75 | " if x != 1 and x + 1 != n:\n", 76 | " for r in range(1, s):\n", 77 | " x = pow(x, 2, n)\n", 78 | " if x == 1:\n", 79 | " return False # Composite for sure\n", 80 | " elif x == n - 1:\n", 81 | " a = 0 # So we know loop didn't continue to end\n", 82 | " break # Could be strong liar, try another a\n", 83 | " if a:\n", 84 | " return False # Composite if we reached end of this loop\n", 85 | " return True # Probably prime if reached end of outer loop" 86 | ], 87 | "execution_count": null, 88 | "outputs": [] 89 | } 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /Matrix/Diagonal_Traverse.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [] 7 | }, 8 | "kernelspec": { 9 | "name": "python3", 10 | "display_name": "Python 3" 11 | }, 12 | "language_info": { 13 | "name": "python" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "code", 19 | "execution_count": 5, 20 | "metadata": { 21 | "id": "1D2s30Rv40Ab" 22 | }, 23 | "outputs": [], 24 | "source": [ 25 | "'''\n", 26 | " Solution to Diagonal Traverse\n", 27 | " Find all the elements of the array in a diagonal order\n", 28 | " Time complexity = O(R.C)\n", 29 | "\n", 30 | " Examples:\n", 31 | " ---------\n", 32 | " >>> mat = [[1,2,3],[4,5,6],[7,8,9]]\n", 33 | " >>> print(findDiagonalOrder(mat))\n", 34 | " [1, 2, 4, 7, 5, 3, 6, 8, 9]\n", 35 | "\n", 36 | " >>> mat = [[1,2],[3,4]]\n", 37 | " >>> print(findDiagonalOrder(mat))\n", 38 | " [1, 2, 3, 4]\n", 39 | "\n", 40 | " References:\n", 41 | " https://leetcode.com/problems/diagonal-traverse\n", 42 | "'''\n", 43 | "from typing import List\n", 44 | "\n", 45 | "def findDiagonalOrder(mat: List[List[int]]) -> List[int]:\n", 46 | " # Diagonal extraction approach\n", 47 | "\n", 48 | " R, C = len(mat), len(mat[0]) # Size of matrix\n", 49 | " seen = set() # To not start in a position that's already seen\n", 50 | " reverse = True # A flag to reverse the diagonal as required in the problem statement\n", 51 | " path = []\n", 52 | "\n", 53 | " for r in range(R):\n", 54 | " for c in range(C):\n", 55 | " if (r, c) not in seen:\n", 56 | "\n", 57 | " d = [] # Diagonal of a submatrix\n", 58 | " i, j = r, c # Position of each element in a diagonal\n", 59 | " while i < R and j >= 0:\n", 60 | " d.append(mat[i][j])\n", 61 | " seen.add((i,j))\n", 62 | " i += 1\n", 63 | " j -= 1\n", 64 | "\n", 65 | " # Decide whether to reverse the diagonal or not\n", 66 | " if reverse == True:\n", 67 | " d = d[::-1]\n", 68 | " reverse = False\n", 69 | " else:\n", 70 | " reverse = True\n", 71 | " path += d\n", 72 | "\n", 73 | " #print(r,c,d) # For debug\n", 74 | "\n", 75 | " return path" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "source": [ 81 | "def findDiagonalOrder(mat: List[List[int]]) -> List[int]:\n", 82 | " # Simulation approach\n", 83 | "\n", 84 | " flag = 'up'\n", 85 | " r, c = 0, 0\n", 86 | " R, C = len(mat), len(mat[0])\n", 87 | " path = []\n", 88 | " seen = set()\n", 89 | "\n", 90 | " while len(path) < R*C:\n", 91 | " #print(r,c, flag, path) # For debug\n", 92 | "\n", 93 | " if (r, c) not in seen:\n", 94 | " path.append(mat[r][c])\n", 95 | " seen.add((r, c))\n", 96 | "\n", 97 | " if flag == 'up':\n", 98 | " if r == 0 or c == C-1: # If reach matrix boundary, then reverse the direction\n", 99 | " flag = 'down'\n", 100 | " if c < C-1:\n", 101 | " c += 1\n", 102 | " elif c == C-1:\n", 103 | " r += 1\n", 104 | " continue\n", 105 | " r -= 1\n", 106 | " c += 1\n", 107 | "\n", 108 | " elif flag == 'down':\n", 109 | " if c == 0 or r == R-1: # If reach matrix boundary, then reverse the direction\n", 110 | " flag = 'up'\n", 111 | " if r < R-1:\n", 112 | " r += 1\n", 113 | " elif r == R-1:\n", 114 | " c += 1\n", 115 | " continue\n", 116 | " r += 1\n", 117 | " c -= 1\n", 118 | "\n", 119 | " return path" 120 | ], 121 | "metadata": { 122 | "id": "Ge7jTwKPuqLD" 123 | }, 124 | "execution_count": 9, 125 | "outputs": [] 126 | } 127 | ] 128 | } 129 | -------------------------------------------------------------------------------- /Matrix/Spiral_Matrix.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [] 7 | }, 8 | "kernelspec": { 9 | "name": "python3", 10 | "display_name": "Python 3" 11 | }, 12 | "language_info": { 13 | "name": "python" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "code", 19 | "execution_count": 2, 20 | "metadata": { 21 | "id": "1D2s30Rv40Ab" 22 | }, 23 | "outputs": [], 24 | "source": [ 25 | "'''\n", 26 | " Solution to Spiral Matrix\n", 27 | " Find all elements of the matrix in spiral order\n", 28 | " Time complexity = O(R.C)\n", 29 | "\n", 30 | " Examples:\n", 31 | " ---------\n", 32 | " >>> matrix = [[1,2,3],[4,5,6],[7,8,9]]\n", 33 | " >>> print(spiralOrder(matrix))\n", 34 | " [1, 2, 3, 6, 9, 8, 7, 4, 5]\n", 35 | "\n", 36 | " >>> matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]\n", 37 | " >>> print(spiralOrder(matrix))\n", 38 | " [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7]\n", 39 | "\n", 40 | " References:\n", 41 | " ---------\n", 42 | " https://leetcode.com/problems/spiral-matrix\n", 43 | "'''\n", 44 | "from typing import List\n", 45 | "\n", 46 | "def spiralOrder(matrix: List[List[int]]) -> List[int]:\n", 47 | " R, C = len(matrix), len(matrix[0]) # Size of matrix\n", 48 | "\n", 49 | " flag = 'right' # Variable to guide to current position to next position\n", 50 | " r, c = 0, 0 # Current position\n", 51 | "\n", 52 | " path = [] # The path that the current position has moved\n", 53 | " seen = set() # To not move to the seen position\n", 54 | "\n", 55 | " while len(path) < R*C:\n", 56 | " #print(path, r,c) # For debug\n", 57 | "\n", 58 | " if (r,c) not in seen:\n", 59 | " path.append(matrix[r][c])\n", 60 | " seen.add((r,c))\n", 61 | "\n", 62 | " if flag == 'right':\n", 63 | " c += 1\n", 64 | " if c == C or (r,c) in seen: # If reach the matrix boundary or seen position, then go down\n", 65 | " c -= 1\n", 66 | " flag = 'down'\n", 67 | "\n", 68 | " elif flag == 'down':\n", 69 | " r += 1\n", 70 | " if r == R or (r,c) in seen: # If reach the matrix boundary or seen position, then go left\n", 71 | " r -= 1\n", 72 | " flag = 'left'\n", 73 | "\n", 74 | " elif flag == 'left':\n", 75 | " c -= 1\n", 76 | " if c == -1 or (r,c) in seen: # If reach the matrix boundary or seen position, then go up\n", 77 | " c += 1\n", 78 | " flag = 'up'\n", 79 | "\n", 80 | " elif flag == 'up':\n", 81 | " r -= 1\n", 82 | " if (r,c) in seen: # If reach the seen position, then go right\n", 83 | " r += 1\n", 84 | " flag = 'right'\n", 85 | "\n", 86 | " return path" 87 | ] 88 | } 89 | ] 90 | } 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Awesome Competitive Programming Problems 2 | 3 | > Please press ⭐ button if you like this repo. Thấy ngon thì nhấn star ⭐ ủng hộ mình nha các đồng râm 4 | 5 |

6 | 7 | 8 | 9 |

10 | 11 |

12 | 13 | 14 | 15 | 16 | 17 |

18 | 19 | This repository contains my implementation of **useful / well-known data structures, algorithms and solutions** for awesome competitive programming problems in **Hackerrank, Project Euler and Leetcode** 20 | 21 | I create this for faster implementation and better preparation in interviews as well as programming contests :trollface: :trollface: 22 | 23 | :warning: This repo is day-by-day updated. Please make sure you have the latest version! 24 | 25 | :fire: **New updates today: [Longest Substring Without Repeating Characters](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Two%20Pointers%20-%20Sliding%20Window/LongestSubstring_0RepeatChars.ipynb)[[Leetcode]](https://leetcode.com/problems/longest-substring-without-repeating-characters/)** 26 | 27 |

28 | 29 |

30 | 31 | :question: How to use 32 | ---------- 33 | **Overview of the file:** 34 |

35 | 36 |

37 | 38 | :firecracker: Tips and Tricks 39 | ---------- 40 | **Here is some tips and tricks to ACE all competitive programming problems and interview questions:** 41 | 42 | ``` 43 | If input array is sorted then 44 | - Binary search 45 | - Two pointers 46 | 47 | If asked for all permutations/subsets then 48 | - Backtracking 49 | 50 | If given a tree then 51 | - DFS 52 | - BFS 53 | 54 | If given a graph then 55 | - DFS 56 | - BFS 57 | 58 | If given a linked list then 59 | - Two pointers 60 | 61 | If recursion is banned then 62 | - Stack 63 | 64 | If must solve in-place then 65 | - Swap corresponding values 66 | - Store one or more different values in the same pointer 67 | 68 | If asked for maximum/minumum subarray/subset/options then 69 | - Dynamic programming 70 | 71 | If asked for top/least K items then 72 | - Heap 73 | 74 | If asked for common strings then 75 | - Map 76 | - Trie 77 | 78 | Else 79 | - Map/Set for O(1) time & O(n) space 80 | - Sort input for O(nlogn) time and O(1) space 81 | ``` 82 | 83 | :watermelon: Data structures, Algorithms and Patterns 84 | ---------- 85 | ### A) Data Structures Applications 86 | #### :palm_tree: Binary Search Tree Algorithm 87 | 1. - [x] [Binary Search Tree](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Structures%20Applications/BST.ipynb): Original Binary Search Tree Algorithm - **O(log(n))** 88 | 89 | 2. - [x] [Binary Search Tree: Check a Number](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Structures%20Applications/BST_Find.ipynb): Check if a Number is in a Sorted List using BST Algorithm - **O(log(n))** 90 | 91 | 3. - [x] [Binary Search Tree: Index of a Number](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Structures%20Applications/BST_Find_Index.ipynb): Find the Index of a Number in a Sorted List using BST Algorithm - **O(log(n))** 92 | 93 | ----------------------------------------------------------------------------------------------------------------------------------- 94 | ### B) String Algorithm 95 | #### :ear_of_rice: Suffix Tree - Suffix Array 96 | 1. - [x] [Suffix Array (Manber-Myers Algorithm)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/String%20Algorithm/SuffixArray_ManberMyers.ipynb): Find suffix array of a string S based on Manber-Myers algorithm - **O(n.log(n))** , n = |S| 97 | 98 | 2. - [x] [Longest Common Prefix Array (Kasai Algorithm)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/String%20Algorithm/LCPArray_Kasai.ipynb): Find longest common prefix array of a string S with the help of suffix array based on Kasai algorithm - **O(n)** , n = |S| 99 | 100 | 3. - [ ] Longest Palindromic Substring - **O(n)** 101 | 102 | 4. - [ ] Pattern Search - **O(log(n))** 103 | 104 | ----------------------------------------------------------------------------------------------------------------------------------- 105 | ### C) Searching and Graph Algorithms 106 | #### :snowflake: Graph Theory 107 | 1. - [x] [Graph Representation using Adjacency List: Unweighted, Un-/Directed](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/Graph_AdjacencyList.ipynb): Create a Unweighted Un-/Directed Graph using Adjacency List 108 | 109 | 2. - [ ] Graph Representation using Adjacency List: Weighted, Un-/Directed 110 | 111 | 3. - [x] [Find All Nodes](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/Find_AllNodes.ipynb): Find All Nodes in the Unweighted Graph - **O(V+E) for Adjacency List** , V, E is the number of vertices and edges 112 | 113 | 4. - [ ] Find All Edges 114 | 115 | 5. - [x] [Find All Paths between 2 Nodes](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/Find_AllPaths_BFS.ipynb): Find All Paths between 2 Nodes in a Unweighted Graph using BFS - **NP-Hard** 116 | 117 | 6. - [x] [Disjoint Set (Union-Find): Union by Rank and Path Compression](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/DisjointSet.ipynb): Create a Disjoint Set (Union-Find) using "Union by Rank and Path Compression" for an Undirected Graph (used to Detect Cycle) - **Time = O(small constant), Space = O(V)** 118 | 119 | #### :recycle: Detect Cycle 120 | 7. - [x] [Detect Cycle: Disjoint Set](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/isCycle_DisjointSet.ipynb): Detect Cycle in an Undirected Graph based on Disjoint Set (Union-Find) using "Union by Rank and Path Compression" - **O(V)** 121 | 122 | #### :airplane: Graph Traversal 123 | 8. - [x] [Breadth-First Search](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/BFS.ipynb): Find BFS Path from a Starting Node in Un-/Directed Graph - **O(V+E) for Adjacency List; O(V2) for Adjacency Matrix** , V, E is the number of vertices and edges 124 | 125 | 9. - [x] [Depth-First Search](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/DFS.ipynb): Find DFS Path from a Starting Node in Un-/Directed Graph - **O(V+E) for Adjacency List; O(V2) for Adjacency Matrix** , V, E is the number of vertices and edges 126 | 127 | #### :shamrock: Minimum Spanning Tree (MST) 128 | 10. - [x] [MST: Prim Algorithm](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/MST_Prim.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/MST_Prim.pdf): Find Minimum Spanning Tree (MST) of an Undirected Graph using Prim Algorithm - **O(E.log(V))** 129 | 130 | 11. - [x] [MST: Kruskal Algorithm](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/MST_Kruskal.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/MST_Kruskal.pdf): Find Minimum Spanning Tree (MST) of an Undirected Graph using Kruskal Algorithm - **O(E.log(E)) or O(E.log(V))** 131 | 132 | #### :kick_scooter: Shortest Path 133 | 134 | | Type of Algorithm | Subjects of Application | Time Complexity | 135 | | :---: | :---: | :---: | 136 | | Breadth-First Search | Unweighted, Un-/Directed Graph | O(V+E) for Adjacency List | 137 | | Dijkstra | Non-Negative Un-/Weighted Un-/Directed Graph | O(E.log(V)) for Min-priority Queue | 138 | | Bellman-Ford | | | 139 | | Floyd-Warshall | | | 140 | 141 | 12. - [x] [Shortest Path: Breadth-First Search](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/SP_BFS.ipynb): Find the Shortest Path in a Unweighted Un-/Directed Graph based on BFS - **O(V+E) for Adjacency List** , V, E is the number of vertices and edges 142 | 143 | 13. - [x] [Shortest Path: Dijkstra using Min-Heap](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Searching%20and%20Graph%20Algorithms/SP_Dijkstra_MinHeap.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/SP_Dijkstra_MinHeap.pdf): Find Shortest Path of an Non-Negative Un-/Weighted Un-/Directed Graph based on Dijkstra Algorithm using Min-Heap - **O(E.log(V))** 144 | 145 | 14. - [ ] Shortest Path: Bellman-Ford 146 | 147 | 15. - [ ] Shortest Path: Floyd-Warshall 148 | 149 | ----------------------------------------------------------------------------------------------------------------------------------- 150 | ### D) Greedy Algorithm 151 | 1. [Sherlock and The Beast](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Greedy%20Algorithm/Sherlock_and_The_Beast.ipynb) 152 | - Find the "Decent Number" having n Digits ("Decent Number" has its digits to be only 3's and/or 5's; the number of 3's it contains is divisible by 5; the number of 5's it contains is divisible by 3; and it is the largest such number for its length) 153 | 154 | 2. [Largest Permutation](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Greedy%20Algorithm/Largest_Permutation.ipynb) 155 | - Swap 2 digits of a number k times to get largest number - **O(n)** 156 | 157 | ----------------------------------------------------------------------------------------------------------------------------------- 158 | ### E) Dynamic Programming 159 | > **Coin Change Algorithms**: Given an array of choices, every choice is picked **unlimited times** 160 | > 161 | > **Knapsack Problems**: Given an array of choices, every choice is picked **only once** 162 | 163 | #### :moneybag: Coin Change Algorithms 164 | 1. - [x] [Coin Change](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/CoinChange.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Coin%20Change.pdf): How many ways to pay V money using C coins [C1,C2,...Cn] - **O(C.V)** 165 | 166 | 2. - [x] [Integer Partition](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/IntegerPartition.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Integer_Partition.pdf): How many ways to partition number N using [1,2,...N] numbers - **O(n1.5)** 167 | 168 | 3. - [x] [Minimum Coin Change](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/MinCoinChange.ipynb)[[Wiki]](https://en.wikipedia.org/wiki/Change-making_problem): Find Minimum Number of Coins to pay V money using C coins [C1,C2,...,Cn] - **O(C.V)** 169 | 170 | #### :handbag: Knapsack Problems 171 | 4. - [x] [Knapsack 0/1](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/Knapsack_01.ipynb)[[Wiki]](https://en.wikipedia.org/wiki/Knapsack_problem#0-1_knapsack_problem): Given a List of Weights associated with their Values, find the Founding Weights and Maximum Total Value attained with its Total Weight <= Given Total Weight, each Weight is only **picked once** (0/1 Rule) - **O(N.W)** , N, W is length of weights array and given total weight 172 | 173 | 5. - [x] [Partition Problem: Subset Sum](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/PartitionProblem_SubsetSum.ipynb)[[Wiki]](https://en.wikipedia.org/wiki/Subset_sum_problem): Given an Array containing only Positive Integers, find if it can be Partitioned into 2 Subsets having Sum of elements in both subsets is Equal. - **O(N.T)** , N, T is the length of numbers array and the target sum (=sum/2) 174 | 175 | 6. - [ ] Partition Problem: Multiway Number Partitioning[[Wiki]](https://en.wikipedia.org/wiki/Multiway_number_partitioning): 176 | 177 | #### :chart_with_upwards_trend: Path Sum Problems 178 | 7. - [x] [Max Path Sum Triangle](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/Max_PathSum_Triangle.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Max_PathSum_Triangle.pdf): Find Maximum Path Sum from Top to Bottom of a Triangle - **O(R)** , R is number of rows of the triangle 179 | 180 | 8. - [x] [Min Path Sum Matrix: Top-Left to Right-Bottom, Right and Down Moves](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/Min_PathSum_Matrix.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Min_PathSum_Matrix.pdf): Find Min Path Sum from Top-Left to Right-Bottom of a Matrix using Right and Down Moves - **O(R.C)** , R, C is length of row and column of the matrix 181 | 182 | > **Subsequence** = Any subset of an array/string 183 | > 184 | > **Subarray** = Contiguous subsequence of an array 185 | > 186 | > **Substring** = Contiguous subsequence of a string 187 | 188 | #### :date: Subarray Problems 189 | 9. - [x] [Max Subarray Sum (Kadane Algorithm)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/Max_SubarraySum.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Max_SubarraySum.pdf): Find Maximum Subarray Sum of an Array - **O(n)** 190 | 191 | 10. - [x] [Max Subarray Sum (Kadane Algorithm - Extended)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/Max_SubarraySum_Extended.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Max_SubarraySum.pdf): Find Maximum Subarray Sum of an Array and its Indices - **O(n)** 192 | 193 | 11. - [x] [Min Subarray Sum (Kadane Algorithm's Min Varient)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/Min_SubarraySum.ipynb): Find Minimum Subarray Sum of an Array - **O(n)** 194 | 195 | 12. - [x] [Subarray Sum Equals K](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/SubarraySum_EqualsK.ipynb)[[Leetcode]](https://leetcode.com/problems/subarray-sum-equals-k/): Find the Number of Continuous Subarrays of an Array whose Sum Equals to K - **O(n)** 196 | 197 | 13. - [x] [Subarray Sum Divisible by K](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/SubarraySum_DivByK.ipynb)[[Leetcode]](https://leetcode.com/problems/subarray-sums-divisible-by-k/): Find the Number of Continuous Subarrays of an Array whose Sum is Divisible by K - **O(n)** 198 | 199 | #### :dango: Subsequence Problems 200 | 14. - [x] [Longest Common Subsequence (LCS)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/LongestCommonSubsequence.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/LongestCommonSubsequence.pdf): Find the longest string S, every character in S is also in S1 and S2 but in order - **O(|S1|.|S2|)** 201 | 202 | 15. - [x] [Longest Increasing/Decreasing Subsequence (Patience Sorting Algorithm)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/Longest_Increasing_Subsequence.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Longest_Increasing_Subsequence.pdf): Find the Longest Increasing or Decreasing Subsequence of an Array List based on Patience Sorting Algorithm- **O(n.log(n))** 203 | 204 | #### :page_with_curl: Substring Problems 205 | 16. - [x] [Longest Common Substring (Longest Common Factor - LCF)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/Longest_Common_Substring.ipynb): Find the Longest Common Substring (Factor) of 2 strings S1 and S2 - **O(|S1|.|S2|)** 206 | 207 | 17. - [x] [Sum Of Substrings](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Dynamic%20Programming/SumOfSubstrings.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/SumOfSubstrings.pdf): Find Sum of All Substrings of an Number String S - **O(|S|)** 208 | 209 | ----------------------------------------------------------------------------------------------------------------------------------- 210 | ### F) Two Pointers - Sliding Window 211 | #### :book: Non-categorized 212 | 1. - [x] [Longest Substring Without Repeating Characters](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Two%20Pointers%20-%20Sliding%20Window/LongestSubstring_0RepeatChars.ipynb)[[Leetcode]](https://leetcode.com/problems/longest-substring-without-repeating-characters/): Find the Length of the Longest Substring Without Repeating Characters - **O(|S|)** 213 | 214 | ----------------------------------------------------------------------------------------------------------------------------------- 215 | ### G) Mathematics 216 | #### :blue_book: Binomial Coefficient Problems 217 | 1. - [x] [Pascal Triangle](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Pascal_Triangle.ipynb): Create Pascal Triangle (to Calculate Multiple Large-Number Combinations) - **O(n2)** 218 | 219 | 2. - [x] [PE #15: Lattice Paths](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Lattice_Paths.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Lattice_Paths.pdf) : Find the number of routes from the top left corner to the bottom right corner in a rectangular grid 220 | 221 | #### :closed_book: Factors Problems 222 | 3. - [x] [Factorization](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Factorization.ipynb): Find All Factors of a Number - **O(n1/2)** 223 | 224 | #### :green_book: Multiples Problems 225 | 4. - [x] [PE #1: Multiples of 3 and 5](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Multiples_of_3_and_5.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Multiples_of_3_and_5.pdf): Find Sum of Multiples of a Number - **O(1)** 226 | 227 | #### :notebook: Permutation Problems 228 | 5. - [x] [Lexicographic Permutations](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Lexicographic_Permutations.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Lexicographic_Permutations.pdf): Find n-th Lexicographic Permutation of a very long Word - **O(n)** 229 | 230 | 6. - [x] [Permutation Check](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/arePermutations.ipynb): Check if 2 Numbers/Strings are Permutations - **O(n)** , n = max(|a|,|b|) 231 | 232 | #### :orange_book: Primes Problems 233 | 7. - [x] ["Sieve Method" All Primes](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Sieve_All_Primes.ipynb): Find All Primes < n - **Space = O(n1/2)** 234 | 235 | 8. - [x] [Primality Test (Common Method)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/isPrime.ipynb): Check if n is a Prime Number using "Common Method" - **O(n1/2)** 236 | 237 | 9. - [x] [Primality Test (Miller-Rabin)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/isPrime_Miller_Rabin.ipynb): Check if n is a Prime Number using Miller-Rabin Probabilistic Test - **O(k.log3n)** , k = \[1,2,...] 238 | 239 | 10. - [x] [Coprimes Check](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/areCoprimes.ipynb): Check if 2 Numbers are Coprime - **O(log a.b)** 240 | 241 | #### :notebook_with_decorative_cover: Primes-Factors Problems 242 | 11. - [x] [Euler Totient Function (Number List)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Euler_Totient_NumList.ipynb): Find ALL Numbers of Coprimes < n based on Euler Totient Function - **O((l) + m.loglogm + l.(logm + k))** , k is the number of prime factors of n; m and l is max value and length of the input number list 243 | 244 | 12. - [x] [Euler Totient Function (Single Number)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Euler_Totient_SingleNum.ipynb): Find the Number of Coprimes < n based on Euler Totient Function - **O(n1/2 + k)** , k is the number of prime factors of the input number n 245 | 246 | 13. - [x] ["Sieve Method" Smallest Prime Factors (SPF)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Sieve_SPF.ipynb): Find Smallest Prime Factors for All Numbers < N - **O(n.loglogn)** 247 | 248 | 14. - [x] [Prime Factorization (Smallest Prime Factor)](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PrimeFactorization_SPF.ipynb): Find All Prime Factors of a Number using Smallest Prime Factor (SPF) - **O(log n)** if a list of all Smallest Prime Factors from 0 to n available 249 | 250 | 15. - [x] [Prime Factorization](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PrimeFactorization.ipynb): Find All Prime Factors of a Number - **O(n1/2)** 251 | 252 | #### :ledger: Pythagorean Theorem 253 | 16. - [x] [Pythagorean Triplets Perimeter](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PythagoreanTriplets_Perimeter.ipynb): Find Pythagorean Triplets having Perimeter (or Sum) P - **O(P)** 254 | 255 | 17. - [x] [Pythagorean Triplets Less or Equal N](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/PythagoreanTriplets_LessEqualN.ipynb): Generate all Pythagorean Triplets <= N - **O(N.log(N))** 256 | 257 | #### :book: Non-categorized 258 | 18. - [x] [Number Spiral Diagonals](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Mathematics/Number_Spiral_Diagonals.ipynb)[[PDF]](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Data%20Bank/Number_Spiral_Diagonals.pdf): Find Sum of Diagonals of Ulam Spiral Matrix 259 | 260 | ----------------------------------------------------------------------------------------------------------------------------------- 261 | ### H) Linked List 262 | #### :snake: Singly-linked List 263 | > Problem statement: Do something on a given singly-linked List 264 | 265 | > Hints: 266 | > 1. Simply convert linked list to 1D array and solve on the array using "ListNode_to_Array" 267 | > 2. If necessary, convert 1D array back to the linked list using "Array_to_ListNode" 268 | 1. - [x] [List Node](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Linked%20List/ListNode.ipynb): Create a Singly-linked List using "Node class" 269 | 270 | 2. - [x] [ListNode to Array](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Linked%20List/ListNode_to_Array.ipynb): Convert ListNode into Array, could be used as print to "see" inside a ListNode - **O(n)** 271 | 272 | 3. - [x] [Array to ListNode](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Linked%20List/Array_to_ListNode.ipynb): Convert Array into ListNode - **O(n)** 273 | 274 | ----------------------------------------------------------------------------------------------------------------------------------- 275 | ### I) Matrix 276 | #### :computer: Matrix x Simulation 277 | > Problem statement: Move current position within the matrix along diagonals, up-down-right-left, ... 278 | 279 | > Hints: 280 | > 1. Use variable flag = 'up' or 'down' ... to guide the current position to the next position 281 | > 282 | > ```python 283 | > if flag == 'up': 284 | > # Do something 285 | > # Consider to change the flag = 'down' or 'right' or 'something' 286 | > ``` 287 | > 2. Pay attention to the matrix boundary when moving 288 | > 289 | > ```python 290 | > def inMatrix(r,c): 291 | > # R, C is the matrix size 292 | > # r, c is current position 293 | > if r >= 0 and c >= 0 and r < R and c < C: 294 | > return True 295 | > else: 296 | > return False 297 | > ``` 298 | > 3. Use variable seen = set() to not move to the seen position or to not start as a current position 299 | > 300 | > ```python 301 | > if (r,c) not in seen: 302 | > # Do something 303 | > ``` 304 | 1. - [x] [Spiral Matrix](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Matrix/Spiral_Matrix.ipynb)[[Leetcode]](https://leetcode.com/problems/spiral-matrix): Find all elements of the matrix in spiral order - **O(R.C)** 305 | 306 | 2. - [x] [Diagonal_Traverse](https://github.com/leduckhai/Awesome-Competitive-Programming/blob/main/Matrix/Diagonal_Traverse.ipynb)[[Leetcode]](https://leetcode.com/problems/diagonal-traverse): Find all the elements of the array in a diagonal order - **O(R.C)** 307 | 308 | #### Matrix x Graph 309 | 310 | ----------------------------------------------------------------------------------------------------------------------------------- 311 | ### Recursion Algorithm 312 | 313 | #### Backtracking 314 | 315 | #### Divide and Conquer 316 | 317 | -------------------------------------------------------------------------------- /Searching and Graph Algorithms/BFS.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "BFS.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Breadth-First Search path from a source node in un-/directed graph\n", 24 | " Time complexity = O(V+E) for Adjacency List\n", 25 | " Time complexity = O(V^2) for Adjacency Matrix\n", 26 | "\n", 27 | " Parameters:\n", 28 | " -----------\n", 29 | " graph: defaultdict\n", 30 | " Graph, each starting vertex as a key is a list of ending vertices\n", 31 | " V : integer\n", 32 | " Number of vertices\n", 33 | " src : integer\n", 34 | " Starting vertex of the BFS path\n", 35 | "\n", 36 | " Returns:\n", 37 | " --------\n", 38 | " path: list\n", 39 | " BFS path, contains all nodes on the path\n", 40 | "\n", 41 | " Examples:\n", 42 | " ---------\n", 43 | " >>> graph = {0: [1, 2], 1: [2], 2: [0, 3], 3: [3]}\n", 44 | " >>> V = 4\n", 45 | " >>> src = 2\n", 46 | " >>> print(BFS(graph, V, src))\n", 47 | " [2, 0, 3, 1]\n", 48 | "\n", 49 | " References:\n", 50 | " https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/\n", 51 | "'''\n", 52 | "\n", 53 | "def BFS(graph, V, src): \n", 54 | " visited = [False]*V # Mark all verices as not visited \n", 55 | " queue = [] # Create a queue for BFS\n", 56 | " queue.append(src) # Push the current source node\n", 57 | " visited[src] = True # Mark the source node as visited\n", 58 | " path = [] # Create BFS path\n", 59 | "\n", 60 | " while queue: \n", 61 | " # Pop a vertex from queue and put into path\n", 62 | " u = queue.pop(0)\n", 63 | " path.append(u)\n", 64 | " # Get all adjacent vertices of the popped vertex u. If a adjacent \n", 65 | " # has not been visited, then mark it as visited and put into the queue \n", 66 | " for v in graph[u]: \n", 67 | " if visited[v] == False: \n", 68 | " queue.append(v) \n", 69 | " visited[v] = True\n", 70 | "\n", 71 | " return path" 72 | ], 73 | "execution_count": null, 74 | "outputs": [] 75 | } 76 | ] 77 | } 78 | -------------------------------------------------------------------------------- /Searching and Graph Algorithms/DFS.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "DFS.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Depth-First Search path from a source node in un-/directed graph\n", 24 | " Time complexity = O(V+E) for Adjacency List\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " graph: defaultdict\n", 29 | " Graph, each starting vertex as a key is a list of ending vertices\n", 30 | " V : integer\n", 31 | " Number of vertices\n", 32 | " src : integer\n", 33 | " Starting vertex of the DFS path\n", 34 | "\n", 35 | " Returns:\n", 36 | " --------\n", 37 | " path: list\n", 38 | " DFS path, contains all nodes on the path\n", 39 | "\n", 40 | " Examples:\n", 41 | " ---------\n", 42 | " >>> graph = {0: [1, 2], 1: [2], 2: [0, 3], 3: [3]}\n", 43 | " >>> V = 4\n", 44 | " >>> src = 2\n", 45 | " >>> print(DFS(graph, V, src))\n", 46 | " [2, 3, 0, 1]\n", 47 | "\n", 48 | " References:\n", 49 | " https://www.geeksforgeeks.org/iterative-depth-first-traversal/\n", 50 | "'''\n", 51 | "\n", 52 | "def DFS(graph, V, src): \n", 53 | " visited = [False]*V # Mark all verices as not visited \n", 54 | " stack = [] # Create a stack for DFS \n", 55 | " stack.append(src) # Push the current source node\n", 56 | " visited[src] = True # Mark the source node as visited\n", 57 | " path = [] # Create DFS path\n", 58 | "\n", 59 | " while stack: \n", 60 | " # Pop a vertex from stack and put into path\n", 61 | " u = stack.pop(-1)\n", 62 | " path.append(u)\n", 63 | " # Get all adjacent vertices of the popped vertex u. If a adjacent \n", 64 | " # has not been visited, then mark it as visited and put into the stack\n", 65 | " for v in graph[u]: \n", 66 | " if visited[v] == False: \n", 67 | " stack.append(v) \n", 68 | " visited[v] = True\n", 69 | "\n", 70 | " return path" 71 | ], 72 | "execution_count": null, 73 | "outputs": [] 74 | } 75 | ] 76 | } -------------------------------------------------------------------------------- /Searching and Graph Algorithms/DisjointSet.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "DisjointSet.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to create a disjoint set (union-find) using \"union by rank and path compression\"\n", 24 | " for an undirected graph (used to detect cycle)\n", 25 | " Time complexity = O(small constant)\n", 26 | " Space complexity = O(V)\n", 27 | "\n", 28 | " Parameters:\n", 29 | " -----------\n", 30 | " graph: defaultdict\n", 31 | " Graph, each starting vertex as a key is a list of ending vertices\n", 32 | " V : integer\n", 33 | " Number of vertex\n", 34 | "\n", 35 | " Returns:\n", 36 | " --------\n", 37 | " subsets: list\n", 38 | " A list of V subsets\n", 39 | "\n", 40 | " Examples:\n", 41 | " --------- \n", 42 | " >>> graph = {0: [1, 2], 1: [2]}\n", 43 | " >>> print(DisjointSet(graph, 3))\n", 44 | " [{'parent': 0, 'rank': 2}, {'parent': 0, 'rank': 0}, {'parent': 0, 'rank': 0}]\n", 45 | "\n", 46 | " References: \n", 47 | " https://www.geeksforgeeks.org/union-find-algorithm-set-2-union-by-rank/\n", 48 | " https://www.youtube.com/watch?v=ID00PMy0-vE\n", 49 | "'''\n", 50 | "\n", 51 | "def DisjointSet(graph, V):\n", 52 | " # Function to create a subset of element nodes\n", 53 | " def DisjointSet_Subset(parent, rank):\n", 54 | " subset = {'parent': parent, 'rank': rank}\n", 55 | " return subset\n", 56 | "\n", 57 | " # Function to find subset of an element node (uses path compression technique)\n", 58 | " def DisjointSet_Find(subsets, node):\n", 59 | " if subsets[node]['parent'] != node:\n", 60 | " subsets[node]['parent'] = DisjointSet_Find(subsets, subsets[node]['parent'])\n", 61 | " return subsets[node]['parent']\n", 62 | " \n", 63 | " # Function that does union of two subsets of u and v (uses union by rank)\n", 64 | " def DisjointSet_Union(subsets, u, v):\n", 65 | " # Attach smaller rank tree under root of high rank tree (Union by Rank)\n", 66 | " if subsets[u]['rank'] > subsets[v]['rank']:\n", 67 | " subsets[v]['parent'] = u\n", 68 | " elif subsets[u]['rank'] < subsets[v]['rank']:\n", 69 | " subsets[u]['parent'] = v\n", 70 | " # If ranks are same, then make one as root and increment its rank by one\n", 71 | " else:\n", 72 | " subsets[v]['parent'] = u\n", 73 | " subsets[u]['rank'] += 1\n", 74 | "\n", 75 | " # Main function\n", 76 | " subsets = [] \n", 77 | " for u in range(V):\n", 78 | " subsets.append(DisjointSet_Subset(u, 0))\n", 79 | " \n", 80 | " # Iterate through all edges of graph, find subsets of both vertices of \n", 81 | " # every edge, then do union of 2 subsets\n", 82 | " for u in graph:\n", 83 | " u_rep = DisjointSet_Find(subsets, u) # Representative node of u\n", 84 | " for v in graph[u]:\n", 85 | " v_rep = DisjointSet_Find(subsets, v) # Representative node of v\n", 86 | " DisjointSet_Union(subsets, u_rep, v_rep)\n", 87 | " \n", 88 | " return subsets" 89 | ], 90 | "execution_count": null, 91 | "outputs": [] 92 | } 93 | ] 94 | } 95 | -------------------------------------------------------------------------------- /Searching and Graph Algorithms/Find_AllNodes.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Find_AllNodes.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find all nodes in the graph\n", 24 | " Time complexity = O(V+E) for Adjacency List\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " graph: defaultdict\n", 29 | " Graph, each starting vertex as a key is a list of ending vertices\n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " AllNodes: set\n", 34 | " A set of all nodes in the graph\n", 35 | "\n", 36 | " Examples:\n", 37 | " ---------\n", 38 | " >>> graph = {0: [1, 3], 1: [2], 3: [4, 7], 4: [5, 6, 7], 5: [6], 6: [7]}\n", 39 | " >>> print(Find_AllNodes(graph))\n", 40 | " {0, 1, 2, 3, 4, 5, 6, 7}\n", 41 | "'''\n", 42 | "\n", 43 | "def Find_AllNodes(graph): \n", 44 | " AllNodes = set(graph.keys())\n", 45 | " for values in graph.values():\n", 46 | " for node in values:\n", 47 | " AllNodes.add(node)\n", 48 | " return AllNodes" 49 | ], 50 | "execution_count": null, 51 | "outputs": [] 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /Searching and Graph Algorithms/Find_AllPaths_BFS.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "Find_AllPaths_BFS.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find all paths between 2 nodes in a graph using BFS\n", 24 | " Time complexity = NP-Hard\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " graph: defaultdict\n", 29 | " Graph, each starting vertex as a key is a list of ending vertices\n", 30 | " start: integer, string\n", 31 | " Starting vertex of the path\n", 32 | " end : integer, string\n", 33 | " Ending vertex of the path\n", 34 | "\n", 35 | " Returns:\n", 36 | " --------\n", 37 | " AllPaths: list\n", 38 | " A list of all paths between 2 nodes in a graph\n", 39 | "\n", 40 | "\n", 41 | " Examples:\n", 42 | " ---------\n", 43 | " >>> graph = {0: [1, 3], 1: [2], 2: [], 3: [4, 7], 4: [5, 6, 7], 5: [6], 6: [7]}\n", 44 | " >>> print(Find_AllPaths_BFS(graph, 0, 7))\n", 45 | " [[0, 3, 7], [0, 3, 4, 7], [0, 3, 4, 6, 7], [0, 3, 4, 5, 6, 7]]\n", 46 | "'''\n", 47 | "\n", 48 | "def Find_AllPaths_BFS(graph, start, end):\n", 49 | " queue = [(start, [start])]\n", 50 | " AllPaths = []\n", 51 | " while queue:\n", 52 | " (vertex, path) = queue.pop(0)\n", 53 | " for next in set(graph[vertex]) - set(path):\n", 54 | " if next == end:\n", 55 | " AllPaths.append(path + [next])\n", 56 | " else:\n", 57 | " queue.append((next, path + [next]))\n", 58 | " return AllPaths\n", 59 | "\n", 60 | "graph = {0: [1, 3], 1: [2], 2: [], 3: [4, 7], 4: [5, 6, 7], 5: [6], 6: [7]}\n", 61 | "print(Find_AllPaths_BFS(graph, 0, 7))\n" 62 | ], 63 | "execution_count": null, 64 | "outputs": [] 65 | } 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /Searching and Graph Algorithms/Graph_AdjacencyList.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "SP_BFS.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Class to create a Unweighted Un-/Directed Graph using Adjacency List\n", 24 | "\n", 25 | " Parameters:\n", 26 | " -----------\n", 27 | " u, v: integer, string\n", 28 | " Name of starting and ending vertex\n", 29 | "\n", 30 | " Returns:\n", 31 | " --------\n", 32 | " self.graph: defaultdict\n", 33 | " Graph, each starting vertex as key is a list of ending vertices\n", 34 | "\n", 35 | " Examples:\n", 36 | " ---------\n", 37 | " >>> g = Graph()\n", 38 | " >>> g.addEdge(1, 2)\n", 39 | " >>> g.addEdge(1, 3)\n", 40 | " >>> g.addEdge(4, 5)\n", 41 | " >>> g.addEdge(6, None)\n", 42 | " >>> print(g.graph)\n", 43 | " defaultdict(, {1: [2, 3], 4: [5], 6: []})\n", 44 | "'''\n", 45 | "\n", 46 | "from collections import defaultdict\n", 47 | "\n", 48 | "class Graph: \n", 49 | " # Constructor \n", 50 | " def __init__(self): \n", 51 | " # Default dictionary to store graph \n", 52 | " self.graph = defaultdict(list) \n", 53 | " \n", 54 | " # Function to add an edge to graph \n", 55 | " def addEdge(self,u,v): \n", 56 | " # In case of disconnected graph\n", 57 | " if v == None:\n", 58 | " self.graph[u]\n", 59 | " # In case of connected graph\n", 60 | " else:\n", 61 | " self.graph[u].append(v)\n", 62 | " # In case of undirected graph\n", 63 | " #self.graph[v].append(u)" 64 | ], 65 | "execution_count": null, 66 | "outputs": [] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /Searching and Graph Algorithms/MST_Kruskal.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "MST_Kruskal.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Minimum Spanning Tree (MST) of an undirected graph using\n", 24 | " Kruskal algorithm\n", 25 | " Time complexity = O(E.log(E)) or O(E.log(V))\n", 26 | "\n", 27 | " Parameters:\n", 28 | " -----------\n", 29 | " graph: list\n", 30 | " An undirected graph list of edges [u,v,w]\n", 31 | " V : integer\n", 32 | " Number of vertex\n", 33 | "\n", 34 | " Returns:\n", 35 | " --------\n", 36 | " mst : list\n", 37 | " An undirected Minimum Spanning Tree list of edges [u,v,w]\n", 38 | " minCost: integer\n", 39 | " Total weights of MST\n", 40 | "\n", 41 | " Examples:\n", 42 | " --------- \n", 43 | " Undirected graph Minimum Spanning Tree\n", 44 | " 10 10\n", 45 | " 0-----1 0-----1\n", 46 | " |\\ | \\ \n", 47 | " | \\ | Kruskal Algorithm \\ Total weights of MST \n", 48 | " 6| \\5 |15 ================> \\5 = 10 + 5 + 4 = 19\n", 49 | " | \\ | \\\n", 50 | " | \\| \\\n", 51 | " 2-----3 2-----3\n", 52 | " 4 4 \n", 53 | "\n", 54 | " >>> graph = [[0, 1, 10], [0, 2, 6], [0, 3, 5], [1, 3, 15], [2, 3, 4]]\n", 55 | " >>> print(MST_Kruskal(graph, 4))\n", 56 | " ([[2, 3, 4], [0, 3, 5], [0, 1, 10]], 19)\n", 57 | "\n", 58 | " References:\n", 59 | " https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/\n", 60 | " https://www.youtube.com/watch?v=fAuF0EuZVCk\n", 61 | "'''\n", 62 | "\n", 63 | "def MST_Kruskal(graph, V):\n", 64 | " # Function to create a subset of element nodes\n", 65 | " def DisjointSet_Subset(parent, rank):\n", 66 | " subset = {'parent': parent, 'rank': rank}\n", 67 | " return subset\n", 68 | "\n", 69 | " # Function to find subset of an element node (uses path compression technique)\n", 70 | " def DisjointSet_Find(subsets, node):\n", 71 | " if subsets[node]['parent'] != node:\n", 72 | " subsets[node]['parent'] = DisjointSet_Find(subsets, subsets[node]['parent'])\n", 73 | " return subsets[node]['parent']\n", 74 | " \n", 75 | " # Function that does union of two subsets of u and v (uses union by rank)\n", 76 | " def DisjointSet_Union(subsets, u, v):\n", 77 | " # Attach smaller rank tree under root of high rank tree (Union by Rank)\n", 78 | " if subsets[u]['rank'] > subsets[v]['rank']:\n", 79 | " subsets[v]['parent'] = u\n", 80 | " elif subsets[u]['rank'] < subsets[v]['rank']:\n", 81 | " subsets[u]['parent'] = v\n", 82 | " # If ranks are same, then make one as root and increment its rank by one\n", 83 | " else:\n", 84 | " subsets[v]['parent'] = u\n", 85 | " subsets[u]['rank'] += 1\n", 86 | "\n", 87 | " # Main function\n", 88 | " mst = [] # This will store the resultant MST \n", 89 | " minCost = 0 # Total weights of MST \n", 90 | " i = 0 # Index of sorted edges with weights being in ascending order\n", 91 | " e = 0 # Number of current edges of MST\n", 92 | "\n", 93 | " # Step 1: Sort all the edges in ascending order of their weight\n", 94 | " sorted_graph = sorted(graph, key=lambda item: item[2])\n", 95 | "\n", 96 | " subsets = [] \n", 97 | " for u in range(V):\n", 98 | " subsets.append(DisjointSet_Subset(u, 0))\n", 99 | " \n", 100 | " # MST's number of edges must be V-1\n", 101 | " while e < V - 1:\n", 102 | " # Step 2: Pick the smallest edge and increase the index for next iteration\n", 103 | " u, v, w = sorted_graph[i]\n", 104 | " i += 1\n", 105 | " x = DisjointSet_Find(subsets, u)\n", 106 | " y = DisjointSet_Find(subsets, v)\n", 107 | " \n", 108 | " # If including this edge doesn't cause cycle, include it in current MST \n", 109 | " if x != y:\n", 110 | " e += 1\n", 111 | " mst.append([u, v, w])\n", 112 | " DisjointSet_Union(subsets, x, y)\n", 113 | " minCost += w\n", 114 | " # Else discard the edge\n", 115 | " else: pass\n", 116 | "\n", 117 | " return mst, minCost" 118 | ], 119 | "execution_count": null, 120 | "outputs": [] 121 | } 122 | ] 123 | } -------------------------------------------------------------------------------- /Searching and Graph Algorithms/MST_Prim.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "SP_Dijkstra_MinHeap.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Minimum Spanning Tree (MST) of an un-/weighted undirected graph \n", 24 | " based on Prim Algorithm using min-heap\n", 25 | " Time complexity = O(E.log(V))\n", 26 | "\n", 27 | " Parameters:\n", 28 | " -----------\n", 29 | " graph: defaultdict\n", 30 | " An undirected graph dictionary: { u: {v1: w1, v2: w2} }\n", 31 | " V : integer\n", 32 | " Number of vertex\n", 33 | "\n", 34 | " Returns:\n", 35 | " --------\n", 36 | " mst : list\n", 37 | " An undirected Minimum Spanning Tree list of edges [u, v]\n", 38 | " minCost: integer\n", 39 | " Total weights of MST\n", 40 | "\n", 41 | " Examples:\n", 42 | " --------- \n", 43 | " Undirected graph Minimum Spanning Tree\n", 44 | " 10 10\n", 45 | " 0-----1 0-----1\n", 46 | " |\\ | \\ \n", 47 | " | \\ | Prim Algorithm \\ Total weights of MST \n", 48 | " 6| \\5 |15 ================> \\5 = 10 + 5 + 4 = 19\n", 49 | " | \\ | \\\n", 50 | " | \\| \\\n", 51 | " 2-----3 2-----3\n", 52 | " 4 4 \n", 53 | "\n", 54 | " >>> graph = {0: {1: 10, 2: 6, 3: 5}, 1: {0: 10, 3: 15}, 2: {0: 6, 3: 4}, 3: {0: 5, 1: 15, 2: 4}}\n", 55 | " >>> V = 4\n", 56 | " >>> print(MST_Prim(graph, V))\n", 57 | " ([[0, 1], [3, 2], [0, 3]], 19)\n", 58 | "\n", 59 | " References:\n", 60 | " https://leetcode.com/problems/network-delay-time/discuss/329376/efficient-oe-log-v-python-dijkstra-min-heap-with-explanation\n", 61 | " https://www.geeksforgeeks.org/prims-mst-for-adjacency-list-representation-greedy-algo-6/?ref=rp\n", 62 | " https://www.youtube.com/watch?v=oP2-8ysT3QQ&list=PLrmLmBdmIlpu2f2g8ltqaaCZiq6GJvl1j&index=3\n", 63 | "'''\n", 64 | "\n", 65 | "import heapq\n", 66 | "\n", 67 | "def MST_Prim(graph, V): \n", 68 | " dist = [float('inf')] * V # Store min-distance from a vertex\n", 69 | " dist[0] = 0 # Set node 0 as starting node of MST\n", 70 | "\n", 71 | " minHeap = [(0,0)] # Heap to store distances\n", 72 | " visited = set() # Set of already visited nodes\n", 73 | " parent = [-1]*V # List to store parents of nodes \n", 74 | " \n", 75 | " while minHeap: \n", 76 | " _, u = heapq.heappop(minHeap) # Extract node \"u\" that haves smallest weight in min-heap\n", 77 | " \n", 78 | " if u in visited: continue\n", 79 | " visited.add(u) \n", 80 | "\n", 81 | " # Run through all adjacent vertices of the extracted vertex u and update their distance values \n", 82 | " for v in graph[u]: \n", 83 | " if v in visited: continue\n", 84 | " w = graph[u][v]\n", 85 | " if w < dist[v]: \n", 86 | " dist[v] = w \n", 87 | " parent[v] = u \n", 88 | " # Update distance value in min heap \n", 89 | " heapq.heappush(minHeap, (w, v))\n", 90 | " \n", 91 | " mst = [ [v, u+1] for u, v in enumerate(parent[1:]) ] # The complete MST\n", 92 | " minCost = sum(dist) # Total weights of the MST\n", 93 | " return mst, minCost" 94 | ], 95 | "execution_count": null, 96 | "outputs": [] 97 | } 98 | ] 99 | } 100 | -------------------------------------------------------------------------------- /Searching and Graph Algorithms/SP_BFS.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "SP_BFS.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Shortest Path based on BFS\n", 24 | " Time complexity = O(V+E); V, E is the number of vertices and edges\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " graph: defaultdict\n", 29 | " Graph, each starting vertex as a key is a list of ending vertices\n", 30 | " start: integer, string\n", 31 | " Starting vertex of the shortest path\n", 32 | " end : integer, string\n", 33 | " Ending vertex of the shortest path\n", 34 | "\n", 35 | " Returns:\n", 36 | " --------\n", 37 | " new_path: list\n", 38 | " Shortest path, contains all nodes on the path\n", 39 | "\n", 40 | " Examples:\n", 41 | " ---------\n", 42 | " >>> graph = {0: [1, 3], 1: [2], 3: [4, 7], 4: [5, 6, 7], 5: [6], 6: [7]}\n", 43 | " >>> print(SP_BFS(graph, 0, 7))\n", 44 | " [0, 3, 7]\n", 45 | "'''\n", 46 | "\n", 47 | "def SP_BFS(graph, start, end): \n", 48 | " explored = [] \n", 49 | " \n", 50 | " # Queue for traversing the graph in the BFS \n", 51 | " queue = [[start]] \n", 52 | " \n", 53 | " # Loop to traverse the graph with the help of the queue \n", 54 | " while queue: \n", 55 | " path = queue.pop(0) \n", 56 | " node = path[-1] \n", 57 | " \n", 58 | " # Condition to check if the current node is not visited \n", 59 | " if node not in explored: \n", 60 | " neighbours = graph[node] \n", 61 | " \n", 62 | " # Loop to iterate over the neighbours of the node \n", 63 | " for neighbour in neighbours: \n", 64 | " new_path = list(path) \n", 65 | " new_path.append(neighbour) \n", 66 | " queue.append(new_path) \n", 67 | " \n", 68 | " # Condition to check if the neighbour node is the end \n", 69 | " if neighbour == end: \n", 70 | " return new_path\n", 71 | "\n", 72 | " explored.append(node)" 73 | ], 74 | "execution_count": null, 75 | "outputs": [] 76 | } 77 | ] 78 | } -------------------------------------------------------------------------------- /Searching and Graph Algorithms/SP_Dijkstra_MinHeap.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "SP_Dijkstra_MinHeap.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find shortest path of an non-negative un-/weighted un-/directed graph\n", 24 | " based on Dijkstra Algorithm using min-heap\n", 25 | " Time complexity = E.log(V)\n", 26 | "\n", 27 | " Parameters:\n", 28 | " -----------\n", 29 | " graph: defaultdict\n", 30 | " Graph, each starting vertex as a key is a dictionary of ending vertices\n", 31 | " and weights\n", 32 | " V : integer\n", 33 | " Number of vertices\n", 34 | " src : integer\n", 35 | " Source node of the shortest path\n", 36 | " end : integer, optional\n", 37 | " Ending node of the shortest path (0 by default)\n", 38 | "\n", 39 | " Returns:\n", 40 | " --------\n", 41 | " path: list\n", 42 | " Shortest path, contains all nodes on the path\n", 43 | " dist: list\n", 44 | " Minimum distance from source to all nodes in the graph\n", 45 | "\n", 46 | " Examples:\n", 47 | " ---------\n", 48 | " Given a weighted undirected graph:\n", 49 | " 20 24\n", 50 | " 3(end)-------0(source)-------1\n", 51 | " | /\n", 52 | " | /\n", 53 | " | /\n", 54 | " 12| /3\n", 55 | " | /\n", 56 | " | /\n", 57 | " |/\n", 58 | " 2\n", 59 | " Shortest path from 0 to 3 is 0 -> 2 -> 3, having weight = 15\n", 60 | "\n", 61 | " >>> graph = {0: {1: 24, 3: 20, 2: 3}, 1: {0: 24}, 3: {0: 20, 2: 12}, 2: {0: 3, 3: 12}}\n", 62 | " >>> V = 4\n", 63 | " >>> src = 0\n", 64 | " >>> end = 3\n", 65 | " >>> print(SP_Dijkstra_MinHeap(graph, V, src, end))\n", 66 | " ([0, 2, 3], [0, 24, 3, 15])\n", 67 | "\n", 68 | " References:\n", 69 | " https://leetcode.com/problems/network-delay-time/discuss/329376/efficient-oe-log-v-python-dijkstra-min-heap-with-explanation\n", 70 | " https://www.geeksforgeeks.org/dijkstras-algorithm-for-adjacency-list-representation-greedy-algo-8/\n", 71 | " https://www.youtube.com/watch?v=lAXZGERcDf4&list=PLrmLmBdmIlpu2f2g8ltqaaCZiq6GJvl1j&index=2\n", 72 | "'''\n", 73 | "\n", 74 | "import heapq\n", 75 | "\n", 76 | "def SP_Dijkstra_MinHeap(graph, V, src, end=0):\n", 77 | " dist = [float('inf')] * V # Store min-distance from a vertex\n", 78 | " dist[src] = 0\n", 79 | "\n", 80 | " minHeap = [(0,src)] # Heap to store distances\n", 81 | " visited = set() # Set of already visited nodes\n", 82 | " parent = [-1]*V # List to store parents of nodes\n", 83 | "\n", 84 | " while minHeap:\n", 85 | " d, u = heapq.heappop(minHeap) # Extract min distance \"d\" and its node \"u\" in min-heap\n", 86 | "\n", 87 | " if u in visited: continue\n", 88 | " visited.add(u) \n", 89 | " \n", 90 | " # Run through all adjacent vertices of the extracted vertex u and update their distance values \n", 91 | " for v in graph[u]:\n", 92 | " if v in visited: continue\n", 93 | " new_d = d + graph[u][v]\n", 94 | " if new_d < dist[v]:\n", 95 | " dist[v] = new_d\n", 96 | " parent[v] = u\n", 97 | " # Update distance value in min heap \n", 98 | " heapq.heappush(minHeap, (new_d, v))\n", 99 | "\n", 100 | " # Find shortest path from source to end vertex \n", 101 | " path = [end]\n", 102 | " v = end\n", 103 | " while v != src:\n", 104 | " u = parent[v]\n", 105 | " path.insert(0,u)\n", 106 | " v = u\n", 107 | "\n", 108 | " return path, dist\n", 109 | "\n", 110 | "graph = {0: {1: 24, 3: 20, 2: 3}, 1: {0: 24}, 3: {0: 20, 2: 12}, 2: {0: 3, 3: 12}}\n", 111 | "V = 4\n", 112 | "src = 0\n", 113 | "end = 3\n", 114 | "print(SP_Dijkstra_MinHeap(graph, V, src, end))" 115 | ], 116 | "execution_count": null, 117 | "outputs": [] 118 | } 119 | ] 120 | } -------------------------------------------------------------------------------- /Searching and Graph Algorithms/isCycle_DisjointSet.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "isCycle_DisjointSet.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to detect cycle in an undirected graph based on disjoint set (union-find) \n", 24 | " using \"union by rank and path compression\"\n", 25 | " Time complexity = O(V)\n", 26 | "\n", 27 | " Parameters:\n", 28 | " -----------\n", 29 | " graph: defaultdict\n", 30 | " Graph, each starting vertex as a key is a list of ending vertices\n", 31 | " V : integer\n", 32 | " Number of vertex\n", 33 | "\n", 34 | " Returns:\n", 35 | " --------\n", 36 | " True/False: boolean\n", 37 | "\n", 38 | " Examples:\n", 39 | " --------- \n", 40 | " >>> graph = {0: [1, 2], 1: [2]}\n", 41 | " >>> print(isCycle_DisjointSet(graph, 3))\n", 42 | " True\n", 43 | "\n", 44 | " >>> graph = {0: [1], 1: [2]}\n", 45 | " >>> print(isCycle_DisjointSet(graph, 3))\n", 46 | " False\n", 47 | "\n", 48 | " References: \n", 49 | " https://www.geeksforgeeks.org/union-find-algorithm-set-2-union-by-rank/\n", 50 | " https://www.youtube.com/watch?v=ID00PMy0-vE\n", 51 | " https://www.youtube.com/watch?v=n_t0a_8H8VY\n", 52 | "'''\n", 53 | "\n", 54 | "def isCycle_DisjointSet(graph, V):\n", 55 | " # Function to create a subset of element nodes\n", 56 | " def DisjointSet_Subset(parent, rank):\n", 57 | " subset = {'parent': parent, 'rank': rank}\n", 58 | " return subset\n", 59 | "\n", 60 | " # Function to find subset of an element node (uses path compression technique)\n", 61 | " def DisjointSet_Find(subsets, node):\n", 62 | " if subsets[node]['parent'] != node:\n", 63 | " subsets[node]['parent'] = DisjointSet_Find(subsets, subsets[node]['parent'])\n", 64 | " return subsets[node]['parent']\n", 65 | " \n", 66 | " # Function that does union of two subsets of u and v (uses union by rank)\n", 67 | " def DisjointSet_Union(subsets, u, v):\n", 68 | " # Attach smaller rank tree under root of high rank tree (Union by Rank)\n", 69 | " if subsets[u]['rank'] > subsets[v]['rank']:\n", 70 | " subsets[v]['parent'] = u\n", 71 | " elif subsets[u]['rank'] < subsets[v]['rank']:\n", 72 | " subsets[u]['parent'] = v\n", 73 | " # If ranks are same, then make one as root and increment its rank by one\n", 74 | " else:\n", 75 | " subsets[v]['parent'] = u\n", 76 | " subsets[u]['rank'] += 1\n", 77 | "\n", 78 | " # Main function\n", 79 | " subsets = [] \n", 80 | " for u in range(V):\n", 81 | " subsets.append(DisjointSet_Subset(u, 0))\n", 82 | " \n", 83 | " # Iterate through all edges of graph, find subsets of both vertices of \n", 84 | " # every edge. If sets are same, then there is cycle in graph.\n", 85 | " for u in graph:\n", 86 | " u_rep = DisjointSet_Find(subsets, u) # Representative node of u\n", 87 | " for v in graph[u]:\n", 88 | " v_rep = DisjointSet_Find(subsets, v) # Representative node of v\n", 89 | " # Detect cycle \n", 90 | " if u_rep == v_rep:\n", 91 | " return True\n", 92 | " # Do union of 2 subsets\n", 93 | " else:\n", 94 | " DisjointSet_Union(subsets, u_rep, v_rep)\n", 95 | " return False" 96 | ], 97 | "execution_count": null, 98 | "outputs": [] 99 | } 100 | ] 101 | } -------------------------------------------------------------------------------- /String Algorithm/LCPArray_Kasai.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "LCPArray_Kasai.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Longest Common Prefix Array based on Kasai algorithm\n", 24 | " Time complexity = O(n)\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " s : string\n", 29 | " Input string to convert into suffix array \n", 30 | " sa: list\n", 31 | " Suffix array of the input string\n", 32 | "\n", 33 | " Returns:\n", 34 | " --------\n", 35 | " l: list\n", 36 | " Longest Common Prefix Array\n", 37 | "\n", 38 | " Examples:\n", 39 | " ---------\n", 40 | " Let the given string be \"banana\".\n", 41 | " Suffix LCP\n", 42 | " 0 banana 5 a 0\n", 43 | " 1 anana Sort the Suffixes 3 ana 1\n", 44 | " 2 nana ----------------> 1 anana 3\n", 45 | " 3 ana alphabetically 0 banana 0\n", 46 | " 4 na 4 na 0\n", 47 | " 5 a 2 nana 2\n", 48 | "\n", 49 | " The suffix array for \"banana\" is [5, 3, 1, 0, 4, 2]\n", 50 | " The LCP array is [0, 1, 3, 0, 0, 2]\n", 51 | "\n", 52 | " >>> s = 'banana'\n", 53 | " >>> sa = SuffixArray_ManberMyers(s)\n", 54 | " >>> print(LCPArray_Kasai(s, sa))\n", 55 | " [0, 1, 3, 0, 0, 2]\n", 56 | "\n", 57 | " References:\n", 58 | " https://leetcode.com/problems/longest-duplicate-substring/discuss/695003/super-simple-using-suffix-array-java-python\n", 59 | " https://www.hackerrank.com/challenges/ashton-and-string/topics/suffix-array\n", 60 | "'''\n", 61 | "\n", 62 | "def LCPArray_Kasai(s, sa):\n", 63 | " n = len(s)\n", 64 | " lcp, ra = [0] * (n-1), [0] * n\n", 65 | " for i in range(n):\n", 66 | " ra[sa[i]] = i\n", 67 | " k = 0\n", 68 | " for i in range(n):\n", 69 | " if ra[i] == n - 1:\n", 70 | " k = 0\n", 71 | " continue\n", 72 | " j = sa[ra[i] + 1]\n", 73 | " while i + k < n and j + k < n and s[i + k] == s[j + k]:\n", 74 | " k += 1\n", 75 | " lcp[ra[i]] = k\n", 76 | " if k > 0:\n", 77 | " k -= 1\n", 78 | " l = [0]\n", 79 | " l.extend(lcp)\n", 80 | " return l" 81 | ], 82 | "execution_count": null, 83 | "outputs": [] 84 | } 85 | ] 86 | } 87 | -------------------------------------------------------------------------------- /String Algorithm/SuffixArray_ManberMyers.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "SuffixArray_ManberMyers.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "a3hYgaHPUkua" 20 | }, 21 | "source": [ 22 | "'''\n", 23 | " Function to find Suffix Array of a string based on Manber-Myers algorithm\n", 24 | " Time complexity = O(n.log(n))\n", 25 | "\n", 26 | " Parameters:\n", 27 | " -----------\n", 28 | " s: string\n", 29 | " Input string to convert into suffix array \n", 30 | "\n", 31 | " Returns:\n", 32 | " --------\n", 33 | " sa: list\n", 34 | " Suffix array of the input string\n", 35 | "\n", 36 | " Examples:\n", 37 | " ---------\n", 38 | " Let the given string be \"banana\".\n", 39 | "\n", 40 | " 0 banana 5 a\n", 41 | " 1 anana Sort the Suffixes 3 ana\n", 42 | " 2 nana ----------------> 1 anana \n", 43 | " 3 ana alphabetically 0 banana \n", 44 | " 4 na 4 na \n", 45 | " 5 a 2 nana\n", 46 | "\n", 47 | " So the suffix array for \"banana\" is [5, 3, 1, 0, 4, 2]\n", 48 | "\n", 49 | " >>> s = 'banana'\n", 50 | " >>> sa = SuffixArray_ManberMyers(s)\n", 51 | " >>> print(sa)\n", 52 | " [5, 3, 1, 0, 4, 2]\n", 53 | "\n", 54 | " References:\n", 55 | " http://algorithmicalley.com/archive/2013/06/30/suffix-arrays.aspx\n", 56 | " https://www.hackerrank.com/challenges/ashton-and-string/topics/suffix-array\n", 57 | "'''\n", 58 | "\n", 59 | "from collections import defaultdict\n", 60 | "\n", 61 | "def SuffixArray_ManberMyers(s):\n", 62 | " # Using Bucket Sort instead of built-in \"sorted\" can save space when dealing\n", 63 | " # with very big input string\n", 64 | " result = []\n", 65 | " def Bucket_Sort(s, bucket, order=1):\n", 66 | " d = defaultdict(list)\n", 67 | " for i in bucket:\n", 68 | " key = s[i:i+order]\n", 69 | " d[key].append(i)\n", 70 | " for k, v in sorted(d.items()):\n", 71 | " if len(v) > 1:\n", 72 | " Bucket_Sort(s, v, order*2)\n", 73 | " else:\n", 74 | " result.append(v[0])\n", 75 | " return result\n", 76 | "\n", 77 | " sa = Bucket_Sort(s, (i for i in range(len(s)))) # Suffix array\n", 78 | " return sa" 79 | ], 80 | "execution_count": null, 81 | "outputs": [] 82 | } 83 | ] 84 | } -------------------------------------------------------------------------------- /Two Pointers - Sliding Window/LongestSubstring_0RepeatChars.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "LongestSubstring_0RepeatChars.ipynb", 7 | "provenance": [], 8 | "collapsed_sections": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "markdown", 18 | "metadata": { 19 | "id": "pKOSH2F9-EUT" 20 | }, 21 | "source": [ 22 | "#### Visualization of how the algorithm works\n", 23 | "\n", 24 | "![Longest Substring Without Repeating Characters.png](data:image/png;base64,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)" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "metadata": { 30 | "id": "a3hYgaHPUkua" 31 | }, 32 | "source": [ 33 | "'''\n", 34 | " Find the length of the longest substring without repeating characters \n", 35 | " Time complexity = O(n)\n", 36 | "\n", 37 | " Parameters:\n", 38 | " -----------\n", 39 | " s: str\n", 40 | " The input string\n", 41 | "\n", 42 | " Returns:\n", 43 | " --------\n", 44 | " Longest length: int\n", 45 | "\n", 46 | " Examples:\n", 47 | " --------- \n", 48 | " Given a string 'ABCBFAC'. \n", 49 | " The longest substring without repeating characters is 'BFAC', and its length is 4.\n", 50 | "\n", 51 | " How the algorithm works?\n", 52 | " See the markdown cell above\n", 53 | "\n", 54 | " >>> s = 'ABCBFAC'\n", 55 | " >>> print(LongestSubstring_0RepeatChars(s))\n", 56 | " 4\n", 57 | "\n", 58 | " References:\n", 59 | " https://leetcode.com/problems/longest-substring-without-repeating-characters/\n", 60 | "'''\n", 61 | "\n", 62 | "def LongestSubstring_0RepeatChars(s):\n", 63 | " from collections import defaultdict\n", 64 | " \n", 65 | " d = defaultdict(list) # Memoization as: character -> its indices\n", 66 | " memo = [] # Memoization of lengths\n", 67 | " i, j = 0, 0 # Two pointers\n", 68 | " \n", 69 | " for j in range(0, len(s)):\n", 70 | " c = s[j] # Current character\n", 71 | " if c in d:\n", 72 | " if d[c][-1] >= i:\n", 73 | " memo.append(j-i) # memo.append([j-i, i, j]) if you wanna output the substring\n", 74 | " i = d[c][-1] + 1 \n", 75 | " d[c].append(j) \n", 76 | " \n", 77 | " if d:\n", 78 | " memo.append(j-i+1) \n", 79 | " return max(memo)\n", 80 | " else:\n", 81 | " return 0 " 82 | ], 83 | "execution_count": 1, 84 | "outputs": [] 85 | } 86 | ] 87 | } --------------------------------------------------------------------------------