├── 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 |
12 |
13 |
14 |
15 |
16 |
17 |
28 |
29 |
35 |
36 |