[
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".gitignore",
    "content": ".vscode\n.idea\n*.exe"
  },
  {
    "path": "2D Arrays (Matrix)/2D_sorted.go",
    "content": "func searchMatrix(matrix [][]int, target int) bool {\n    if len(matrix) == 0 || len(matrix[0]) == 0 {\n        return false\n    }\n\n    rows, cols := len(matrix), len(matrix[0])\n    left, right := 0, rows*cols-1\n\n    for left <= right {\n        mid := left + (right-left)/2\n        // Convert the 1D index back to 2D coordinates\n        row, col := mid/cols, mid%cols\n        midValue := matrix[row][col]\n\n        if midValue == target {\n            return true\n        } else if midValue < target {\n            left = mid + 1\n        } else {\n            right = mid - 1\n        }\n    }\n\n    return false\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/2D_sorted_array.java",
    "content": "/*\n\nThe algorithm starts by initializing two pointers, left and right, which represent the start and end indices of the search range. The range spans from the first element (matrix[0][0]) to the last element (matrix[m - 1][n - 1]) in the matrix, where m is the number of rows and n is the number of columns.\n\nThe function then enters a while loop that continues as long as left is less than or equal to right. In each iteration, it calculates the middle index mid using the formula mid = left + (right - left) / 2. This ensures that mid is always rounded down to the lower integer if the range is odd.\n\nThe middle index mid is then mapped to its corresponding row and column indices in the matrix using the formulas row = mid / n and col = mid % n.\n\nThe number num at the middle position (matrix[row][col]) is retrieved and compared with the target. If num is equal to the target, the function returns true as the target is found in the matrix. If num is less than the target, the left pointer is updated to mid + 1 to search in the upper half of the range. If num is greater than the target, the right pointer is updated to mid - 1 to search in the lower half of the range.\n\nIf the while loop terminates without finding the target, the function returns false.\n\nThe algorithm achieves a time complexity of O(log(m * n)), where m is the number of rows and n is the number of columns in the matrix, as it uses binary search to efficiently search within the given range.\n\n*/\n\n\n\n#include <vector>\nclass Solution {\npublic:\n    /**\n     * Searches for a target integer in a matrix with specific properties.\n     *\n     * @param matrix The input matrix.\n     * @param target The target integer to search for.\n     * @return True if the target is found in the matrix, false otherwise.\n     */\n    bool searchMatrix(std::vector<std::vector<int>>& matrix, int target) {\n        int m = matrix.size();\n        int n = matrix[0].size();\n\n        int left = 0;              // Start index of the search range\n        int right = m * n - 1;     // End index of the search range\n\n        while (left <= right) {\n            int mid = left + (right - left) / 2;   // Calculate middle index\n            int row = mid / n;                     // Calculate row index\n            int col = mid % n;                     // Calculate column index\n            int num = matrix[row][col];            // Get the number at the middle position\n\n            if (num == target) {\n                return true;                       // Target found in the matrix\n            } else if (num < target) {\n                left = mid + 1;                     // Search in the upper half of the range\n            } else {\n                right = mid - 1;                    // Search in the lower half of the range\n            }\n        }\n\n        return false;                               // Target not found in the matrix\n    }\n};\n"
  },
  {
    "path": "2D Arrays (Matrix)/binary_search.cpp",
    "content": "/*\n    You are given an m x n integer matrix matrix with the following two properties:\n\n    Each row is sorted in non-decreasing order.\n    The first integer of each row is greater than the last integer of the previous row.\n    Given an integer target, return true if target is in matrix or false otherwise.\n\n    You must write a solution in O(log(m * n)) time complexity.\n\n\n    1.Input: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3\n    Output: true\n\n    2.Input: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13\n    Output: false\n*/\n\nclass Solution {\n    bool costumBinarySearch(const vector<vector<int>>& matrix, int target, int low, int high){\n        int size = matrix[0].size();\n        while(high - low > 1){\n            int mid = (high + low) / 2;\n            if(matrix[mid / size][mid % size] < target) {\n                low = mid + 1;\n            } else {\n                high = mid;\n            }\n        }\n        if(matrix[low / size][low % size] == target || matrix[high / size][high % size] == target){\n            return true;\n        }\n        return false;\n    }\npublic:\n    bool searchMatrix(vector<vector<int>>& matrix, int target) {\n        return costumBinarySearch(matrix, target, 0, matrix.size() * matrix[0].size() - 1);\n    }\n};"
  },
  {
    "path": "2D Arrays (Matrix)/count_negatives_in_sorted_matrix.cpp",
    "content": "/*\n    Given a m x n matrix grid which is sorted in non-increasing order both row-wise and column-wise, return the number of negative numbers in grid.\n\n    Example 1:\n    Input: grid = [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]\n    Output: 8\n    Explanation: There are 8 negatives number in the matrix.\n    \n    Example 2:\n    Input: grid = [[3,2],[1,0]]\n    Output: 0\n\n    Constraints:\n    m == grid.length\n    n == grid[i].length\n    1 <= m, n <= 100\n    -100 <= grid[i][j] <= 100\n\n    Follow up: Could you find an O(n + m) solution?\n*/\n\nclass Solution {\npublic:\n    int countNegatives(vector<vector<int>>& grid) {\n        int len = grid.size(), m = grid[0].size();\n        int ans = 0;\n        int j = 0, i = len - 1;\n        while(j < m && i >= 0){\n            if(grid[i][j] < 0){\n                ans += (m - j);\n                i--;\n            }\n            else{\n                j++;\n            }\n        }\n        return ans;\n    }\n};"
  },
  {
    "path": "2D Arrays (Matrix)/matrix_diagonal_sum.cpp",
    "content": "/*\n    Given a square matrix mat, return the sum of the matrix diagonals.\n\n    Only include the sum of all the elements on the primary diagonal and all the elements on the secondary diagonal that are not part of the primary diagonal.\n\n    Example 1:\n    Input: mat = [[1,2,3],\n                [4,5,6],\n                [7,8,9]]\n    Output: 25\n    Explanation: Diagonals sum: 1 + 5 + 9 + 3 + 7 = 25\n    Notice that element mat[1][1] = 5 is counted only once.\n    \n    Example 2:\n    Input: mat = [[1,1,1,1],\n                [1,1,1,1],\n                [1,1,1,1],\n                [1,1,1,1]]\n    Output: 8\n\n    Example 3:\n    Input: mat = [[5]]\n    Output: 5\n    \n    Constraints:\n    n == mat.length == mat[i].length\n    1 <= n <= 100\n    1 <= mat[i][j] <= 100\n*/\n\nclass Solution {\npublic:\n    int diagonalSum(vector<vector<int>>& mat) {\n        int len = mat.size(), sum = 0;\n        for(int i = 0; i < len; i++){\n            sum += mat[i][i] + mat[i][len - 1 - i];\n        }\n        // if length is odd then subtract mid element, because its added twice\n        if(len & 1){\n            sum -= mat[len / 2][len / 2];\n        }\n        return sum;\n    }\n};"
  },
  {
    "path": "2D Arrays (Matrix)/matrix_wave_print.cpp",
    "content": "// Prints a matrix in wave form \n#include<bits/stdc++.h>\nusing namespace std;\nvoid wave_print(int Mat[][10], int R, int C){\n    for(int j = 0; j < C; j++){\n        if(j & 1){\n            for(int i = R - 1; i >= 0; i--){\n                cout << Mat[i][j] << \" \";\n            }\n        }\n        else{\n            for(int i = 0; i < R; i++){\n                cout << Mat[i][j] << \" \";\n            }\n        }\n    }\n}\nint main(){\n    int Mat[10][10], R, C;\n    cin >> R >> C;\n    for(int i = 0; i < R; i++){\n        for(int j = 0; j < C; j++){\n            cin >> Mat[i][j];\n        }\n    }\n    for(int i = 0; i < R; i++){\n        for(int j = 0; j < C; j++){\n            cout << Mat[i][j] << \" \";\n        }\n        cout << endl;\n    }\n    wave_print(Mat, R, C);\n}"
  },
  {
    "path": "2D Arrays (Matrix)/rotate_matrix.cpp",
    "content": "// Rotate clockwise and anti-clockwise\n/*\nThis implementation first defines two functions, rotateClockwise and rotateCounterclockwise, \nto rotate the image by 90 degrees clockwise and counterclockwise, respectively. \nEach function takes a 2D vector image as input and modifies it in place.\n\nThe printImage function is used to print the image for demonstration purposes.\n\nFinally, the main function initializes an example image, prints it, rotates \nit by 90 degrees clockwise, prints it again, rotates it by 90 degrees counterclockwise, \nand prints it one last time to verify that the rotations worked as expected.\n*/\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\n// Function to rotate the image by 90 degrees clockwise\nvoid rotateClockwise(vector<vector<int>>& image) {\n    int n = image.size();\n    for (int i = 0; i < n / 2; i++) {\n        for (int j = i; j < n - i - 1; j++) {\n            int temp = image[i][j];\n            image[i][j] = image[n - j - 1][i];\n            image[n - j - 1][i] = image[n - i - 1][n - j - 1];\n            image[n - i - 1][n - j - 1] = image[j][n - i - 1];\n            image[j][n - i - 1] = temp;\n        }\n    }\n}\n\n// Function to rotate the image by 90 degrees counterclockwise\nvoid rotateCounterclockwise(vector<vector<int>>& image) {\n    int n = image.size();\n    for (int i = 0; i < n / 2; i++) {\n        for (int j = i; j < n - i - 1; j++) {\n            int temp = image[i][j];\n            image[i][j] = image[j][n - i - 1];\n            image[j][n - i - 1] = image[n - i - 1][n - j - 1];\n            image[n - i - 1][n - j - 1] = image[n - j - 1][i];\n            image[n - j - 1][i] = temp;\n        }\n    }\n}\n\n// Function to print the image\nvoid printImage(vector<vector<int>>& image) {\n    for (auto row : image) {\n        for (auto pixel : row) {\n            cout << pixel << \" \";\n        }\n        cout << endl;\n    }\n}\n\n// Driver code\nint main() {\n    vector<vector<int>> image = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};\n\n    cout << \"Original Image:\" << endl;\n    printImage(image);\n\n    rotateClockwise(image);\n    cout << \"Image rotated by 90 degrees clockwise:\" << endl;\n    printImage(image);\n\n    rotateCounterclockwise(image);\n    cout << \"Image rotated by 90 degrees counterclockwise:\" << endl;\n    printImage(image);\n\n    return 0;\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/rotate_matrix.go",
    "content": "// Rotate clockwise and anti-clockwise\n/*\n\tThe rotateClockwise function takes an image array as input and returns the image rotated by 90 degrees clockwise. \n\tIt creates a new rotated array with the same dimensions as the original image, and then iterates over \n\teach element of the image, assigning it to a new position in the rotated array.\n\n\tThe rotateCounterClockwise function works similarly, but it rotates the image counterclockwise instead. \n\tThe n-j-1 and n-i-1 indices are used to swap the rows and columns, respectively.\n\n\tIn the main function, we create an example image, and then call the rotateClockwise and \n\trotateCounterClockwise functions to rotate the image by 90 degrees in each direction. \n\tFinally, we print the rotated images.\n*/\npackage main\n\nimport \"fmt\"\n\nfunc rotateClockwise(image [][]int) [][]int {\n    n := len(image)\n    rotated := make([][]int, n)\n    for i := 0; i < n; i++ {\n        rotated[i] = make([]int, n)\n        for j := 0; j < n; j++ {\n            rotated[i][j] = image[n-j-1][i]\n        }\n    }\n    return rotated\n}\n\nfunc rotateCounterClockwise(image [][]int) [][]int {\n    n := len(image)\n    rotated := make([][]int, n)\n    for i := 0; i < n; i++ {\n        rotated[i] = make([]int, n)\n        for j := 0; j < n; j++ {\n            rotated[i][j] = image[j][n-i-1]\n        }\n    }\n    return rotated\n}\n\nfunc main() {\n    // example image\n    image := [][]int{\n        {1, 2, 3},\n        {4, 5, 6},\n        {7, 8, 9},\n    }\n\n    // rotate clockwise\n    rotatedClockwise := rotateClockwise(image)\n    fmt.Println(\"Rotated Clockwise:\")\n    for _, row := range rotatedClockwise {\n        fmt.Println(row)\n    }\n\n    // rotate counterclockwise\n    rotatedCounterClockwise := rotateCounterClockwise(image)\n    fmt.Println(\"Rotated Counterclockwise:\")\n    for _, row := range rotatedCounterClockwise {\n        fmt.Println(row)\n    }\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/rotate_matrix.java",
    "content": "// Rotate clockwise and anti-clockwise\n/*\n    This program takes a 2D array (matrix) and performs two types of 90-degree rotations: clockwise and \n    anti-clockwise. The rotateClockwise method takes a matrix and returns a new matrix with its \n    elements rotated 90 degrees clockwise. The rotateAntiClockwise method takes a matrix and \n    returns a new matrix with its elements rotated 90 degrees anti-clockwise.\n\n    The printMatrix method is used to print the matrix elements in a readable format. \n    Finally, the main method initializes a test matrix and performs the two rotations on it.\n*/\npublic class RotateMatrix {\n\n    // Rotate matrix by 90 degrees clockwise\n    public static int[][] rotateClockwise(int[][] matrix) {\n        int n = matrix.length;\n        int[][] result = new int[n][n];\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                result[i][j] = matrix[n - j - 1][i];\n            }\n        }\n\n        return result;\n    }\n\n    // Rotate matrix by 90 degrees anti-clockwise\n    public static int[][] rotateAntiClockwise(int[][] matrix) {\n        int n = matrix.length;\n        int[][] result = new int[n][n];\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                result[i][j] = matrix[j][n - i - 1];\n            }\n        }\n\n        return result;\n    }\n\n    // Print matrix\n    public static void printMatrix(int[][] matrix) {\n        for (int i = 0; i < matrix.length; i++) {\n            for (int j = 0; j < matrix[i].length; j++) {\n                System.out.print(matrix[i][j] + \" \");\n            }\n            System.out.println();\n        }\n    }\n\n    // Test program\n    public static void main(String[] args) {\n        int[][] matrix = {\n            {1, 2, 3},\n            {4, 5, 6},\n            {7, 8, 9}\n        };\n\n        System.out.println(\"Original Matrix:\");\n        printMatrix(matrix);\n\n        int[][] rotatedClockwise = rotateClockwise(matrix);\n        System.out.println(\"Matrix after 90 degree clockwise rotation:\");\n        printMatrix(rotatedClockwise);\n\n        int[][] rotatedAntiClockwise = rotateAntiClockwise(matrix);\n        System.out.println(\"Matrix after 90 degree anti-clockwise rotation:\");\n        printMatrix(rotatedAntiClockwise);\n    }\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/rotate_matrix.js",
    "content": "// Rotate clockwise and anti-clockwise\n/*\n    Here, we first get the number of rows and columns in the matrix. Then, for rotating the matrix clockwise, \n    we iterate over the columns in reverse order and create a new row in the rotated matrix by iterating \n    over each row in the original matrix and adding the corresponding element to the new row. \n    Finally, we add the new row to the rotated matrix.\n\n    For rotating the matrix anti-clockwise, we again iterate over the columns but this time in the \n    forward order and create a new row in the rotated matrix by iterating over each row in the original \n    matrix in reverse order and adding the corresponding element to the new row. Finally, we add the \n    new row to the rotated matrix.\n*/\nfunction rotateClockwise(matrix) {\n  // Get the number of rows and columns in the matrix\n  const rows = matrix.length;\n  const cols = matrix[0].length;\n\n  // Create a new matrix to store the rotated matrix\n  const rotated = [];\n\n  // Iterate over the columns in reverse order and create a new row in the rotated matrix\n  for (let j = cols - 1; j >= 0; j--) {\n    const newRow = [];\n    // Iterate over each row in the matrix and add the corresponding element to the new row\n    for (let i = 0; i < rows; i++) {\n      newRow.push(matrix[i][j]);\n    }\n    // Add the new row to the rotated matrix\n    rotated.push(newRow);\n  }\n\n  // Return the rotated matrix\n  return rotated;\n}\n\nfunction rotateAntiClockwise(matrix) {\n  // Get the number of rows and columns in the matrix\n  const rows = matrix.length;\n  const cols = matrix[0].length;\n\n  // Create a new matrix to store the rotated matrix\n  const rotated = [];\n\n  // Iterate over the columns in reverse order and create a new row in the rotated matrix\n  for (let j = 0; j < cols; j++) {\n    const newRow = [];\n    // Iterate over each row in the matrix in reverse order and add the corresponding element to the new row\n    for (let i = rows - 1; i >= 0; i--) {\n      newRow.push(matrix[i][j]);\n    }\n    // Add the new row to the rotated matrix\n    rotated.push(newRow);\n  }\n\n  // Return the rotated matrix\n  return rotated;\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/rotate_matrix.py",
    "content": "# Rotate clockwise and anti-clockwise\n'''\n    The rotate_clockwise() function takes a matrix as input and returns the matrix rotated by 90 degrees \n    clockwise. It does this by first transposing the matrix (swapping the elements across the diagonal), \n    and then reversing each row of the transposed matrix.\n\n    The rotate_counterclockwise() function takes a matrix as input and returns the matrix rotated by 90 \n    degrees counterclockwise. It also transposes the matrix first, and then reverses each column of \n    the transposed matrix.\n\n    Both functions use two nested loops to iterate through the matrix and perform the required operations. \n    The n variable represents the size of the matrix, and is used to control the range of the loops.\n'''\ndef rotate_clockwise(matrix):\n    \"\"\"\n    Function to rotate the given matrix by 90 degrees clockwise\n    \"\"\"\n    n = len(matrix)\n    # Transpose the matrix\n    for i in range(n):\n        for j in range(i, n):\n            matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]\n\n    # Reverse each row to get the final rotated matrix\n    for i in range(n):\n        matrix[i] = matrix[i][::-1]\n\n    return matrix\n\n\ndef rotate_counterclockwise(matrix):\n    \"\"\"\n    Function to rotate the given matrix by 90 degrees counterclockwise\n    \"\"\"\n    n = len(matrix)\n    # Transpose the matrix\n    for i in range(n):\n        for j in range(i, n):\n            matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]\n\n    # Reverse each column to get the final rotated matrix\n    for i in range(n//2):\n        for j in range(n):\n            matrix[j][i], matrix[j][n-i-1] = matrix[j][n-i-1], matrix[j][i]\n\n    return matrix\n"
  },
  {
    "path": "2D Arrays (Matrix)/search_element.cpp",
    "content": "/*\n    You are given an m x n integer matrix matrix with the following two properties:\n\n    Each row is sorted in non-decreasing order.\n    The first integer of each row is greater than the last integer of the previous row.\n    Given an integer target, return true if target is in matrix or false otherwise.\n\n    You must write a solution in O(log(m * n)) time complexity.\n\n\n    1.Input: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3\n    Output: true\n\n    2.Input: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13\n    Output: false\n*/\n\nclass Solution {\npublic:\n    bool searchMatrix(vector<vector<int>> &matrix,int target) {\n        int i = 0;\n        int j = matrix[0].size() - 1; \n        \n        while(i < matrix.size() && j >= 0)\n        {\n            if(target == matrix[i][j])\n                return true;         \n            else if(target < matrix[i][j])\n                j--;\n            else \n                i++;\n        }\n        return false;\n    }\n};\n"
  },
  {
    "path": "2D Arrays (Matrix)/searching_in_sorted_array.cpp",
    "content": "/* Name : Rajeev Kumar\nGithub username : Tonystart121\nRepository name : data-structures-and-algorithms\nProblem : Searching in 2D sorted array in C++\nIssue Number : #273\nProblem statement : Given a sorted matrix mat[n][m] and an element ‘x’. Find the position of x in the matrix if it is present, else print -1.\n\nSample testcases: \n\nTestcase 1 --> \n\nInput: number of rows(n) and column(m).Let n=3,m=3 and value to search x = 20 .\narr[n][m] =  { {1, 5, 9},\n              {14, 20, 21},\n               {30, 34, 43} }\n\nOutput: found at (1,2);\n\nTestcase 2 -->\nInput: number of rows(n) and column(m).Let n=3,m=4 and value to search x = 43\narr[n][m] = { {1, 5, 9, 11},\n              {14, 20, 21, 26},\n              {30, 34, 43, 50} }\nOutput: Found at (2,3);\n\nTime Complexity = O(n+m)\nSpace Complexity = O(n+m)\n\n\nExplanation:\nThis code asks the user to enter the number of rows and column in the array and element to find in the array, and then prompts them to enter each element of the array one at a time. Once the array is complete, the code applies the linear search/mapping algorithm to find the element within the array, and then prints the position of that element to the console.\n\nStart at the top left corner of the matrix.\nCompare the target element to the element at the current position.\nIf the target element is equal to the element at the current position, then return the current position.\nIf the target element is less than the element at the current position, then move down one row.\nIf the target element is greater than the element at the current position, then move right one column.\nRepeat steps 2-5 until the target element is found or the entire matrix has been searched.\n*/\n\n// ----------------------------------------------------------------------------- code begins now!\n\n\n#include<bits/stdc++.h>\nusing namespace std;\n\nint main(){\n\n    // enter array rows and column\n    int n,m;\n    cin>>n>>m;\n\n    // taking input array.\n    int arr[n][m];\n    for(int i=0;i<n;i++){\n        for(int j=0;j<m;j++){\n            cin>>arr[i][j];\n        }\n    }\n   \n    // taking input value to search.\n    int key;\n    cin>>key;\n\n    // initializing rightmost element as current element.\n    int cr_row =  0, cr_col=m-1;\n    bool ans = false;\n    while(cr_row<n and cr_col>=0){\n        \n        // if key==curr output its position\n        if(arr[cr_row][cr_col]==key){\n            cout<<cr_row<<\" \"<<cr_col;\n            ans=true;\n            break;\n        }\n       \n        // if key greater than array elements, row increasing.\n        else if(key>arr[cr_row][cr_col]){\n            cr_row++;\n        }\n\n        // if key less than array elements, col decreasing. \n        else if(key<arr[cr_row][cr_col]){\n            cr_col--;\n        }\n    }\n\n    // if not found outputting -1.\n    if(ans==false) cout<<\"-1\"<<endl;\n\n    return 0;\n}"
  },
  {
    "path": "2D Arrays (Matrix)/searching_in_sorted_array.java",
    "content": "\n/* Issue 271\nAuthor:maneesha\nDate:10/06/2023\n##Assignee:Mani1881\n\n//About:Search in 2D sorted array in Java\n//Input:\nYou are given an m x n integer matrix matrix with the following two properties:\nEach row is sorted in non-decreasing order.\nThe first integer of each row is greater than the last integer of the previous row.\nGiven an integer target, return true if target is in matrix or false otherwise.\n//Time Complexity:O(log(m * n))\n//Space Complexity:O(1)\n//Example 1:\nInput: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3\nOutput: true\n\n//Example 2:\nInput: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13\nOutput: false\n \n//Explanation:\n>>In this code, we have the Solution class with the searchMatrix method that takes a 2D matrix and a target value as parameters. \n>>It iterates through each element in the matrix and checks if the current element is equal to the target value. \n>>If a match is found, it returns true. If no match is found after checking all elements, it returns false.\n>>In the main function, we create an instance of the Solution class and define a sample matrix and target value.\n>>We then call the searchMatrix method with the provided matrix and target, and store the result in the found variable. \n>>Finally, we print whether the target was found or not. \n>>In this example, the output will be \"Target found: true\" since the target value 5 exists in the matrix. \n*/\n\nclass Solution\n{\npublic boolean searchMatrix(int[][] matrix, int target)\n{\n  int m = matrix.length;\n  int i = 0;\n  for (i = 0; i < m; i++) \n  {\n  for (int j = 0; j < matrix[i].length; j++)\n  {\n     if (matrix[i][j] == target)\n     return true;\n  }\n  }\nreturn false;\n}\n\npublic static void main(String[] args) \n{\n    Solution solution = new Solution();\n    int[][] matrix = {\n        {1, 2, 3},\n        {4, 5, 6},\n        {7, 8, 9}\n    };\n    int target = 5;\n\n    boolean found = solution.searchMatrix(matrix, target);\n    System.out.println(\"Target found: \" + found);\n}\n}\n\n"
  },
  {
    "path": "2D Arrays (Matrix)/searching_in_sorted_array.js",
    "content": "/*Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem : Search in 2D sorted array in Javascript\nIssue Number : #272\nProblem statement : \n\nExplanation of the below Javascript code :\n\nThe function searchMatrix takes in a matrix (matrix) and a target integer (target) as parameters. It returns true if the target is found in the matrix and false otherwise.\n\nThe function first checks for edge cases where the matrix is empty or the rows are empty, and immediately returns false in such cases.\n\nIt then initializes variables for the number of rows (rows) and columns (cols) in the matrix, and sets the left and right indices for the binary search.\n\nThe binary search is performed using a while loop, with the left and right indices as the condition. Inside the loop, the middle index (mid) is calculated using Math.floor((left + right) / 2), and the corresponding row and column indices are derived from the mid index.\n\nThe element at the mid index is compared with the target, and based on the comparison, the search space is narrowed down by updating the left and right indices accordingly.\n\nIf the target is found, the function returns true. If the loop completes without finding the target, the function returns false.\n\nThe time complexity of this JavaScript solution is O(log(m * n)), as it performs a binary search on a list of size m * n.\n\n\n*/\n\n-------------------------------------------------------------------------//Javascript code begins here-----------------------------------------------------------------------\n\n\n/**\n * Searches for a target integer in a matrix.\n * @param {number[][]} matrix - The matrix to search in.\n * @param {number} target - The target integer to search for.\n * @return {boolean} - True if the target is found, false otherwise.\n */\nfunction searchMatrix(matrix, target) {\n    // Check for empty matrix or empty rows\n    if (!matrix || matrix.length === 0 || matrix[0].length === 0) {\n        return false;\n    }\n\n    const rows = matrix.length;\n    const cols = matrix[0].length;\n    let left = 0;\n    let right = rows * cols - 1;\n\n    // Perform binary search on the matrix\n    while (left <= right) {\n        const mid = Math.floor((left + right) / 2);\n        const row = Math.floor(mid / cols);\n        const col = mid % cols;\n\n        if (matrix[row][col] === target) {\n            // Target found\n            return true;\n        } else if (matrix[row][col] < target) {\n            // Target is in the right half of the matrix\n            left = mid + 1;\n        } else {\n            // Target is in the left half of the matrix\n            right = mid - 1;\n        }\n    }\n\n    // Target not found\n    return false;\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/searching_in_sorted_array.py",
    "content": "'''\nDate:28/6/23\nAbout:Search in 2D sorted array in Python\n\nInput:\nYou are given an m x n integer matrix matrix with the following two properties:\nEach row is sorted in non-decreasing order.\nThe first integer of each row is greater than the last integer of the previous row.\nGiven an integer target, return true if target is in matrix or false otherwise.\n\nTime Complexity:\nYou must write a solution in O(log(m * n)) time complexity.\nSpace Complexity:O(1)\n\n//Example 1:\nInput: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3\nOutput: true\n//Example 2:\nInput: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13\nOutput: false\n\n//Explanation\nThe method takes two parameters: matrix, which represents the sorted matrix, and target, which is the value we want to find in the matrix.\n\nThe code initializes variables nRows and nCols to store the number of rows and columns in the matrix, respectively.\n\nThe starting position for the search is set to the bottom-left corner of the matrix (row = nRows - 1, col = 0).\n\nThe code enters a while loop that continues as long as the current row index (row) is within the bounds of the matrix (0 to nRows - 1\nand the current column index (col) is within the bounds of the matrix (0 to nCols - 1).\n\nInside the loop, the code retrieves the value at the current position in the matrix (val = matrix[row][col]).\n\nIf the current value (val) == value, the method returns True, indicating that the target is found in the matrix.\n\nIf the current value (val) < target value, it means the target can only be found in the rows above the current row. \nTherefore, the column index (col) is incremented to move to the next column.\n\nIf the current value (val) >target value, it means the target can only be found in the columns to the left of the current column. \nTherefore, the row index (row) is decremented to move to the previous row.\n\nIf the loop completes without finding the target value, the method returns False.\n\n'''\nclass Solution(object):\n    def searchMatrix(self, matrix, target):\n        nRows = len(matrix)\n        nCols = len(matrix[0])\n        row = nRows - 1\n        col = 0\n        while 0 <= row < nRows and 0 <= col < nCols:\n            val = matrix[row][col]\n            if val == target:\n                return True\n            elif val < target:\n                col += 1\n            else:\n                row -= 1\n        return False\n\n\n# Create an instance of the Solution class\nsolution = Solution()\n\n# Define the matrix and target value\nmatrix = [[1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 60]]\ntarget = 3\n\n# Call the searchMatrix method and print the result\nresult = solution.searchMatrix(matrix, target)\nprint(result)\n\n\n\n\n \n\n"
  },
  {
    "path": "2D Arrays (Matrix)/set_matrix_0.cpp",
    "content": "/*\nProblem:\nYou are given a 2D matrix, and the task is to modify it such that if an element in the matrix is zero, you need to set all the elements in the \ncorresponding row and column to zero as well.\n\nSolution:\nTo solve this problem, you can follow the steps below:\n\n1. Create two sets, rows and columns, to keep track of the rows and columns that need to be set to zero.\n\n2. Iterate through the matrix row by row, and for each element, if it is zero, add its row index to the rows set and its column index to the columns set.\n\n3. Iterate through the matrix again, and for each element, check if its row index or column index exists in the respective sets (rows or columns). \nIf either index exists, set the element to zero.\n\n4. Finally, iterate through the matrix one more time, and for each row or column index in the rows or columns sets, set all the elements in that \nrow or column to zero.\n\n5. Return the modified matrix.\n\nComplexity:\nLet's assume the matrix has dimensions MxN.\n\nStep 2: In this step, we iterate through the matrix once, which takes O(M*N) time.\n\nStep 3: In this step, we again iterate through the matrix once, which takes O(M*N) time.\n\nStep 4: In this step, we iterate through the rows and columns sets, which contain at most M+N elements. Therefore, this step takes O(M+N) time.\n\nOverall, the time complexity of the solution is O(MN + M + N), which can be simplified to O(MN). The space complexity is O(M+N) since we are \nusing two sets to store the rows and columns that need to be set to zero.\n*/\n\n#include <iostream>\n#include <vector>\n#include <unordered_set>\n\nusing namespace std;\n\nvoid setZeroes(vector<vector<int>>& matrix) {\n    unordered_set<int> rows;\n    unordered_set<int> columns;\n\n    // Step 1: Find the rows and columns that need to be set to zero\n    for (int i = 0; i < matrix.size(); i++) {\n        for (int j = 0; j < matrix[0].size(); j++) {\n            if (matrix[i][j] == 0) {\n                rows.insert(i);\n                columns.insert(j);\n            }\n        }\n    }\n\n    // Step 2: Set the corresponding rows and columns to zero\n    for (int i = 0; i < matrix.size(); i++) {\n        for (int j = 0; j < matrix[0].size(); j++) {\n            if (rows.count(i) || columns.count(j)) {\n                matrix[i][j] = 0;\n            }\n        }\n    }\n}\n\nvoid printMatrix(const vector<vector<int>>& matrix) {\n    for (const auto& row : matrix) {\n        for (int num : row) {\n            cout << num << \" \";\n        }\n        cout << endl;\n    }\n}\n\nint main() {\n    vector<vector<int>> matrix = {\n        {1, 1, 1},\n        {1, 0, 1},\n        {1, 1, 1}\n    };\n\n    cout << \"Original Matrix:\" << endl;\n    printMatrix(matrix);\n\n    setZeroes(matrix);\n\n    cout << \"Modified Matrix:\" << endl;\n    printMatrix(matrix);\n\n    return 0;\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/set_matrix_0.go",
    "content": "/*\nProblem:\nYou are given a 2D matrix, and the task is to modify it such that if an element in the matrix is zero, you need to set all the elements in the \ncorresponding row and column to zero as well.\n\nSolution:\nTo solve this problem, you can follow the steps below:\n\n1. Create two sets, rows and columns, to keep track of the rows and columns that need to be set to zero.\n\n2. Iterate through the matrix row by row, and for each element, if it is zero, add its row index to the rows set and its column index to the columns set.\n\n3. Iterate through the matrix again, and for each element, check if its row index or column index exists in the respective sets (rows or columns). \nIf either index exists, set the element to zero.\n\n4. Finally, iterate through the matrix one more time, and for each row or column index in the rows or columns sets, set all the elements in that \nrow or column to zero.\n\n5. Return the modified matrix.\n\nComplexity:\nLet's assume the matrix has dimensions MxN.\n\nStep 2: In this step, we iterate through the matrix once, which takes O(M*N) time.\n\nStep 3: In this step, we again iterate through the matrix once, which takes O(M*N) time.\n\nStep 4: In this step, we iterate through the rows and columns sets, which contain at most M+N elements. Therefore, this step takes O(M+N) time.\n\nOverall, the time complexity of the solution is O(MN + M + N), which can be simplified to O(MN). The space complexity is O(M+N) since we are \nusing two sets to store the rows and columns that need to be set to zero.\n*/\n\npackage main\n\nimport (\n\t\"fmt\"\n)\n\nfunc setZeroes(matrix [][]int) {\n\trows := make(map[int]bool)\n\tcolumns := make(map[int]bool)\n\n\t// Step 1: Find the rows and columns that need to be set to zero\n\tfor i := 0; i < len(matrix); i++ {\n\t\tfor j := 0; j < len(matrix[0]); j++ {\n\t\t\tif matrix[i][j] == 0 {\n\t\t\t\trows[i] = true\n\t\t\t\tcolumns[j] = true\n\t\t\t}\n\t\t}\n\t}\n\n\t// Step 2: Set the corresponding rows and columns to zero\n\tfor i := 0; i < len(matrix); i++ {\n\t\tfor j := 0; j < len(matrix[0]); j++ {\n\t\t\tif rows[i] || columns[j] {\n\t\t\t\tmatrix[i][j] = 0\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc main() {\n\tmatrix := [][]int{\n\t\t{1, 1, 1},\n\t\t{1, 0, 1},\n\t\t{1, 1, 1},\n\t}\n\n\tfmt.Println(\"Original Matrix:\")\n\tprintMatrix(matrix)\n\n\tsetZeroes(matrix)\n\n\tfmt.Println(\"Modified Matrix:\")\n\tprintMatrix(matrix)\n}\n\nfunc printMatrix(matrix [][]int) {\n\tfor i := 0; i < len(matrix); i++ {\n\t\tfor j := 0; j < len(matrix[0]); j++ {\n\t\t\tfmt.Print(matrix[i][j], \" \")\n\t\t}\n\t\tfmt.Println()\n\t}\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/set_matrix_0.java",
    "content": "/* SET MATRIX ZERO - JAVA LANGUAGE\n   Problem Link1 : https://leetcode.com/problems/set-matrix-zeroes/\n   Problem Link2 : https://www.codingninjas.com/codestudio/problems/zero-matrix_1171153\t\n\t\nProblem:\nYou are given a 2D matrix, and the task is to modify it such that if an element in the matrix is zero, you need to set all the elements in the \ncorresponding row and column to zero as well. \n\nE.g- Input: | 1 1 1 |\n\t        | 1 0 1 |\n\t        | 1 1 1 |\n\n    Output: | 1 0 1 |\n\t        | 0 0 0 |\n\t        | 1 0 1 |\n\t\nMETHOD 1] Brute Force Approach for Set Matrix Zeroes\nStep 1. Create an array answer of size (n X m) and initialize every element as 1.\nStep 2. Traverse the matrix array row-wise and set the current row as 0 in answer array if the current row contains an element equals to 0.\nStep 3. Traverse the matrix array column-wise and set the current column as 0 in answer array if the current column contains an element equals to 0.\nStep 4. Now traverse the answer array, if the current element is 0, then set this element as 0 in a matrix array.\nStep 5. Return matrix array\n\nComplexity Analysis:\nTime Complexity = O(n * m)\nSpace Complexity = O(n * m) \nwhere n is the number of rows in the matrix and m is the number of columns in the matrix.\n\nMETHOD 2] Optimal Approach for Set Matrix Zeroes\nIf we assume that -1, do not occur in the matrix array, then\n\nStep 1. Traverse the matrix array row-wise and set all the elements of current row which are not 0 as -1, if the current row contains an element equals to 0.\nStep 2. Traverse the matrix array column-wise and set all the elements of the current column which are not 0 as -1, if the current column contains an element equals to 0.\nStep 3. Again traverse the matrix and set all the elements that are -1 to 0.\nStep 4. Return matrix array.\n\t\nComplexity Analysis:\nTime Complexity = O(n * m)\nSpace Complexity = O(1) \nwhere n is the number of rows in the matrix and m is the number of columns in the matrix.\n*/\n\n\npublic class setMatrixZero {\n\n    // Method 1] Brute Force Approach\n    private static void setZeroes_bruteForce(int[][] matrix, int n, int m) {\n        int answer[][] = new int[n][m]; // Step 1\n        // Set all elements of answer array as 1\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < m; j++) {\n                answer[i][j] = 1; // making each element as 1\n            }\n        }\n        // Traverse row wise --> Step 2\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < m; j++) {\n                if (matrix[i][j] == 0) {\n                    // Set this row as zero in answer array\n                    for (int k = 0; k < m; k++) {\n                        answer[i][k] = 0;\n                    }\n                    break;\n                }\n            }\n        }\n        // Traverse column wise --> Step 3\n        for (int j = 0; j < m; j++) {\n            for (int i = 0; i < n; i++) {\n                if (matrix[i][j] == 0) {\n                    // Set this column as 0 in answer array\n                    for (int k = 0; k < n; k++) {\n                        answer[k][j] = 0;\n                    }\n                }\n            }\n        }\n        // Update the elements in matrix array --> Step 4\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < m; j++) {\n                if (answer[i][j] == 0) {\n                    matrix[i][j] = 0;\n                }\n            }\n        }\n    }\n\n    // Method 2] Optimal Approach\n    private static void setZeroes_optimalMethod(int[][] matrix, int n, int m) {\n        // Traverse row wise\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < m; j++) {\n                if (matrix[i][j] == 0) {\n                    // Set all the elements that are not zero as -1\n                    for (int k = 0; k < m; k++) {\n                        if (matrix[i][k] != 0) {\n                            matrix[i][k] = -1;\n                        }\n                    }\n                }\n            }\n        }\n        // Traverse column wise\n        for (int j = 0; j < m; j++) {\n            for (int i = 0; i < n; i++) {\n                if (matrix[i][j] == 0) {\n                    // Set all the elements that are not zero as -1\n                    for (int k = 0; k < n; k++) {\n                        if (matrix[k][j] != 0) {\n                            matrix[k][j] = -1;\n                        }\n                    }\n                }\n            }\n        }\n        \n        // Update all -1 as 0\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < m; j++) {\n                if (matrix[i][j] == -1) {\n                    matrix[i][j] = 0;\n                }\n            }\n        }\n    }\n    \n    public static void main(String[] args) {\n        // Example using Method 1 - Brute Force\n        int[][] matrix1 = new int[][] {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}};    //  Defining Matrix\n        int n = matrix1.length;\n        int m = matrix1[0].length;\n\n        setZeroes_bruteForce(matrix1, n, m);\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < m; j++) {\n                System.out.print(matrix1[i][j] + \" \");  // Printing Matrix\n            }\n            System.out.println();\n        }\n\n        System.out.println(\"-----------------\");\n\n        // Example using Method 2 - Optimal \n        int[][] matrix2 = new int[][] {{0, 0, 6, 0}, {1, 4, 9, 0}, {1, 8, 1, 8}};   //  Defining Matrix\n        n = matrix2.length;\n        m = matrix2[0].length;\n\n        setZeroes_optimalMethod(matrix2, n, m);\n\n        for (int i = 0; i < n; i++) {   \n            for (int j = 0; j < m; j++) {\n                System.out.print(matrix2[i][j] + \" \");  // Printing Matrix\n            }\n            System.out.println();\n        }\n    }\n}"
  },
  {
    "path": "2D Arrays (Matrix)/spiral_traverse.cpp",
    "content": "/*\n\tWrite a function that takes in an n x m two-dimensional array (that can be square-shaped when n == m) and\n\treturns a one-dimensional array of all the array's elements in spiral order.\n\n\tSpiral order starts at the top left corner of the two-dimensional array, goes to the right, and proceeds\n\tin a spiral pattern all the way until every element has been visited.\n\n\tExplanation:\n\n\tThe SpiralTraverse function takes a 2D integer array array and returns a 1D integer slice that contains the\n\telements of array traversed in a spiral order, starting from the top-left corner and moving clockwise.\n\n\tThe function first initializes an empty slice result to hold the elements of the spiral traversal.\n\tIf the input array is empty, the function immediately returns the empty result.\n\n\tNext, the function initializes variables startRow, endRow, startCol, and endCol to keep track of the\n\tboundaries of the matrix. These variables will be updated as the function traverses the matrix.\n\n\tThe function then enters a loop that traverses the matrix in a spiral order. The loop continues\n\tas long as startRow <= endRow and startCol <= endCol, which means that there are still elements\n\tin the matrix to be traversed.\n\n\tThe first step in the loop is to traverse the top row of the matrix from left to right, and append\n\teach element to the result slice. The next step is to traverse the rightmost column of the matrix from top to bottom,\n\tand append each element to the result slice. If there is more than one row in the matrix, the function then traverses\n\tthe bottom row of the matrix from right to left, and appends each element to the result slice. If there is only one row left,\n\tthe loop is broken to avoid duplicating the elements. Finally, if there is more than one column in the matrix,\n\tthe function traverses the left\n\n\tO(n) time | O(n) space - where n is the total number of elements in the array\n*/\n#include<bits/stdc++.h>\nusing namespace std;\n\n#include <vector>\nusing namespace std;\n\nvector<int> SpiralTraverse(vector<vector<int>> array) {\n    vector<int> result; // vector to store the spiral traversal\n    int rows = array.size(); // number of rows in the input array\n    int cols = array[0].size(); // number of columns in the input array\n    int startRow = 0, endRow = rows - 1; // indices for the start and end row of the current subarray\n    int startCol = 0, endCol = cols - 1; // indices for the start and end column of the current subarray\n\n    // loop until the entire input array is traversed\n    while (startRow <= endRow && startCol <= endCol) {\n        // traverse the top row from left to right\n        for (int col = startCol; col <= endCol; col++) {\n            result.push_back(array[startRow][col]);\n        }\n        // traverse the right column from top to bottom\n        for (int row = startRow + 1; row <= endRow; row++) {\n            result.push_back(array[row][endCol]);\n        }\n        // traverse the bottom row from right to left\n        for (int col = endCol - 1; col >= startCol; col--) {\n            // check if there is only one row in the subarray\n            if (startRow == endRow) {\n                break;\n            }\n            result.push_back(array[endRow][col]);\n        }\n        // traverse the left column from bottom to top\n        for (int row = endRow - 1; row > startRow; row--) {\n            // check if there is only one column in the subarray\n            if (startCol == endCol) {\n                break;\n            }\n            result.push_back(array[row][startCol]);\n        }\n        // update the indices for the next subarray to be traversed\n        startRow++;\n        endRow--;\n        startCol++;\n        endCol--;\n    }\n\n    return result;\n}\n\nint main() {\n    vector<vector<int>> array = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};\n    vector<int> result = SpiralTraverse(array);\n    cout << \"Spiral traversal: \";\n    for (int i = 0; i < result.size(); i++) {\n        cout << result[i] << \" \";\n    }\n    cout << endl;\n    return 0;\n}"
  },
  {
    "path": "2D Arrays (Matrix)/spiral_traverse.go",
    "content": "/*\n\tWrite a function that takes in an n x m two-dimensional array (that can be square-shaped when n == m) and\n\treturns a one-dimensional array of all the array's elements in spiral order.\n\n\tSpiral order starts at the top left corner of the two-dimensional array, goes to the right, and proceeds\n\tin a spiral pattern all the way until every element has been visited.\n\n\tExplanation:\n\n\tThe SpiralTraverse function takes a 2D integer array array and returns a 1D integer slice that contains the\n\telements of array traversed in a spiral order, starting from the top-left corner and moving clockwise.\n\n\tThe function first initializes an empty slice result to hold the elements of the spiral traversal.\n\tIf the input array is empty, the function immediately returns the empty result.\n\n\tNext, the function initializes variables startRow, endRow, startCol, and endCol to keep track of the\n\tboundaries of the matrix. These variables will be updated as the function traverses the matrix.\n\n\tThe function then enters a loop that traverses the matrix in a spiral order. The loop continues\n\tas long as startRow <= endRow and startCol <= endCol, which means that there are still elements\n\tin the matrix to be traversed.\n\n\tThe first step in the loop is to traverse the top row of the matrix from left to right, and append\n\teach element to the result slice. The next step is to traverse the rightmost column of the matrix from top to bottom,\n\tand append each element to the result slice. If there is more than one row in the matrix, the function then traverses\n\tthe bottom row of the matrix from right to left, and appends each element to the result slice. If there is only one row left,\n\tthe loop is broken to avoid duplicating the elements. Finally, if there is more than one column in the matrix,\n\tthe function traverses the left\n\n\tO(n) time | O(n) space - where n is the total number of elements in the array\n*/\npackage main\n\nimport \"fmt\"\n\nfunc SpiralTraverse(array [][]int) []int {\n\t// Initialize an empty slice to hold the result\n\tresult := []int{}\n\t// If the input array is empty, return the empty result\n\tif len(array) == 0 {\n\t\treturn result\n\t}\n\t// Initialize variables to keep track of the boundaries of the matrix\n\tstartRow, endRow := 0, len(array)-1\n\tstartCol, endCol := 0, len(array[0])-1\n\n\t// Traverse the matrix in a spiral order\n\tfor startRow <= endRow && startCol <= endCol {\n\t\t// Traverse the top row from left to right\n\t\tfor col := startCol; col <= endCol; col++ {\n\t\t\tresult = append(result, array[startRow][col])\n\t\t}\n\t\t// Traverse the rightmost column from top to bottom\n\t\tfor row := startRow + 1; row <= endRow; row++ {\n\t\t\tresult = append(result, array[row][endCol])\n\t\t}\n\t\t// Traverse the bottom row from right to left, if there is more than one row\n\t\tfor col := endCol - 1; col >= startCol; col-- {\n\t\t\t// If there is only one row left, break the loop to avoid duplicating the elements\n\t\t\tif startRow == endRow {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tresult = append(result, array[endRow][col])\n\t\t}\n\t\t// Traverse the leftmost column from bottom to top, if there is more than one column\n\t\tfor row := endRow - 1; row > startRow; row-- {\n\t\t\t// If there is only one column left, break the loop to avoid duplicating the elements\n\t\t\tif startCol == endCol {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tresult = append(result, array[row][startCol])\n\t\t}\n\t\t// Update the boundaries of the matrix\n\t\tstartRow++\n\t\tendRow--\n\t\tstartCol++\n\t\tendCol--\n\t}\n\t// Return the result slice\n\treturn result\n}\n\nfunc main() {\n\t// Example 2D array\n\tarray := [][]int{\n\t\t{1, 2, 3, 4},\n\t\t{10, 11, 12, 5},\n\t\t{9, 8, 7, 6},\n\t}\n\n\t// Call SpiralTraverse function on array\n\tresult := SpiralTraverse(array)\n\n\t// Print the result to console\n\tfmt.Println(result)\n}"
  },
  {
    "path": "2D Arrays (Matrix)/spiral_traverse.java",
    "content": "/*\n\tWrite a function that takes in an n x m two-dimensional array (that can be square-shaped when n == m) and\n\treturns a one-dimensional array of all the array's elements in spiral order.\n\n\tSpiral order starts at the top left corner of the two-dimensional array, goes to the right, and proceeds\n\tin a spiral pattern all the way until every element has been visited.\n\n\tExplanation:\n\n\tThe SpiralTraverse function takes a 2D integer array array and returns a 1D integer slice that contains the\n\telements of array traversed in a spiral order, starting from the top-left corner and moving clockwise.\n\n\tThe function first initializes an empty slice result to hold the elements of the spiral traversal.\n\tIf the input array is empty, the function immediately returns the empty result.\n\n\tNext, the function initializes variables startRow, endRow, startCol, and endCol to keep track of the\n\tboundaries of the matrix. These variables will be updated as the function traverses the matrix.\n\n\tThe function then enters a loop that traverses the matrix in a spiral order. The loop continues\n\tas long as startRow <= endRow and startCol <= endCol, which means that there are still elements\n\tin the matrix to be traversed.\n\n\tThe first step in the loop is to traverse the top row of the matrix from left to right, and append\n\teach element to the result slice. The next step is to traverse the rightmost column of the matrix from top to bottom,\n\tand append each element to the result slice. If there is more than one row in the matrix, the function then traverses\n\tthe bottom row of the matrix from right to left, and appends each element to the result slice. If there is only one row left,\n\tthe loop is broken to avoid duplicating the elements. Finally, if there is more than one column in the matrix,\n\tthe function traverses the left\n\n\tO(n) time | O(n) space - where n is the total number of elements in the array\n*/\nimport java.util.*;\npublic class SpiralTraverse {\n\n    public static void main(String[] args) {\n        int[][] array = { {1, 2, 3},\n                {12, 13, 4},\n                {11, 14, 5},\n                {10, 15, 6},\n                {9, 8, 7} };\n        System.out.println(spiralFillUsingLoop(array));\n\n//        spiralFillUsingRecursion(array, 0, array.length - 1, 0, array[0].length - 1, result);\n    }\n    public static List<Integer> spiralFillUsingLoop(int[][] array) {\n        // O(n) time | O(n) space;\n        if(array.length == 0) return new ArrayList<>();\n\n        var result = new ArrayList<Integer>();\n        var startRow = 0;\n        var endRow = array.length - 1;\n        var startCol = 0;\n        var endCol = array[0].length - 1;\n\n        while(startRow <= endRow && startCol <= endCol) {\n\n            for(int col = startCol; col <= endCol; col++)\n                result.add(array[startRow][col]);\n\n            for(int row = startRow + 1; row <= endRow; row++)\n                result.add(array[row][endCol]);\n\n            for(int col = endCol - 1; col >= startCol; col--) {\n                /**\n                 * Handle the edge case when there's a single row\n                 * in the middle of the matrix, In this case. we don't\n                 * want to double-count the values in this row, which\n                 * we've already counted in the first for loop above.\n                 * Test case for this edge case :\n                 *                              [\n                 *                                 [1, 2, 3, 4],\n                 *                                 [10, 11, 12, 5],\n                 *                                 [9, 8, 7, 6]\n                 *                               ]\n                 *\n                 *\n                 */\n                if(startRow == endRow) break;\n                result.add(array[endRow][col]);\n            }\n\n            for(int row = endRow - 1; row > startRow; row--) {\n                /**\n                 * Handle the edge case when there's a single column\n                 * in the middle of the matrix, In this case. we don't\n                 * want to double-count the values in this row, which\n                 * we've already counted in the first for loop above.\n                 * Test case for this edge case :\n                 *                              [\n                 *                                 [1, 2, 3],\n                 *                                 [12, 13, 4],\n                 *                                 [11, 14, 5],\n                 *                                 [10, 15, 6],\n                 *                               ]\n                 *\n                 */\n                if(startCol == endCol) break;\n                result.add(array[row][startCol]);\n            }\n\n            startRow++;\n            endRow--;\n            startCol++;\n            endCol--;\n        }\n\n        return result;\n    }\n    public static void spiralFillUsingRecursion(\n            int[][] array,\n            int startRow,\n            int endRow,\n            int startCol,\n            int endCol,\n            ArrayList<Integer> result) {\n        // O(n) time | O(n) space;\n        if(startRow > endRow || startCol > endCol) return;\n\n        for(int col = startCol; col <= endCol; col++)\n            result.add(array[startRow][col]);\n        for(int row = startRow + 1; row <= endRow; row++)\n            result.add(array[row][endCol]);\n        for(int col = endCol - 1; col >= startCol; col--) {\n            if(startRow == endRow) break;\n            result.add(array[endRow][col]);\n        }\n        for(int row = endRow - 1; row > startRow; row--) {\n            if(startCol == endCol) break;\n            result.add(array[row][startCol]);\n        }\n        spiralFillUsingRecursion(array, startRow + 1, endRow -1, startCol + 1, endCol - 1, result);\n    }\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/spiral_traverse.py",
    "content": "##### LEETCODE 54. Spiral Matrix ####\n\n##### INPUT OUTPUT #####\n\n# Given an m x n matrix, return all elements of the matrix in spiral order.\n# Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]\n# Output: [1,2,3,6,9,8,7,4,5]\n# Input: matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]\n# Output: [1,2,3,4,8,12,11,10,9,5,6,7]\n# Write python code along with explanation and comments use meaningful variables\n\n##### EXPLAINATION #####\n\n# The given problem statement is to return all elements of the matrix in spiral order. We can start by defining the four boundaries of the matrix - top, bottom, left and right. We can then traverse the matrix in a spiral order by following these four steps:\n\n# Traverse from left to right along the top boundary\n# Traverse from top to bottom along the right boundary\n# Traverse from right to left along the bottom boundary\n# Traverse from bottom to top along the left boundary\n# After each traversal, we need to update the corresponding boundary and change the direction of traversal.\n\n# We can implement this algorithm using a while loop that runs as long as the top boundary is less than or equal to the bottom boundary and the left boundary is less than or equal to the right boundary. Within the while loop, we can use an if-else ladder to check the current direction of traversal and perform the corresponding traversal along the boundary.\n\n# Finally, we can return the result list containing all the spiral order elements of the matrix.\n\n\n#### DRY RUN: ####\n\n# Initially, we have the matrix:\n# 1 2 3\n# 4 5 6\n# 7 8 9\n\n# We initialize the variables top, bottom, left, and right to 0, 2, 0, and 2 respectively. We also set the direction variable to 0.\n# Now, we enter the while loop since top<=bottom and left<=right.\n# In the first iteration of the while loop, direction=0 means we need to traverse from left to right along the top boundary.\n# We iterate the for loop from left=0 to right=2 and append the elements 1, 2, 3 to the result list. After this, we increment top by 1 to mark that the top boundary is now done.\n# The result list now contains [1, 2, 3].\n# In the second iteration of the while loop, direction=1 means we need to traverse from top to bottom along the right boundary.\n# We iterate the for loop from top=1 to bottom=2 and append the elements 6, 9 to the result list. After this, we decrement right by 1 to mark that the right boundary is now done.\n# The result list now contains [1, 2, 3, 6, 9].\n# In the third iteration of the while loop, direction=2 means we need to traverse from right to left along the bottom boundary.\n# We iterate the for loop from right=1 to left=0 and append the elements 8, 7 to the result list. After this, we decrement bottom by 1 to mark that the bottom boundary is now done.\n# The result list now contains [1, 2, 3, 6, 9, 8, 7].\n# In the fourth iteration of the while loop, direction=3 means we need to traverse from bottom to top along the left boundary.\n# We iterate the for loop from bottom=1 to top=1 and append the element 4 and 5 to the result list. After this, we increment left by 1 to mark that the left boundary is now done.\n# The result list now contains [1, 2, 3, 6, 9, 8, 7, 4, 5].\n# Now, we have completed one full spiral traversal of the matrix. The direction variable is updated as (0+1)%4=1 which sets it to 1 for the next iteration.\n# We continue with the while loop since top<=bottom and left<=right. In the second iteration, the process continues in the same way as described above until all elements of the matrix are visited.\n# Finally, the function returns the result list containing all the spiral order elements of the matrix.\n\ndef spiralOrder(matrix):\n    # Initialize variables to keep track of indices and boundaries\n    top, bottom = 0, len(matrix) - 1\n    left, right = 0, len(matrix[0]) - 1\n    direction = 0  # 0 = right, 1 = down, 2 = left, 3 = up\n\n    # Initialize an empty result list to store the spiral order elements\n    result = []\n\n    while top <= bottom and left <= right:\n        if direction == 0:\n            # Traverse right\n            for i in range(left, right+1):\n                result.append(matrix[top][i])\n            top += 1\n        elif direction == 1:\n            # Traverse down\n            for i in range(top, bottom+1):\n                result.append(matrix[i][right])\n            right -= 1\n        elif direction == 2:\n            # Traverse left\n            for i in range(right, left-1, -1):\n                result.append(matrix[bottom][i])\n            bottom -= 1\n        else:\n            # Traverse up\n            for i in range(bottom, top-1, -1):\n                result.append(matrix[i][left])\n            left += 1\n\n        # Update direction after completing one full traversal\n        direction = (direction + 1) % 4\n\n    return result\n\n\nmatrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\nprint(spiralOrder(matrix))\n"
  },
  {
    "path": "2D Arrays (Matrix)/zigzag_traversal.cpp",
    "content": "/*\n\n\tWrite a function that takes in an n x m two-dimensional array (that can be square-shaped when n == m)\n\tand returns a one-dimensional array of all the array's elements in zigzag order.\n\n\tSample Input:= [\n\t\t[1,  3,  4, 10],\n\t\t[2,  5,  9, 11],\n\t\t[6,  8, 12, 15],\n\t\t[7, 13, 14, 16],\n\t]\n\tOutput: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]\n\n\tExplanation:\n\tThe given code snippet implements the ZigzagTraverse algorithm, which traverses a 2D array in a zigzag pattern and\n\treturns the elements in a 1D array.\n\n\tHere's an explanation of the code:\n\n\t1. `ZigzagTraverse`: This is the main function that takes a 2D array `array` as input and returns a 1D array containing\n\t   the elements traversed in zigzag order.\n\n\t2. `height` and `width`: These variables store the height and width of the 2D array, respectively.\n\t   The `height` represents the number of rows (minus 1 as it is 0-based indexing), and the `width` represents the number of columns (minus 1 as it is 0-based indexing).\n\n\t3. `row` and `col`: These variables keep track of the current position while traversing the 2D array.\n\n\t4. `goingDown`: This boolean variable determines the direction of traversal. When `goingDown` is `true`, the traversal\n\t   is in the downward direction; otherwise, it is in the upward direction.\n\n\t5. `result`: This array stores the elements of the 2D array in zigzag order, which will be returned as the final result.\n\n\t6. The main loop: The loop runs until the current position is within bounds (not out of the 2D array).\n\n\t7. Append element to result: The code appends the current element at position `(row, col)` to the `result` array.\n\n\t8. Traversal logic: The algorithm decides the next position for traversal based on the current position and the `goingDown` flag.\n\t   If `goingDown` is `true`, it will traverse diagonally downwards (towards the bottom-right or the bottom-left corner, depending on the position). Otherwise, it will traverse diagonally upwards (towards the top-right or the top-left corner, depending on the position).\n\n\t9. `isOutOfBounds`: This is a helper function that checks if the current position `(row, col)` is out of bounds of the\n\t   2D array (i.e., if `row` or `col` is less than 0 or greater than the height or width, respectively).\n\n\t10. Return result: After the traversal is complete, the function returns the `result` array, which contains the elements of\n\t   the 2D array in zigzag order.\n\n\tThe ZigzagTraverse algorithm efficiently zigzags through the 2D array by changing the direction of traversal whenever it reaches\n\tthe boundary or the corners of the array, allowing it to cover all elements in zigzag order.\n\n\tO(n) time | O(n) space - where n is the total number of elements in the two-dimensional array\n*/\n\n#include <vector>\n\nusing namespace std;\n\nvector<int> ZigzagTraverse(vector<vector<int>>& array) {\n    // Get the height (number of rows) and width (number of columns) of the array.\n    int height = array.size();\n    int width = array[0].size();\n\n    // Initialize the row and column pointers to start from the top-left element (0,0).\n    int row = 0;\n    int col = 0;\n\n    // Initialize a flag to track the direction of traversal (goingDown).\n    // true means moving down, false means moving up.\n    bool goingDown = true;\n\n    // Initialize a vector to store the elements in zigzag order.\n    vector<int> result;\n\n    // Loop until the current position is within the bounds of the array.\n    while (!isOutOfBounds(row, col, height, width)) {\n        // Append the current element to the result vector.\n        result.push_back(array[row][col]);\n\n        // If moving down, check if we reached the bottom row or leftmost column.\n        if (goingDown) {\n            if (col == 0 || row == height - 1) {\n                // Change direction if we reached the bottom row or leftmost column.\n                goingDown = false;\n                if (row == height - 1) {\n                    // Move right if we reached the bottom row.\n                    col++;\n                } else {\n                    // Move down if we reached the leftmost column.\n                    row++;\n                }\n            } else {\n                // Move diagonally down-left.\n                row++;\n                col--;\n            }\n        } else {\n            // If moving up, check if we reached the top row or rightmost column.\n            if (row == 0 || col == width - 1) {\n                // Change direction if we reached the top row or rightmost column.\n                goingDown = true;\n                if (col == width - 1) {\n                    // Move down if we reached the rightmost column.\n                    row++;\n                } else {\n                    // Move right if we reached the top row.\n                    col++;\n                }\n            } else {\n                // Move diagonally up-right.\n                row--;\n                col++;\n            }\n        }\n    }\n\n    // Return the vector containing the elements in zigzag order.\n    return result;\n}\n\nbool isOutOfBounds(int row, int col, int height, int width) {\n    // Check if the current position is outside the bounds of the array.\n    return row < 0 || col < 0 || row >= height || col >= width;\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/zigzag_traversal.go",
    "content": "/*\n\n\tWrite a function that takes in an n x m two-dimensional array (that can be square-shaped when n == m)\n\tand returns a one-dimensional array of all the array's elements in zigzag order.\n\n\tSample Input:= [\n\t\t[1,  3,  4, 10],\n\t\t[2,  5,  9, 11],\n\t\t[6,  8, 12, 15],\n\t\t[7, 13, 14, 16],\n\t]\n\tOutput: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]\n\n\tExplanation:\n\tThe given code snippet implements the ZigzagTraverse algorithm, which traverses a 2D array in a zigzag pattern and\n\treturns the elements in a 1D array.\n\n\tHere's an explanation of the code:\n\n\t1. `ZigzagTraverse`: This is the main function that takes a 2D array `array` as input and returns a 1D array containing\n\t   the elements traversed in zigzag order.\n\n\t2. `height` and `width`: These variables store the height and width of the 2D array, respectively.\n\t   The `height` represents the number of rows (minus 1 as it is 0-based indexing), and the `width` represents the number of columns (minus 1 as it is 0-based indexing).\n\n\t3. `row` and `col`: These variables keep track of the current position while traversing the 2D array.\n\n\t4. `goingDown`: This boolean variable determines the direction of traversal. When `goingDown` is `true`, the traversal\n\t   is in the downward direction; otherwise, it is in the upward direction.\n\n\t5. `result`: This array stores the elements of the 2D array in zigzag order, which will be returned as the final result.\n\n\t6. The main loop: The loop runs until the current position is within bounds (not out of the 2D array).\n\n\t7. Append element to result: The code appends the current element at position `(row, col)` to the `result` array.\n\n\t8. Traversal logic: The algorithm decides the next position for traversal based on the current position and the `goingDown` flag.\n\t   If `goingDown` is `true`, it will traverse diagonally downwards (towards the bottom-right or the bottom-left corner, depending on the position). Otherwise, it will traverse diagonally upwards (towards the top-right or the top-left corner, depending on the position).\n\n\t9. `isOutOfBounds`: This is a helper function that checks if the current position `(row, col)` is out of bounds of the\n\t   2D array (i.e., if `row` or `col` is less than 0 or greater than the height or width, respectively).\n\n\t10. Return result: After the traversal is complete, the function returns the `result` array, which contains the elements of\n\t   the 2D array in zigzag order.\n\n\tThe ZigzagTraverse algorithm efficiently zigzags through the 2D array by changing the direction of traversal whenever it reaches\n\tthe boundary or the corners of the array, allowing it to cover all elements in zigzag order.\n\n\tO(n) time | O(n) space - where n is the total number of elements in the two-dimensional array\n*/\npackage main\n\n// ZigzagTraverse traverses a 2D array in a zigzag pattern and returns the elements in a 1D array.\nfunc ZigzagTraverse(array [][]int) []int {\n\t// Get the height and width of the 2D array.\n\theight := len(array) - 1\n\twidth := len(array[0]) - 1\n\n\t// Initialize variables to keep track of the current position while traversing.\n\trow, col := 0, 0\n\n\t// Initialize a boolean variable to determine the direction of traversal.\n\tgoingDown := true\n\n\t// Initialize an array to store the elements traversed in zigzag order.\n\tresult := []int{}\n\n\t// The main loop runs until the current position is within bounds (not out of the 2D array).\n\tfor !isOutOfBounds(row, col, height, width) {\n\t\t// Append the current element at position (row, col) to the result array.\n\t\tresult = append(result, array[row][col])\n\n\t\t// Traversal logic: Decide the next position for traversal based on the current position and the goingDown flag.\n\t\tif goingDown {\n\t\t\tif col == 0 || row == height {\n\t\t\t\t// Change direction to upward if at the top-left or bottom-right corner.\n\t\t\t\tgoingDown = false\n\n\t\t\t\t// Decide the next position based on whether we are at the bottom or right boundary.\n\t\t\t\tif row == height {\n\t\t\t\t\tcol++\n\t\t\t\t} else {\n\t\t\t\t\trow++\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Continue diagonally downward.\n\t\t\t\trow++\n\t\t\t\tcol--\n\t\t\t}\n\t\t} else {\n\t\t\tif row == 0 || col == width {\n\t\t\t\t// Change direction to downward if at the top-right or bottom-left corner.\n\t\t\t\tgoingDown = true\n\n\t\t\t\t// Decide the next position based on whether we are at the top or right boundary.\n\t\t\t\tif col == width {\n\t\t\t\t\trow++\n\t\t\t\t} else {\n\t\t\t\t\tcol++\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Continue diagonally upward.\n\t\t\t\trow--\n\t\t\t\tcol++\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the final result, which contains the elements of the 2D array in zigzag order.\n\treturn result\n}\n\n// isOutOfBounds checks if the current position (row, col) is out of bounds of the 2D array.\nfunc isOutOfBounds(row, col, height, width int) bool {\n\treturn row < 0 || col < 0 || row > height || col > width\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/zigzag_traversal.java",
    "content": "/*\n\n\tWrite a function that takes in an n x m two-dimensional array (that can be square-shaped when n == m)\n\tand returns a one-dimensional array of all the array's elements in zigzag order.\n\n\tSample Input:= [\n\t\t[1,  3,  4, 10],\n\t\t[2,  5,  9, 11],\n\t\t[6,  8, 12, 15],\n\t\t[7, 13, 14, 16],\n\t]\n\tOutput: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]\n\n\tExplanation:\n\tThe given code snippet implements the ZigzagTraverse algorithm, which traverses a 2D array in a zigzag pattern and\n\treturns the elements in a 1D array.\n\n\tHere's an explanation of the code:\n\n\t1. `ZigzagTraverse`: This is the main function that takes a 2D array `array` as input and returns a 1D array containing\n\t   the elements traversed in zigzag order.\n\n\t2. `height` and `width`: These variables store the height and width of the 2D array, respectively.\n\t   The `height` represents the number of rows (minus 1 as it is 0-based indexing), and the `width` represents the number of columns (minus 1 as it is 0-based indexing).\n\n\t3. `row` and `col`: These variables keep track of the current position while traversing the 2D array.\n\n\t4. `goingDown`: This boolean variable determines the direction of traversal. When `goingDown` is `true`, the traversal\n\t   is in the downward direction; otherwise, it is in the upward direction.\n\n\t5. `result`: This array stores the elements of the 2D array in zigzag order, which will be returned as the final result.\n\n\t6. The main loop: The loop runs until the current position is within bounds (not out of the 2D array).\n\n\t7. Append element to result: The code appends the current element at position `(row, col)` to the `result` array.\n\n\t8. Traversal logic: The algorithm decides the next position for traversal based on the current position and the `goingDown` flag.\n\t   If `goingDown` is `true`, it will traverse diagonally downwards (towards the bottom-right or the bottom-left corner, depending on the position). Otherwise, it will traverse diagonally upwards (towards the top-right or the top-left corner, depending on the position).\n\n\t9. `isOutOfBounds`: This is a helper function that checks if the current position `(row, col)` is out of bounds of the\n\t   2D array (i.e., if `row` or `col` is less than 0 or greater than the height or width, respectively).\n\n\t10. Return result: After the traversal is complete, the function returns the `result` array, which contains the elements of\n\t   the 2D array in zigzag order.\n\n\tThe ZigzagTraverse algorithm efficiently zigzags through the 2D array by changing the direction of traversal whenever it reaches\n\tthe boundary or the corners of the array, allowing it to cover all elements in zigzag order.\n\n\tO(n) time | O(n) space - where n is the total number of elements in the two-dimensional array\n*/\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class Main {\n\n    public static List<Integer> ZigzagTraverse(int[][] array) {\n        // Get the height (number of rows) and width (number of columns) of the array.\n        int height = array.length;\n        int width = array[0].length;\n\n        // Initialize the row and column pointers to start from the top-left element (0,0).\n        int row = 0;\n        int col = 0;\n\n        // Initialize a flag to track the direction of traversal (goingDown).\n        // true means moving down, false means moving up.\n        boolean goingDown = true;\n\n        // Initialize a list to store the elements in zigzag order.\n        List<Integer> result = new ArrayList<>();\n\n        // Loop until the current position is within the bounds of the array.\n        while (!isOutOfBounds(row, col, height, width)) {\n            // Append the current element to the result list.\n            result.add(array[row][col]);\n\n            // If moving down, check if we reached the bottom row or leftmost column.\n            if (goingDown) {\n                if (col == 0 || row == height - 1) {\n                    // Change direction if we reached the bottom row or leftmost column.\n                    goingDown = false;\n                    if (row == height - 1) {\n                        // Move right if we reached the bottom row.\n                        col++;\n                    } else {\n                        // Move down if we reached the leftmost column.\n                        row++;\n                    }\n                } else {\n                    // Move diagonally down-left.\n                    row++;\n                    col--;\n                }\n            } else {\n                // If moving up, check if we reached the top row or rightmost column.\n                if (row == 0 || col == width - 1) {\n                    // Change direction if we reached the top row or rightmost column.\n                    goingDown = true;\n                    if (col == width - 1) {\n                        // Move down if we reached the rightmost column.\n                        row++;\n                    } else {\n                        // Move right if we reached the top row.\n                        col++;\n                    }\n                } else {\n                    // Move diagonally up-right.\n                    row--;\n                    col++;\n                }\n            }\n        }\n\n        // Return the list containing the elements in zigzag order.\n        return result;\n    }\n\n    public static boolean isOutOfBounds(int row, int col, int height, int width) {\n        // Check if the current position is outside the bounds of the array.\n        return row < 0 || col < 0 || row >= height || col >= width;\n    }\n\n    public static void main(String[] args) {\n        int[][] array = {\n                {1, 3, 4, 10},\n                {2, 5, 9, 11},\n                {6, 8, 12, 15},\n                {7, 13, 14, 16}\n        };\n\n        List<Integer> result = ZigzagTraverse(array);\n        System.out.println(result);\n    }\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/zigzag_traversal.js",
    "content": "/*\n\n\tWrite a function that takes in an n x m two-dimensional array (that can be square-shaped when n == m)\n\tand returns a one-dimensional array of all the array's elements in zigzag order.\n\n\tSample Input:= [\n\t\t[1,  3,  4, 10],\n\t\t[2,  5,  9, 11],\n\t\t[6,  8, 12, 15],\n\t\t[7, 13, 14, 16],\n\t]\n\tOutput: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]\n\n\tExplanation:\n\tThe given code snippet implements the ZigzagTraverse algorithm, which traverses a 2D array in a zigzag pattern and\n\treturns the elements in a 1D array.\n\n\tHere's an explanation of the code:\n\n\t1. `ZigzagTraverse`: This is the main function that takes a 2D array `array` as input and returns a 1D array containing\n\t   the elements traversed in zigzag order.\n\n\t2. `height` and `width`: These variables store the height and width of the 2D array, respectively.\n\t   The `height` represents the number of rows (minus 1 as it is 0-based indexing), and the `width` represents the number of columns (minus 1 as it is 0-based indexing).\n\n\t3. `row` and `col`: These variables keep track of the current position while traversing the 2D array.\n\n\t4. `goingDown`: This boolean variable determines the direction of traversal. When `goingDown` is `true`, the traversal\n\t   is in the downward direction; otherwise, it is in the upward direction.\n\n\t5. `result`: This array stores the elements of the 2D array in zigzag order, which will be returned as the final result.\n\n\t6. The main loop: The loop runs until the current position is within bounds (not out of the 2D array).\n\n\t7. Append element to result: The code appends the current element at position `(row, col)` to the `result` array.\n\n\t8. Traversal logic: The algorithm decides the next position for traversal based on the current position and the `goingDown` flag.\n\t   If `goingDown` is `true`, it will traverse diagonally downwards (towards the bottom-right or the bottom-left corner, depending on the position). Otherwise, it will traverse diagonally upwards (towards the top-right or the top-left corner, depending on the position).\n\n\t9. `isOutOfBounds`: This is a helper function that checks if the current position `(row, col)` is out of bounds of the\n\t   2D array (i.e., if `row` or `col` is less than 0 or greater than the height or width, respectively).\n\n\t10. Return result: After the traversal is complete, the function returns the `result` array, which contains the elements of\n\t   the 2D array in zigzag order.\n\n\tThe ZigzagTraverse algorithm efficiently zigzags through the 2D array by changing the direction of traversal whenever it reaches\n\tthe boundary or the corners of the array, allowing it to cover all elements in zigzag order.\n\n\tO(n) time | O(n) space - where n is the total number of elements in the two-dimensional array\n*/\nfunction ZigzagTraverse(array) {\n  // Get the height (number of rows) and width (number of columns) of the array.\n  const height = array.length;\n  const width = array[0].length;\n\n  // Initialize the row and column pointers to start from the top-left element (0,0).\n  let row = 0;\n  let col = 0;\n\n  // Initialize a flag to track the direction of traversal (goingDown).\n  // true means moving down, false means moving up.\n  let goingDown = true;\n\n  // Initialize an array to store the elements in zigzag order.\n  const result = [];\n\n  // Loop until the current position is within the bounds of the array.\n  while (!isOutOfBounds(row, col, height, width)) {\n    // Append the current element to the result array.\n    result.push(array[row][col]);\n\n    // If moving down, check if we reached the bottom row or leftmost column.\n    if (goingDown) {\n      if (col === 0 || row === height - 1) {\n        // Change direction if we reached the bottom row or leftmost column.\n        goingDown = false;\n        if (row === height - 1) {\n          // Move right if we reached the bottom row.\n          col++;\n        } else {\n          // Move down if we reached the leftmost column.\n          row++;\n        }\n      } else {\n        // Move diagonally down-left.\n        row++;\n        col--;\n      }\n    } else {\n      // If moving up, check if we reached the top row or rightmost column.\n      if (row === 0 || col === width - 1) {\n        // Change direction if we reached the top row or rightmost column.\n        goingDown = true;\n        if (col === width - 1) {\n          // Move down if we reached the rightmost column.\n          row++;\n        } else {\n          // Move right if we reached the top row.\n          col++;\n        }\n      } else {\n        // Move diagonally up-right.\n        row--;\n        col++;\n      }\n    }\n  }\n\n  // Return the array containing the elements in zigzag order.\n  return result;\n}\n\nfunction isOutOfBounds(row, col, height, width) {\n  // Check if the current position is outside the bounds of the array.\n  return row < 0 || col < 0 || row >= height || col >= width;\n}\n"
  },
  {
    "path": "2D Arrays (Matrix)/zigzag_traversal.py",
    "content": "'''\n\n\tWrite a function that takes in an n x m two-dimensional array (that can be square-shaped when n == m)\n\tand returns a one-dimensional array of all the array's elements in zigzag order.\n\n\tSample Input:= [\n\t\t[1,  3,  4, 10],\n\t\t[2,  5,  9, 11],\n\t\t[6,  8, 12, 15],\n\t\t[7, 13, 14, 16],\n\t]\n\tOutput: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]\n\n\tExplanation:\n\tThe given code snippet implements the ZigzagTraverse algorithm, which traverses a 2D array in a zigzag pattern and\n\treturns the elements in a 1D array.\n\n\tHere's an explanation of the code:\n\n\t1. `ZigzagTraverse`: This is the main function that takes a 2D array `array` as input and returns a 1D array containing\n\t   the elements traversed in zigzag order.\n\n\t2. `height` and `width`: These variables store the height and width of the 2D array, respectively.\n\t   The `height` represents the number of rows (minus 1 as it is 0-based indexing), and the `width` represents the number of columns (minus 1 as it is 0-based indexing).\n\n\t3. `row` and `col`: These variables keep track of the current position while traversing the 2D array.\n\n\t4. `goingDown`: This boolean variable determines the direction of traversal. When `goingDown` is `true`, the traversal\n\t   is in the downward direction; otherwise, it is in the upward direction.\n\n\t5. `result`: This array stores the elements of the 2D array in zigzag order, which will be returned as the final result.\n\n\t6. The main loop: The loop runs until the current position is within bounds (not out of the 2D array).\n\n\t7. Append element to result: The code appends the current element at position `(row, col)` to the `result` array.\n\n\t8. Traversal logic: The algorithm decides the next position for traversal based on the current position and the `goingDown` flag.\n\t   If `goingDown` is `true`, it will traverse diagonally downwards (towards the bottom-right or the bottom-left corner, depending on the position). Otherwise, it will traverse diagonally upwards (towards the top-right or the top-left corner, depending on the position).\n\n\t9. `isOutOfBounds`: This is a helper function that checks if the current position `(row, col)` is out of bounds of the\n\t   2D array (i.e., if `row` or `col` is less than 0 or greater than the height or width, respectively).\n\n\t10. Return result: After the traversal is complete, the function returns the `result` array, which contains the elements of\n\t   the 2D array in zigzag order.\n\n\tThe ZigzagTraverse algorithm efficiently zigzags through the 2D array by changing the direction of traversal whenever it reaches\n\tthe boundary or the corners of the array, allowing it to cover all elements in zigzag order.\n\n\tO(n) time | O(n) space - where n is the total number of elements in the two-dimensional array\n'''\n\ndef ZigzagTraverse(array):\n    # Get the height (number of rows) and width (number of columns) of the array.\n    height = len(array)\n    width = len(array[0])\n\n    # Initialize the row and column pointers to start from the top-left element (0,0).\n    row, col = 0, 0\n\n    # Initialize a flag to track the direction of traversal (goingDown).\n    # True means moving down, False means moving up.\n    goingDown = True\n\n    # Initialize a list to store the elements in zigzag order.\n    result = []\n\n    # Loop until the current position is within the bounds of the array.\n    while not isOutOfBounds(row, col, height, width):\n        # Append the current element to the result list.\n        result.append(array[row][col])\n\n        # If moving down, check if we reached the bottom row or leftmost column.\n        if goingDown:\n            if col == 0 or row == height - 1:\n                # Change direction if we reached the bottom row or leftmost column.\n                goingDown = False\n                if row == height - 1:\n                    # Move right if we reached the bottom row.\n                    col += 1\n                else:\n                    # Move down if we reached the leftmost column.\n                    row += 1\n            else:\n                # Move diagonally down-left.\n                row += 1\n                col -= 1\n        else:\n            # If moving up, check if we reached the top row or rightmost column.\n            if row == 0 or col == width - 1:\n                # Change direction if we reached the top row or rightmost column.\n                goingDown = True\n                if col == width - 1:\n                    # Move down if we reached the rightmost column.\n                    row += 1\n                else:\n                    # Move right if we reached the top row.\n                    col += 1\n            else:\n                # Move diagonally up-right.\n                row -= 1\n                col += 1\n\n    # Return the list containing the elements in zigzag order.\n    return result\n\ndef isOutOfBounds(row, col, height, width):\n    # Check if the current position is outside the bounds of the array.\n    return row < 0 or col < 0 or row >= height or col >= width\n"
  },
  {
    "path": "Arrays/Jobassign.cpp",
    "content": "#include <stdio.h>\n#include <limits.h>\n\n#define N 4 // Number of workers and tasks\n\nvoid hungarianAlgorithm(int costMatrix[N][N]);\n\nint main() {\n    int costMatrix[N][N] = {\n        {9, 2, 7, 8},\n        {6, 4, 3, 7},\n        {5, 8, 1, 8},\n        {7, 6, 9, 4}\n    };\n\n    hungarianAlgorithm(costMatrix);\n\n    return 0;\n}\n\nvoid hungarianAlgorithm(int costMatrix[N][N]) {\n    int i, j;\n    int numWorkers = N, numTasks = N;\n\n    int minCost, minCostIdx;\n    int rowCover[N] = {0};\n    int colCover[N] = {0};\n    int assignment[N][2] = {0}; // Stores the assignment\n\n    // Step 1: Subtract the smallest value in each row from all elements in that row\n    for (i = 0; i < numWorkers; i++) {\n        minCost = INT_MAX;\n        for (j = 0; j < numTasks; j++) {\n            if (costMatrix[i][j] < minCost) {\n                minCost = costMatrix[i][j];\n            }\n        }\n        for (j = 0; j < numTasks; j++) {\n            costMatrix[i][j] -= minCost;\n        }\n    }\n\n    // Step 2: Find a zero in the cost matrix and mark the row and column\n    for (i = 0; i < numWorkers; i++) {\n        for (j = 0; j < numTasks; j++) {\n            if (costMatrix[i][j] == 0 && !rowCover[i] && !colCover[j]) {\n                assignment[i][0] = i;\n                assignment[i][1] = j;\n                rowCover[i] = 1;\n                colCover[j] = 1;\n            }\n        }\n    }\n\n    // Step 3: Check if all rows are covered\n    int rowCoveredCount = 0;\n    for (i = 0; i < numWorkers; i++) {\n        rowCoveredCount += rowCover[i];\n    }\n\n    if (rowCoveredCount == numWorkers) {\n        // All rows are covered, we have the optimal assignment\n        printf(\"Optimal Assignment:\\n\");\n        for (i = 0; i < numWorkers; i++) {\n            printf(\"Worker %d -> Task %d\\n\", assignment[i][0] + 1, assignment[i][1] + 1);\n        }\n        return;\n    } else {\n        // Proceed to step 4\n    }\n    \n    // Step 4: Find the minimum uncovered value (minCost) in the cost matrix\n    minCost = INT_MAX;\n    for (i = 0; i < numWorkers; i++) {\n        for (j = 0; j < numTasks; j++) {\n            if (!rowCover[i] && !colCover[j] && costMatrix[i][j] < minCost) {\n                minCost = costMatrix[i][j];\n            }\n        }\n    }\n\n    // Step 5: Subtract minCost from all uncovered elements and add it to all elements at the intersection of covering lines\n    for (i = 0; i < numWorkers; i++) {\n        for (j = 0; j < numTasks; j++) {\n            if (!rowCover[i] && !colCover[j]) {\n                costMatrix[i][j] -= minCost;\n            } else if (rowCover[i] && colCover[j]) {\n                costMatrix[i][j] += minCost;\n            }\n        }\n    }\n\n    // Continue to step 3\n    hungarianAlgorithm(costMatrix);\n}\n"
  },
  {
    "path": "Arrays/Maximum_freq.py",
    "content": "class Solution {\n    public int majorityElement(int[] nums) {\n        int candidate = nums[0]; // Initialize the candidate as the first element\n        int count = 1; // Initialize the count of the current candidate as 1\n        \n        // Iterate through the array starting from the second element\n        for (int i = 1; i < nums.length; i++) {\n            if (nums[i] == candidate) {\n                // If the current element is the same as the candidate, increment the count\n                count++;\n            } else if (count > 0) {\n                // If the current element is different from the candidate and count is positive,\n                // decrement the count since we have a matching pair (candidate vs. current element)\n                count--;\n            } else {\n                // If count becomes zero, update the candidate to the current element and set count to 1\n                candidate = nums[i];\n                count = 1;\n            }\n        }\n        \n        // At the end, the candidate will be the majority element\n        return candidate;\n    }\n}\n"
  },
  {
    "path": "Arrays/Rotatedarr.cpp",
    "content": "class Solution {\npublic:\n    int search(std::vector<int>& nums, int target) {\n        int low = 0, high = nums.size() - 1;\n\n        while (low <= high) {\n            int mid = (low + high) / 2;\n\n            if (nums[mid] == target) {\n                return mid;\n            }\n\n            if (nums[low] <= nums[mid]) {\n                if (nums[low] <= target && target < nums[mid]) {\n                    high = mid - 1;\n                } else {\n                    low = mid + 1;\n                }\n            } else {\n                if (nums[mid] < target && target <= nums[high]) {\n                    low = mid + 1;\n                } else {\n                    high = mid - 1;\n                }\n            }\n        }\n\n        return -1;\n    }\n};\n"
  },
  {
    "path": "Arrays/array_of_products.cpp",
    "content": "/*\n\tGiven an array of integers A, find and return the product array of the same size where the ith\n\telement of the product array will be equal to the product of all the elements divided by the ith\n\telement of the array.\n\n\tNote: It is always possible to form the product array with integer (32 bit) values.\n\tSolve it without using the division operator.\n\n\tInput: [1, 2, 3, 4, 5]\n\tOutput : [120, 60, 40, 30, 24]\n\n\tExplanation:\n\tThe code snippet provides a function called `ArrayOfProducts` that takes an array of integers as input and returns another array where each element is the product of all the integers in the input array except for the one at that index. Here's how the code works:\n\n\t1. It initializes an empty result array with the same length as the input array to store the final products.\n\t2. It uses a left-to-right approach to compute the running product of all elements to the left of each index.\n\t3. It initializes a variable `leftRunningProduct` to keep track of the running product of elements on the left side.\n\t4. It iterates over the input array from left to right using a `for` loop.\n\t5. For each index `i`, it stores the current `leftRunningProduct` in the result array at index `i` and then updates the\n\t   `leftRunningProduct` by multiplying it with the corresponding element in the input array.\n\t6. After the loop, the result array will contain the product of all elements to the left of each index.\n\t7. It uses a right-to-left approach to compute the running product of all elements to the right of each index and\n\t   multiply it with the corresponding left product in the result array.\n\t8. It initializes a variable `rightRunningProduct` to keep track of the running product of elements on the right side.\n\t9. It iterates over the input array from right to left using a `for` loop.\n\t10. For each index `i`, it multiplies the `rightRunningProduct` with the corresponding left product in the result array\n\t   and updates the `rightRunningProduct` by multiplying it with the corresponding element in the input array.\n\t11. After the loop, the result array will contain the product of all elements to the left and right of each index,\n\t   except for the element at that index.\n\t12. Finally, it returns the result array.\n\n\tThis algorithm avoids using division and solves the problem in linear time complexity, making two passes over the input array. The space complexity is also linear, as it uses an additional array to store the products.\n*/\n\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\n// Given an array of integers, returns an array where each element\n// is the product of all the integers in the input array except for the one at that index.\nvector<int> ArrayOfProducts(vector<int>& array) {\n    int n = array.size();\n    vector<int> result(n, 1);\n\n    // Compute the running product of all elements to the left of each index\n    // and store it in the result array.\n    int leftRunningProduct = 1;\n    for (int i = 0; i < n; i++) {\n        result[i] = leftRunningProduct;  // Store left product in the result array\n        leftRunningProduct *= array[i];  // Update left product\n    }\n\n    // Compute the running product of all elements to the right of each index\n    // and multiply it with the corresponding left product in the result array.\n    int rightRunningProduct = 1;\n    for (int i = n - 1; i >= 0; i--) {\n        result[i] *= rightRunningProduct;  // Multiply the right product with the corresponding left product\n        rightRunningProduct *= array[i];   // Update right product\n    }\n\n    return result;\n}\n\nint main() {\n    // Example usage\n    vector<int> input = {1, 2, 3, 4, 5};\n    vector<int> output = ArrayOfProducts(input);\n\n    // Print the result\n    for (int num : output) {\n        cout << num << \" \";\n    }\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Arrays/array_of_products.go",
    "content": "/*\n\tGiven an array of integers A, find and return the product array of the same size where the ith\n\telement of the product array will be equal to the product of all the elements divided by the ith\n\telement of the array.\n\n\tNote: It is always possible to form the product array with integer (32 bit) values.\n\tSolve it without using the division operator.\n\n\tInput: [1, 2, 3, 4, 5]\n\tOutput : [120, 60, 40, 30, 24]\n\n\tExplanation:\n\tThe code snippet provides a function called `ArrayOfProducts` that takes an array of integers as input and returns another array where each element is the product of all the integers in the input array except for the one at that index. Here's how the code works:\n\n\t1. It initializes an empty result array with the same length as the input array to store the final products.\n\t2. It uses a left-to-right approach to compute the running product of all elements to the left of each index.\n\t3. It initializes a variable `leftRunningProduct` to keep track of the running product of elements on the left side.\n\t4. It iterates over the input array from left to right using a `for` loop.\n\t5. For each index `i`, it stores the current `leftRunningProduct` in the result array at index `i` and then updates the\n\t   `leftRunningProduct` by multiplying it with the corresponding element in the input array.\n\t6. After the loop, the result array will contain the product of all elements to the left of each index.\n\t7. It uses a right-to-left approach to compute the running product of all elements to the right of each index and\n\t   multiply it with the corresponding left product in the result array.\n\t8. It initializes a variable `rightRunningProduct` to keep track of the running product of elements on the right side.\n\t9. It iterates over the input array from right to left using a `for` loop.\n\t10. For each index `i`, it multiplies the `rightRunningProduct` with the corresponding left product in the result array\n\t   and updates the `rightRunningProduct` by multiplying it with the corresponding element in the input array.\n\t11. After the loop, the result array will contain the product of all elements to the left and right of each index,\n\t   except for the element at that index.\n\t12. Finally, it returns the result array.\n\n\tThis algorithm avoids using division and solves the problem in linear time complexity, making two passes over the input array. The space complexity is also linear, as it uses an additional array to store the products.\n*/\n\npackage main\n\n// Given an array of integers, returns an array where each element\n// is the product of all the integers in the input array except for the one at that index.\n func ArrayOfProducts(array []int) []int {\n\t result := make([]int, len(array))\n \n\t // Compute the running product of all elements to the left of each index\n\t // and store it in the result array.\n\t leftRunningProduct := 1\n\t for i := 0; i < len(array); i++ {\n\t\t result[i] = leftRunningProduct // Store left product in the result array\n\t\t leftRunningProduct *= array[i] // Update left product\n\t }\n \n\t // Compute the running product of all elements to the right of each index\n\t // and multiply it with the corresponding left product in the result array.\n\t rightRunningProduct := 1\n\t for i := len(array) - 1; i >= 0; i-- {\n\t\t result[i] = rightRunningProduct * result[i] // Multiply the right product with the corresponding left product\n\t\t rightRunningProduct *= array[i]             // Update right product\n\t }\n \n\t return result\n }\n \n"
  },
  {
    "path": "Arrays/array_of_products.java",
    "content": "/*\n\tGiven an array of integers A, find and return the product array of the same size where the ith\n\telement of the product array will be equal to the product of all the elements divided by the ith\n\telement of the array.\n\n\tNote: It is always possible to form the product array with integer (32 bit) values.\n\tSolve it without using the division operator.\n\n\tInput: [1, 2, 3, 4, 5]\n\tOutput : [120, 60, 40, 30, 24]\n\n\tExplanation:\n\tThe code snippet provides a function called `ArrayOfProducts` that takes an array of integers as input and returns another array where each element is the product of all the integers in the input array except for the one at that index. Here's how the code works:\n\n\t1. It initializes an empty result array with the same length as the input array to store the final products.\n\t2. It uses a left-to-right approach to compute the running product of all elements to the left of each index.\n\t3. It initializes a variable `leftRunningProduct` to keep track of the running product of elements on the left side.\n\t4. It iterates over the input array from left to right using a `for` loop.\n\t5. For each index `i`, it stores the current `leftRunningProduct` in the result array at index `i` and then updates the\n\t   `leftRunningProduct` by multiplying it with the corresponding element in the input array.\n\t6. After the loop, the result array will contain the product of all elements to the left of each index.\n\t7. It uses a right-to-left approach to compute the running product of all elements to the right of each index and\n\t   multiply it with the corresponding left product in the result array.\n\t8. It initializes a variable `rightRunningProduct` to keep track of the running product of elements on the right side.\n\t9. It iterates over the input array from right to left using a `for` loop.\n\t10. For each index `i`, it multiplies the `rightRunningProduct` with the corresponding left product in the result array\n\t   and updates the `rightRunningProduct` by multiplying it with the corresponding element in the input array.\n\t11. After the loop, the result array will contain the product of all elements to the left and right of each index,\n\t   except for the element at that index.\n\t12. Finally, it returns the result array.\n\n\tThis algorithm avoids using division and solves the problem in linear time complexity, making two passes over the input array. The space complexity is also linear, as it uses an additional array to store the products.\n*/\nimport java.util.Arrays;\n\npublic class ArrayOfProducts {\n    public static int[] arrayOfProducts(int[] array) {\n        int n = array.length;\n        int[] result = new int[n];\n\n        // Compute the running product of all elements to the left of each index\n        // and store it in the result array.\n        int leftRunningProduct = 1;\n        for (int i = 0; i < n; i++) {\n            result[i] = leftRunningProduct;  // Store left product in the result array\n            leftRunningProduct *= array[i];  // Update left product\n        }\n\n        // Compute the running product of all elements to the right of each index\n        // and multiply it with the corresponding left product in the result array.\n        int rightRunningProduct = 1;\n        for (int i = n - 1; i >= 0; i--) {\n            result[i] *= rightRunningProduct;  // Multiply the right product with the corresponding left product\n            rightRunningProduct *= array[i];   // Update right product\n        }\n\n        return result;\n    }\n\n    public static void main(String[] args) {\n        // Example usage\n        int[] input = {1, 2, 3, 4, 5};\n        int[] output = arrayOfProducts(input);\n\n        // Print the result\n        System.out.println(Arrays.toString(output));\n    }\n}\n"
  },
  {
    "path": "Arrays/array_of_products.js",
    "content": "/*\n\tGiven an array of integers A, find and return the product array of the same size where the ith\n\telement of the product array will be equal to the product of all the elements divided by the ith\n\telement of the array.\n\n\tNote: It is always possible to form the product array with integer (32 bit) values.\n\tSolve it without using the division operator.\n\n\tInput: [1, 2, 3, 4, 5]\n\tOutput : [120, 60, 40, 30, 24]\n\n\tExplanation:\n\tThe code snippet provides a function called `ArrayOfProducts` that takes an array of integers as input and returns another array where each element is the product of all the integers in the input array except for the one at that index. Here's how the code works:\n\n\t1. It initializes an empty result array with the same length as the input array to store the final products.\n\t2. It uses a left-to-right approach to compute the running product of all elements to the left of each index.\n\t3. It initializes a variable `leftRunningProduct` to keep track of the running product of elements on the left side.\n\t4. It iterates over the input array from left to right using a `for` loop.\n\t5. For each index `i`, it stores the current `leftRunningProduct` in the result array at index `i` and then updates the\n\t   `leftRunningProduct` by multiplying it with the corresponding element in the input array.\n\t6. After the loop, the result array will contain the product of all elements to the left of each index.\n\t7. It uses a right-to-left approach to compute the running product of all elements to the right of each index and\n\t   multiply it with the corresponding left product in the result array.\n\t8. It initializes a variable `rightRunningProduct` to keep track of the running product of elements on the right side.\n\t9. It iterates over the input array from right to left using a `for` loop.\n\t10. For each index `i`, it multiplies the `rightRunningProduct` with the corresponding left product in the result array\n\t   and updates the `rightRunningProduct` by multiplying it with the corresponding element in the input array.\n\t11. After the loop, the result array will contain the product of all elements to the left and right of each index,\n\t   except for the element at that index.\n\t12. Finally, it returns the result array.\n\n\tThis algorithm avoids using division and solves the problem in linear time complexity, making two passes over the input array. The space complexity is also linear, as it uses an additional array to store the products.\n*/\nfunction arrayOfProducts(array) {\n  const n = array.length;\n  const result = new Array(n).fill(1);\n\n  // Compute the running product of all elements to the left of each index\n  // and store it in the result array.\n  let leftRunningProduct = 1;\n  for (let i = 0; i < n; i++) {\n    result[i] = leftRunningProduct; // Store left product in the result array\n    leftRunningProduct *= array[i]; // Update left product\n  }\n\n  // Compute the running product of all elements to the right of each index\n  // and multiply it with the corresponding left product in the result array.\n  let rightRunningProduct = 1;\n  for (let i = n - 1; i >= 0; i--) {\n    result[i] *= rightRunningProduct; // Multiply the right product with the corresponding left product\n    rightRunningProduct *= array[i]; // Update right product\n  }\n\n  return result;\n}\n\n// Example usage\nconst inputArray = [1, 2, 3, 4, 5];\nconst outputArray = arrayOfProducts(inputArray);\n\n// Print the result\nconsole.log(outputArray);\n"
  },
  {
    "path": "Arrays/array_of_products.py",
    "content": "'''\n\tGiven an array of integers A, find and return the product array of the same size where the ith\n\telement of the product array will be equal to the product of all the elements divided by the ith\n\telement of the array.\n\n\tNote: It is always possible to form the product array with integer (32 bit) values.\n\tSolve it without using the division operator.\n\n\tInput: [1, 2, 3, 4, 5]\n\tOutput : [120, 60, 40, 30, 24]\n\n\tExplanation:\n\tThe code snippet provides a function called `ArrayOfProducts` that takes an array of integers as input and returns another array where each element is the product of all the integers in the input array except for the one at that index. Here's how the code works:\n\n\t1. It initializes an empty result array with the same length as the input array to store the final products.\n\t2. It uses a left-to-right approach to compute the running product of all elements to the left of each index.\n\t3. It initializes a variable `leftRunningProduct` to keep track of the running product of elements on the left side.\n\t4. It iterates over the input array from left to right using a `for` loop.\n\t5. For each index `i`, it stores the current `leftRunningProduct` in the result array at index `i` and then updates the\n\t   `leftRunningProduct` by multiplying it with the corresponding element in the input array.\n\t6. After the loop, the result array will contain the product of all elements to the left of each index.\n\t7. It uses a right-to-left approach to compute the running product of all elements to the right of each index and\n\t   multiply it with the corresponding left product in the result array.\n\t8. It initializes a variable `rightRunningProduct` to keep track of the running product of elements on the right side.\n\t9. It iterates over the input array from right to left using a `for` loop.\n\t10. For each index `i`, it multiplies the `rightRunningProduct` with the corresponding left product in the result array\n\t   and updates the `rightRunningProduct` by multiplying it with the corresponding element in the input array.\n\t11. After the loop, the result array will contain the product of all elements to the left and right of each index,\n\t   except for the element at that index.\n\t12. Finally, it returns the result array.\n\n\tThis algorithm avoids using division and solves the problem in linear time complexity, making two passes over the input array. The space complexity is also linear, as it uses an additional array to store the products.\n'''\ndef array_of_products(array):\n    n = len(array)\n    result = [1] * n\n\n    # Compute the running product of all elements to the left of each index\n    # and store it in the result array.\n    left_running_product = 1\n    for i in range(n):\n        result[i] = left_running_product  # Store left product in the result array\n        left_running_product *= array[i]  # Update left product\n\n    # Compute the running product of all elements to the right of each index\n    # and multiply it with the corresponding left product in the result array.\n    right_running_product = 1\n    for i in range(n - 1, -1, -1):\n        result[i] *= right_running_product  # Multiply the right product with the corresponding left product\n        right_running_product *= array[i]   # Update right product\n\n    return result\n\n# Example usage\ninput_array = [1, 2, 3, 4, 5]\noutput_array = array_of_products(input_array)\n\n# Print the result\nprint(output_array)\n"
  },
  {
    "path": "Arrays/ceaser_cipher.cpp",
    "content": "/*\n    Given a non-empty string of lowercase letters and a non-negative integer\n    representing a key, write a function that returns a new string obtained by\n    shifting every letter in the input string by k positions in the alphabet,\n    where k is the key.\n\n    Note that letters should \"wrap\" around the alphabet; in other words, the\n    letter z shifted by one returns the letter a\n\n    Sample Input : abz key: 3\n    Output: dec\n\n    Explanation:\n\n    The CaesarCipherEncryptor function takes a string and a key (integer) as input and returns a new string\n    obtained by shifting each character of the input string by the key number of positions to the right in\n    the alphabet, wrapping around if necessary.\n\n    The function first calculates the shift amount and offset value. The shift amount is calculated by taking\n    the key modulo 26, which ensures that the shift amount is always within the range of 0 to 25. The offset\n    value is calculated by taking 26, which is the number of letters in the alphabet.\n\n    The function then converts the input string to a rune slice (for ease of manipulation). A rune is a single\n    character in a programming language. The rune type is used to represent characters in Go.\n\n    The function then iterates over each character in the rune slice. For each character, the function checks\n\n    if the character is a lowercase letter and if shifting it will still be within the lowercase range.\n\n    If the character is a lowercase letter and shifting it will still be within the lowercase range, the\n    function simply adds the shift amount to the character. If the character is outside of the lowercase range after shifting, the function wraps it around by adding the shift amount - offset to the character.\n\n    The function then updates the character in the rune slice.\n\n    The function then converts the resulting rune slice back to a string and returns it.\n\n    The time complexity of the CaesarCipherEncryptor function is O(n), where n is the length of the input string.\n    This is because the function iterates over each character in the input string, performing a constant amount\n    of work for each character.\n\n    The space complexity of the CaesarCipherEncryptor function is O(n), where n is the length of the input string.\n    This is because the function creates a new rune slice to store the encrypted string. The rune slice is the\n    same size as the input string, so the space complexity is O(n).\n*/\n// C++\n\n#include <iostream>\n#include <string>\n\nusing namespace std;\n\nstring CaesarCipherEncryptor(string str, int key) {\n  // Calculate the shift amount and offset value\n  int shift = key % 26;\n  int offset = 26;\n\n  // Convert the input string to a vector of characters\n  vector<char> chars(str.begin(), str.end());\n\n  // Iterate over each character in the vector\n  for (int i = 0; i < chars.size(); i++) {\n    // If the character is a lowercase letter and shifting it will still be within the lowercase range\n    if (chars[i] >= 'a' && chars[i] + shift <= 'z') {\n      chars[i] += shift;\n    } else {\n      // If the character is outside of the lowercase range after shifting, wrap it around\n      chars[i] += shift - offset;\n    }\n  }\n\n  // Convert the resulting vector of characters back to a string and return it\n  return string(chars.begin(), chars.end());\n}\n\nint main() {\n  // Get the input string and key from the user\n  string str;\n  cout << \"Enter a string: \";\n  cin >> str;\n\n  int key;\n  cout << \"Enter a key: \";\n  cin >> key;\n\n  // Encrypt the string using the Caesar cipher\n  string encrypted_str = CaesarCipherEncryptor(str, key);\n\n  // Print the encrypted string\n  cout << \"Encrypted string: \" << encrypted_str << endl;\n\n  return 0;\n}\n"
  },
  {
    "path": "Arrays/ceaser_cipher.go",
    "content": "/*\n\tGiven a non-empty string of lowercase letters and a non-negative integer\n\trepresenting a key, write a function that returns a new string obtained by\n\tshifting every letter in the input string by k positions in the alphabet,\n\twhere k is the key.\n\n\tNote that letters should \"wrap\" around the alphabet; in other words, the\n\tletter z shifted by one returns the letter a\n\n\tSample Input : abz key: 3\n\tOutput: dec\n\n\tExplanation:\n\n\tThe CaesarCipherEncryptor function takes a string and a key (integer) as input and returns a new string\n\tobtained by shifting each character of the input string by the key number of positions to the right in\n\tthe alphabet, wrapping around if necessary.\n\n\tThe function first calculates the shift amount and offset value. The shift amount is calculated by taking\n\tthe key modulo 26, which ensures that the shift amount is always within the range of 0 to 25. The offset\n\tvalue is calculated by taking 26, which is the number of letters in the alphabet.\n\n\tThe function then converts the input string to a rune slice (for ease of manipulation). A rune is a single\n\tcharacter in a programming language. The rune type is used to represent characters in Go.\n\n\tThe function then iterates over each character in the rune slice. For each character, the function checks\n\n\tif the character is a lowercase letter and if shifting it will still be within the lowercase range.\n\n\tIf the character is a lowercase letter and shifting it will still be within the lowercase range, the\n\tfunction simply adds the shift amount to the character. If the character is outside of the lowercase range after shifting, the function wraps it around by adding the shift amount - offset to the character.\n\n\tThe function then updates the character in the rune slice.\n\n\tThe function then converts the resulting rune slice back to a string and returns it.\n\n\tThe time complexity of the CaesarCipherEncryptor function is O(n), where n is the length of the input string.\n\tThis is because the function iterates over each character in the input string, performing a constant amount\n\tof work for each character.\n\n\tThe space complexity of the CaesarCipherEncryptor function is O(n), where n is the length of the input string.\n\tThis is because the function creates a new rune slice to store the encrypted string. The rune slice is the\n\tsame size as the input string, so the space complexity is O(n).\n*/\npackage main\n\n// CaesarCipherEncryptor takes a string and a key (integer) as input and returns\n// a new string obtained by shifting each character of the input string by the\n// key number of positions to the right in the alphabet, wrapping around if necessary.\nfunc CaesarCipherEncryptor(str string, key int) string {\n\t// Calculate the shift amount and offset value\n\tshift, offset := rune(key % 26), rune(26)\n\t\n\t// Convert the input string to a rune slice (for ease of manipulation)\n    runes := []rune(str)\n    \n    // Iterate over each character in the rune slice\n    for i, char := range runes {\n    \t// If the character is a lowercase letter and shifting it will still be within the lowercase range\n        if char >= 'a' && char + shift <= 'z' {\n            char += shift\n        } else {\n        \t// If the character is outside of the lowercase range after shifting, wrap it around\n            char += shift - offset\n        }\n        // Update the character in the rune slice\n        runes[i] = char\n    }\n    \n    // Convert the resulting rune slice back to a string and return it\n    return string(runes)\n}\n"
  },
  {
    "path": "Arrays/ceaser_cipher.java",
    "content": "/*\n    Given a non-empty string of lowercase letters and a non-negative integer\n    representing a key, write a function that returns a new string obtained by\n    shifting every letter in the input string by k positions in the alphabet,\n    where k is the key.\n\n    Note that letters should \"wrap\" around the alphabet; in other words, the\n    letter z shifted by one returns the letter a\n\n    Sample Input : abz key: 3\n    Output: dec\n\n    Explanation:\n\n    The CaesarCipherEncryptor function takes a string and a key (integer) as input and returns a new string\n    obtained by shifting each character of the input string by the key number of positions to the right in\n    the alphabet, wrapping around if necessary.\n\n    The function first calculates the shift amount and offset value. The shift amount is calculated by taking\n    the key modulo 26, which ensures that the shift amount is always within the range of 0 to 25. The offset\n    value is calculated by taking 26, which is the number of letters in the alphabet.\n\n    The function then converts the input string to a rune slice (for ease of manipulation). A rune is a single\n    character in a programming language. The rune type is used to represent characters in Go.\n\n    The function then iterates over each character in the rune slice. For each character, the function checks\n\n    if the character is a lowercase letter and if shifting it will still be within the lowercase range.\n\n    If the character is a lowercase letter and shifting it will still be within the lowercase range, the\n    function simply adds the shift amount to the character. If the character is outside of the lowercase range after shifting, the function wraps it around by adding the shift amount - offset to the character.\n\n    The function then updates the character in the rune slice.\n\n    The function then converts the resulting rune slice back to a string and returns it.\n\n    The time complexity of the CaesarCipherEncryptor function is O(n), where n is the length of the input string.\n    This is because the function iterates over each character in the input string, performing a constant amount\n    of work for each character.\n\n    The space complexity of the CaesarCipherEncryptor function is O(n), where n is the length of the input string.\n    This is because the function creates a new rune slice to store the encrypted string. The rune slice is the\n    same size as the input string, so the space complexity is O(n).\n*/\n// Java\n\nimport java.util.Scanner;\n\npublic class CaesarCipherEncryptor {\n\n  public static String encrypt(String str, int key) {\n    // Calculate the shift amount and offset value\n    int shift = key % 26;\n    int offset = 26;\n\n    // Convert the input string to a char array\n    char[] chars = str.toCharArray();\n\n    // Iterate over each character in the char array\n    for (int i = 0; i < chars.length; i++) {\n      // If the character is a lowercase letter and shifting it will still be within the lowercase range\n      if (chars[i] >= 'a' && chars[i] + shift <= 'z') {\n        chars[i] += shift;\n      } else {\n        // If the character is outside of the lowercase range after shifting, wrap it around\n        chars[i] += shift - offset;\n      }\n    }\n\n    // Convert the resulting char array back to a string and return it\n    return new String(chars);\n  }\n\n  public static void main(String[] args) {\n    // Get the input string and key from the user\n    Scanner scanner = new Scanner(System.in);\n    System.out.println(\"Enter a string: \");\n    String str = scanner.nextLine();\n\n    System.out.println(\"Enter a key: \");\n    int key = scanner.nextInt();\n\n    // Encrypt the string using the Caesar cipher\n    String encrypted_str = encrypt(str, key);\n\n    // Print the encrypted string\n    System.out.println(\"Encrypted string: \" + encrypted_str);\n  }\n}\n"
  },
  {
    "path": "Arrays/ceaser_cipher.js",
    "content": "/*\n    Given a non-empty string of lowercase letters and a non-negative integer\n    representing a key, write a function that returns a new string obtained by\n    shifting every letter in the input string by k positions in the alphabet,\n    where k is the key.\n\n    Note that letters should \"wrap\" around the alphabet; in other words, the\n    letter z shifted by one returns the letter a\n\n    Sample Input : abz key: 3\n    Output: dec\n\n    Explanation:\n\n    The CaesarCipherEncryptor function takes a string and a key (integer) as input and returns a new string\n    obtained by shifting each character of the input string by the key number of positions to the right in\n    the alphabet, wrapping around if necessary.\n\n    The function first calculates the shift amount and offset value. The shift amount is calculated by taking\n    the key modulo 26, which ensures that the shift amount is always within the range of 0 to 25. The offset\n    value is calculated by taking 26, which is the number of letters in the alphabet.\n\n    The function then converts the input string to a rune slice (for ease of manipulation). A rune is a single\n    character in a programming language. The rune type is used to represent characters in Go.\n\n    The function then iterates over each character in the rune slice. For each character, the function checks\n\n    if the character is a lowercase letter and if shifting it will still be within the lowercase range.\n\n    If the character is a lowercase letter and shifting it will still be within the lowercase range, the\n    function simply adds the shift amount to the character. If the character is outside of the lowercase range after shifting, the function wraps it around by adding the shift amount - offset to the character.\n\n    The function then updates the character in the rune slice.\n\n    The function then converts the resulting rune slice back to a string and returns it.\n\n    The time complexity of the CaesarCipherEncryptor function is O(n), where n is the length of the input string.\n    This is because the function iterates over each character in the input string, performing a constant amount\n    of work for each character.\n\n    The space complexity of the CaesarCipherEncryptor function is O(n), where n is the length of the input string.\n    This is because the function creates a new rune slice to store the encrypted string. The rune slice is the\n    same size as the input string, so the space complexity is O(n).\n*/\nfunction caesarCipherEncryptor(str, key) {\n  // Calculate the shift amount and offset value\n  let shift = key % 26;\n  let offset = 26;\n\n  // Convert the input string to a lowercase string\n  str = str.toLowerCase();\n\n  // Iterate over each character in the string\n  for (let i = 0; i < str.length; i++) {\n    // If the character is a letter and shifting it will still be within the lowercase range\n    if (str[i] >= \"a\" && str[i] + shift <= \"z\") {\n      str[i] += shift;\n    } else {\n      // If the character is outside of the lowercase range after shifting, wrap it around\n      str[i] += shift - offset;\n    }\n  }\n\n  // Return the encrypted string\n  return str;\n}\n\n// Example usage\nlet str = \"Hello, world!\";\nlet key = 3;\n\nlet encryptedStr = caesarCipherEncryptor(str, key);\nconsole.log(encryptedStr); // Output: \"Khoor, zloor!\"\n"
  },
  {
    "path": "Arrays/ceaser_cipher.py",
    "content": "'''\n    Given a non-empty string of lowercase letters and a non-negative integer\n    representing a key, write a function that returns a new string obtained by\n    shifting every letter in the input string by k positions in the alphabet,\n    where k is the key.\n\n    Note that letters should \"wrap\" around the alphabet; in other words, the\n    letter z shifted by one returns the letter a\n\n    Sample Input : abz key: 3\n    Output: dec\n\n    Explanation:\n\n    The CaesarCipherEncryptor function takes a string and a key (integer) as input and returns a new string\n    obtained by shifting each character of the input string by the key number of positions to the right in\n    the alphabet, wrapping around if necessary.\n\n    The function first calculates the shift amount and offset value. The shift amount is calculated by taking\n    the key modulo 26, which ensures that the shift amount is always within the range of 0 to 25. The offset\n    value is calculated by taking 26, which is the number of letters in the alphabet.\n\n    The function then converts the input string to a rune slice (for ease of manipulation). A rune is a single\n    character in a programming language. The rune type is used to represent characters in Go.\n\n    The function then iterates over each character in the rune slice. For each character, the function checks\n\n    if the character is a lowercase letter and if shifting it will still be within the lowercase range.\n\n    If the character is a lowercase letter and shifting it will still be within the lowercase range, the\n    function simply adds the shift amount to the character. If the character is outside of the lowercase range after shifting, the function wraps it around by adding the shift amount - offset to the character.\n\n    The function then updates the character in the rune slice.\n\n    The function then converts the resulting rune slice back to a string and returns it.\n\n    The time complexity of the CaesarCipherEncryptor function is O(n), where n is the length of the input string.\n    This is because the function iterates over each character in the input string, performing a constant amount\n    of work for each character.\n\n    The space complexity of the CaesarCipherEncryptor function is O(n), where n is the length of the input string.\n    This is because the function creates a new rune slice to store the encrypted string. The rune slice is the\n    same size as the input string, so the space complexity is O(n).\n'''\n# Python\n\ndef caesar_cipher_encryptor(str, key):\n  # Calculate the shift amount and offset value\n  shift = key % 26\n  offset = 26\n\n  # Convert the input string to a list of characters\n  chars = list(str)\n\n  # Iterate over each character in the list\n  for i in range(len(chars)):\n    # If the character is a lowercase letter and shifting it will still be within the lowercase range\n    if chars[i] >= 'a' and chars[i] + shift <= 'z':\n      chars[i] += shift\n    else:\n      # If the character is outside of the lowercase range after shifting, wrap it around\n      chars[i] += shift - offset\n\n  # Convert the resulting list of characters back to a string and return it\n  return ''.join(chars)\n\n"
  },
  {
    "path": "Arrays/dutch_national_flag.cpp",
    "content": "/*\n    Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.\n\n    We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.\n\n    Input: nums = [2,0,2,1,1,0]\n    Output: [0,0,1,1,2,2]\n\n    Explanation:\n\n\n    The algorithm partitions the array into three sections: elements with the value 0, elements with the value 1, and elements \n    with the value 2. It uses three pointers, `start`, `low`, and `end`, to keep track of the boundaries between these sections.\n\n    The algorithm iterates through the array using the `low` pointer. Here's how it works:\n\n    1. If the element at `low` is 0, it means it should be in the first section. In this case, the algorithm swaps the element \n       with the element at the `start` position, increments both `start` and `low` pointers, and moves the `low` pointer to the \n       next element to process.\n\n    2. If the element at `low` is 1, it means it should be in the second section. In this case, the algorithm simply increments \n       the `low` pointer and moves to the next element to process.\n\n    3. If the element at `low` is 2, it means it should be in the third section. In this case, the algorithm swaps the element \n       with the element at the `end` position, decrements the `end` pointer, and moves the `low` pointer to the next element to process. The reason for moving the `low` pointer to the next element is to recheck the value after the swap, as the swapped element could be 0 or 1.\n\n    The algorithm continues these steps until the `low` pointer surpasses the `end` pointer, indicating that all elements have \n    been processed.\n\n    The \"Dutch National Flag\" algorithm has a time complexity of O(n), where n is the size of the input array. \n    It performs a single pass through the array, ensuring that all elements are correctly placed in their respective sections.\n\n    Note that the code assumes the input vector `nums` contains only values 0, 1, and 2, and it modifies the vector in-place \n    to achieve the sorted order.\n\n    Time complexity: O(n)\n    Space complexity: O(1)\n*/\n\n\n\n#include <bits/stdc++.h>\nusing namespace std;\n\nvoid sortColors(vector<int> &nums)\n{\n    // created 3 variables start , low and end which are pointing start and low which are pointing to first index , end is pointing to last index .\n\n    int start = 0, low = 0, end = nums.size() - 1;\n    while (low <= end)\n    {\n        if (nums[low] == 0) // checking if element of low is 0 . If yes then  swap to start and low .\n        {\n            swap(nums[low], nums[start]);\n            start++, low++;\n        }\n        else if (nums[low] == 1) // checking if element at low index is 1 , If yes then increase the index by 1 .\n        {\n            low++;\n        }\n        else // else swap the element of low index to end .\n        {\n            swap(nums[low], nums[end]);\n            end--;\n        }\n    }\n}\nint main()\n{\n    vector<int> nums{2, 0, 2, 1, 1, 0};\n    sortColors(nums);\n\n    // Printing array's elements ..\n    for (auto i : nums)\n    {\n        cout << i << \" \";\n    }\n}\n"
  },
  {
    "path": "Arrays/dutch_national_flag.go",
    "content": "/*\n   Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.\n\n   We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.\n\n   Input: nums = [2,0,2,1,1,0]\n   Output: [0,0,1,1,2,2]\n\n   Explanation:\n\n   The algorithm partitions the array into three sections: elements with the value 0, elements with the value 1, and elements\n   with the value 2. It uses three pointers, `start`, `low`, and `end`, to keep track of the boundaries between these sections.\n\n   The algorithm iterates through the array using the `low` pointer. Here's how it works:\n\n   1. If the element at `low` is 0, it means it should be in the first section. In this case, the algorithm swaps the element\n      with the element at the `start` position, increments both `start` and `low` pointers, and moves the `low` pointer to the\n      next element to process.\n\n   2. If the element at `low` is 1, it means it should be in the second section. In this case, the algorithm simply increments\n      the `low` pointer and moves to the next element to process.\n\n   3. If the element at `low` is 2, it means it should be in the third section. In this case, the algorithm swaps the element\n      with the element at the `end` position, decrements the `end` pointer, and moves the `low` pointer to the next element to process. The reason for moving the `low` pointer to the next element is to recheck the value after the swap, as the swapped element could be 0 or 1.\n\n   The algorithm continues these steps until the `low` pointer surpasses the `end` pointer, indicating that all elements have\n   been processed.\n\n   The \"Dutch National Flag\" algorithm has a time complexity of O(n), where n is the size of the input array.\n   It performs a single pass through the array, ensuring that all elements are correctly placed in their respective sections.\n\n   Note that the code assumes the input vector `nums` contains only values 0, 1, and 2, and it modifies the vector in-place\n   to achieve the sorted order.\n\n   Time complexity: O(n)\n   Space complexity: O(1)\n*/\npackage main\n\nimport \"fmt\"\n\nfunc sortColors(nums []int) {\n\tstart := 0\n\tlow := 0\n\tend := len(nums) - 1\n\n\tfor low <= end {\n\t\tif nums[low] == 0 {\n\t\t\t// Swap the element at low with the element at start\n\t\t\tnums[low], nums[start] = nums[start], nums[low]\n\t\t\tstart++\n\t\t\tlow++\n\t\t} else if nums[low] == 1 {\n\t\t\t// Move to the next element\n\t\t\tlow++\n\t\t} else {\n\t\t\t// Swap the element at low with the element at end\n\t\t\tnums[low], nums[end] = nums[end], nums[low]\n\t\t\tend--\n\t\t}\n\t}\n}\n\nfunc main() {\n\tnums := []int{2, 0, 2, 1, 1, 0}\n\tsortColors(nums)\n\tfmt.Println(nums)\n}\n"
  },
  {
    "path": "Arrays/dutch_national_flag.java",
    "content": "/*\n    Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.\n\n    We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.\n\n    Input: nums = [2,0,2,1,1,0]\n    Output: [0,0,1,1,2,2]\n\n    Explanation:\n\n    The algorithm partitions the array into three sections: elements with the value 0, elements with the value 1, and elements \n    with the value 2. It uses three pointers, `start`, `low`, and `end`, to keep track of the boundaries between these sections.\n\n    The algorithm iterates through the array using the `low` pointer. Here's how it works:\n\n    1. If the element at `low` is 0, it means it should be in the first section. In this case, the algorithm swaps the element \n       with the element at the `start` position, increments both `start` and `low` pointers, and moves the `low` pointer to the \n       next element to process.\n\n    2. If the element at `low` is 1, it means it should be in the second section. In this case, the algorithm simply increments \n       the `low` pointer and moves to the next element to process.\n\n    3. If the element at `low` is 2, it means it should be in the third section. In this case, the algorithm swaps the element \n       with the element at the `end` position, decrements the `end` pointer, and moves the `low` pointer to the next element to process. The reason for moving the `low` pointer to the next element is to recheck the value after the swap, as the swapped element could be 0 or 1.\n\n    The algorithm continues these steps until the `low` pointer surpasses the `end` pointer, indicating that all elements have \n    been processed.\n\n    The \"Dutch National Flag\" algorithm has a time complexity of O(n), where n is the size of the input array. \n    It performs a single pass through the array, ensuring that all elements are correctly placed in their respective sections.\n\n    Note that the code assumes the input vector `nums` contains only values 0, 1, and 2, and it modifies the vector in-place \n    to achieve the sorted order.\n\n    Time complexity: O(n)\n    Space complexity: O(1)\n*/\npublic class Main {\n    public static void sortColors(int[] nums) {\n        int start = 0;\n        int low = 0;\n        int end = nums.length - 1;\n\n        while (low <= end) {\n            if (nums[low] == 0) {\n                // Swap the element at low with the element at start\n                int temp = nums[low];\n                nums[low] = nums[start];\n                nums[start] = temp;\n                start++;\n                low++;\n            } else if (nums[low] == 1) {\n                // Move to the next element\n                low++;\n            } else {\n                // Swap the element at low with the element at end\n                int temp = nums[low];\n                nums[low] = nums[end];\n                nums[end] = temp;\n                end--;\n            }\n        }\n    }\n\n    public static void main(String[] args) {\n        int[] nums = {2, 0, 2, 1, 1, 0};\n        sortColors(nums);\n        for (int num : nums) {\n            System.out.print(num + \" \");\n        }\n    }\n}\n"
  },
  {
    "path": "Arrays/dutch_national_flag.js",
    "content": "/*\n    Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.\n\n    We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.\n\n    Input: nums = [2,0,2,1,1,0]\n    Output: [0,0,1,1,2,2]\n\n    Explanation:\n\n    The algorithm partitions the array into three sections: elements with the value 0, elements with the value 1, and elements \n    with the value 2. It uses three pointers, `start`, `low`, and `end`, to keep track of the boundaries between these sections.\n\n    The algorithm iterates through the array using the `low` pointer. Here's how it works:\n\n    1. If the element at `low` is 0, it means it should be in the first section. In this case, the algorithm swaps the element \n       with the element at the `start` position, increments both `start` and `low` pointers, and moves the `low` pointer to the \n       next element to process.\n\n    2. If the element at `low` is 1, it means it should be in the second section. In this case, the algorithm simply increments \n       the `low` pointer and moves to the next element to process.\n\n    3. If the element at `low` is 2, it means it should be in the third section. In this case, the algorithm swaps the element \n       with the element at the `end` position, decrements the `end` pointer, and moves the `low` pointer to the next element to process. The reason for moving the `low` pointer to the next element is to recheck the value after the swap, as the swapped element could be 0 or 1.\n\n    The algorithm continues these steps until the `low` pointer surpasses the `end` pointer, indicating that all elements have \n    been processed.\n\n    The \"Dutch National Flag\" algorithm has a time complexity of O(n), where n is the size of the input array. \n    It performs a single pass through the array, ensuring that all elements are correctly placed in their respective sections.\n\n    Note that the code assumes the input vector `nums` contains only values 0, 1, and 2, and it modifies the vector in-place \n    to achieve the sorted order.\n\n    Time complexity: O(n)\n    Space complexity: O(1)\n*/\nfunction sortColors(nums) {\n  let start = 0;\n  let low = 0;\n  let end = nums.length - 1;\n\n  while (low <= end) {\n    if (nums[low] === 0) {\n      // Swap the element at low with the element at start\n      [nums[low], nums[start]] = [nums[start], nums[low]];\n      start++;\n      low++;\n    } else if (nums[low] === 1) {\n      // Move to the next element\n      low++;\n    } else {\n      // Swap the element at low with the element at end\n      [nums[low], nums[end]] = [nums[end], nums[low]];\n      end--;\n    }\n  }\n}\n\n// Example usage:\nconst nums = [2, 0, 2, 1, 1, 0];\nsortColors(nums);\nconsole.log(nums);\n"
  },
  {
    "path": "Arrays/dutch_national_flag.py",
    "content": "'''\n    Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.\n\n    We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.\n\n    Input: nums = [2,0,2,1,1,0]\n    Output: [0,0,1,1,2,2]\n\n    Explanation:\n\n    The algorithm partitions the array into three sections: elements with the value 0, elements with the value 1, and elements \n    with the value 2. It uses three pointers, `start`, `low`, and `end`, to keep track of the boundaries between these sections.\n\n    The algorithm iterates through the array using the `low` pointer. Here's how it works:\n\n    1. If the element at `low` is 0, it means it should be in the first section. In this case, the algorithm swaps the element \n       with the element at the `start` position, increments both `start` and `low` pointers, and moves the `low` pointer to the \n       next element to process.\n\n    2. If the element at `low` is 1, it means it should be in the second section. In this case, the algorithm simply increments \n       the `low` pointer and moves to the next element to process.\n\n    3. If the element at `low` is 2, it means it should be in the third section. In this case, the algorithm swaps the element \n       with the element at the `end` position, decrements the `end` pointer, and moves the `low` pointer to the next element to process. The reason for moving the `low` pointer to the next element is to recheck the value after the swap, as the swapped element could be 0 or 1.\n\n    The algorithm continues these steps until the `low` pointer surpasses the `end` pointer, indicating that all elements have \n    been processed.\n\n    The \"Dutch National Flag\" algorithm has a time complexity of O(n), where n is the size of the input array. \n    It performs a single pass through the array, ensuring that all elements are correctly placed in their respective sections.\n\n    Note that the code assumes the input vector `nums` contains only values 0, 1, and 2, and it modifies the vector in-place \n    to achieve the sorted order.\n\n    Time complexity: O(n)\n    Space complexity: O(1)\n'''\ndef sortColors(nums):\n    start = 0\n    low = 0\n    end = len(nums) - 1\n    \n    while low <= end:\n        if nums[low] == 0:\n            # Swap the element at low with the element at start\n            nums[low], nums[start] = nums[start], nums[low]\n            start += 1\n            low += 1\n        elif nums[low] == 1:\n            # Move to the next element\n            low += 1\n        else:\n            # Swap the element at low with the element at end\n            nums[low], nums[end] = nums[end], nums[low]\n            end -= 1\n\n# Example usage:\nnums = [2, 0, 2, 1, 1, 0]\nsortColors(nums)\nprint(nums)\n"
  },
  {
    "path": "Arrays/find_three_largest_integers.js",
    "content": "/*\n    Write a function that takes in an array of at least three integers and,\n    without sorting the input array, returns a sorted array of the three largest\n    integers in the input array.\n\n    Explanation:\n\n    This code defines a function called `FindThreeLargestNumbers` that takes an array of integers as input and\n    returns an array of the three largest integers in the input array.\n\n    The `triplets` array is initialized with three smallest possible values. Then, the function iterates through\n    the input array using a `for` loop and calls the `updateLargest` function to update the `triplets` array with\n    the current number if it is larger than one of the values in the array.\n\n    The `updateLargest` function takes two arguments: `triplets` and `num`. It first checks if `num` is greater\n    than the third value in the `triplets` array. If so, it calls the `shiftAndUpdate` function to update the\n    `triplets` array with the current number at the third index.\n\n    If `num` is not greater than the third value in the `triplets` array, it checks if `num` is greater than the second value in the `triplets` array.\n\n    If so, it calls the `shiftAndUpdate` function to update the `triplets` array with the current number at\n    the second index. Finally, if `num` is not greater than either the third or second value in the `triplets`\n    array, it checks if `num` is greater than the first value in the `triplets` array.\n\n    If so, it calls the `shiftAndUpdate` function to update the `triplets` array with the current number at\n    the first index.\n\n    The `shiftAndUpdate` function takes three arguments: `triplets`, `num`, and `idx`. It iterates through the\n    `triplets` array using a `for` loop and shifts each value to the left by one position until it reaches\n    the `idx` index. Then it updates the value at the `idx` index with the current number `num`.\n\n    Time and Space complexity : O(n) time | O(1) space - where n is the length of the input array\n*/\nfunction findThreeLargestNumbers(array) {\n  // Initialize an array to hold the three largest numbers, starting with negative infinity\n  let triplets = [-Infinity, -Infinity, -Infinity];\n\n  // Iterate through each number in the input array\n  for (let num of array) {\n    // Call the updateLargest function to determine if the number should be included in the triplet\n    updateLargest(triplets, num);\n  }\n\n  // Return the array containing the three largest numbers\n  return triplets;\n}\n\nfunction updateLargest(triplets, num) {\n  // If the number is larger than the third-largest element in the triplet\n  if (num > triplets[2]) {\n    // Shift the other elements to make room and add the number as the new third-largest element\n    shiftAndUpdate(triplets, num, 2);\n  }\n  // Otherwise, if the number is larger than the second-largest element\n  else if (num > triplets[1]) {\n    // Shift and update the triplet accordingly\n    shiftAndUpdate(triplets, num, 1);\n  }\n  // Otherwise, if the number is larger than the first-largest element\n  else if (num > triplets[0]) {\n    // Shift and update the triplet accordingly\n    shiftAndUpdate(triplets, num, 0);\n  }\n}\n\nfunction shiftAndUpdate(triplets, num, idx) {\n  // Iterate through the elements of the triplet\n  for (let i = 0; i <= idx; i++) {\n    // If the loop reaches the specified index, add the new number to the triplet\n    if (i === idx) {\n      triplets[i] = num;\n    }\n    // Otherwise, shift the elements to the right\n    else {\n      triplets[i] = triplets[i + 1];\n    }\n  }\n}\n\n// Test the findThreeLargestNumbers function\nconst array = [1, 5, 2, 9, 10, 3];\nconst result = findThreeLargestNumbers(array);\nconsole.log(result);\n"
  },
  {
    "path": "Arrays/find_three_largest_number.cpp",
    "content": "/*\n  Write a function that takes in an array of at least three integers and,\n  without sorting the input array, returns a sorted array of the three largest\n  integers in the input array.\n*/\n/* Explanation\n   This code defines a function called `FindThreeLargestNumbers` that takes an array of integers as input and\n   returns an array of the three largest integers in the input array.\n\n   The `triplets` array is initialized with three smallest possible values. Then, the function iterates through\n   the input array using a `for` loop and calls the `updateLargest` function to update the `triplets` array with\n   the current number if it is larger than one of the values in the array.\n\n   The `updateLargest` function takes two arguments: `triplets` and `num`. It first checks if `num` is greater\n   than the third value in the `triplets` array. If so, it calls the `shiftAndUpdate` function to update the\n   `triplets` array with the current number at the third index.\n\n   If `num` is not greater than the third value in the `triplets` array, it checks if `num` is greater than the second value in the `triplets` array.\n\n   If so, it calls the `shiftAndUpdate` function to update the `triplets` array with the current number at\n   the second index. Finally, if `num` is not greater than either the third or second value in the `triplets`\n   array, it checks if `num` is greater than the first value in the `triplets` array.\n\n   If so, it calls the `shiftAndUpdate` function to update the `triplets` array with the current number at\n   the first index.\n\n   The `shiftAndUpdate` function takes three arguments: `triplets`, `num`, and `idx`. It iterates through the\n   `triplets` array using a `for` loop and shifts each value to the left by one position until it reaches\n   the `idx` index. Then it updates the value at the `idx` index with the current number `num`.\n\n   Time and Space complexity : O(n) time | O(1) space - where n is the length of the input array\n*/\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <climits>\n\nusing namespace std;\n\n// Function to update the triplet if the input number is larger than any of its elements.\nvoid updateLargest(vector<int>& triplets, int num);\n\n// Function to shift the elements of the triplet to make room for a new number and add the number to the specified index.\nvoid shiftAndUpdate(vector<int>& triplets, int num, int idx);\n\n// Function to find the three largest integers in the input array in descending order.\nvector<int> findThreeLargestNumbers(vector<int>& array);\n\nint main() {\n    // Create an input array.\n    vector<int> array = {141, 1, 17, -7, -17, -27, 18, 541, 8, 7, 7};\n\n    // Find the three largest integers in the input array.\n    vector<int> result = findThreeLargestNumbers(array);\n\n    // Output the three largest integers in descending order.\n    for (int num : result) {\n        cout << num << \" \";\n    }\n    cout << endl;\n    return 0;\n}\n\nvector<int> findThreeLargestNumbers(vector<int>& array) {\n    // Initialize a vector to hold the three largest integers, starting with negative infinity.\n    vector<int> triplets = {INT_MIN, INT_MIN, INT_MIN};\n\n    // Iterate over each number in the input array and call the updateLargest function to determine if it should be included in the triplet.\n    for (int num : array) {\n        updateLargest(triplets, num);\n    }\n\n    // Return the vector containing the three largest integers in descending order.\n    return triplets;\n}\n\nvoid updateLargest(vector<int>& triplets, int num) {\n    // If the number is larger than the third-largest element in the triplet, shift the other elements to make room and add the number.\n    if (num > triplets[2]) {\n        shiftAndUpdate(triplets, num, 2);\n    // Otherwise, if the number is larger than the second-largest element, shift and update the triplet accordingly.\n    } else if (num > triplets[1]) {\n        shiftAndUpdate(triplets, num, 1);\n    // Otherwise, if the number is larger than the first-largest element, shift and update the triplet accordingly.\n    } else if (num > triplets[0]) {\n        shiftAndUpdate(triplets, num, 0);\n    }\n}\n\nvoid shiftAndUpdate(vector<int>& triplets, int num, int idx) {\n    // Shift the elements of the triplet to the right starting at the specified index, and add the new number to the specified index.\n    for (int i = 0; i < idx + 1; i++) {\n        // If the loop reaches the specified index, add the new number to the triplet.\n        if (i == idx) {\n            triplets[i] = num;\n        // Otherwise, shift the elements to the right.\n        } else {\n            triplets[i] = triplets[i + 1];\n        }\n    }\n}\n"
  },
  {
    "path": "Arrays/find_three_largest_numbers.go",
    "content": "/*\n    Write a function that takes in an array of at least three integers and,\n    without sorting the input array, returns a sorted array of the three largest\n    integers in the input array.\n\n    Explanation:\n\n    This code defines a function called `FindThreeLargestNumbers` that takes an array of integers as input and\n    returns an array of the three largest integers in the input array.\n\n    The `triplets` array is initialized with three smallest possible values. Then, the function iterates through\n    the input array using a `for` loop and calls the `updateLargest` function to update the `triplets` array with\n    the current number if it is larger than one of the values in the array.\n\n    The `updateLargest` function takes two arguments: `triplets` and `num`. It first checks if `num` is greater\n    than the third value in the `triplets` array. If so, it calls the `shiftAndUpdate` function to update the\n    `triplets` array with the current number at the third index.\n\n    If `num` is not greater than the third value in the `triplets` array, it checks if `num` is greater than the second value in the `triplets` array.\n\n    If so, it calls the `shiftAndUpdate` function to update the `triplets` array with the current number at\n    the second index. Finally, if `num` is not greater than either the third or second value in the `triplets`\n    array, it checks if `num` is greater than the first value in the `triplets` array.\n\n    If so, it calls the `shiftAndUpdate` function to update the `triplets` array with the current number at\n    the first index.\n\n    The `shiftAndUpdate` function takes three arguments: `triplets`, `num`, and `idx`. It iterates through the\n    `triplets` array using a `for` loop and shifts each value to the left by one position until it reaches\n    the `idx` index. Then it updates the value at the `idx` index with the current number `num`.\n\n    Time and Space complexity : O(n) time | O(1) space - where n is the length of the input array\n*/\npackage main\n\nimport \"math\"\n\n// FindThreeLargestNumbers returns the three largest integers in the input array in descending order.\nfunc FindThreeLargestNumbers(array []int) []int {\n\t// Initialize a slice to hold the three largest integers, starting with negative infinity.\n\ttriplets := []int{math.MinInt32, math.MinInt32, math.MinInt32}\n\tfor _, num := range array {\n\t\t// For each number in the array, call the updateLargest function to determine if it should be included in the triplet.\n\t\tupdateLargest(triplets, num)\n\t}\n\treturn triplets\n}\n\n// updateLargest updates the triplet if the input number is larger than any of its elements.\nfunc updateLargest(triplets []int, num int) {\n\t// If the number is larger than the third-largest element in the triplet, shift the other elements to make room and add the number.\n\tif num > triplets[2] {\n\t\tshiftAndUpdate(triplets, num, 2)\n\t// Otherwise, if the number is larger than the second-largest element, shift and update the triplet accordingly.\n\t} else if num > triplets[1] {\n\t\tshiftAndUpdate(triplets, num, 1)\n\t// Otherwise, if the number is larger than the first-largest element, shift and update the triplet accordingly.\n\t} else if num > triplets[0] {\n\t\tshiftAndUpdate(triplets, num, 0)\n\t}\n}\n\n// shiftAndUpdate shifts the elements of the triplet to make room for a new number and adds the number to the specified index.\nfunc shiftAndUpdate(triplets []int, num int, idx int) {\n\tfor i := 0; i < idx+1; i++ {\n\t\t// If the loop reaches the specified index, add the new number to the triplet.\n\t\tif i == idx {\n\t\t\ttriplets[i] = num\n\t\t// Otherwise, shift the elements to the right.\n\t\t} else {\n\t\t\ttriplets[i] = triplets[i+1]\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "Arrays/find_three_largest_numbers.java",
    "content": "/*\n    Write a function that takes in an array of at least three integers and,\n    without sorting the input array, returns a sorted array of the three largest\n    integers in the input array.\n\n    Explanation:\n\n    This code defines a function called `FindThreeLargestNumbers` that takes an array of integers as input and\n    returns an array of the three largest integers in the input array.\n\n    The `triplets` array is initialized with three smallest possible values. Then, the function iterates through\n    the input array using a `for` loop and calls the `updateLargest` function to update the `triplets` array with\n    the current number if it is larger than one of the values in the array.\n\n    The `updateLargest` function takes two arguments: `triplets` and `num`. It first checks if `num` is greater\n    than the third value in the `triplets` array. If so, it calls the `shiftAndUpdate` function to update the\n    `triplets` array with the current number at the third index.\n\n    If `num` is not greater than the third value in the `triplets` array, it checks if `num` is greater than the second value in the `triplets` array.\n\n    If so, it calls the `shiftAndUpdate` function to update the `triplets` array with the current number at\n    the second index. Finally, if `num` is not greater than either the third or second value in the `triplets`\n    array, it checks if `num` is greater than the first value in the `triplets` array.\n\n    If so, it calls the `shiftAndUpdate` function to update the `triplets` array with the current number at\n    the first index.\n\n    The `shiftAndUpdate` function takes three arguments: `triplets`, `num`, and `idx`. It iterates through the\n    `triplets` array using a `for` loop and shifts each value to the left by one position until it reaches\n    the `idx` index. Then it updates the value at the `idx` index with the current number `num`.\n\n    Time and Space complexity : O(n) time | O(1) space - where n is the length of the input array\n*/\n\nimport java.util.Arrays;\n\npublic class Main {\n    // Function to find the three largest numbers in the input array\n    public static int[] findThreeLargestNumbers(int[] array) {\n        // Initialize an array to hold the three largest numbers, starting with negative infinity\n        int[] triplets = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE};\n\n        // Iterate through each number in the input array\n        for (int num : array) {\n            // Call the updateLargest function to determine if the number should be included in the triplet\n            updateLargest(triplets, num);\n        }\n\n        // Return the array containing the three largest numbers\n        return triplets;\n    }\n\n    // Function to update the triplet if the input number is larger than any of its elements\n    private static void updateLargest(int[] triplets, int num) {\n        // If the number is larger than the third-largest element in the triplet\n        if (num > triplets[2]) {\n            // Shift the other elements to make room and add the number as the new third-largest element\n            shiftAndUpdate(triplets, num, 2);\n        }\n        // Otherwise, if the number is larger than the second-largest element\n        else if (num > triplets[1]) {\n            // Shift and update the triplet accordingly\n            shiftAndUpdate(triplets, num, 1);\n        }\n        // Otherwise, if the number is larger than the first-largest element\n        else if (num > triplets[0]) {\n            // Shift and update the triplet accordingly\n            shiftAndUpdate(triplets, num, 0);\n        }\n    }\n\n    // Function to shift the elements of the triplet and add the new number to the specified index\n    private static void shiftAndUpdate(int[] triplets, int num, int idx) {\n        // Iterate through the elements of the triplet\n        for (int i = 0; i < idx + 1; i++) {\n            // If the loop reaches the specified index, add the new number to the triplet\n            if (i == idx) {\n                triplets[i] = num;\n            }\n            // Otherwise, shift the elements to the right\n            else {\n                triplets[i] = triplets[i + 1];\n            }\n        }\n    }\n\n    // Main function to test the findThreeLargestNumbers function\n    public static void main(String[] args) {\n        int[] array = {1, 5, 2, 9, 10, 3};\n        int[] result = findThreeLargestNumbers(array);\n        System.out.println(Arrays.toString(result));\n    }\n}\n"
  },
  {
    "path": "Arrays/find_three_largest_numbers.py",
    "content": "'''\n    Write a function that takes in an array of at least three integers and,\n    without sorting the input array, returns a sorted array of the three largest\n    integers in the input array.\n\n    Explanation:\n\n    This code defines a function called `FindThreeLargestNumbers` that takes an array of integers as input and\n    returns an array of the three largest integers in the input array.\n\n    The `triplets` array is initialized with three smallest possible values. Then, the function iterates through\n    the input array using a `for` loop and calls the `updateLargest` function to update the `triplets` array with\n    the current number if it is larger than one of the values in the array.\n\n    The `updateLargest` function takes two arguments: `triplets` and `num`. It first checks if `num` is greater\n    than the third value in the `triplets` array. If so, it calls the `shiftAndUpdate` function to update the\n    `triplets` array with the current number at the third index.\n\n    If `num` is not greater than the third value in the `triplets` array, it checks if `num` is greater than the second value in the `triplets` array.\n\n    If so, it calls the `shiftAndUpdate` function to update the `triplets` array with the current number at\n    the second index. Finally, if `num` is not greater than either the third or second value in the `triplets`\n    array, it checks if `num` is greater than the first value in the `triplets` array.\n\n    If so, it calls the `shiftAndUpdate` function to update the `triplets` array with the current number at\n    the first index.\n\n    The `shiftAndUpdate` function takes three arguments: `triplets`, `num`, and `idx`. It iterates through the\n    `triplets` array using a `for` loop and shifts each value to the left by one position until it reaches\n    the `idx` index. Then it updates the value at the `idx` index with the current number `num`.\n\n    Time and Space complexity : O(n) time | O(1) space - where n is the length of the input array\n\n'''\ndef find_three_largest_numbers(array):\n    # Initialize a list to hold the three largest numbers, starting with negative infinity\n    triplets = [float('-inf'), float('-inf'), float('-inf')]\n    \n    # Iterate through each number in the input array\n    for num in array:\n        # Call the update_largest function to determine if the number should be included in the triplet\n        update_largest(triplets, num)\n    \n    # Return the list containing the three largest numbers\n    return triplets\n\n\ndef update_largest(triplets, num):\n    # If the number is larger than the third-largest element in the triplet\n    if num > triplets[2]:\n        # Shift the other elements to make room and add the number as the new third-largest element\n        shift_and_update(triplets, num, 2)\n    # Otherwise, if the number is larger than the second-largest element\n    elif num > triplets[1]:\n        # Shift and update the triplet accordingly\n        shift_and_update(triplets, num, 1)\n    # Otherwise, if the number is larger than the first-largest element\n    elif num > triplets[0]:\n        # Shift and update the triplet accordingly\n        shift_and_update(triplets, num, 0)\n\n\ndef shift_and_update(triplets, num, idx):\n    # Iterate through the elements of the triplet\n    for i in range(idx + 1):\n        # If the loop reaches the specified index, add the new number to the triplet\n        if i == idx:\n            triplets[i] = num\n        # Otherwise, shift the elements to the right\n        else:\n            triplets[i] = triplets[i + 1]\n\n\n# Test the find_three_largest_numbers function\narray = [1, 5, 2, 9, 10, 3]\nresult = find_three_largest_numbers(array)\nprint(result)\n"
  },
  {
    "path": "Arrays/first_duplicate_value.cpp",
    "content": "/*\n\tGiven an array of integers between 1 and n, inclusive, where n is the length of the array, write a function\n\tthat returns the first integer that appears more than once (when the array is read from left to right).\n\n\tSample Input = [2, 1, 5, 2, 3, 3, 4]\n\tOutput : 2\n\n\tPlease provide O(n) time and O(1) space solution along with O(n) time and O(n) space solution\n*/\n\n#include <bits/stdc++.h>\nusing namespace std;\n\nclass Solution{\npublic:\n    // O(N) time complexity and O(N) Space Complexity Solution\n    int findDuplicate1(vector<int>& nums)\n    {\n        int N=nums.size();\n    \n        // Use Vector Instead of Unordered Set or Map for O(1) extraction time complexity\n        vector<bool> trk(N,false);\n    \n        for(int i=0;i<N;i++)\n        {\n            if(trk[nums[i]]==true) return nums[i];\n            trk[nums[i]]=true;\n        }\n        return -1;\n    }\n\n    // O(N) time complexity and O(1) Space Complexity Solution\n    int findDuplicate2(vector<int>& nums)\n    {\n        int N=nums.size();\n        for(int i=0;i<N;i++)\n        {\n            if(nums[abs(nums[i])]<0) return nums[i];\n            nums[abs(nums[i])]*=-1;\n        }\n        return -1;\n    }\n};"
  },
  {
    "path": "Arrays/first_duplicate_value.go",
    "content": "/*\n\tGiven an array of integers between 1 and n, inclusive where n  is the length of the array, write a function\n\tthat returns the first integer that appears more than once (when the array isread from left to right).\n\n\tSample Input: [2, 3, 1, 4, 2, 5, 3]\n\tOutput: 2\n*/\n\npackage main\n\nimport \"fmt\"\n\n/*\nApproach 1:\n\t1. We define the `FirstDuplicateValue` function that takes an array of integers as input and returns the\n\tfirst duplicate value found in the array.\n\n\t2. Inside the function, we create a map named `seenSoFar` using the `make` function. This map will be\n\tused to keep track of the numbers that have been seen so far in the array.\n\n\t3. We iterate over each number in the `array` using the `range` keyword.\n\n\t4. For each number, we check if it exists as a key in the `seenSoFar` map. If the value exists, it means\n\tthe number has been seen before and is a duplicate.\n\n\t5. If a duplicate value is found, we immediately return the duplicate value as the result.\n\n\t6. If the number is not a duplicate, we add it to the `seenSoFar` map by setting the corresponding key to\n\t`true`, indicating that it has been seen.\n\n\t7. After iterating through all the numbers in the array without finding a duplicate, we return -1 to\n\tindicate that no duplicate value was found.\n\n\tIn the `main` function, we demonstrate the usage of the `FirstDuplicateValue` function by creating an\n\texample array with some duplicate values. We call the function and store the result in the `firstDuplicate`\n\tvariable. Finally, we print the `firstDuplicate` value, which gives us the first duplicate value in the array.\n\tIn this case, the output will be \"2\" since it is the first duplicate value encountered in the array\n\t`[2, 3, 1, 4, 2, 5, 3]`.\n*/\n\nfunc FirstDuplicateValue(array []int) int {\n\t// Create a map to store the numbers that have been seen so far.\n\tseenSoFar := make(map[int]bool)\n\n\t// Iterate over each number in the array.\n\tfor _, num := range array {\n\t\t// Check if the current number has been seen before.\n\t\tif _, valueExists := seenSoFar[num]; valueExists {\n\t\t\t// If the number is already in the map, it is the first duplicate value.\n\t\t\treturn num\n\t\t}\n\n\t\t// Add the current number to the map to mark it as seen.\n\t\tseenSoFar[num] = true\n\t}\n\n\t// If no duplicate value is found, return -1.\n\treturn -1\n}\n\n/*\nApproach2:\n\tThe code defines a function FirstDuplicateValue that takes an integer array array as its input and returns the\n\tfirst integer value that appears more than once in the input array. The function implements this using a\n\ttechnique called \"negation of visited elements\".\n\n\tThe function first loops through each element in the input array array. For each element, it computes the\n\tabsolute value using the abs function, which is defined as a separate helper function. The absolute value\n\tis used to get the index of the element in the array (adjusted by -1 to account for 0-based indexing).\n\n\tIf the element at the computed index in the array is already negative, it means that we have seen this\n\telement before and hence it is a duplicate. In this case, we return the absolute value of the element.\n\n\tIf the element is not negative, we negate it to mark it as visited. This is done by multiplying the\n\telement at the computed index in the array by -1.\n\n\tIf there are no duplicate values in the input array, the function returns -1.\n\n\tOverall, this approach uses constant extra space and has a time complexity of O(n), where n is the\n\tlength of the input array.\n*/\n// Function to find the first duplicate value in an array.\nfunc FirstDuplicateValue2(array []int) int {\n   // Iterate over each element in the array.\n   for _, num := range array {\n       // Get the absolute value of the current element.\n       absValue := abs(num)\n\n       // Check if the value at the index (absValue - 1) in the array is negative.\n       if array[absValue - 1] < 0 {\n           // If it is negative, then the current element is the first duplicate value.\n           return absValue\n       }\n\n       // Otherwise, mark the value at the index (absValue - 1) in the array as negative.\n       array[absValue - 1] *= -1\n   }\n\n   // If no duplicates are found, return -1.\n   return -1\n}\n\n// Function to get the absolute value of a number.\nfunc abs(num int) int {\n    if num < 0 {\n        return -num\n    }\n    return num\n}\n\nfunc main() {\n\t// Example usage of FirstDuplicateValue function\n\tarray := []int{2, 3, 1, 4, 2, 5, 3}\n\tfirstDuplicate := FirstDuplicateValue(array)\n\tfmt.Println(\"First Duplicate Value:\", firstDuplicate)\n\tfirstDuplicate = FirstDuplicateValue2(array)\n\tfmt.Println(\"First Duplicate Value:\", firstDuplicate)\n}"
  },
  {
    "path": "Arrays/first_duplicate_value.java",
    "content": "/* Sure, here's a brief explanation of each solution:\n\nSolution 1 (O(n) time, O(1) space):\nThis solution uses Floyd's Tortoise and Hare algorithm to find the first duplicate value in the array. \nIt initializes two pointers, a slow pointer and a fast pointer, to the first value in the array. \nThe slow pointer moves one step at a time, while the fast pointer moves two steps at a time. \nWhen they meet at a certain point, it indicates that there is a cycle in the array. \nThen, the slow pointer is reset to the first value, and both pointers move one step at a time until they meet again, \nwhich is the start of the cycle (i.e., the first duplicate value in the array).\n\nSolution 2 (O(n) time, O(n) space):\nThis solution uses a HashSet to keep track of the integers that have been seen so far in the array. \nAs the array is iterated over, each integer is checked to see if it is already in the set. \nIf it is, then it is returned as the first integer that appears more than once. \nIf no such integer is found, then -1 is returned. This solution has a time complexity of O(n) and a space complexity of O(n). */\n\n// Solution 1: O(n) time and O(1) space\npublic static int findDuplicate(int[] nums) {\n    // iterate through the array\n    for (int i = 0; i < nums.length; i++) {\n        // calculate the absolute value of the current element\n        int val = Math.abs(nums[i]);\n        // check if the value at the calculated index is negative\n        if (nums[val - 1] < 0) {\n            // if it is, return the absolute value of the current element\n            return val;\n        }\n        // otherwise, negate the value at the calculated index\n        nums[val - 1] = -nums[val - 1];\n    }\n    // if no duplicate is found, return -1\n    return -1;\n}\n\n\n// Solution 2: O(n) time and O(n) space solution:\npublic static int findDuplicate(int[] nums) {\n    // create a set to keep track of visited elements\n    Set<Integer> visited = new HashSet<>();\n    // iterate through the array\n    for (int num : nums) {\n        // check if the current element has already been visited\n        if (visited.contains(num)) {\n            // if it has, return the current element\n            return num;\n        }\n        // otherwise, add it to the set of visited elements\n        visited.add(num);\n    }\n    // if no duplicate is found, return -1\n    return -1;\n}\n\n"
  },
  {
    "path": "Arrays/first_duplicate_value.js",
    "content": "/*\n\tGiven an array of integers between 1 and n, inclusive, where n is the length of the array, write a function\n\tthat returns the first integer that appears more than once (when the array is read from left to right).\n\n\tSample Input = [2, 1, 5, 2, 3, 3, 4]\n\tOutput : 2\n\n\t\n*/\n\n//  O(n) time and O(1) space solution.\n// Approach: The approach utilizes the fact that the array contains integers between 1 and n, \n// where n is the length of the array. By negating the values at specific indices,\n// we can track which numbers have appeared before. If a number has appeared before,\n// its corresponding index will have a negative value.\n// This allows us to identify the first duplicate encountered during the iteration.\nfunction findFirstDuplicate(nums){\n    let n=nums.length;\n    for(let i=0;i<n;i++){\n        // Check if the absolute value at the current number's index is negative\n        if(nums[Math.abs(nums[i])]<0){\n        // If it is negative, the number has appeared before and is a duplicate\n            return nums[i];\n        }\n        else{\n            // Mark the number at its index as visited by negating its value\n            nums[nums[i]]*=-1;\n        }\n    }\n     // No duplicates found\n    return -1;\n}\n\n// O(n) time and O(n) space solution.\n// Approach: Using Set object or map to check if a number appears more than ones.\n\nfunction findFirstDuplicate(nums){\n    let set=new Set();\n    for(let i=0;i<nums.length;i++){\n        if(set.has(nums[i])==false){\n            // If a number does not exists in set add it to set;\n            set.add(nums[i]);\n        }\n        else{\n            // Number already exits in set. So return the duplicate number.\n            return nums[i]; \n        }\n    }\n    // If no duplicate element found.\n    return -1;\n}"
  },
  {
    "path": "Arrays/first_duplicate_value.py",
    "content": "'''\nIn the code I implemented a solution using Floyd's Tortoise and Hare algorithm \nfor finding the first integer that appears more than once in an array of integers. \n\nThe first solution has a time complexity of O(n) and a space complexity of O(1). \nIt uses the fact that the integers in the array are between 1 and n, inclusive, where n is the length of the array. \nThe solution works by using the array itself as a hash table, \nby marking an integer as negative if it is encountered for the first time, \nand returning it if it is already marked negative. \n\n'''\n\ndef find_duplicate(nums):\n    slow = fast = nums[0]\n    while True:\n        slow = nums[slow]\n        fast = nums[nums[fast]]\n        if slow == fast:\n            break\n    \n    slow = nums[0]\n    while slow != fast:\n        slow = nums[slow]\n        fast = nums[fast]\n    \n    return slow\n"
  },
  {
    "path": "Arrays/four_sum.py",
    "content": "'''\nauthor:maneesha\nInput:\nGiven an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that:\n0 <= a, b, c, d < n\na, b, c, and d are distinct.\nnums[a] + nums[b] + nums[c] + nums[d] == target\nYou may return the answer in any order.\n\nExample 1:\nInput: nums = [1,0,-1,0,-2,2], target = 0\nOutput: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]\nExample 2:\nInput: nums = [2,2,2,2,2], target = 8\nOutput: [[2,2,2,2]]\n\nTime Complexity:O(n^3)\nSpace Complexity:O(1)\n\nExplanation:\n>>The fourSum function takes in a list of integers (nums) and a target value (target).\n>>The code sorts the nums list in ascending order.\n>>It initializes an empty list res to store the resulting quadruplets.\n>>Code uses two nested loops to iterate over combinations of four numbers from the nums list.\n>>It avoids duplicates by skipping iterations when the current element is the same as the previous element\n  in both the outer and inner loops.\n>>Inside  nested loops,  code uses two pointers (lo and hi) to find pairs of elements that sum up to the remaining target value.\n>>It compares the sum of the four elements with the target value and takes appropriate actions:\n\n. If  sum equals the target, it adds the quadruplet to the result list res and skips any duplicate elements by moving the pointers accordingly.\n\n. If  sum is less than the target, it increments the lo pointer to try larger values.\n\n. If sum is greater than the target, it decrements the hi pointer to try smaller values.\n>>After the nested loops, the function returns the resulting list of quadruplets res.\n\n'''\n from typing import List\nclass Solution:\n    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:\n        n = len(nums)\n        nums.sort()\n        res = []\n\n        for i in range(n-3):\n            # avoid the duplicates while moving i\n            if i > 0 and nums[i] == nums[i - 1]:\n                continue\n            for j in range(i+1, n-2):\n                # avoid the duplicates while moving j\n                if j > i + 1 and nums[j] == nums[j - 1]:\n                    continue\n                lo = j + 1\n                hi = n - 1\n                while lo < hi:\n                    temp = nums[i] + nums[j] + nums[lo] + nums[hi]\n                    if temp == target:\n                        res += [nums[i], nums[j], nums[lo], nums[hi]],\n\n                        # skip duplicates\n                        while lo < hi and nums[lo] == nums[lo + 1]:\n                            lo += 1\n                        lo += 1\n                        while lo < hi and nums[hi] == nums[hi - 1]:\n                            hi -= 1\n                        hi -= 1\n                    elif temp < target:\n                        lo += 1\n                    else:\n                        hi -= 1\n        return res\n# Test case\nnums = [1, 0, -1, 0, -2, 2]\ntarget = 0\nsolution = Solution()\nresult = solution.fourSum(nums, target)\nprint(result)\n"
  },
  {
    "path": "Arrays/insert_interval.cpp",
    "content": "/*\n\tInsert Interval\n\n\tIn this implementation, the `Interval` struct represents an interval with a start and end value.\n\tThe `insert` function takes a sorted list of intervals and a new interval as input and returns a new\n\tlist of intervals after merging the new interval with the existing intervals.\n\n\tHere's how the `insert` function works:\n\n\t1. It initializes an empty `result` slice to store the merged intervals and sets the index `i` to 0.\n\t2. It iterates over the existing intervals and adds intervals that end before the new interval starts to the\n\t`result` slice.\n\t3. It merges intervals that overlap with the new interval by updating the start and end values of the new\n\tinterval accordingly.\n\t4. It adds the merged new interval to the `result` slice.\n\t5. It adds any remaining intervals from the original list to the `result` slice.\n\t6. Finally, it returns the `result` slice containing the merged intervals.\n\n\tThe `min` and `max` functions are helper functions to find the minimum and maximum of two integers.\n\n\tIn the `main` function, an example input is provided with a list of intervals and a new interval.\n\tThe `insert` function is called with these inputs, and the result is printed to the console.\n\n\tTime Complexity:\n\tThe time complexity is O(n), where n is the number of intervals in the input list. This is because we need to\n\titerate through each interval in the list to merge and insert the new interval. In the worst case, we may\n\tneed to traverse all intervals in the list.\n\n\tSpace Complexity:\n\tThe space complexity is O(n), where n is the number of intervals in the input list. This is because we\n\tcreate a new result slice to store the merged intervals, which can potentially contain all the intervals\n\tfrom the input list plus the merged new interval. Therefore, the space required is proportional to the\n\tnumber of intervals in the input list.\n\n\tOverall, the algorithm has a linear time complexity and linear space complexity with respect to the number\n\tof intervals in the input list.\n*/\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\n// Interval represents a closed interval [start, end].\nstruct Interval {\n    int start;\n    int end;\n\n    Interval(int s, int e) : start(s), end(e) {}\n};\n\nvector<Interval> insertInterval(vector<Interval>& intervals, Interval newInterval) {\n    vector<Interval> result;\n\n    // Traverse through each interval in the input list\n    // and perform the necessary merging and inserting.\n    for (const auto& interval : intervals) {\n        // If the current interval ends before the new interval starts,\n        // add it to the result as it does not overlap.\n        if (interval.end < newInterval.start) {\n            result.push_back(interval);\n        }\n        // If the current interval starts after the new interval ends,\n        // add the new interval and update it to the current interval\n        // as there won't be any more overlap with subsequent intervals.\n        else if (interval.start > newInterval.end) {\n            result.push_back(newInterval);\n            newInterval = interval;\n        }\n        // If there is an overlap between the current interval and the new interval,\n        // merge them by updating the new interval's start and end.\n        else {\n            newInterval.start = min(interval.start, newInterval.start);\n            newInterval.end = max(interval.end, newInterval.end);\n        }\n    }\n\n    // Add the final merged or inserted interval to the result.\n    result.push_back(newInterval);\n\n    return result;\n}\n\n// Utility function to print the intervals.\nvoid printIntervals(const vector<Interval>& intervals) {\n    for (const auto& interval : intervals) {\n        cout << \"[\" << interval.start << \", \" << interval.end << \"] \";\n    }\n    cout << endl;\n}\n\nint main() {\n    // Example usage\n    vector<Interval> intervals = {Interval(1, 3), Interval(6, 9)};\n    Interval newInterval(2, 5);\n\n    cout << \"Original intervals: \";\n    printIntervals(intervals);\n\n    vector<Interval> mergedIntervals = insertInterval(intervals, newInterval);\n\n    cout << \"Merged intervals: \";\n    printIntervals(mergedIntervals);\n\n    return 0;\n}\n"
  },
  {
    "path": "Arrays/insert_interval.go",
    "content": "/*\n\tInsert Interval\n\n\tIn this implementation, the `Interval` struct represents an interval with a start and end value.\n\tThe `insert` function takes a sorted list of intervals and a new interval as input and returns a new\n\tlist of intervals after merging the new interval with the existing intervals.\n\n\tHere's how the `insert` function works:\n\n\t1. It initializes an empty `result` slice to store the merged intervals and sets the index `i` to 0.\n\t2. It iterates over the existing intervals and adds intervals that end before the new interval starts to the\n\t`result` slice.\n\t3. It merges intervals that overlap with the new interval by updating the start and end values of the new\n\tinterval accordingly.\n\t4. It adds the merged new interval to the `result` slice.\n\t5. It adds any remaining intervals from the original list to the `result` slice.\n\t6. Finally, it returns the `result` slice containing the merged intervals.\n\n\tThe `min` and `max` functions are helper functions to find the minimum and maximum of two integers.\n\n\tIn the `main` function, an example input is provided with a list of intervals and a new interval.\n\tThe `insert` function is called with these inputs, and the result is printed to the console.\n\n\tTime Complexity:\n\tThe time complexity is O(n), where n is the number of intervals in the input list. This is because we need to\n\titerate through each interval in the list to merge and insert the new interval. In the worst case, we may\n\tneed to traverse all intervals in the list.\n\n\tSpace Complexity:\n\tThe space complexity is O(n), where n is the number of intervals in the input list. This is because we\n\tcreate a new result slice to store the merged intervals, which can potentially contain all the intervals\n\tfrom the input list plus the merged new interval. Therefore, the space required is proportional to the\n\tnumber of intervals in the input list.\n\n\tOverall, the algorithm has a linear time complexity and linear space complexity with respect to the number\n\tof intervals in the input list.\n*/\npackage main\n\nimport (\n\t\"fmt\"\n)\n\n// Interval represents an interval with a start and end value.\ntype Interval struct {\n\tStart int\n\tEnd   int\n}\n\n// insert merges a new interval into a sorted list of intervals.\nfunc insert(intervals []Interval, newInterval Interval) []Interval {\n\tresult := make([]Interval, 0)\n\ti := 0\n\n\t// Add intervals that end before the new interval starts\n\tfor i < len(intervals) && intervals[i].End < newInterval.Start {\n\t\tresult = append(result, intervals[i])\n\t\ti++\n\t}\n\n\t// Merge intervals that overlap with the new interval\n\tfor i < len(intervals) && intervals[i].Start <= newInterval.End {\n\t\tnewInterval.Start = min(newInterval.Start, intervals[i].Start)\n\t\tnewInterval.End = max(newInterval.End, intervals[i].End)\n\t\ti++\n\t}\n\n\t// Add the merged new interval\n\tresult = append(result, newInterval)\n\n\t// Add remaining intervals\n\tfor i < len(intervals) {\n\t\tresult = append(result, intervals[i])\n\t\ti++\n\t}\n\n\treturn result\n}\n\n// min returns the minimum of two integers.\nfunc min(a, b int) int {\n\tif a < b {\n\t\treturn a\n\t}\n\treturn b\n}\n\n// max returns the maximum of two integers.\nfunc max(a, b int) int {\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n\nfunc main() {\n\tintervals := []Interval{\n\t\t{1, 3},\n\t\t{6, 9},\n\t}\n\tnewInterval := Interval{2, 5}\n\n\tresult := insert(intervals, newInterval)\n\tfmt.Println(\"Merged Intervals:\", result)\n}\n"
  },
  {
    "path": "Arrays/insert_interval.java",
    "content": "/*\n\tInsert Interval\n\n\tIn this implementation, the `Interval` struct represents an interval with a start and end value.\n\tThe `insert` function takes a sorted list of intervals and a new interval as input and returns a new\n\tlist of intervals after merging the new interval with the existing intervals.\n\n\tHere's how the `insert` function works:\n\n\t1. It initializes an empty `result` slice to store the merged intervals and sets the index `i` to 0.\n\t2. It iterates over the existing intervals and adds intervals that end before the new interval starts to the\n\t`result` slice.\n\t3. It merges intervals that overlap with the new interval by updating the start and end values of the new\n\tinterval accordingly.\n\t4. It adds the merged new interval to the `result` slice.\n\t5. It adds any remaining intervals from the original list to the `result` slice.\n\t6. Finally, it returns the `result` slice containing the merged intervals.\n\n\tThe `min` and `max` functions are helper functions to find the minimum and maximum of two integers.\n\n\tIn the `main` function, an example input is provided with a list of intervals and a new interval.\n\tThe `insert` function is called with these inputs, and the result is printed to the console.\n\n\tTime Complexity:\n\tThe time complexity is O(n), where n is the number of intervals in the input list. This is because we need to\n\titerate through each interval in the list to merge and insert the new interval. In the worst case, we may\n\tneed to traverse all intervals in the list.\n\n\tSpace Complexity:\n\tThe space complexity is O(n), where n is the number of intervals in the input list. This is because we\n\tcreate a new result slice to store the merged intervals, which can potentially contain all the intervals\n\tfrom the input list plus the merged new interval. Therefore, the space required is proportional to the\n\tnumber of intervals in the input list.\n\n\tOverall, the algorithm has a linear time complexity and linear space complexity with respect to the number\n\tof intervals in the input list.\n*/\nimport java.util.ArrayList;\nimport java.util.List;\n\nclass Interval {\n    int start;\n    int end;\n\n    Interval(int start, int end) {\n        this.start = start;\n        this.end = end;\n    }\n}\n\npublic class InsertInterval {\n    public static List<Interval> insertInterval(List<Interval> intervals, Interval newInterval) {\n        List<Interval> result = new ArrayList<>();\n\n        // Traverse through each interval in the input list\n        // and perform the necessary merging and inserting.\n        for (Interval interval : intervals) {\n            // If the current interval ends before the new interval starts,\n            // add it to the result as it does not overlap.\n            if (interval.end < newInterval.start) {\n                result.add(interval);\n            }\n            // If the current interval starts after the new interval ends,\n            // add the new interval and update it to the current interval\n            // as there won't be any more overlap with subsequent intervals.\n            else if (interval.start > newInterval.end) {\n                result.add(newInterval);\n                newInterval = interval;\n            }\n            // If there is an overlap between the current interval and the new interval,\n            // merge them by updating the new interval's start and end.\n            else {\n                newInterval.start = Math.min(interval.start, newInterval.start);\n                newInterval.end = Math.max(interval.end, newInterval.end);\n            }\n        }\n\n        // Add the final merged or inserted interval to the result.\n        result.add(newInterval);\n\n        return result;\n    }\n\n    // Utility function to print the intervals.\n    public static void printIntervals(List<Interval> intervals) {\n        for (Interval interval : intervals) {\n            System.out.print(\"[\" + interval.start + \", \" + interval.end + \"] \");\n        }\n        System.out.println();\n    }\n\n    public static void main(String[] args) {\n        // Example usage\n        List<Interval> intervals = new ArrayList<>();\n        intervals.add(new Interval(1, 3));\n        intervals.add(new Interval(6, 9));\n        Interval newInterval = new Interval(2, 5);\n\n        System.out.print(\"Original intervals: \");\n        printIntervals(intervals);\n\n        List<Interval> mergedIntervals = insertInterval(intervals, newInterval);\n\n        System.out.print(\"Merged intervals: \");\n        printIntervals(mergedIntervals);\n    }\n}\n"
  },
  {
    "path": "Arrays/insert_interval.js",
    "content": "/*\n\tInsert Interval\n\n\tIn this implementation, the `Interval` struct represents an interval with a start and end value.\n\tThe `insert` function takes a sorted list of intervals and a new interval as input and returns a new\n\tlist of intervals after merging the new interval with the existing intervals.\n\n\tHere's how the `insert` function works:\n\n\t1. It initializes an empty `result` slice to store the merged intervals and sets the index `i` to 0.\n\t2. It iterates over the existing intervals and adds intervals that end before the new interval starts to the\n\t`result` slice.\n\t3. It merges intervals that overlap with the new interval by updating the start and end values of the new\n\tinterval accordingly.\n\t4. It adds the merged new interval to the `result` slice.\n\t5. It adds any remaining intervals from the original list to the `result` slice.\n\t6. Finally, it returns the `result` slice containing the merged intervals.\n\n\tThe `min` and `max` functions are helper functions to find the minimum and maximum of two integers.\n\n\tIn the `main` function, an example input is provided with a list of intervals and a new interval.\n\tThe `insert` function is called with these inputs, and the result is printed to the console.\n\n\tTime Complexity:\n\tThe time complexity is O(n), where n is the number of intervals in the input list. This is because we need to\n\titerate through each interval in the list to merge and insert the new interval. In the worst case, we may\n\tneed to traverse all intervals in the list.\n\n\tSpace Complexity:\n\tThe space complexity is O(n), where n is the number of intervals in the input list. This is because we\n\tcreate a new result slice to store the merged intervals, which can potentially contain all the intervals\n\tfrom the input list plus the merged new interval. Therefore, the space required is proportional to the\n\tnumber of intervals in the input list.\n\n\tOverall, the algorithm has a linear time complexity and linear space complexity with respect to the number\n\tof intervals in the input list.\n*/\nclass Interval {\n  constructor(start, end) {\n    this.start = start;\n    this.end = end;\n  }\n}\n\nfunction insertInterval(intervals, newInterval) {\n  const mergedIntervals = [];\n  let i = 0;\n\n  // Skip all intervals that end before the new interval starts\n  while (i < intervals.length && intervals[i].end < newInterval.start) {\n    mergedIntervals.push(intervals[i]);\n    i++;\n  }\n\n  // Merge intervals that overlap with the new interval\n  while (i < intervals.length && intervals[i].start <= newInterval.end) {\n    newInterval.start = Math.min(intervals[i].start, newInterval.start);\n    newInterval.end = Math.max(intervals[i].end, newInterval.end);\n    i++;\n  }\n\n  mergedIntervals.push(newInterval);\n\n  // Add the remaining intervals to the merged intervals list\n  while (i < intervals.length) {\n    mergedIntervals.push(intervals[i]);\n    i++;\n  }\n\n  return mergedIntervals;\n}\n\n// Example usage\nconst intervals = [new Interval(1, 3), new Interval(6, 9)];\nconst newInterval = new Interval(2, 5);\n\nconsole.log(\"Original intervals:\", intervals);\nconst mergedIntervals = insertInterval(intervals, newInterval);\nconsole.log(\"Merged intervals:\", mergedIntervals);\n"
  },
  {
    "path": "Arrays/insert_interval.py",
    "content": "'''\n    Insert Interval\n\t\n    In this implementation, the `Interval` struct represents an interval with a start and end value.\n\tThe `insert` function takes a sorted list of intervals and a new interval as input and returns a new\n\tlist of intervals after merging the new interval with the existing intervals.\n\n\tHere's how the `insert` function works:\n\n\t1. It initializes an empty `result` slice to store the merged intervals and sets the index `i` to 0.\n\t2. It iterates over the existing intervals and adds intervals that end before the new interval starts to the\n\t`result` slice.\n\t3. It merges intervals that overlap with the new interval by updating the start and end values of the new\n\tinterval accordingly.\n\t4. It adds the merged new interval to the `result` slice.\n\t5. It adds any remaining intervals from the original list to the `result` slice.\n\t6. Finally, it returns the `result` slice containing the merged intervals.\n\n\tThe `min` and `max` functions are helper functions to find the minimum and maximum of two integers.\n\n\tIn the `main` function, an example input is provided with a list of intervals and a new interval.\n\tThe `insert` function is called with these inputs, and the result is printed to the console.\n\n\tTime Complexity:\n\tThe time complexity is O(n), where n is the number of intervals in the input list. This is because we need to\n\titerate through each interval in the list to merge and insert the new interval. In the worst case, we may\n\tneed to traverse all intervals in the list.\n\n\tSpace Complexity:\n\tThe space complexity is O(n), where n is the number of intervals in the input list. This is because we\n\tcreate a new result slice to store the merged intervals, which can potentially contain all the intervals\n\tfrom the input list plus the merged new interval. Therefore, the space required is proportional to the\n\tnumber of intervals in the input list.\n\n\tOverall, the algorithm has a linear time complexity and linear space complexity with respect to the number\n\tof intervals in the input list.\n'''\nclass Interval:\n    def __init__(self, start, end):\n        self.start = start\n        self.end = end\n\ndef insertInterval(intervals, newInterval):\n    mergedIntervals = []\n    i = 0\n\n    # Skip all intervals that end before the new interval starts\n    while i < len(intervals) and intervals[i].end < newInterval.start:\n        mergedIntervals.append(intervals[i])\n        i += 1\n\n    # Merge intervals that overlap with the new interval\n    while i < len(intervals) and intervals[i].start <= newInterval.end:\n        newInterval.start = min(intervals[i].start, newInterval.start)\n        newInterval.end = max(intervals[i].end, newInterval.end)\n        i += 1\n\n    mergedIntervals.append(newInterval)\n\n    # Add the remaining intervals to the merged intervals list\n    while i < len(intervals):\n        mergedIntervals.append(intervals[i])\n        i += 1\n\n    return mergedIntervals\n\n# Example usage\nintervals = [\n    Interval(1, 3),\n    Interval(6, 9)\n]\nnewInterval = Interval(2, 5)\n\nprint('Original intervals:', [(i.start, i.end) for i in intervals])\nmergedIntervals = insertInterval(intervals, newInterval)\nprint('Merged intervals:', [(i.start, i.end) for i in mergedIntervals])\n"
  },
  {
    "path": "Arrays/insert_intervals.cpp",
    "content": "/* You are given an array of non-overlapping intervals intervals where intervals[i] = [starti, endi] represent the start and the end of the ith interval and intervals is sorted in ascending order by starti. You are also given an interval newInterval = [start, end] that represents the start and end of another interval.\n\nInsert newInterval into intervals such that intervals is still sorted in ascending order by starti and intervals still does not have any overlapping intervals (merge overlapping intervals if necessary).\n\nReturn intervals after the insertion.\n\nExample 1:\n\nInput: intervals = [[1,3],[6,9]], newInterval = [2,5]\nOutput: [[1,5],[6,9]]\n*/\n\n\nclass Solution {\npublic:\n   vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {\n        // get the number of intervals and initialize an index variable\n        int n = intervals.size(), i = 0;\n        // initialize a vector to store the result\n        vector<vector<int>> res;\n        \n        // loop through the intervals until the end or until the end of the first interval that comes after the new interval\n        while(i < n && intervals[i][1] < newInterval[0]){\n            // add the current interval to the result\n            res.push_back(intervals[i]);\n            i++;\n        }                           \n        // loop through the intervals that overlap with the new interval\n        while(i < n && newInterval[1] >= intervals[i][0]){\n            // update the start and end of the new interval to include the current interval\n            newInterval[0] = min(newInterval[0], intervals[i][0]);\n            newInterval[1] = max(newInterval[1], intervals[i][1]);\n            i++;\n        }\n        // add the new interval to the result\n        res.push_back(newInterval);\n        \n        // add the remaining intervals to the result\n        while(i < n){\n            res.push_back(intervals[i]);\n            i++;\n        }\n        // return the result\n        return res;\n    }\n};\n\n"
  },
  {
    "path": "Arrays/insert_intervals.go",
    "content": "// 57. Insert Interval\n// You are given an array of non-overlapping intervals intervals where intervals[i] = [starti, endi] represent the start and the end of the ith interval and intervals is sorted in ascending order by starti. You are also given an interval newInterval = [start, end] that represents the start and end of another interval.\n// Insert newInterval into intervals such that intervals is still sorted in ascending order by starti and intervals still does not have any overlapping intervals (merge overlapping intervals if necessary).\n// Return intervals after the insertion.\n// Example 1:\n// Input: intervals = [[1,3],[6,9]], newInterval = [2,5]\n// Output: [[1,5],[6,9]]\n// Example 2:\n// Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]\n// Output: [[1,2],[3,10],[12,16]]\n// Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].\n\n// CODE EXPLAINATION WITH DRY RUN:\n// The insert function takes in two inputs: an array of non-overlapping intervals represented as an array of arrays of integers (intervals), and a single interval represented as an array of integers (newInterval). The function returns the updated intervals after inserting the new interval such that the intervals remain sorted by the start value and do not overlap.\n\n// The function first initializes some variables:\n\n// n: the new interval\n// j: the array of existing intervals\n// i: a counter variable initialized to 0\n// m: the starting point of the new interval; initially set to the starting point of n\n// m1: the ending point of the new interval; initially set to the ending point of n\n// The function then enters a loop that iterates through each interval in the array of existing intervals j. For each iteration, it checks if the new interval overlaps with the current interval. An overlap occurs if any of the following conditions are met:\n\n// The starting point of the new interval is between the starting and ending points of the current interval\n// The ending point of the new interval is between the starting and ending points of the current interval\n// The new interval completely engulfs the current interval\n// If an overlap is detected, the function updates the starting point and ending point of the new interval (m and m1) based on the starting and ending points of the current interval (j[i][0] and j[i][1], respectively). It then removes the current interval from the array of existing intervals j using the append function with a slice operation that excludes the current element (append(j[:i], j[i+1:]...)) and decrements the counter variable i so that the loop will consider the next interval after removing the current one.\n\n// After iterating through all intervals in j, the function appends the new interval represented by [m, m1] to the end of the j array using the append function. Finally, the intervals in the array are sorted based on their starting points using two nested loops that swap elements if they are not in order.\n\n// Now, let's do a dry run of the example input and output:\n\n// Input:\n\n// intervals = [[1,3],[6,9]]\n// newInterval = [2,5]\n// The initial values of variables are:\n\n// n = [2,5]\n// j = [[1,3],[6,9]]\n// i = 0\n// m = 2\n// m1 = 5\n// In the first iteration of the loop, the current interval is [1,3]. Since n overlaps with this interval, m is updated to 1 and m1 is updated to 5. The current interval is removed from j, which becomes [[6,9]]. The counter variable i is decremented to account for the removal, making its value -1. In the next iteration of the loop, i is incremented to 0, so the current interval is [6,9]. Since there is no overlap between n and this interval, nothing happens. The loop exits, and the updated j array is [[1,5],[6,9]], which matches the expected output.\n\n// Thus, the function correctly inserts the new interval and sorts the resulting array.\n\npackage main\n\nimport \"fmt\"\n\nfunc insert(intervals [][]int, newInterval []int) [][]int {\n    n := newInterval\n    j := intervals\n    i := 0\n    m := n[0]  // Initialize starting point of the interval to be inserted\n    m1 := n[1]  // Initialize ending point of the interval to be inserted\n\n    for i < len(j) {\n        if n[0] >= j[i][0] && n[0] <= j[i][1] || n[1] >= j[i][0] && n[1] <= j[i][1] || n[0] <= j[i][0] && n[1] >= j[i][1] {\n            if j[i][0] < m {\n                m = j[i][0]\n            }\n            if j[i][1] > m1 {\n                m1 = j[i][1]\n            }\n            j = append(j[:i], j[i+1:]...)\n            i--\n        }\n        i++\n    }\n    s1 := []int{m, m1}\n    j = append(j, s1)\n    for i := 0; i < len(j); i++ {\n        for k := i + 1; k < len(j); k++ {\n            if j[i][0] > j[k][0] {\n                j[i], j[k] = j[k], j[i]\n            }\n        }\n    }\n    return j\n}\n\nfunc main() {\n    intervals := [][]int{{1, 3}, {6, 9}}\n    newInterval := []int{2, 5}\n    result := insert(intervals, newInterval)\n    fmt.Println(result)\n}\n"
  },
  {
    "path": "Arrays/is_monotonic.cpp",
    "content": "/*\n\tAn array is said to be monotonic in nature if it is either continuously increasing or continuously decreasing.\n\tMathematically, An array A is continuously increasing if for all i <= j, A[i] <= A[j].\n\n\tThe IsMonotonic function takes an array of integers and returns a boolean value indicating whether the array\n\tis monotonic or not. A monotonic array is one in which the elements are either non-increasing or non-decreasing.\n\n\tThe function works by initializing two boolean variables, isNonDecreasing and isNonIncreasing, to true.\n\tIt then iterates over the array from the first element to the second-to-last element, comparing each element to the next one.\n\n\tIf the current element is less than the next element, it sets isNonDecreasing to false, indicating that the\n\tarray is not non-decreasing. If the current element is greater than the next element, it sets isNonIncreasing to false,\n\tindicating that the array is not non-increasing.\n\n\tAt the end of the loop, the function returns true if either isNonDecreasing or isNonIncreasing is still true,\n\tindicating that the array is monotonic. Otherwise, it returns false.\n\n\tO(n) time | O(1) space - where n is the length of the array\n*/\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nbool IsMonotonic(vector<int>& array) {\n    bool isNonDecreasing = true; // flag to track if array is non-decreasing\n    bool isNonIncreasing = true; // flag to track if array is non-increasing\n    \n    // iterate through the array starting at index 1\n    for (int i = 1; i < array.size(); i++) {\n        if (array[i] < array[i - 1]) {\n            // if the current element is less than the previous element, array is not non-decreasing\n            isNonDecreasing = false;\n        }\n        if (array[i] > array[i - 1]) {\n            // if the current element is greater than the previous element, array is not non-increasing\n            isNonIncreasing = false;\n        }\n    }\n    \n    // if either flag is true, return true indicating that array is monotonic\n    return isNonDecreasing || isNonIncreasing;\n}\n\nint main() {\n    // example usage\n    vector<int> arr = {1, 2, 3, 3, 4, 5};\n    bool isMonotonic = IsMonotonic(arr);\n    cout << \"Array is monotonic: \" << isMonotonic << endl;\n    \n    return 0;\n}"
  },
  {
    "path": "Arrays/is_monotonic.go",
    "content": "/*\n\tAn array is said to be monotonic in nature if it is either continuously increasing or continuously decreasing.\n\tMathematically, An array A is continuously increasing if for all i <= j, A[i] <= A[j].\n\n\tThe IsMonotonic function takes an array of integers and returns a boolean value indicating whether the array\n\tis monotonic or not. A monotonic array is one in which the elements are either non-increasing or non-decreasing.\n\n\tThe function works by initializing two boolean variables, isNonDecreasing and isNonIncreasing, to true.\n\tIt then iterates over the array from the first element to the second-to-last element, comparing each element to the next one.\n\n\tIf the current element is less than the next element, it sets isNonDecreasing to false, indicating that the\n\tarray is not non-decreasing. If the current element is greater than the next element, it sets isNonIncreasing to false,\n\tindicating that the array is not non-increasing.\n\n\tAt the end of the loop, the function returns true if either isNonDecreasing or isNonIncreasing is still true,\n\tindicating that the array is monotonic. Otherwise, it returns false.\n\n\tO(n) time | O(1) space - where n is the length of the array\n*/\npackage main\n\nimport \"fmt\"\n\n\nfunc IsMonotonic(array []int) bool {\n\t// assume the array is non-decreasing until we find a decreasing element\n\tisNonDecreasing := true \n\t// assume the array is non-increasing until we find an increasing element\n\tisNonIncreasing := true \n\tfor i := 1; i < len(array); i++ {\n\t\tif array[i] < array[i - 1] {\n\t\t\t// if the current element is less than the previous element, the array is not non-decreasing\n\t\t\tisNonDecreasing = false\n\t\t}\n\t\tif array[i] > array[i - 1] {\n\t\t\t// if the current element is greater than the previous element, the array is not non-increasing\n\t\t\tisNonIncreasing = false\n\t\t}\n\t}\n\t// return true if the array is either non-decreasing or non-increasing\n\treturn isNonDecreasing || isNonIncreasing \n}\n\nfunc main() {\n\tArr := []int{1, 2, 3, 4, 5}\n\tArr2 := []int{5, 4, 3, 2, 1}\n\tfmt.Println(IsMonotonic(Arr))\n\tfmt.Println(IsMonotonic(Arr2))\n}"
  },
  {
    "path": "Arrays/is_monotonic.java",
    "content": "/*\n\tAn array is said to be monotonic in nature if it is either continuously increasing or continuously decreasing.\n\tMathematically, An array A is continuously increasing if for all i <= j, A[i] <= A[j].\n\n\tThe IsMonotonic function takes an array of integers and returns a boolean value indicating whether the array\n\tis monotonic or not. A monotonic array is one in which the elements are either non-increasing or non-decreasing.\n\n\tThe function works by initializing two boolean variables, isNonDecreasing and isNonIncreasing, to true.\n\tIt then iterates over the array from the first element to the second-to-last element, comparing each element to the next one.\n\n\tIf the current element is less than the next element, it sets isNonDecreasing to false, indicating that the\n\tarray is not non-decreasing. If the current element is greater than the next element, it sets isNonIncreasing to false,\n\tindicating that the array is not non-increasing.\n\n\tAt the end of the loop, the function returns true if either isNonDecreasing or isNonIncreasing is still true,\n\tindicating that the array is monotonic. Otherwise, it returns false.\n\n\tO(n) time | O(1) space - where n is the length of the array\n*/\npublic class Main {\n    public static boolean isMonotonic(int[] array) {\n        boolean isNonDecreasing = true; // Assume the array is non-decreasing until we find a decreasing element\n        boolean isNonIncreasing = true; // Assume the array is non-increasing until we find an increasing element\n        for (int i = 1; i < array.length; i++) {\n            if (array[i] < array[i - 1]) {\n                // If the current element is less than the previous element, the array is not non-decreasing\n                isNonDecreasing = false;\n            }\n            if (array[i] > array[i - 1]) {\n                // If the current element is greater than the previous element, the array is not non-increasing\n                isNonIncreasing = false;\n            }\n        }\n        // Return true if the array is either non-decreasing or non-increasing\n        return isNonDecreasing || isNonIncreasing;\n    }\n\n    public static void main(String[] args) {\n        int[] arr = { 1, 2, 3, 4, 5 };\n        int[] arr2 = { 5, 4, 3, 2, 1 };\n        System.out.println(isMonotonic(arr));\n        System.out.println(isMonotonic(arr2));\n    }\n}\n"
  },
  {
    "path": "Arrays/is_monotonic.js",
    "content": "/*\n\tAn array is said to be monotonic in nature if it is either continuously increasing or continuously decreasing.\n\tMathematically, An array A is continuously increasing if for all i <= j, A[i] <= A[j].\n\n\tThe IsMonotonic function takes an array of integers and returns a boolean value indicating whether the array\n\tis monotonic or not. A monotonic array is one in which the elements are either non-increasing or non-decreasing.\n\n\tThe function works by initializing two boolean variables, isNonDecreasing and isNonIncreasing, to true.\n\tIt then iterates over the array from the first element to the second-to-last element, comparing each element to the next one.\n\n\tIf the current element is less than the next element, it sets isNonDecreasing to false, indicating that the\n\tarray is not non-decreasing. If the current element is greater than the next element, it sets isNonIncreasing to false,\n\tindicating that the array is not non-increasing.\n\n\tAt the end of the loop, the function returns true if either isNonDecreasing or isNonIncreasing is still true,\n\tindicating that the array is monotonic. Otherwise, it returns false.\n\n\tO(n) time | O(1) space - where n is the length of the array\n*/\nfunction isMonotonic(array) {\n    let isNonDecreasing = true; // Assume the array is non-decreasing until we find a decreasing element\n    let isNonIncreasing = true; // Assume the array is non-increasing until we find an increasing element\n    for (let i = 1; i < array.length; i++) {\n        if (array[i] < array[i - 1]) {\n            // If the current element is less than the previous element, the array is not non-decreasing\n            isNonDecreasing = false;\n        }\n        if (array[i] > array[i - 1]) {\n            // If the current element is greater than the previous element, the array is not non-increasing\n            isNonIncreasing = false;\n        }\n    }\n    // Return true if the array is either non-decreasing or non-increasing\n    return isNonDecreasing || isNonIncreasing;\n}\n\nconst arr = [1, 2, 3, 4, 5];\nconst arr2 = [\n"
  },
  {
    "path": "Arrays/is_monotonic.py",
    "content": "'''\n\tAn array is said to be monotonic in nature if it is either continuously increasing or continuously decreasing.\n\tMathematically, An array A is continuously increasing if for all i <= j, A[i] <= A[j].\n\n\tThe IsMonotonic function takes an array of integers and returns a boolean value indicating whether the array\n\tis monotonic or not. A monotonic array is one in which the elements are either non-increasing or non-decreasing.\n\n\tThe function works by initializing two boolean variables, isNonDecreasing and isNonIncreasing, to true.\n\tIt then iterates over the array from the first element to the second-to-last element, comparing each element to the next one.\n\n\tIf the current element is less than the next element, it sets isNonDecreasing to false, indicating that the\n\tarray is not non-decreasing. If the current element is greater than the next element, it sets isNonIncreasing to false,\n\tindicating that the array is not non-increasing.\n\n\tAt the end of the loop, the function returns true if either isNonDecreasing or isNonIncreasing is still true,\n\tindicating that the array is monotonic. Otherwise, it returns false.\n\n\tO(n) time | O(1) space - where n is the length of the array\n'''\ndef is_monotonic(array):\n    is_non_decreasing = True  # Assume the array is non-decreasing until we find a decreasing element\n    is_non_increasing = True  # Assume the array is non-increasing until we find an increasing element\n    for i in range(1, len(array)):\n        if array[i] < array[i - 1]:\n            # If the current element is less than the previous element, the array is not non-decreasing\n            is_non_decreasing = False\n        if array[i] > array[i - 1]:\n            # If the current element is greater than the previous element, the array is not non-increasing\n            is_non_increasing = False\n    # Return true if the array is either non-decreasing or non-increasing\n    return is_non_decreasing or is_non_increasing\n\narr = [1, 2, 3, 4, 5]\narr2 = [5, 4, 3, 2, 1]\nprint(is_monotonic(arr))\nprint(is_monotonic(arr2))\n"
  },
  {
    "path": "Arrays/longest_peak.cpp",
    "content": "/*\n  \tWrite a function that takes in an array of integers and returns the length of the longest peak in the array.\n\tA peak is defined as adjacent integers in the array that are strictly increasing until they reach a tip (the highest value in the peak),\n\tat which point they become strictly decreasing. At least three integers are required to form a peak.\n\n\tThe code defines a function named LongestPeak that takes an array of integers as an argument and returns an integer\n\trepresenting the length of the longest \"peak\" in the array.\n\n\tA \"peak\" is defined as a sequence of integers in the array that begins with an increasing sequence of integers,\n\treaches a maximum value (the \"peak\"), and ends with a decreasing sequence of integers.\n\n\tThe function first initializes a variable longestPeak to 0, which will be used to store the length of the longest\n\tpeak found so far. It then initializes a variable i to 1, which will be used to iterate over the elements of the array.\n\n\tThe function then enters a loop that continues until i is less than len(array) - 1. Inside the loop, the function checks\n\twhether the current element at i is a peak, by comparing it to its neighboring elements. If it is not a peak, the loop continues by incrementing i.\n\n\tIf the current element at i is a peak, the function searches to the left and right of the peak to find the beginning\n\tand end of the peak. It does this by iterating left and right from the peak until it finds a decreasing sequence of\n\tintegers, using the variables leftIndex and rightIndex.\n\n\tOnce the function has found the beginning and end of the peak, it calculates the length of the peak using the formula\n\trightIndex - leftIndex - 1. If the length of the current peak is greater than the current longest peak, it updates\n\tlongestPeak to the length of the current peak.\n\n\tFinally, the function updates the value of i to be the end of the peak (rightIndex), so that the loop will skip over\n\tthe entire peak and continue iterating from the end of the peak.\n\n\tThe function returns the value of longestPeak once it has finished iterating over the array.\n\n\tThe time complexity of the LongestPeak function is O(n), where n is the length of the input array, because it iterates through the array only once.\n\n\tThe space complexity of the function is O(1), because it uses a constant amount of extra space, regardless of the size of the input array.\n*/\n#include <vector>\n\nint LongestPeak(std::vector<int>& array) {\n    int longestPeak = 0;\n    int i = 1;\n\n    while (i < array.size() - 1) {\n        // Check if i is a peak (i.e., it's greater than its neighbors)\n        bool isPeak = array[i - 1] < array[i] && array[i] > array[i + 1];\n\n        if (!isPeak) {\n            // If i is not a peak, move to the next element\n            i += 1;\n            continue;\n        }\n\n        // Search left of i to find the beginning of the peak\n        int leftIndex = i - 2;\n        while (leftIndex >= 0 && array[leftIndex] < array[leftIndex + 1]) {\n            leftIndex--;\n        }\n\n        // Search right of i to find the end of the peak\n        int rightIndex = i + 2;\n        while (rightIndex < array.size() && array[rightIndex] < array[rightIndex - 1]) {\n            rightIndex++;\n        }\n\n        // Calculate the length of the current peak\n        int currentPeak = rightIndex - leftIndex - 1;\n\n        // Update longestPeak if currentPeak is longer\n        if (currentPeak > longestPeak) {\n            longestPeak = currentPeak;\n        }\n\n        // Move i to the end of the current peak\n        i = rightIndex;\n    }\n\n    return longestPeak;\n}\n"
  },
  {
    "path": "Arrays/longest_peak.go",
    "content": "/*\n  \tWrite a function that takes in an array of integers and returns the length of the longest peak in the array.\n\tA peak is defined as adjacent integers in the array that are strictly increasing until they reach a tip (the highest value in the peak),\n\tat which point they become strictly decreasing. At least three integers are required to form a peak.\n\n\tThe code defines a function named LongestPeak that takes an array of integers as an argument and returns an integer\n\trepresenting the length of the longest \"peak\" in the array.\n\n\tA \"peak\" is defined as a sequence of integers in the array that begins with an increasing sequence of integers,\n\treaches a maximum value (the \"peak\"), and ends with a decreasing sequence of integers.\n\n\tThe function first initializes a variable longestPeak to 0, which will be used to store the length of the longest\n\tpeak found so far. It then initializes a variable i to 1, which will be used to iterate over the elements of the array.\n\n\tThe function then enters a loop that continues until i is less than len(array) - 1. Inside the loop, the function checks\n\twhether the current element at i is a peak, by comparing it to its neighboring elements. If it is not a peak, the loop continues by incrementing i.\n\n\tIf the current element at i is a peak, the function searches to the left and right of the peak to find the beginning\n\tand end of the peak. It does this by iterating left and right from the peak until it finds a decreasing sequence of\n\tintegers, using the variables leftIndex and rightIndex.\n\n\tOnce the function has found the beginning and end of the peak, it calculates the length of the peak using the formula\n\trightIndex - leftIndex - 1. If the length of the current peak is greater than the current longest peak, it updates\n\tlongestPeak to the length of the current peak.\n\n\tFinally, the function updates the value of i to be the end of the peak (rightIndex), so that the loop will skip over\n\tthe entire peak and continue iterating from the end of the peak.\n\n\tThe function returns the value of longestPeak once it has finished iterating over the array.\n\n\tThe time complexity of the LongestPeak function is O(n), where n is the length of the input array, because it iterates through the array only once.\n\n\tThe space complexity of the function is O(1), because it uses a constant amount of extra space, regardless of the size of the input array.\n*/\npackage main\n\nimport \"fmt\"\n\n// LongestPeak function takes an integer array and returns the length of the longest peak in the array.\nfunc LongestPeak(array []int) int {\n\tlongestPeak := 0\n\ti := 1\n\tfor i < len(array)-1 {\n\t\t// check if i is a peak (i.e., it's greater than its neighbors)\n\t\tisPeak := array[i-1] < array[i] && array[i] > array[i+1]\n\t\tif !isPeak {\n\t\t\t// if i is not a peak, move to the next element\n\t\t\ti += 1\n\t\t\tcontinue\n\t\t}\n\n\t\t// search left of i to find the beginning of the peak\n\t\tleftIndex := i - 2\n\t\tfor leftIndex >= 0 && array[leftIndex] < array[leftIndex+1] {\n\t\t\tleftIndex--\n\t\t}\n\n\t\t// search right of i to find the end of the peak\n\t\trightIndex := i + 2\n\t\tfor rightIndex < len(array) && array[rightIndex] < array[rightIndex-1] {\n\t\t\trightIndex++\n\t\t}\n\n\t\t// calculate the length of the current peak\n\t\tcurrentPeak := rightIndex - leftIndex - 1\n\n\t\t// update longestPeak if currentPeak is longer\n\t\tif currentPeak > longestPeak {\n\t\t\tlongestPeak = currentPeak\n\t\t}\n\n\t\t// move i to the end of the current peak\n\t\ti = rightIndex\n\t}\n\treturn longestPeak\n}\n\nfunc main() {\n\tarray := []int{1, 2, 3, 4, 5, 4, 3, 2, 1}\n\tlongestPeak := LongestPeak(array)\n\tfmt.Println(longestPeak) // Output: 9\n}"
  },
  {
    "path": "Arrays/longest_peak.java",
    "content": "/*\n  \tWrite a function that takes in an array of integers and returns the length of the longest peak in the array.\n\tA peak is defined as adjacent integers in the array that are strictly increasing until they reach a tip (the highest value in the peak),\n\tat which point they become strictly decreasing. At least three integers are required to form a peak.\n\n\tThe code defines a function named LongestPeak that takes an array of integers as an argument and returns an integer\n\trepresenting the length of the longest \"peak\" in the array.\n\n\tA \"peak\" is defined as a sequence of integers in the array that begins with an increasing sequence of integers,\n\treaches a maximum value (the \"peak\"), and ends with a decreasing sequence of integers.\n\n\tThe function first initializes a variable longestPeak to 0, which will be used to store the length of the longest\n\tpeak found so far. It then initializes a variable i to 1, which will be used to iterate over the elements of the array.\n\n\tThe function then enters a loop that continues until i is less than len(array) - 1. Inside the loop, the function checks\n\twhether the current element at i is a peak, by comparing it to its neighboring elements. If it is not a peak, the loop continues by incrementing i.\n\n\tIf the current element at i is a peak, the function searches to the left and right of the peak to find the beginning\n\tand end of the peak. It does this by iterating left and right from the peak until it finds a decreasing sequence of\n\tintegers, using the variables leftIndex and rightIndex.\n\n\tOnce the function has found the beginning and end of the peak, it calculates the length of the peak using the formula\n\trightIndex - leftIndex - 1. If the length of the current peak is greater than the current longest peak, it updates\n\tlongestPeak to the length of the current peak.\n\n\tFinally, the function updates the value of i to be the end of the peak (rightIndex), so that the loop will skip over\n\tthe entire peak and continue iterating from the end of the peak.\n\n\tThe function returns the value of longestPeak once it has finished iterating over the array.\n\n\tThe time complexity of the LongestPeak function is O(n), where n is the length of the input array, because it iterates through the array only once.\n\n\tThe space complexity of the function is O(1), because it uses a constant amount of extra space, regardless of the size of the input array.\n*/"
  },
  {
    "path": "Arrays/longest_peak.js",
    "content": "/*\n  \tWrite a function that takes in an array of integers and returns the length of the longest peak in the array.\n\tA peak is defined as adjacent integers in the array that are strictly increasing until they reach a tip (the highest value in the peak),\n\tat which point they become strictly decreasing. At least three integers are required to form a peak.\n\n\tThe code defines a function named LongestPeak that takes an array of integers as an argument and returns an integer\n\trepresenting the length of the longest \"peak\" in the array.\n\n\tA \"peak\" is defined as a sequence of integers in the array that begins with an increasing sequence of integers,\n\treaches a maximum value (the \"peak\"), and ends with a decreasing sequence of integers.\n\n\tThe function first initializes a variable longestPeak to 0, which will be used to store the length of the longest\n\tpeak found so far. It then initializes a variable i to 1, which will be used to iterate over the elements of the array.\n\n\tThe function then enters a loop that continues until i is less than len(array) - 1. Inside the loop, the function checks\n\twhether the current element at i is a peak, by comparing it to its neighboring elements. If it is not a peak, the loop continues by incrementing i.\n\n\tIf the current element at i is a peak, the function searches to the left and right of the peak to find the beginning\n\tand end of the peak. It does this by iterating left and right from the peak until it finds a decreasing sequence of\n\tintegers, using the variables leftIndex and rightIndex.\n\n\tOnce the function has found the beginning and end of the peak, it calculates the length of the peak using the formula\n\trightIndex - leftIndex - 1. If the length of the current peak is greater than the current longest peak, it updates\n\tlongestPeak to the length of the current peak.\n\n\tFinally, the function updates the value of i to be the end of the peak (rightIndex), so that the loop will skip over\n\tthe entire peak and continue iterating from the end of the peak.\n\n\tThe function returns the value of longestPeak once it has finished iterating over the array.\n\n\tThe time complexity of the LongestPeak function is O(n), where n is the length of the input array, because it iterates through the array only once.\n\n\tThe space complexity of the function is O(1), because it uses a constant amount of extra space, regardless of the size of the input array.\n*/\nfunction longestPeak(array) {\n  let longestPeak = 0;\n  let i = 1;\n\n  while (i < array.length - 1) {\n    // Check if i is a peak (i.e., it's greater than its neighbors)\n    const isPeak = array[i - 1] < array[i] && array[i] > array[i + 1];\n\n    if (!isPeak) {\n      // If i is not a peak, move to the next element\n      i += 1;\n      continue;\n    }\n\n    // Search left of i to find the beginning of the peak\n    let leftIndex = i - 2;\n    while (leftIndex >= 0 && array[leftIndex] < array[leftIndex + 1]) {\n      leftIndex--;\n    }\n\n    // Search right of i to find the end of the peak\n    let rightIndex = i + 2;\n    while (\n      rightIndex < array.length &&\n      array[rightIndex] < array[rightIndex - 1]\n    ) {\n      rightIndex++;\n    }\n\n    // Calculate the length of the current peak\n    const currentPeak = rightIndex - leftIndex - 1;\n\n    // Update longestPeak if currentPeak is longer\n    if (currentPeak > longestPeak) {\n      longestPeak = currentPeak;\n    }\n\n    // Move i to the end of the current peak\n    i = rightIndex;\n  }\n\n  return longestPeak;\n}\n\n// Test the function\nconst array = [1, 3, 2, 1, 4, 7, 3, 2, 1];\nconst result = longestPeak(array);\nconsole.log(result); // Output: 6\n"
  },
  {
    "path": "Arrays/longest_peak.py",
    "content": "'''\n    Write a function that takes in an array of integers and returns the length of the longest peak in the array.\n\tA peak is defined as adjacent integers in the array that are strictly increasing until they reach a tip (the highest value in the peak),\n\tat which point they become strictly decreasing. At least three integers are required to form a peak.\n\n\tThe code defines a function named LongestPeak that takes an array of integers as an argument and returns an integer\n\trepresenting the length of the longest \"peak\" in the array.\n\n\tA \"peak\" is defined as a sequence of integers in the array that begins with an increasing sequence of integers,\n\treaches a maximum value (the \"peak\"), and ends with a decreasing sequence of integers.\n\n\tThe function first initializes a variable longestPeak to 0, which will be used to store the length of the longest\n\tpeak found so far. It then initializes a variable i to 1, which will be used to iterate over the elements of the array.\n\n\tThe function then enters a loop that continues until i is less than len(array) - 1. Inside the loop, the function checks\n\twhether the current element at i is a peak, by comparing it to its neighboring elements. If it is not a peak, the loop continues by incrementing i.\n\n\tIf the current element at i is a peak, the function searches to the left and right of the peak to find the beginning\n\tand end of the peak. It does this by iterating left and right from the peak until it finds a decreasing sequence of\n\tintegers, using the variables leftIndex and rightIndex.\n\n\tOnce the function has found the beginning and end of the peak, it calculates the length of the peak using the formula\n\trightIndex - leftIndex - 1. If the length of the current peak is greater than the current longest peak, it updates\n\tlongestPeak to the length of the current peak.\n\n\tFinally, the function updates the value of i to be the end of the peak (rightIndex), so that the loop will skip over\n\tthe entire peak and continue iterating from the end of the peak.\n\n\tThe function returns the value of longestPeak once it has finished iterating over the array.\n\n\tThe time complexity of the LongestPeak function is O(n), where n is the length of the input array, because it iterates through the array only once.\n\n\tThe space complexity of the function is O(1), because it uses a constant amount of extra space, regardless of the size of the input array.\n\n'''\n\ndef longest_peak(array):\n    longest_peak = 0\n    i = 1\n\n    while i < len(array) - 1:\n        # Check if i is a peak (i.e., it's greater than its neighbors)\n        is_peak = array[i - 1] < array[i] > array[i + 1]\n\n        if not is_peak:\n            # If i is not a peak, move to the next element\n            i += 1\n            continue\n\n        # Search left of i to find the beginning of the peak\n        left_index = i - 2\n        while left_index >= 0 and array[left_index] < array[left_index + 1]:\n            left_index -= 1\n\n        # Search right of i to find the end of the peak\n        right_index = i + 2\n        while right_index < len(array) and array[right_index] < array[right_index - 1]:\n            right_index += 1\n\n        # Calculate the length of the current peak\n        current_peak = right_index - left_index - 1\n\n        # Update longest_peak if current_peak is longer\n        if current_peak > longest_peak:\n            longest_peak = current_peak\n\n        # Move i to the end of the current peak\n        i = right_index\n\n    return longest_peak\n\n# Test the function\narray = [1, 3, 2, 1, 4, 7, 3, 2, 1]\nresult = longest_peak(array)\nprint(result)  # Output: 6\n\n\n\narr=[1, 2, 3, 3, 4, 0, 10, 6, 5, -1, -3, 2, 3]\n\n\ndef longestPeak(arr: list) -> int:\n        ans = 0\n        # iterate through the array from index 1 to len(arr) - 1\n        for indx in range(1, len(arr) - 1):\n            # check if the current element is a peak\n            if arr[indx - 1] < arr[indx] > arr[indx + 1]:\n                # if it is a peak, then find the length of the peak\n                uphill_start = downhill_ends = indx\n                # go to the uphill start\n                while uphill_start > 0 and arr[uphill_start] > arr[uphill_start - 1]:\n                    uphill_start -= 1\n                    # go to the downhill end\n                while downhill_ends + 1 < len(arr) and arr[downhill_ends] > arr[downhill_ends + 1]:\n                    downhill_ends += 1\n                    # update the ans \n                ans = max(ans, (downhill_ends - uphill_start + 1))\n        return ans\n\n\nprint(longestPeak(arr))\n# output: 6"
  },
  {
    "path": "Arrays/majority_element.go",
    "content": "/*\nGiven an array nums of size n, return the majority element.\n\nThe majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.\n\n\n\nExample 1:\n\nInput: nums = [3,2,3]\nOutput: 3\nExample 2:\n\nInput: nums = [2,2,1,1,1,2,2]\nOutput: 2\n\n\nConstraints:\n\nn == nums.length\n1 <= n <= 5 * 104\n-109 <= nums[i] <= 109\n\n\nFollow-up: Could you solve the problem in linear time and in O(1) space?\n*/\npackage main\n\nimport \"fmt\"\n\n//Boyer-Moore Voting Algorithm\n/*\nSource(https://leetcode.com/problems/majority-element/solutions/127412/majority-element/)\nIntuition\nIf we had some way of counting instances of the majority element as +1+1+1 and\ninstances of any other element as −1-1−1, summing them would make it obvious\nthat the majority element is indeed the majority element.\n\nAlgorithm\nEssentially, what Boyer-Moore does is look for a suffix sufsufsuf of nums\nwhere suf[0]suf[0]suf[0] is the majority element in that suffix.\nTo do this, we maintain a count, which is incremented whenever we see an\ninstance of our current candidate for majority element and decremented\nwhenever we see anything else. Whenever count equals 0, we effectively\nforget about everything in nums up to the current index and consider the current\nnumber as the candidate for majority element. It is not immediately obvious\nwhy we can get away with forgetting prefixes of nums -\nconsider the following examples (pipes are inserted to separate runs of nonzero count).\n\n[7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]\n\nHere, the 7 at index 0 is selected to be the first candidate for majority element.\ncount will eventually reach 0 after index 5 is processed, so the 5 at index 6 will\nbe the next candidate. In this case, 7 is the true majority element, so by disregarding\nthis prefix, we are ignoring an equal number of majority and minority elements - therefore,\n7 will still be the majority element in the suffix formed by throwing away the first prefix.\n\n[7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 5, 5, 5, 5]\n\nNow, the majority element is 5 (we changed the last run of the array from 7s to 5s),\nbut our first candidate is still 7. In this case, our candidate is not the true majority element,\nbut we still cannot discard more majority elements than minority elements (this would imply that\n\tcount could reach -1 before we reassign candidate, which is obviously false).\n\nTherefore, given that it is impossible (in both cases) to discard more majority elements\nthan minority elements, we are safe in discarding the prefix and attempting to recursively\nsolve the majority element problem for the suffix. Eventually, a suffix will be found for\nwhich count does not hit 0, and the majority element of that suffix will necessarily be the\nsame as the majority element of the overall array.\n*/\n\nfunc MajorityElement(nums []int) int {\n    count, value := 0, 0\n    for i := range nums {\n        if count == 0 {\n         value = nums[i]\n        }\n        if value == nums[i] {\n            count++\n        } else {\n            count--\n        }\n    }\n    return value\n}\n\nfunc main() {\n\tArr := []int{2, 2, 2, 1, 1, 1, 3, 3, 3, 3, 2, 3}\n\tfmt.Println(MajorityElement(Arr))\n}"
  },
  {
    "path": "Arrays/majority_element.java",
    "content": "/*\n    Majority Element\n    Given an array nums of size n, return the majority element.\n    The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.\n\n    Example 1:\n    Input: nums = [3,2,3]\n    Output: 3\n\n    Example 2:\n    Input: nums = [2,2,1,1,1,2,2]\n    Output: 2\n*/\n\nclass Solution {\n    public int majorityElement(int[] nums) {\n        int count = 0;\n        int target = nums[0];\n        for(int i=0; i<nums.length; i++){\n            if(nums[i]==target){\n                count++;\n            }\n            else if(nums[i]!=target){\n                count--;\n            }\n            if(count==0){\n                target = nums[i];\n                count = 1;\n            }\n        }\n        return target;\n    }\n}"
  },
  {
    "path": "Arrays/maximum_subarray_sum.cpp",
    "content": "// Maximum Subarray\n/*\n\tThe maxSubarraySum function takes an integer slice arr as input and returns the maximum subarray\n\tsum as an integer.\n\n\tThe maxSoFar variable is initialized to the smallest possible integer value, since any valid subarray\n\tsum must be greater than or equal to this value. The maxEndingHere variable is initialized to 0,\n\tsince an empty subarray has a sum of 0.\n\n\tThe function then iterates through the elements of arr, updating maxEndingHere and maxSoFar as necessary.\n\tAt each iteration, the maximum ending here is updated by adding the current element to it.\n\tIf the maximum ending here becomes negative, it is reset to 0, since any subarray that includes a negative\n\tsum will not be the maximum subarray. If the maximum ending here is greater than the maximum subarray\n\tsum so far, maxSoFar is updated to the new maximum.\n\n\tFinally, the function returns maxSoFar.\n\n\tIn the main function, an example input array is defined and passed to maxSubarraySum.\n\tThe resulting maximum subarray sum is printed to the console.\n\n\tThe time complexity of the above implementation of Kadane's algorithm for finding the maximum subarray sum is O(n),\n\twhere n is the length of the input array. This is because we are iterating over each element of the array only once.\n\n\tThe space complexity of the implementation is O(1), as we are only using a constant amount of extra space for\n\tstoring the maximum subarray sum and the current subarray sum.\n\n    Example Input: arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4]\n    Example Output: 6\n    Explanation: The maximum subarray sum is [4, -1, 2, 1] which adds up to 6.\n    \n*/\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\n// Function to find the maximum subarray sum using Kadane's algorithm\nint maxSubArraySum(vector<int>& nums) {\n    int maxSum = INT_MIN;\n    int currSum = 0;\n\n    // Iterate over each element in the array\n    for (int i = 0; i < nums.size(); i++) {\n        // Add the current element to the current sum\n        currSum += nums[i];\n\n        // Update the maximum sum seen so far\n        if (currSum > maxSum) {\n            maxSum = currSum;\n        }\n\n        // If the current sum is negative, we reset it to zero\n        if (currSum < 0) {\n            currSum = 0;\n        }\n    }\n\n    // Return the maximum sum\n    return maxSum;\n}\n\n// Function to calculate maximum subarray sum using brute force approach\nint maxSubarraySumBruteForce(vector<int>& nums) {\n    int maxSum = INT_MIN; // Initialize maximum sum to smallest integer value\n    // Consider all subarrays starting from i to j and calculate their sum\n    for (int i = 0; i < nums.size(); i++) {\n        int sum = 0; // Initialize sum for each subarray\n        for (int j = i; j < nums.size(); j++) {\n            sum += nums[j]; // Add element to sum\n            // Update maxSum if sum is greater\n            if (sum > maxSum) {\n                maxSum = sum;\n            }\n        }\n    }\n    return maxSum; // Return maximum sum\n}\n\n// Driver code to test the function\nint main() {\n    // Example usage\n    vector<int> nums = {-2, 1, -3, 4, -1, 2, 1, -5, 4};\n    int maxSum = maxSubArraySum(nums);\n    cout << \"Maximum subarray sum: \" << maxSum << endl;\n    maxSum = maxSubarraySumBruteForce(nums);\n    cout << \"Maximum subarray sum using brute force: \" << maxSum << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Arrays/maximum_subarray_sum.go",
    "content": "// Maximum Subarray\n/*\n\tThe maxSubarraySum function takes an integer slice arr as input and returns the maximum subarray\n\tsum as an integer.\n\n\tThe maxSoFar variable is initialized to the smallest possible integer value, since any valid subarray\n\tsum must be greater than or equal to this value. The maxEndingHere variable is initialized to 0,\n\tsince an empty subarray has a sum of 0.\n\n\tThe function then iterates through the elements of arr, updating maxEndingHere and maxSoFar as necessary.\n\tAt each iteration, the maximum ending here is updated by adding the current element to it.\n\tIf the maximum ending here becomes negative, it is reset to 0, since any subarray that includes a negative\n\tsum will not be the maximum subarray. If the maximum ending here is greater than the maximum subarray\n\tsum so far, maxSoFar is updated to the new maximum.\n\n\tFinally, the function returns maxSoFar.\n\n\tIn the main function, an example input array is defined and passed to maxSubarraySum.\n\tThe resulting maximum subarray sum is printed to the console.\n\n\tThe time complexity of the above implementation of Kadane's algorithm for finding the maximum subarray sum is O(n),\n\twhere n is the length of the input array. This is because we are iterating over each element of the array only once.\n\n\tThe space complexity of the implementation is O(1), as we are only using a constant amount of extra space for\n\tstoring the maximum subarray sum and the current subarray sum.\n\n\tExample Input: arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4]\n    Example Output: 6\n    Explanation: The maximum subarray sum is [4, -1, 2, 1] which adds up to 6.\n\n*/\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\n// Kadanes algorithm\n// This function returns the maximum subarray sum in a given slice of integers.\n// It takes an integer slice as input and returns the maximum subarray sum as an integer.\nfunc maxSubarraySum(arr []int) int {\n\tmaxSoFar := math.MinInt32 // Initialize the maximum subarray sum to the smallest possible integer value\n\tmaxEndingHere := 0        // Initialize the maximum ending here to 0\n\n\tfor _, num := range arr {\n\t\t// Update the maximum ending here\n\t\tmaxEndingHere += num\n\n\t\t// If the maximum ending here is negative, we reset it to 0\n\t\tif maxEndingHere < 0 {\n\t\t\tmaxEndingHere = 0\n\t\t}\n\n\t\t// If the maximum ending here is greater than the maximum subarray sum so far,\n\t\t// we update the maximum subarray sum so far\n\t\tif maxEndingHere > maxSoFar {\n\t\t\tmaxSoFar = maxEndingHere\n\t\t}\n\t}\n\n\treturn maxSoFar\n}\n\n// Brute Force Solution\nfunc maxSubarraySumBruteForce(nums []int) int {\n    maxSum := math.MinInt32 // Initialize the maximum sum to the smallest possible integer\n    n := len(nums)\n\n    // Consider all possible subarrays and keep track of the maximum sum\n    for i := 0; i < n; i++ {\n        currSum := 0 // Initialize the current sum to 0\n\n        // Consider all subarrays starting from i and ending at j\n        for j := i; j < n; j++ {\n            currSum += nums[j] // Add the jth element to the current sum\n\n            // Update the maximum sum if the current sum is greater\n            if currSum > maxSum {\n                maxSum = currSum\n            }\n        }\n    }\n\n    return maxSum\n}\n\n\nfunc main() {\n\tarr := []int{-2, 1, -3, 4, -1, 2, 1, -5, 4}\n\tmaxSum := maxSubarraySum(arr)\n\tfmt.Println(\"Maximum subarray sum:\", maxSum)\n\tmaxSum = maxSubarraySumBruteForce(arr)\n\tfmt.Println(\"Maximum subarray sum using brute force:\", maxSum)\n}\n"
  },
  {
    "path": "Arrays/maximum_subarray_sum.py",
    "content": "'''\n    The max_subarray_sum function takes an array arr as input and returns the maximum sum of a \n    contiguous subarray in the given array.\n\n    The function initializes two variables curr_sum and max_sum to the first element of the array. \n    It then loops through the rest of the array starting from the second element.\n\n    Inside the loop, the function updates the curr_sum variable by adding the current element to it. \n    If the current sum is less than the current element, it means that starting a new subarray at this \n    point will result in a greater sum, so the function starts a new subarray with the current element. \n    The max_sum variable is then updated with the maximum value of max_sum and curr_sum.\n\n    Once the loop is finished, the function returns the max_sum variable as the maximum sum of a \n    contiguous subarray in the given array.\n\n    The time complexity of this algorithm is O(n), where n is the length of the input array, \n    since we only loop through the array once. \n    \n    The space complexity is O(1), since we only use \n    a constant amount of extra space to store the current sum and maximum sum variables.\n    \n    Example Input: arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4]\n    Example Output: 6\n    Explanation: The maximum subarray sum is [4, -1, 2, 1] which adds up to 6.\n    \n'''\ndef max_subarray_sum(arr):\n    \"\"\"\n    Returns the maximum sum of a contiguous subarray in the given array.\n\n    Parameters:\n    arr (list): A list of integers.\n\n    Returns:\n    int: The maximum sum of a contiguous subarray.\n\n    \"\"\"\n\n    # Initialize variables to keep track of the current sum and maximum sum\n    curr_sum = max_sum = arr[0]\n\n    # Loop through the array starting from the second element\n    for i in range(1, len(arr)):\n\n        # Update the current sum by adding the current element\n        curr_sum += arr[i]\n\n        # If the current sum is less than the current element, start a new subarray\n        curr_sum = max(curr_sum, arr[i])\n\n        # Update the maximum sum if the current sum is greater\n        max_sum = max(max_sum, curr_sum)\n\n    # Return the maximum sum\n    return max_sum\n\narr = [-2, 1, -3, 4, -1, 2, 1, -5, 4]\nprint(max_subarray_sum(arr))"
  },
  {
    "path": "Arrays/merge_intervals.cpp",
    "content": "/* Array: Merge intervals in C++ #1113\nGiven an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.\n\nExample 1:\n\nInput: intervals = [[1,3],[2,6],[8,10],[15,18]]\nOutput: [[1,6],[8,10],[15,18]]\nExplanation: Since intervals [1,3] and [2,6] overlap, merge them into [1,6].\n*/\n\n\nclass Solution {\npublic:\n    vector<vector<int>> merge(vector<vector<int>>& intervals) {\n        vector<vector<int>>v;  // Create an empty vector of vectors to store the merged intervals\n        sort(intervals.begin(), intervals.end());  // Sort the intervals based on their start times\n        vector<int>v1=intervals[0];  // Initialize the first merged interval to be the first interval in the sorted list\n        for(int i=1; i<intervals.size(); i++){  // Iterate through the sorted intervals starting from the second interval\n            if(v1[1]<intervals[i][0]){  \n            // If the end time of the current merged interval is less than the start time of the next interval, then they don't overlap\n                v.push_back(v1);  // Add the current merged interval to the output vector\n                v1=intervals[i];  // Update the current merged interval to be the next interval\n            }\n            else{  // If the current merged interval and the next interval overlap\n                v1[1]=max(v1[1], intervals[i][1]);  // Update the end time of the current merged interval to be the maximum of the two end times\n            }\n        }\n        v.push_back(v1);  // Add the last merged interval to the output vector\n        return v;  // Return the vector of merged intervals\n    }\n};\n\n// TIME COMPLEXITY : O(n log n)\n// SPACE COMPLEXITY : O(n)\n"
  },
  {
    "path": "Arrays/merge_intervals.go",
    "content": "/*\n   Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals,\n   and return an array of the non-overlapping intervals that cover all the intervals in the input.\n\n   Sample Input: [[1, 2], [3, 5], [4, 7], [6, 8], [9, 10]]\n   Output: [[1, 2], [3, 8], [9, 10]]\n\n   Explanation:\n\n   The function takes an array of intervals as input.\n   First, a copy of the input intervals is made and sorted by the start time of each interval. This is stored in a\n   temporary variable called sortedIntervals.\n   A new array called mergedIntervals is created to store the merged intervals. The first interval in sortedIntervals\n   is added to mergedIntervals to start the merging process.\n   Next, a loop iterates through each interval in sortedIntervals. For each interval, the start and end times of\n   the current interval and the next interval are compared. If they overlap, the end time of the current interval\n   is updated to the maximum of the two end times.\n   If they don't overlap, the next interval becomes the current interval and is added to mergedIntervals.\n   The loop continues until all intervals have been compared and merged, and the final mergedIntervals array\n   is returned.\n   To find the maximum of two numbers, the function uses a helper function called max. This function simply\n   compares the two numbers and returns the greater one.\n\n   Time complexity O(nlog(n))\n   Space complexity: | O(n) where n is the length of the input array\n*/\npackage main\n\nimport \"sort\"\n\n// function to merge overlapping intervals\nfunc MergeOverlappingIntervals(intervals [][]int) [][]int {\n\n    // make a copy of the input intervals to sort\n    sortedIntervals := make([][]int, len(intervals))\n    copy(sortedIntervals, intervals)\n\n    // sort the intervals by their start time\n    sort.Slice(sortedIntervals, func(i, j int) bool {\n        return sortedIntervals[i][0] < sortedIntervals[j][0]\n    })\n\n    // create an empty list to store the merged intervals\n    mergedIntervals := make([][]int, 0)\n\n    // set the current interval to the first interval in the sorted list\n    currentInterval := sortedIntervals[0]\n\n    // add the current interval to the merged intervals list\n    mergedIntervals = append(mergedIntervals, currentInterval)\n\n    // loop through the sorted intervals starting from the second interval\n    for _, nextInterval := range sortedIntervals[1:] {\n\n        // print the start and end time of the next interval (for debugging purposes)\n        print(nextInterval[0], \" \", nextInterval[1], \"-->\")\n\n        // get the end time of the current interval and the start and end time of the next interval\n        currentIntervalEnd := currentInterval[1]\n        nextIntervalStart, nextIntervalEnd := nextInterval[0], nextInterval[1]\n\n        // if the end time of the current interval is greater than or equal to the start time of the next interval,\n        // then the two intervals overlap and should be merged\n        if currentIntervalEnd >= nextIntervalStart {\n\n            // set the end time of the current interval to the maximum of its current end time and the end time of the next interval\n            currentInterval[1] = max(currentIntervalEnd, nextIntervalEnd)\n\n        } else {\n            // if the two intervals do not overlap, then the next interval becomes the new current interval and is added to the merged intervals list\n            currentInterval = nextInterval\n            mergedIntervals = append(mergedIntervals, currentInterval)\n        }\n    }\n\n    // return the list of merged intervals\n    return mergedIntervals\n}\n\n// function to return the maximum of two integers\nfunc max(a, b int) int {\n    if a > b {\n        return a\n    }\n    return b\n}\n"
  },
  {
    "path": "Arrays/merge_intervals.java",
    "content": "/* Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.\n\nExample 1:\n\nInput: intervals = [[1,3],[2,6],[8,10],[15,18]]\nOutput: [[1,6],[8,10],[15,18]]\nExplanation: Since intervals [1,3] and [2,6] overlap, merge them into [1,6]. */\n\n\n\n\n\n\n\nint len = intervals.length;  // Get the length of the input intervals array\nint i = 0;  // Initialize a variable to keep track of the current interval being merged\nList<int[]> result = new ArrayList<>();  // Create an empty ArrayList to store the merged intervals\nArrays.sort(intervals, Comparator.comparingInt(a -> a[0]));  // Sort the intervals based on their start times using a lambda expression\nint first = intervals[i][0];  // Initialize the start time of the first merged interval to be the start time of the first interval in the sorted list\nint second = intervals[i][1];  // Initialize the end time of the first merged interval to be the end time of the first interval in the sorted list\n\nwhile (i < len) {  // Iterate through the intervals until all have been merged\n    if (intervals[i][0] <= second) {  // If the start time of the current interval is less than or equal to the end time of the current merged interval, they overlap\n        second = Math.max(second, intervals[i][1]);  // Update the end time of the current merged interval to be the maximum of the two end times\n    } else {  // If the current interval does not overlap with the current merged interval\n        result.add(new int[]{first, second});  // Add the current merged interval to the output list\n        first = intervals[i][0];  // Update the start time of the current merged interval to be the start time of the current interval\n        second = intervals[i][1];  // Update the end time of the current merged interval to be the end time of the current interval\n    }\n    i++;  // Move on to the next interval\n}\nresult.add(new int[]{first, second});  // Add the last merged interval to the output list\nreturn result.toArray(new int[0][]);  // Convert the output ArrayList to an array and return it\n\n"
  },
  {
    "path": "Arrays/merge_intervals.js",
    "content": "/*\n\tProblem definition:\n\t\tGiven an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, \n\t\tand return an array of the non-overlapping intervals that cover all the intervals in the input.\n\n\tApproach:\n\t\tThe approach is to first sort the intervals by their start times. \n\t\tThen we initialize a new merged intervals array and loop through all the intervals. \n\t\tFor each interval, if the merged array is empty or \n\t\tthe current interval does not overlap with the previous interval, \n\t\tthen we add the current interval to the merged array. \n\t\tOtherwise, we merge the current interval with the previous interval \n\t\tby updating the end time of the previous interval to the maximum of \n\t\tits original end time and the end time of the current interval. \n\t\tFinally, we return the merged array.\n\n\tComplexity:\n\t\tThe time complexity of this solution is O(n log n) due to the initial sorting step. \n\t\tThe space complexity is O(n) to store the merged intervals array.\n\n\tSample input/outputs:\n\t\tExample 1:\n\t\tInput: [[1,4],[4,5]]\n\t\tOutput: [[1,5]]\n\n\t\tExample 2:\n\t\tInput: [[1,3],[2,6],[8,10],[9,12]]\n\t\tOutput: [[1,6],[8,12]]\n\n\t\tExample 3:\n\t\tInput: [[1,4],[0,4]]\n\t\tOutput: [[0,4]]\n*/\n\nfunction merge(intervals) {\n    // Sort the intervals by their start times\n    intervals.sort((a, b) => a[0] - b[0]);\n  \n    // Initialize a new merged intervals array\n    const merged = [];\n  \n    // Loop through all the intervals\n    for (let i = 0; i < intervals.length; i++) {\n      let interval = intervals[i];\n  \n      // If the merged array is empty or the current interval does not overlap with the previous interval\n      // then add the current interval to the merged array\n      if (merged.length === 0 || interval[0] > merged[merged.length - 1][1]) {\n        merged.push(interval);\n      } else {\n        // Otherwise, merge the current interval with the previous interval\n        merged[merged.length - 1][1] = Math.max(merged[merged.length - 1][1], interval[1]);\n      }\n    }\n  \n    // Return the merged array\n    return merged;\n  }\n  \n  // Example usage:\n  const intervals = [[1,3],[2,6],[8,10],[15,18]];\n  console.log(merge(intervals)); // [[1,6],[8,10],[15,18]]\n  "
  },
  {
    "path": "Arrays/merge_intervals.py",
    "content": "#Program Author : TheCodeVenturer [Niraj Modi]\n'''\n    Problem definition:\n\t\tGiven an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, \n\t\tand return an array of the non-overlapping intervals that cover all the intervals in the input.\n\n    Approach:\n        The Approach to this problem is that it will be more easier if we start merging the time linear increasing fashion\n        To Make It in Linear Increasing Fashion We will Sort the Array \n        Then will initialise a new mergeIntervals Array. Here, sol\n        then will pick the first starting and ending point and will iterate through the array .Here, start,end\n        and insert it if the new start time is Greater then previous one(end) or will merge it with previous Start Time,end Time(start,end).\n        and at finally when the loop is over again will insert the start and end for the final Interval\n        then Will the mergedIntervals Array\n    Complexity:\n        Time Complexity: O(n logn) for sorting the array and additional O(n) for the complete iteration\n                All Over It will be O(n logn)\n        Space Complexity: O(1) as we are not using any extra Spaces\n                Space to Store Solution is not counted in Space complexity\n    Sample input/outputs:\n\t\tExample 1:\n\t\tInput: [[1,9],[4,5]]\n\t\tOutput: [[1,9]]\n\n\t\tExample 2:\n\t\tInput: [[1,3],[2,6],[8,10],[9,12]]\n\t\tOutput: [[1,6],[8,12]]\n\n\t\tExample 3:\n\t\tInput: [[1,4],[0,2]]\n\t\tOutput: [[0,4]]\n'''\n\nclass Solution(object):\n    def mergeIntervals(self, Intervals):\n        Intervals.sort()   # Sorting the Intervals to make the Array in Linear Increasing Fashion             \n        sol = []            # MergedIntervals Array Initialisation\n        start = Intervals[0][0]   \n        end = Intervals[0][1]\n        #setting up the first start and end Point\n        for [l, u] in Intervals:\n            # if l (current start) is Greater then previous end then will add it to mergedIntervals Array\n            # else will update the end with the greater end that is max(end,u)\n            if (l > end):\n                sol.append([start, end])\n                start, end = l, u\n            else:\n                end = max(end, u)\n        #finally adding the final start and end point to sol\n        sol.append([start, end])\n        return sol\nif __name__ == \"__main__\":\n    Intervals = [[1,3],[2,6],[8,10],[9,12]]\n    sol = Solution()\n    print(sol.mergeIntervals(Intervals))\n"
  },
  {
    "path": "Arrays/merge_sorted_array.cpp",
    "content": "/*\nProblem Statement :- You are given two integer arrays nums1 and nums2, sorted in non-decreasing order,\nand two integers m and n, representing the number of elements in nums1 and nums2 respectively.\nMerge nums1 and nums2 into a single array sorted in non-decreasing order.\nThe final sorted array should not be returned by the function, but instead be stored inside the array nums1. \nTo accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that should be merged, \nand the last n elements are set to 0 and should be ignored. nums2 has a length of n.\nExample 1 :-\nInput: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3\nOutput: [1,2,2,3,5,6]\nExplanation: The arrays we are merging are [1,2,3] and [2,5,6].\nThe result of the merge is [1,2,2,3,5,6] with the underlined elements coming from nums1.\nExample 2 :-\nInput: nums1 = [1], m = 1, nums2 = [], n = 0\nOutput: [1]\nExplanation: The arrays we are merging are [1] and [].\nThe result of the merge is [1].\nExample 3 :-\nInput: nums1 = [0], m = 0, nums2 = [1], n = 1\nOutput: [1]\nExplanation: The arrays we are merging are [] and [1].\nThe result of the merge is [1].\nNote that because m = 0, there are no elements in nums1. The 0 is only there to ensure the merge result can fit in nums1.\n*/\n// Two Pointer Approch From index 0;\n\nvoid merge( vector < int > & nums1 , int m , vector< int > & nums2 , int n ) {\n        int i , j = 0 , u = 0 ;\n        vector< int > temp ;\n        \n        for( i = 0 ; i < m ; i++ )\n            temp.push_back( nums1[i] ) ;       // Copying the element form num1 that is needed to merged\n            \n        i = 0 ;\n        while( i < m && j < n ){\n        \n            if( temp[i] > nums2[j] ) \n                nums1[ u++ ] = nums2[ j++ ] ;\n            else\n                nums1[ u++ ] = temp[ i++ ] ;\n        }\n        \n         while( i < m )\n            nums1[ u++ ] = temp[ i++ ] ;\n            \n         while( j < n )\n            nums1[ u++ ] = nums2[ j++ ] ;\n            \n}\n\n// Two Pointer Approch From index last\n\n void merge( vector< int > & nums1 , int m , vector< int > & nums2 , int n ) {\n       \n        int  j = n-1 , i = m-1 , k = m+n-1 ;\n        \n        while( j >= 0 ){\n            if( i >= 0 && nums1[ i ] > nums2[ j ] ) \n                nums1[ k-- ] = nums1[ i-- ] ;\n            else\n                nums1[ k-- ] = nums2[ j-- ] ;\n                \n        }\n    }\n/*\nTip :- Dry Run this code on Copy to Understand the key factors.\n*/\n"
  },
  {
    "path": "Arrays/merge_sorted_array.java",
    "content": "//You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, and two integers\n// m and n, representing the number of elements in nums1 and nums2 respectively.\n\n//Merge nums1 and nums2 into a single array sorted in non-decreasing order.\n\n//The final sorted array should not be returned by the function, but instead be stored inside the array nums1.\n// To accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that\n// should be merged, and the last n elements are set to 0 and should be ignored. nums2 has a length of n.\n\n\nimport java.util.Arrays;\n\nclass merge_sorted_array{\n\n    public void merge(int[] nums1, int m, int[] nums2, int n){\n        int[] merged=new int[m+n]; //new merged array\n        //copying the first m elements from nums1 to the merged array\n        if (m >= 0) System.arraycopy(nums1, 0, merged, 0, m);\n        //copying the first n elements from nums2 to the merged array\n        if (n >= 0) System.arraycopy(nums2, 0, merged, m + 0, n);\n        //sorting the merged array\n        Arrays.sort(merged);\n        //copying the merged array to the nums1 array\n        System.arraycopy(merged, 0, nums1, 0, nums1.length);\n    }\n\n    public static void main(String[] args){\n        int[] nums1 = {1, 2, 3, 0, 0, 0};\n        int m = 3, n = 3;\n        int[] nums2 ={2, 5, 6};\n\n        merge_sorted_array is = new merge_sorted_array();\n        is.merge(nums1, m, nums2, n);\n        for (int j : nums1) {\n            System.out.print(j + \" \");\n        }\n    }\n}\n"
  },
  {
    "path": "Arrays/merge_sorted_arrays.py",
    "content": "class Solution:\n    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:\n        \"\"\"\n        Do not return anything, modify nums1 in-place instead.\n        \"\"\"\n        #Time Complexity - O(M+N)\n        #Space Complexity - O(1)\n\n        #Using similar to merge sort algorithm implementation.\n        #Traversing in reverse order and comparing m,n values.\n        #Placing the highest element last and continuing with the algorithm. \n        i, j, k = m - 1, n - 1, m + n - 1\n        while(i >= 0 and j >= 0):\n            if(nums1[i] > nums2[j]):\n                nums1[k] = nums1[i]\n                i -= 1\n                k -= 1\n            else:\n                nums1[k] = nums2[j]\n                j -= 1\n                k -= 1\n        \n        #placing left over elements from num1 to nums1\n        while(i >= 0):\n            nums1[k] = nums1[i]\n            i -= 1\n            k -= 1\n        \n        #placing left over elements from num2 to num1\n        while(j >= 0):\n            nums1[k] = nums2[j]\n            j -= 1\n            k -= 1\n"
  },
  {
    "path": "Arrays/minimum_size_subarray_sum.java",
    "content": "/**\n * Given an array of positive integers nums and a positive integer target, return the minimal length of a subarray whose sum is greater than or equal to target. If there is no such subarray, return 0 instead.\n *\n *\n *\n * Example 1:\n *\n * Input: target = 7, nums = [2,3,1,2,4,3]\n * Output: 2\n * Explanation: The subarray [4,3] has the minimal length under the problem constraint.\n * Example 2:\n *\n * Input: target = 4, nums = [1,4,4]\n * Output: 1\n * Example 3:\n *\n * Input: target = 11, nums = [1,1,1,1,1,1,1,1]\n * Output: 0\n *\n *\n * Constraints:\n *\n * 1 <= target <= 109\n * 1 <= nums.length <= 105\n * 1 <= nums[i] <= 104\n *\n * https://leetcode.com/problems/minimum-size-subarray-sum/\n */\npublic class MinimumSizeSubarraySum {\n    public static void main(String[] args) {\n        int[] nums = {2, 3, 1, 2, 4, 3};\n\n        int target = 7;\n        int ans = solve(nums, target);\n        System.out.println(ans);\n    }\n    public static int solve(int[] nums, int target) {\n        // O(N) time | O(1) space\n\n        // Sliding Window\n\n        int leftIdx = 0,\n                rightIdx = 0,\n                currentSum = 0,\n                minIdx = Integer.MAX_VALUE,\n                len = nums.length;\n\n        // Variable size sliding window: 2 - pointer\n        while (rightIdx < len) {\n            int currentNum = nums[rightIdx];\n            currentSum += currentNum;\n\n            if (currentSum >= target) { // Check id currentSum >= target\n                //Skip all left elements until currentSum < target (To find the smallest window)\n                while (currentSum >= target) {\n                    currentSum -= nums[leftIdx++];\n                }\n                int currentWindowSize = rightIdx - leftIdx + 1 + 1; // including leftIdx - 1 idx and update smallest window size.\n                minIdx = Math.min(minIdx, currentWindowSize);\n            }\n            rightIdx++;\n        }\n        return minIdx == Integer.MAX_VALUE ? 0 : minIdx;\n\n        // O(N^2) time | O(1) space\n//        int ans = Integer.MAX_VALUE, len = nums.length;\n//        for (int i = 0; i < len; i++) {;\n//            int sum = 0;\n//            for (int j = i; j < len; j++) {\n//                int currentNum = nums[j];\n//                sum += currentNum;\n//                if (sum >= target) {\n//                    ans =  Math.min(ans, j - i + 1);\n//                }\n//            }\n//        }\n//        return ans == Integer.MAX_VALUE ? 0 : ans;\n\n\n\n    }\n}\n"
  },
  {
    "path": "Arrays/move_element_to_end.cpp",
    "content": "/*\n\tMove Element to end\n\tSample Input : [1, 0, 3, 0, 0, 5] To move: 0\n\tOutput : [1, 3, 5, 0, 0, 0]\n\n\tThis is a function called MoveElementToEnd that takes an array of integers array and an integer toMove as input,\n\tand returns a modified array with all instances of toMove moved to the end of the array.\n\n\tThe function first initializes an integer variable index to 0, which will keep track of the index of the first\n\telement in the array that is not equal to toMove. Then, it loops through the array using a for loop, and if the\n\tcurrent element is not equal to toMove, it replaces the element at the index position with the current element\n\tand increments the index variable by 1. This effectively shifts all elements that are not equal to toMove to the\n\tbeginning of the array.\n\n\tNext, the function loops through the remaining elements of the array (i.e., those that were not overwritten in\n\tthe previous loop), and sets their value to toMove. This effectively moves all instances of toMove to the\n\tend of the array.\n\n\tFinally, the modified array is returned.\n\n\tO(n) time | O(1) space - where n is the length of the array\n*/\n#include <vector>\n\nstd::vector<int> MoveElementToEnd(std::vector<int>& array, int toMove) {\n    int index = 0; // initialize a variable to keep track of the index where elements should be moved to\n    for (int i = 0; i < array.size(); i++) { // loop through the entire array\n        if (array[i] != toMove) { // check if the current element is not equal to the element to be moved\n            array[index] = array[i]; // move the current element to the left side of the array by replacing the element at the current index (index) with the current element (array[i])\n            index++; // increment the index variable by 1 to keep track of the index where the next non-target element should be moved\n        }\n    }\n    for (int i = index; i < array.size(); i++) { // loop through the remaining elements in the array from index to the end\n        array[i] = toMove; // set each element to be the target element\n    }\n    return array; // return the modified array\n}\n"
  },
  {
    "path": "Arrays/move_element_to_end.go",
    "content": "/*\n\tMove Element to end\n\tSample Input : [1, 0, 3, 0, 0, 5] To move: 0\n\tOutput : [1, 3, 5, 0, 0, 0]\n\n\tThis is a function called MoveElementToEnd that takes an array of integers array and an integer toMove as input,\n\tand returns a modified array with all instances of toMove moved to the end of the array.\n\n\tThe function first initializes an integer variable index to 0, which will keep track of the index of the first\n\telement in the array that is not equal to toMove. Then, it loops through the array using a for loop, and if the\n\tcurrent element is not equal to toMove, it replaces the element at the index position with the current element\n\tand increments the index variable by 1. This effectively shifts all elements that are not equal to toMove to the\n\tbeginning of the array.\n\n\tNext, the function loops through the remaining elements of the array (i.e., those that were not overwritten in\n\tthe previous loop), and sets their value to toMove. This effectively moves all instances of toMove to the\n\tend of the array.\n\n\tFinally, the modified array is returned.\n\n\tO(n) time | O(1) space - where n is the length of the array\n*/\npackage main\n\nfunc MoveElementToEnd(array []int, toMove int) []int {\n\tindex := 0 // initialize a variable to keep track of the index where elements should be moved to\n    for i := 0; i < len(array); i++ { // loop through the entire array\n        if array[i] != toMove { // check if the current element is not equal to the element to be moved\n            array[index] = array[i] // move the current element to the left side of the array by replacing the element at the current index (index) with the current element (array[i])\n            index++ // increment the index variable by 1 to keep track of the index where the next non-target element should be moved\n        }\n    }\n    for i := index; i < len(array); i++ { // loop through the remaining elements in the array from index to the end\n        array[i] = toMove // set each element to be the target element\n    }\n    return array // return the modified array\n}\n"
  },
  {
    "path": "Arrays/move_element_to_end.java",
    "content": "/*\n\tMove Element to end\n\tSample Input : [1, 0, 3, 0, 0, 5] To move: 0\n\tOutput : [1, 3, 5, 0, 0, 0]\n\n\tThis is a function called MoveElementToEnd that takes an array of integers array and an integer toMove as input,\n\tand returns a modified array with all instances of toMove moved to the end of the array.\n\n\tThe function first initializes an integer variable index to 0, which will keep track of the index of the first\n\telement in the array that is not equal to toMove. Then, it loops through the array using a for loop, and if the\n\tcurrent element is not equal to toMove, it replaces the element at the index position with the current element\n\tand increments the index variable by 1. This effectively shifts all elements that are not equal to toMove to the\n\tbeginning of the array.\n\n\tNext, the function loops through the remaining elements of the array (i.e., those that were not overwritten in\n\tthe previous loop), and sets their value to toMove. This effectively moves all instances of toMove to the\n\tend of the array.\n\n\tFinally, the modified array is returned.\n\n\tO(n) time | O(1) space - where n is the length of the array\n*/\n\nimport java.util.List;\n\npublic class MoveElementToEnd {\n    public static List<Integer> moveElementToEnd(List<Integer> array, int toMove) {\n        int index = 0; // initialize a variable to keep track of the index where elements should be moved to\n        for (int i = 0; i < array.size(); i++) { // loop through the entire array\n            if (array.get(i) != toMove) { // check if the current element is not equal to the element to be moved\n                array.set(index, array.get(i)); // move the current element to the left side of the array by replacing the element at the current index (index) with the current element (array.get(i))\n                index++; // increment the index variable by 1 to keep track of the index where the next non-target element should be moved\n            }\n        }\n        for (int i = index; i < array.size(); i++) { // loop through the remaining elements in the array from index to the end\n            array.set(i, toMove); // set each element to be the target element\n        }\n        return array; // return the modified array\n    }\n}\n"
  },
  {
    "path": "Arrays/move_element_to_end.js",
    "content": "/*\n\tMove Element to end\n\tSample Input : [1, 0, 3, 0, 0, 5] To move: 0\n\tOutput : [1, 3, 5, 0, 0, 0]\n\n\tThis is a function called MoveElementToEnd that takes an array of integers array and an integer toMove as input,\n\tand returns a modified array with all instances of toMove moved to the end of the array.\n\n\tThe function first initializes an integer variable index to 0, which will keep track of the index of the first\n\telement in the array that is not equal to toMove. Then, it loops through the array using a for loop, and if the\n\tcurrent element is not equal to toMove, it replaces the element at the index position with the current element\n\tand increments the index variable by 1. This effectively shifts all elements that are not equal to toMove to the\n\tbeginning of the array.\n\n\tNext, the function loops through the remaining elements of the array (i.e., those that were not overwritten in\n\tthe previous loop), and sets their value to toMove. This effectively moves all instances of toMove to the\n\tend of the array.\n\n\tFinally, the modified array is returned.\n\n\tO(n) time | O(1) space - where n is the length of the array\n*/\nfunction moveElementToEnd(array, toMove) {\n  let index = 0; // initialize a variable to keep track of the index where elements should be moved to\n  for (let i = 0; i < array.length; i++) {\n    // loop through the entire array\n    if (array[i] !== toMove) {\n      // check if the current element is not equal to the element to be moved\n      array[index] = array[i]; // move the current element to the left side of the array by replacing the element at the current index (index) with the current element (array[i])\n      index++; // increment the index variable by 1 to keep track of the index where the next non-target element should be moved\n    }\n  }\n  for (let i = index; i < array.length; i++) {\n    // loop through the remaining elements in the array from index to the end\n    array[i] = toMove; // set each element to be the target element\n  }\n  return array; // return the modified array\n}\n"
  },
  {
    "path": "Arrays/move_element_to_end.py",
    "content": "'''\n\tMove 0's to end\n\tSample Input : [1, 0, 3, 0, 0, 5]\n\tOutput : [1, 3, 5, 0, 0, 0]\n\n\tThis is a function called MoveElementToEnd that takes an array of integers array and an integer toMove as input,\n\tand returns a modified array with all instances of toMove moved to the end of the array.\n\n\tThe function first initializes an integer variable index to 0, which will keep track of the index of the first\n\telement in the array that is not equal to toMove. Then, it loops through the array using a for loop, and if the\n\tcurrent element is not equal to toMove, it replaces the element at the index position with the current element\n\tand increments the index variable by 1. This effectively shifts all elements that are not equal to toMove to the\n\tbeginning of the array.\n\n\tNext, the function loops through the remaining elements of the array (i.e., those that were not overwritten in\n\tthe previous loop), and sets their value to toMove. This effectively moves all instances of toMove to the\n\tend of the array.\n\n\tFinally, the modified array is returned.\n\n\tO(n) time | O(1) space - where n is the length of the array\n'''\ndef move_element_to_end(array, to_move):\n    index = 0 # initialize a variable to keep track of the index where elements should be moved to\n    for i in range(len(array)): # loop through the entire array\n        if array[i] != to_move: # check if the current element is not equal to the element to be moved\n            array[index] = array[i] # move the current element to the left side of the array by replacing the element at the current index (index) with the current element (array[i])\n            index += 1 # increment the index variable by 1 to keep track of the index where the next non-target element should be moved\n    for i in range(index, len(array)): # loop through the remaining elements in the array from index to the end\n        array[i] = to_move # set each element to be the target element\n    return array # return the modified array\n"
  },
  {
    "path": "Arrays/non-overlapping intervals.cpp",
    "content": "// Given an array of intervals intervals where intervals[i] = [starti, endi], return the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping.\n// Example 1:\n\n// Input: intervals = [[1,2],[2,3],[3,4],[1,3]]\n// Output: 1\n// Explanation: [1,3] can be removed and the rest of the intervals are non-overlapping.\n// Example 2:\n\n// Input: intervals = [[1,2],[1,2],[1,2]]\n// Output: 2\n// Explanation: You need to remove two [1,2] to make the rest of the intervals non-overlapping.\n// Example 3:\n\n// Input: intervals = [[1,2],[2,3]]\n// Output: 0\n// Explanation: You don't need to remove any of the intervals since they're already non-overlapping.\n \n\n// Constraints:\n// 1 <= intervals.length <= 105\n// intervals[i].length == 2\n// -5 * 104 <= starti < endi <= 5 * 104\n\n//   CODE:\n\n  class Solution {\npublic:\n    int eraseOverlapIntervals(vector<vector<int>>& intervals) {\n        sort(intervals.begin(),intervals.end());\n        int previous = 0;\n        int n = intervals.size();\n        int ans = 0;\n        for(int current = 1;current<n; current++){\n            if(intervals[current][0]<intervals[previous][1]){\n                ans++;\n                if(intervals[current][1]<=intervals[previous][1])\n                previous = current;\n            }\n           \n            else{\n                previous = current;\n\n            }\n\n        }\n        return ans;\n\n        \n    }\n};\n"
  },
  {
    "path": "Arrays/pallindromic_permutations.cpp",
    "content": "// Write a function to check if it is a permutation of a pallindrome\n// Program Author : Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\n// TC O(n) n is length of string\nbool is_permutation_pallindrome(string s){\n    // we built a hash table to count how many times each character appears\n    // we then iterate through hashtable to find out no more than one character has \n    // odd count\n    vector<int> table(26, 0);\n    bool found_odd = false;\n    for(int i = 0; i < s.length(); i++){\n        table[s[i]-'a']++; \n    }\n    for(int x : table){\n        if(x&1){\n            if(found_odd){\n                return false;\n            }\n            found_odd = true;\n        }\n    }\n    return true;\n}\nbool is_permutation_pallindrome_improved(string s){\n    // instead of checking oddcounts at end we can check \n    // as we traverse the chars in string, as soon as we reach end \n    // we have out answer.\n    vector<int> table(26, 0);\n    int count_odd = 0;\n    for(int i = 0; i < s.length(); i++){\n        int x = s[i]-'a'; \n        table[x]++;\n        if(table[x] & 1){\n            count_odd++;\n        } \n        else{\n            count_odd--;\n        }\n    }\n    return count_odd <= 1;\n}\nvoid print_ans(bool ans){\n    if(ans){\n        cout << \"YES\\n\";\n    }\n    else{\n        cout << \"NO\\n\";\n    }\n}\nint main(){\n    is_permutation_pallindrome(\"aaabdddcba\") ? print_ans(true) : print_ans(false);\n    is_permutation_pallindrome(\"abab\") ? print_ans(true) : print_ans(false);\n    is_permutation_pallindrome(\"ABA\") ? print_ans(true) : print_ans(false);\n    is_permutation_pallindrome(\"abcddeab\") ? print_ans(true) : print_ans(false);\n    cout << \"**********IMPROVED*********\\n\";\n    is_permutation_pallindrome_improved(\"a\") ? print_ans(true) : print_ans(false);\n    is_permutation_pallindrome_improved(\"ab\") ? print_ans(true) : print_ans(false);\n    is_permutation_pallindrome_improved(\"ABA\") ? print_ans(true) : print_ans(false);\n    is_permutation_pallindrome_improved(\"abcddeab\") ? print_ans(true) : print_ans(false);\n    return 0;\n}"
  },
  {
    "path": "Arrays/sign_of_the_product_of_an_array.cpp",
    "content": "// Leetcode 1822 : Sign of the Product of an Array\n/*\nQUESTION\nThere is a function signFunc(x) that returns:\n\n1 if x is positive.\n-1 if x is negative.\n0 if x is equal to 0.\nYou are given an integer array nums. Let product be the product of all values in the array nums.\nReturn signFunc(product).\nExample 1:\n\nInput: nums = [-1,-2,-3,-4,3,2,1]\nOutput: 1\nExplanation: The product of all values in the array is 144, and signFunc(144) = 1\nExample 2:\n\nInput: nums = [1,5,0,2,-3]\nOutput: 0\nExplanation: The product of all values in the array is 0, and signFunc(0) = 0\nExample 3:\n\nInput: nums = [-1,1,-1,1,-1]\nOutput: -1\nExplanation: The product of all values in the array is -1, and signFunc(-1) = -1\n\nConstraints:\n1 <= nums.length <= 1000\n-100 <= nums[i] <= 100\n\nCODE EXPLANATION WITH DRY RUN\n\nSuppose we have the following input vector:\n{-1, -2, -3, -4, 3, 2, 1}\nWe want to find the sign of the product of all elements in the vector.\n\nHere's how the code will execute:\n\n1-We define the input vector nums in the main function.\n2-We call the arraySign function with nums as the argument.\n3-The arraySign function initializes the sign variable to 1.\n4-The function iterates over each element of the nums vector using a range-based for loop.\n5-On the first iteration, num is -1. The element is negative, so the sign variable is multiplied by -1, changing its value to -1.\n6-On the second iteration, num is -2. The element is negative, so the sign variable is multiplied by -1 again, changing its value to 1.\n7-On the third iteration, num is -3. The element is negative, so the sign variable is multiplied by -1, changing its value to -1.\n8-On the fourth iteration, num is -4. The element is negative, so the sign variable is multiplied by -1 again, changing its value to 1.\n9-On the fifth iteration, num is 3. The element is positive, so the sign variable is not changed and remains 1.\n10-On the sixth iteration, num is 2. The element is positive, so the sign variable is not changed and remains 1.\n11-On the seventh iteration, num is 1. The element is positive, so the sign variable is not changed and remains 1.\n12-The arraySign function returns sign, which has a value of 1.\n13-In the main function, we check if sign is equal to 1. It is, so we print \"Product is Positive\" to the console.\nTherefore, the output of the program will be:\n\"Product is Positive\"\n*/\n#include <vector>\n#include <iostream>\nusing namespace std;\n\n// Function to find the sign of the product of all elements in the input vector\nint arraySign(vector<int> &nums)\n{\n    int ans = 1; // Initialize answer to 1\n    // Iterate over each element of the vector\n    for (int i = 0; i < nums.size(); i++)\n    {\n        // If element is negative, change answer to -1\n        if (nums[i] < 0)\n        {\n            ans *= -1;\n        }\n        // If element is zero, answer is 0 and loop is exited\n        else if (nums[i] == 0)\n        {\n            ans = 0;\n            break;\n        }\n    }\n    return ans; // Return answer\n}\n\nint main()\n{\n    // Example usage\n    vector<int> nums = {-1, -2, -3, -4, 3, 2, 1};\n    int ans = arraySign(nums); // Print the sign of the product of the vector\n    if (ans == 1)\n    {\n        cout << \"Product is Positive\";\n    }\n    else if (ans == -1)\n    {\n        cout << \"Product is Negative\";\n    }\n    else\n    {\n        cout << \"Product is Zero\";\n    }\n    return 0;\n}"
  },
  {
    "path": "Arrays/smallest_difference.cpp",
    "content": "/*\n\tWrite a function that takes in two non-empty arrays of integers, finds the pair of numbers (one from each array)\n\twhose absolute difference is closest to zero, and returns an array containing these two numbers, with the number from\n\tthe first array in the first position.\n\n\tNote that the absolute difference of two integers is the distance between them on the real number line.\n\tFor example, the absolute difference of -5 and 5 is 10, and the absolute difference of -5 and -4 is 1.\n\n  \tYou can assume that there will only be one pair of numbers with the smallest difference.\n\n\tSample Input Array1 = [-1, 5, 10, 20, 28, 3]\n\tSample Input Array2 = [26, 134, 135, 15, 17]\n\n\tSample Output = [28, 26]\n\n\n    The code finds the pair of elements from two arrays, array1 and array2, whose absolute difference is the smallest \n    among all possible pairs. It does this by first sorting both arrays and then using two pointers (idx1 and idx2) \n    to iterate through the arrays. At each iteration, it compares the current element of array1 and array2, \n    and updates smallest (the smallest absolute difference so far) and result (the pair of elements that give \n    the smallest absolute difference) if the absolute difference between the current elements is smaller than \n    the current smallest. The function returns the result at the end.\n\n    Time complexity: O(nlog(n) + mlog(m)), where n and m are the lengths of array1 and array2, respectively\n    Space complexity: O(1)\n*/\n#include <iostream>\n#include <algorithm>\n#include <vector>\n#include <cmath>\n\nusing namespace std;\n\n// SmallestDifference takes in two Vector of integers and returns a pair of integers, one from each Vector, such that their\n// absolute difference is as close to zero as possible. If multiple pairs have the same absolute difference, SmallestDifference\n// returns the pair whose elements come first in the respective slices.\nvector<int> SmallestDifference(vector<int> array1, vector<int> array2) {\n    // Initialize variables to track the smallest absolute difference seen so far and the current absolute difference\n    int current = INT_MAX, smallest = INT_MAX;\n    // Sort the input arrays in ascending order to enable efficient searching for the pair with the smallest absolute difference\n    sort(array1.begin(), array1.end());\n    sort(array2.begin(), array2.end());\n    // Initialize variables to track the current index in each array\n    int idx1 = 0, idx2 = 0;\n    // Initialize an empty vector to store the pair of integers with the smallest absolute difference\n    vector<int> result;\n    // Loop through both arrays until the end of at least one of them is reached\n    while (idx1 < array1.size() && idx2 < array2.size()) {\n        // Get the current elements from both arrays\n        int first = array1[idx1], second = array2[idx2];\n        // Compute the absolute difference between the current elements\n        if (first < second) {\n            current = second - first;\n            idx1++;\n        } else if (second < first) {\n            current = first - second;\n            idx2++;\n        } else {\n            // If the current elements are equal, we have found a pair with an absolute difference of 0 and can return it\n            return vector<int>{first, second};\n        }\n        // If the current absolute difference is smaller than the smallest seen so far, update the smallest difference and the result vector\n        if (smallest > current) {\n            smallest = current;\n            result = vector<int>{first, second};\n        }\n    }\n    // Return the pair of integers with the smallest absolute difference\n    return result;\n}\n\n\nint main() {\n    vector<int> array1 = {1, 3, 15, 11, 2};\n    vector<int> array2 = {23, 127, 235, 19, 8};\n    vector<int> result = SmallestDifference(array1, array2);\n    cout << \"Smallest difference pair: [\" << result[0] << \", \" << result[1] << \"]\" << endl;\n    return 0;\n}\n"
  },
  {
    "path": "Arrays/smallest_difference.go",
    "content": "/*\n\tWrite a function that takes in two non-empty arrays of integers, finds the pair of numbers (one from each array)\n\twhose absolute difference is closest to zero, and returns an array containing these two numbers, with the number from\n\tthe first array in the first position.\n\n\tNote that the absolute difference of two integers is the distance between them on the real number line.\n\tFor example, the absolute difference of -5 and 5 is 10, and the absolute difference of -5 and -4 is 1.\n\n  \tYou can assume that there will only be one pair of numbers with the smallest difference.\n\n\tSample Input Array1 = [-1, 5, 10, 20, 28, 3]\n\tSample Input Array2 = [26, 134, 135, 15, 17]\n\n\tSample Output = [28, 26]\n\n\n\tThis code implements the Smallest Difference problem which takes two arrays of integers as input and returns a pair of integers,\n\tone from each array, with the smallest absolute difference between them.\n\n\tThe function first initializes two variables current and smallest to the maximum integer value. It then sorts both input arrays\n\tin ascending order using the sort.Ints function from the sort package.\n\n\tThe function then iterates through both arrays using two pointers, idx1 and idx2, initialized to 0. Inside the loop, it compares\n\tthe elements at the current indices of the two arrays, first and second, and calculates the absolute difference between\n\tthem in the current variable.\n\n\tIf current is smaller than the smallest variable, it updates smallest to current and assigns the current pair of integers\n\tto the result variable.\n\n\tThe function returns the result variable, which contains the pair of integers with the smallest absolute difference.\n\n\tIf there are identical integers in the two input arrays, the function will return them immediately, without any further comparisons.\n\n\tO(nlog(n) + mlog(m)) time | O(1) space - where n is the length of the first input array and m is the length of the second input array\n*/\npackage main\n\nimport (\n\t\"math\"\n\t\"sort\"\n)\n\n// SmallestDifference takes two integer slices as input and returns a slice with two integers.\n// The two integers in the returned slice have the smallest absolute difference among all pairs\n// of integers from the two input slices.\nfunc SmallestDifference(array1, array2 []int) []int {\n\t// Initialize variables for the smallest difference and the current difference being calculated\n\tcurrent, smallest := math.MaxInt32, math.MaxInt32\n\t// Sort the input slices\n\tsort.Ints(array1)\n\tsort.Ints(array2)\n\t// Initialize variables for the indices for the two slices\n\tidx1, idx2 := 0, 0\n\t// Initialize an empty slice for the result\n\tresult := []int{}\n\t// Loop through the two slices until we reach the end of one of the slices\n\tfor idx1 < len(array1) && idx2 < len(array2) {\n\t\t// Get the values at the current indices for the two slices\n\t\tfirst, second := array1[idx1], array2[idx2]\n\t\t// Calculate the current difference between the two values\n\t\tif first < second {\n\t\t\tcurrent = second - first\n\t\t\tidx1++\n\t\t} else if second < first {\n\t\t\tcurrent = first - second\n\t\t\tidx2++\n\t\t} else {\n\t\t\t// If the two values are equal, we can return the pair\n\t\t\treturn []int{first, second}\n\t\t}\n\t\t// Update the smallest difference and result slice if the current difference is smaller\n\t\tif smallest > current {\n\t\t\tsmallest = current\n\t\t\tresult = []int{first, second}\n\t\t}\n\t}\n\t// Return the pair with the smallest absolute difference\n\treturn result\n}\n"
  },
  {
    "path": "Arrays/smallest_difference.java",
    "content": "/*\n\tWrite a function that takes in two non-empty arrays of integers, finds the pair of numbers (one from each array)\n\twhose absolute difference is closest to zero, and returns an array containing these two numbers, with the number from\n\tthe first array in the first position.\n\n\tNote that the absolute difference of two integers is the distance between them on the real number line.\n\tFor example, the absolute difference of -5 and 5 is 10, and the absolute difference of -5 and -4 is 1.\n\n  \tYou can assume that there will only be one pair of numbers with the smallest difference.\n\n\tSample Input Array1 = [-1, 5, 10, 20, 28, 3]\n\tSample Input Array2 = [26, 134, 135, 15, 17]\n\n\tSample Output = [28, 26]\n\n\n\tThis code implements the Smallest Difference problem which takes two arrays of integers as input and returns a pair of integers,\n\tone from each array, with the smallest absolute difference between them.\n\n\tThe function first initializes two variables current and smallest to the maximum integer value. It then sorts both input arrays\n\tin ascending order using the sort.Ints function from the sort package.\n\n\tThe function then iterates through both arrays using two pointers, idx1 and idx2, initialized to 0. Inside the loop, it compares\n\tthe elements at the current indices of the two arrays, first and second, and calculates the absolute difference between\n\tthem in the current variable.\n\n\tIf current is smaller than the smallest variable, it updates smallest to current and assigns the current pair of integers\n\tto the result variable.\n\n\tThe function returns the result variable, which contains the pair of integers with the smallest absolute difference.\n\n\tIf there are identical integers in the two input arrays, the function will return them immediately, without any further comparisons.\n\n\tO(nlog(n) + mlog(m)) time | O(1) space - where n is the length of the first input array and m is the length of the second input array\n*/\nimport java.util.Arrays;\n\npublic class Main {\n\n    public static int[] smallestDifference(int[] array1, int[] array2) {\n        // Initialize variables for the smallest difference and the current difference being calculated\n        int current = Integer.MAX_VALUE;\n        int smallest = Integer.MAX_VALUE;\n\n        // Sort the input arrays\n        Arrays.sort(array1);\n        Arrays.sort(array2);\n\n        // Initialize variables for the indices for the two arrays\n        int idx1 = 0;\n        int idx2 = 0;\n\n        // Initialize an empty array for the result\n        int[] result = new int[2];\n\n        // Loop through the two arrays until we reach the end of one of the arrays\n        while (idx1 < array1.length && idx2 < array2.length) {\n            // Get the values at the current indices for the two arrays\n            int first = array1[idx1];\n            int second = array2[idx2];\n\n            // Calculate the current difference between the two values\n            if (first < second) {\n                current = second - first;\n                idx1++;\n            } else if (second < first) {\n                current = first - second;\n                idx2++;\n            } else {\n                // If the two values are equal, we can return the pair\n                return new int[]{first, second};\n            }\n\n            // Update the smallest difference and result array if the current difference is smaller\n            if (smallest > current) {\n                smallest = current;\n                result[0] = first;\n                result[1] = second;\n            }\n        }\n\n        // Return the pair with the smallest absolute difference\n        return result;\n    }\n\n    public static void main(String[] args) {\n        int[] array1 = {1, 3, 5, 23, 11, 2};\n        int[] array2 = {8, 19, 3, 15, 9};\n\n        int[] result = smallestDifference(array1, array2);\n        System.out.println(Arrays.toString(result));  // Output: [3, 3]\n    }\n}\n"
  },
  {
    "path": "Arrays/smallest_difference.js",
    "content": "/*\n    Write a function that takes in two non-empty arrays of integers, finds the pair of numbers (one from each array)\n\twhose absolute difference is closest to zero, and returns an array containing these two numbers, with the number from\n\tthe first array in the first position.\n\n\tNote that the absolute difference of two integers is the distance between them on the real number line.\n\tFor example, the absolute difference of -5 and 5 is 10, and the absolute difference of -5 and -4 is 1.\n\n  \tYou can assume that there will only be one pair of numbers with the smallest difference.\n\n\tSample Input Array1 = [-1, 5, 10, 20, 28, 3]\n\tSample Input Array2 = [26, 134, 135, 15, 17]\n\n\tSample Output = [28, 26]\n    The smallestDifference function takes in two arrays of integers and finds the pair of values (one from each array) \n    that have the smallest difference. It does this by sorting the two arrays in ascending order, and then iterating \n    through both arrays using two index variables. At each step, the function calculates the difference between the \n    values pointed to by the index variables, updates the current difference, and moves the index of the array with \n    the smaller value to the right. If the values are equal, the function returns the pair as an array. \n    The function keeps track of the smallest difference seen so far, and updates the result array accordingly. \n    Finally, the function returns the result array containing the pair with the smallest difference.\n\n    O(nlog(n) + mlog(m)) time | O(1) space - where n is the length of the first input array and m is the length of the second input array\n*/\n/**\n * Given two arrays of integers, finds a pair of values (one value from each array)\n * that have the smallest difference. Returns the pair as an array.\n * @param {number[]} array1 - The first array of integers\n * @param {number[]} array2 - The second array of integers\n * @returns {number[]} - The pair of values that have the smallest difference\n */\nfunction smallestDifference(array1, array2) {\n  let currentDiff = Infinity; // initialize current difference to a large number\n  let smallestDiff = Infinity; // initialize smallest difference to a large number\n  let result = []; // initialize result array\n  array1.sort((a, b) => a - b); // sort the first array in ascending order\n  array2.sort((a, b) => a - b); // sort the second array in ascending order\n  let idx1 = 0; // initialize index for first array\n  let idx2 = 0; // initialize index for second array\n  while (idx1 < array1.length && idx2 < array2.length) {\n    const first = array1[idx1];\n    const second = array2[idx2];\n    if (first < second) {\n      // if the value from first array is smaller\n      currentDiff = second - first; // update the current difference\n      idx1++; // move the index of first array to the right\n    } else if (second < first) {\n      // if the value from second array is smaller\n      currentDiff = first - second; // update the current difference\n      idx2++; // move the index of second array to the right\n    } else {\n      // if the values are equal, the smallest difference is 0\n      return [first, second];\n    }\n    if (smallestDiff > currentDiff) {\n      // if the current difference is smaller than the smallest difference so far\n      smallestDiff = currentDiff; // update the smallest difference\n      result = [first, second]; // update the result array\n    }\n  }\n  return result;\n}\n"
  },
  {
    "path": "Arrays/smallest_difference.py",
    "content": "'''\n    Write a function that takes in two non-empty arrays of integers, finds the pair of numbers (one from each array)\n\twhose absolute difference is closest to zero, and returns an array containing these two numbers, with the number from\n\tthe first array in the first position.\n\n\tNote that the absolute difference of two integers is the distance between them on the real number line.\n\tFor example, the absolute difference of -5 and 5 is 10, and the absolute difference of -5 and -4 is 1.\n\n  \tYou can assume that there will only be one pair of numbers with the smallest difference.\n\n\tSample Input Array1 = [-1, 5, 10, 20, 28, 3]\n\tSample Input Array2 = [26, 134, 135, 15, 17]\n\n\tSample Output = [28, 26]\n    \n    The smallest_difference function takes two arrays of integers as input and returns a list of two integers, where the first integer \n    is from the first array and the second is from the second array, and the absolute difference between them is the smallest among \n    all such pairs. It achieves this by sorting the two arrays and then iterating through them in parallel, keeping track of the \n    current smallest difference and the pair of integers that produced it. The function returns the pair with the smallest difference.\n\n    O(nlog(n) + mlog(m)) time | O(1) space - where n is the length of the first input array and m is the length of the second input array\n'''\nfrom typing import List\nimport math\n\ndef smallest_difference(array1: List[int], array2: List[int]) -> List[int]:\n    \"\"\"\n    Finds the pair of integers, one from each of the two given arrays, with the smallest difference between them.\n\n    Args:\n        array1: A list of integers.\n        array2: A list of integers.\n\n    Returns:\n        A list of two integers, where the first integer is from array1 and the second is from array2, and the absolute\n        difference between them is the smallest among all such pairs.\n\n    Example:\n        >>> smallest_difference([1, 3, 15, 11, 2], [23, 127, 235, 19, 8])\n        [11, 8]\n    \"\"\"\n    current = math.inf\n    smallest = math.inf\n    result = []\n\n    # Sort both input arrays in ascending order\n    array1.sort()\n    array2.sort()\n\n    # Initialize two pointers, one for each array\n    idx1, idx2 = 0, 0\n\n    # Loop through both arrays while the pointers are still within bounds\n    while idx1 < len(array1) and idx2 < len(array2):\n        first, second = array1[idx1], array2[idx2]\n\n        # Calculate the absolute difference between the two current numbers\n        current = abs(first - second)\n\n        # Update the smallest difference and the result if the current difference is smaller\n        if current < smallest:\n            smallest = current\n            result = [first, second]\n\n        # If the first number is smaller than the second number, increment the pointer\n        # for the first array, otherwise increment the pointer for the second array.\n        if first < second:\n            idx1 += 1\n        else:\n            idx2 += 1\n\n    # Return the result\n    return result\n\ndef main():\n    array1 = [1, 3, 15, 11, 2]\n    array2 = [23, 127, 235, 19, 8]\n    result = smallest_difference(array1, array2)\n    print(\"Array 1:\", array1)\n    print(\"Array 2:\", array2)\n    print(\"Smallest Difference Pair:\", result)\n\nif __name__ == \"__main__\":\n    main()"
  },
  {
    "path": "Arrays/sorted_square_array,js",
    "content": "/*\n\tWrite a function that takes in a non-empty array of integers that are sorted\n\tin ascending order and returns a new array of the same length with the squares\n\tof the original integers also sorted in ascending order.\n\n\tSample Input: [-6, 1, 2, 3, 4]\n\tOutput: [1, 4, 6, 16, 36]\n\n\tExplanation:\n\n\tThe `SortedSquaredArray` function takes an integer array as input and returns a new array where each element is the square of the corresponding element in the input array. The new array is sorted in non-decreasing order.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. Initialize an empty result array of the same length as the original array: `result := make([]int, len(array))`.\n\t2. Initialize variables to mark the start and end positions of the array, as well as the end_pos, which is the \n\t   index of the last element in the result array: `end_pos := len(array) - 1`, `start := 0`, `end := len(array) - 1`.\n\t3. Inside the loop, calculate the square of the absolute value for the elements at the current start and \n\t   end positions: `sq1 = array[start] * array[start]`, `sq2 = array[end] * array[end]`.\n\t4. Compare `sq1` and `sq2` to determine which one is greater. If `sq1` is greater, assign it to the `end_pos` \n\t   index of the result array and increment the start position by 1: `result[end_pos] = sq1`, `start++`. \n\t   This ensures that the greater squared value is placed at the end of the result array.\n\t5. If `sq2` is greater, assign it to the `end_pos` index of the result array and decrement the end position \n\t   by 1: `result[end_pos] = sq2`, `end--`. This ensures that the greater squared value is still placed at the \n\t   end of the result array.\n\t6. Decrement the `end_pos` variable to move to the previous index in the result array: `end_pos--`.\n\t7. Repeat the process until the start and end positions cross each other.\n\t8. Finally, return the result array, which contains the squared values of the input array elements \n\t   in non-decreasing order.\n\n\tThe code effectively uses a two-pointer approach to compare the squared values of the elements at the start and end positions and places the greater squared value at the end of the result array. This ensures that the result array is sorted in non-decreasing order.\n\n\tThe time complexity of the `SortedSquaredArray` function is O(n), where n is the length of the input array. This is because the function performs a single pass through the array to calculate the squares and populate the result array.\n\n\tThe space complexity of the function is O(n) as well. This is because it creates a new result array of the same length as the input array to store the squared values. Therefore, the space required is proportional to the size of the input array.\n\n\tOverall, the function has a linear time complexity and linear space complexity.\n*/\nfunction sortedSquaredArray(array) {\n  // Initialize an empty result array of the same length as the original array\n  const result = Array(array.length).fill(0);\n\n  // Set the start and end positions and the end_pos\n  let end_pos = array.length - 1;\n  let start = 0;\n  let sq1 = 0;\n  let sq2 = 0;\n  let end = array.length - 1;\n\n  // Using the two-pointer approach, calculate the square of the absolute value and add the greatest value to the end of the result array\n  while (start <= end) {\n    sq1 = array[start] * array[start];\n    sq2 = array[end] * array[end];\n\n    if (sq1 > sq2) {\n      result[end_pos] = sq1;\n      start++; // Square of the start pointer is greater, so increment start by 1\n    } else {\n      result[end_pos] = sq2;\n      end--; // Square of the end pointer is greater, so decrement end by 1\n    }\n    end_pos--;\n  }\n\n  return result;\n}\n\nconst arr = [-6, 1, 2, 3, 4, 5];\nconst result = sortedSquaredArray(arr);\nconsole.log(result);\n"
  },
  {
    "path": "Arrays/sorted_square_array.cpp",
    "content": "/*\n\tWrite a function that takes in a non-empty array of integers that are sorted\n\tin ascending order and returns a new array of the same length with the squares\n\tof the original integers also sorted in ascending order.\n\n\tSample Input: [-6, 1, 2, 3, 4]\n\tOutput: [1, 4, 6, 16, 36]\n\n\tExplanation:\n\n\tThe `SortedSquaredArray` function takes an integer array as input and returns a new array where each element is the square of the corresponding element in the input array. The new array is sorted in non-decreasing order.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. Initialize an empty result array of the same length as the original array: `result := make([]int, len(array))`.\n\t2. Initialize variables to mark the start and end positions of the array, as well as the end_pos, which is the \n\t   index of the last element in the result array: `end_pos := len(array) - 1`, `start := 0`, `end := len(array) - 1`.\n\t3. Inside the loop, calculate the square of the absolute value for the elements at the current start and \n\t   end positions: `sq1 = array[start] * array[start]`, `sq2 = array[end] * array[end]`.\n\t4. Compare `sq1` and `sq2` to determine which one is greater. If `sq1` is greater, assign it to the `end_pos` \n\t   index of the result array and increment the start position by 1: `result[end_pos] = sq1`, `start++`. \n\t   This ensures that the greater squared value is placed at the end of the result array.\n\t5. If `sq2` is greater, assign it to the `end_pos` index of the result array and decrement the end position \n\t   by 1: `result[end_pos] = sq2`, `end--`. This ensures that the greater squared value is still placed at the \n\t   end of the result array.\n\t6. Decrement the `end_pos` variable to move to the previous index in the result array: `end_pos--`.\n\t7. Repeat the process until the start and end positions cross each other.\n\t8. Finally, return the result array, which contains the squared values of the input array elements \n\t   in non-decreasing order.\n\n\tThe code effectively uses a two-pointer approach to compare the squared values of the elements at the start and end positions and places the greater squared value at the end of the result array. This ensures that the result array is sorted in non-decreasing order.\n\n\tThe time complexity of the `SortedSquaredArray` function is O(n), where n is the length of the input array. This is because the function performs a single pass through the array to calculate the squares and populate the result array.\n\n\tThe space complexity of the function is O(n) as well. This is because it creates a new result array of the same length as the input array to store the squared values. Therefore, the space required is proportional to the size of the input array.\n\n\tOverall, the function has a linear time complexity and linear space complexity.\n*/\n#include <iostream>\n#include <vector>\n\nstd::vector<int> sortedSquaredArray(std::vector<int>& array) {\n    // Initialize an empty result vector of the same length as the original array\n    std::vector<int> result(array.size());\n\n    // Set the start and end positions and the end_pos\n    int end_pos = array.size() - 1;\n    int start = 0;\n    int sq1 = 0;\n    int sq2 = 0;\n    int end = array.size() - 1;\n\n    // Using the two-pointer approach, calculate the square of the absolute value and add the greatest value to the end of the result vector\n    while (start <= end) {\n        sq1 = array[start] * array[start];\n        sq2 = array[end] * array[end];\n\n        if (sq1 > sq2) {\n            result[end_pos] = sq1;\n            start++; // Square of the start pointer is greater, so increment start by 1\n        } else {\n            result[end_pos] = sq2;\n            end--; // Square of the end pointer is greater, so decrement end by 1\n        }\n        end_pos--;\n    }\n\n    return result;\n}\n\nint main() {\n    std::vector<int> arr = {-6, 1, 2, 3, 4, 5};\n    std::vector<int> result = sortedSquaredArray(arr);\n\n    for (int num : result) {\n        std::cout << num << \" \";\n    }\n    std::cout << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Arrays/sorted_square_array.go",
    "content": "/*\n\tWrite a function that takes in a non-empty array of integers that are sorted\n\tin ascending order and returns a new array of the same length with the squares\n\tof the original integers also sorted in ascending order.\n\n\tSample Input: [-6, 1, 2, 3, 4]\n\tOutput: [1, 4, 6, 16, 36]\n\n\tExplanation:\n\n\tThe `SortedSquaredArray` function takes an integer array as input and returns a new array where each element is the square of the corresponding element in the input array. The new array is sorted in non-decreasing order.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. Initialize an empty result array of the same length as the original array: `result := make([]int, len(array))`.\n\t2. Initialize variables to mark the start and end positions of the array, as well as the end_pos, which is the \n\t   index of the last element in the result array: `end_pos := len(array) - 1`, `start := 0`, `end := len(array) - 1`.\n\t3. Inside the loop, calculate the square of the absolute value for the elements at the current start and \n\t   end positions: `sq1 = array[start] * array[start]`, `sq2 = array[end] * array[end]`.\n\t4. Compare `sq1` and `sq2` to determine which one is greater. If `sq1` is greater, assign it to the `end_pos` \n\t   index of the result array and increment the start position by 1: `result[end_pos] = sq1`, `start++`. \n\t   This ensures that the greater squared value is placed at the end of the result array.\n\t5. If `sq2` is greater, assign it to the `end_pos` index of the result array and decrement the end position \n\t   by 1: `result[end_pos] = sq2`, `end--`. This ensures that the greater squared value is still placed at the \n\t   end of the result array.\n\t6. Decrement the `end_pos` variable to move to the previous index in the result array: `end_pos--`.\n\t7. Repeat the process until the start and end positions cross each other.\n\t8. Finally, return the result array, which contains the squared values of the input array elements \n\t   in non-decreasing order.\n\n\tThe code effectively uses a two-pointer approach to compare the squared values of the elements at the start and end positions and places the greater squared value at the end of the result array. This ensures that the result array is sorted in non-decreasing order.\n\n\tThe time complexity of the `SortedSquaredArray` function is O(n), where n is the length of the input array. This is because the function performs a single pass through the array to calculate the squares and populate the result array.\n\n\tThe space complexity of the function is O(n) as well. This is because it creates a new result array of the same length as the input array to store the squared values. Therefore, the space required is proportional to the size of the input array.\n\n\tOverall, the function has a linear time complexity and linear space complexity.\n*/\npackage main\n\nimport \"fmt\"\n\nfunc SortedSquaredArray(array []int) []int {\n\t// initialize empty result array of same length as original array\n\tresult := make([]int, len(array))\n\t// mark start and end, and end_pos\n\tend_pos := len(array) - 1\n\tstart := 0\n\tsq1 := 0\n\tsq2 := 0\n\tend := len(array) - 1\n\t// using two pointer appraoch take the  absolute value's square \n\t// add the greatest at end of output array\n\tfor start <= end {\n\t\tsq1 = array[start] * array[start]\n\t\tsq2 = array[end] * array[end]\n\t\tif sq1 > sq2 {\n\t\t\tresult[end_pos] = sq1\n\t\t\tstart++ // square of start pointer is greater so increment start by 1 \n\t\t} else {\n\t\t\tresult[end_pos] = sq2\n\t\t\tend-- // // square of end pointer is greater so decrement end by 1 \n\t\t}\n\t\tend_pos--\n\t}\n\treturn result\n}\n\nfunc main() {\n\tarr := []int{-6, 1, 2, 3, 4, 5}\n\tmsg := SortedSquaredArray(arr)\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Arrays/sorted_square_array.java",
    "content": "/*\n\tWrite a function that takes in a non-empty array of integers that are sorted\n\tin ascending order and returns a new array of the same length with the squares\n\tof the original integers also sorted in ascending order.\n\n\tSample Input: [-6, 1, 2, 3, 4]\n\tOutput: [1, 4, 6, 16, 36]\n\n\tExplanation:\n\n\tThe `SortedSquaredArray` function takes an integer array as input and returns a new array where each element is the square of the corresponding element in the input array. The new array is sorted in non-decreasing order.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. Initialize an empty result array of the same length as the original array: `result := make([]int, len(array))`.\n\t2. Initialize variables to mark the start and end positions of the array, as well as the end_pos, which is the \n\t   index of the last element in the result array: `end_pos := len(array) - 1`, `start := 0`, `end := len(array) - 1`.\n\t3. Inside the loop, calculate the square of the absolute value for the elements at the current start and \n\t   end positions: `sq1 = array[start] * array[start]`, `sq2 = array[end] * array[end]`.\n\t4. Compare `sq1` and `sq2` to determine which one is greater. If `sq1` is greater, assign it to the `end_pos` \n\t   index of the result array and increment the start position by 1: `result[end_pos] = sq1`, `start++`. \n\t   This ensures that the greater squared value is placed at the end of the result array.\n\t5. If `sq2` is greater, assign it to the `end_pos` index of the result array and decrement the end position \n\t   by 1: `result[end_pos] = sq2`, `end--`. This ensures that the greater squared value is still placed at the \n\t   end of the result array.\n\t6. Decrement the `end_pos` variable to move to the previous index in the result array: `end_pos--`.\n\t7. Repeat the process until the start and end positions cross each other.\n\t8. Finally, return the result array, which contains the squared values of the input array elements \n\t   in non-decreasing order.\n\n\tThe code effectively uses a two-pointer approach to compare the squared values of the elements at the start and end positions and places the greater squared value at the end of the result array. This ensures that the result array is sorted in non-decreasing order.\n\n\tThe time complexity of the `SortedSquaredArray` function is O(n), where n is the length of the input array. This is because the function performs a single pass through the array to calculate the squares and populate the result array.\n\n\tThe space complexity of the function is O(n) as well. This is because it creates a new result array of the same length as the input array to store the squared values. Therefore, the space required is proportional to the size of the input array.\n\n\tOverall, the function has a linear time complexity and linear space complexity.\n*/\nimport java.util.Arrays;\n\npublic class Main {\n\n    public static int[] sortedSquaredArray(int[] array) {\n        // Initialize an empty result array of the same length as the original array\n        int[] result = new int[array.length];\n\n        // Set the start and end positions and the end_pos\n        int end_pos = array.length - 1;\n        int start = 0;\n        int sq1 = 0;\n        int sq2 = 0;\n        int end = array.length - 1;\n\n        // Using the two-pointer approach, calculate the square of the absolute value and add the greatest value to the end of the result array\n        while (start <= end) {\n            sq1 = array[start] * array[start];\n            sq2 = array[end] * array[end];\n\n            if (sq1 > sq2) {\n                result[end_pos] = sq1;\n                start++; // Square of the start pointer is greater, so increment start by 1\n            } else {\n                result[end_pos] = sq2;\n                end--; // Square of the end pointer is greater, so decrement end by 1\n            }\n            end_pos--;\n        }\n\n        return result;\n    }\n\n    public static void main(String[] args) {\n        int[] arr = {-6, 1, 2, 3, 4, 5};\n        int[] result = sortedSquaredArray(arr);\n\n        for (int num : result) {\n            System.out.print(num + \" \");\n        }\n        System.out.println();\n    }\n}\n"
  },
  {
    "path": "Arrays/sorted_square_array.py",
    "content": "'''\n    Write a function that takes in a non-empty array of integers that are sorted\n    in ascending order and returns a new array of the same length with the squares\n    of the original integers also sorted in ascending order.\n\n    Sample Input: [-6, 1, 2, 3, 4]\n    Output: [1, 4, 6, 16, 36]\n\n    Explanation:\n\n    The `SortedSquaredArray` function takes an integer array as input and returns a new array where each element is the square of the corresponding element in the input array. The new array is sorted in non-decreasing order.\n\n    Here's a step-by-step explanation of the code:\n\n    1. Initialize an empty result array of the same length as the original array: `result := make([]int, len(array))`.\n    2. Initialize variables to mark the start and end positions of the array, as well as the end_pos, which is the \n        index of the last element in the result array: `end_pos := len(array) - 1`, `start := 0`, `end := len(array) - 1`.\n    3. Inside the loop, calculate the square of the absolute value for the elements at the current start and \n        end positions: `sq1 = array[start] * array[start]`, `sq2 = array[end] * array[end]`.\n    4. Compare `sq1` and `sq2` to determine which one is greater. If `sq1` is greater, assign it to the `end_pos` \n        index of the result array and increment the start position by 1: `result[end_pos] = sq1`, `start++`. \n        This ensures that the greater squared value is placed at the end of the result array.\n    5. If `sq2` is greater, assign it to the `end_pos` index of the result array and decrement the end position \n        by 1: `result[end_pos] = sq2`, `end--`. This ensures that the greater squared value is still placed at the \n        end of the result array.\n    6. Decrement the `end_pos` variable to move to the previous index in the result array: `end_pos--`.\n    7. Repeat the process until the start and end positions cross each other.\n    8. Finally, return the result array, which contains the squared values of the input array elements \n        in non-decreasing order.\n\n    The code effectively uses a two-pointer approach to compare the squared values of the elements at the start and end positions and places the greater squared value at the end of the result array. This ensures that the result array is sorted in non-decreasing order.\n\n    The time complexity of the `SortedSquaredArray` function is O(n), where n is the length of the input array. This is because the function performs a single pass through the array to calculate the squares and populate the result array.\n\n    The space complexity of the function is O(n) as well. This is because it creates a new result array of the same length as the input array to store the squared values. Therefore, the space required is proportional to the size of the input array.\n\n    Overall, the function has a linear time complexity and linear space complexity.\n'''\ndef sortedSquaredArray(array):\n    # Initialize an empty result array of the same length as the original array\n    result = [0] * len(array)\n\n    # Set the start and end positions and the end_pos\n    end_pos = len(array) - 1\n    start = 0\n    sq1 = 0\n    sq2 = 0\n    end = len(array) - 1\n\n    # Using the two-pointer approach, calculate the square of the absolute value and add the greatest value to the end of the result array\n    while start <= end:\n        sq1 = array[start] * array[start]\n        sq2 = array[end] * array[end]\n\n        if sq1 > sq2:\n            result[end_pos] = sq1\n            start += 1  # Square of the start pointer is greater, so increment start by 1\n        else:\n            result[end_pos] = sq2\n            end -= 1  # Square of the end pointer is greater, so decrement end by 1\n        end_pos -= 1\n\n    return result\n\narr = [-6, 1, 2, 3, 4, 5]\nresult = sortedSquaredArray(arr)\nprint(result)\n"
  },
  {
    "path": "Arrays/string_halves.cpp",
    "content": "/*\nYou are given a string s of even length. Split this string into two halves of equal lengths, and let a be the first half and b be the second half.\n\nTwo strings are alike if they have the same number of vowels ('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'). Notice that s contains uppercase and lowercase letters.\n\nReturn true if a and b are alike. Otherwise, return false.\n\n \n\nExample 1:\n\nInput: s = \"book\"\nOutput: true\nExplanation: a = \"bo\" and b = \"ok\". a has 1 vowel and b has 1 vowel. Therefore, they are alike.\nExample 2:\n\nInput: s = \"textbook\"\nOutput: false\nExplanation: a = \"text\" and b = \"book\". a has 1 vowel whereas b has 2. Therefore, they are not alike.\nNotice that the vowel o is counted twice.\n \n\nConstraints:\n\n2 <= s.length <= 1000\ns.length is even.\ns consists of uppercase and lowercase letters.\n*/\n\n#include<bits/stdc++.h>\nclass Solution {\npublic:\n    bool halvesAreAlike(string s) {\n        set<char> X {'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'};\n        int half = s.size() / 2;\n        int c = 0, d = 0;\n        for(int i = 0; i < half; i++){\n            if(X.find(s[i]) != X.end())\n                c++;\n        }\n        for(int i = half; i < s.size(); i++){\n            if(X.find(s[i]) != X.end()){\n                d++;\n            }\n        }\n        return c == d;\n    }\n};"
  },
  {
    "path": "Arrays/three_largest_no.py",
    "content": "\n\n\"\"\"\nWrite a function that takes in an array of at least three integers and, \nwithout sorting the input array, returns a sorted array of the three largest \nintegers in the input array.\n\n# Approach\n\n- We will use three variables to store the three max values and initialize them with int_minimum\n- We will iterate through the array and compare the values with the three variables\n- If the value is greater than the first variable, we will update the variables\n- If the value is greater than the second variable, we will update the variables\n- If the value is greater than the third variable, we will update the variables\n- Return the three variables as a sorted array\n\n\"\"\"\n\n\n\ndef three_max_no(arr:list)-> list:\n    # give int minvalue to a,b,\n    max_1,max_2,max_3= -9999,-9999,-9999\n    # we will iterate through the array and compare the values\n    for i in arr:\n        if i > max_1:\n            # if the value is greater than the first variable, we will update the variables\n            max_1,max_2,max_3 = i, max_1, max_2\n        elif i > max_2:\n            # if the value is greater than the second variable, we will update the variables\n            max_2, max_3 = i, max_2\n        elif i > max_3:\n            # if the value is greater than the third variable, we will update the variables\n            max_3 = i\n    # return the three max values as a sorted array\n    return [max_1, max_2, max_3]\n\n\n# example-1\narr=[141,1,17,-7,-17,-27,18,541,8,7,7]\nprint(three_max_no(arr))\n\n# sample output    [541, 141, 18]\n"
  },
  {
    "path": "Arrays/total_hamming_distance.cpp",
    "content": "/* \n\nIntroduction:\n\n    This documentation provides a detailed explanation of the problem statement, algorithm, and implementation of \n    calculating the sum of Hamming distances between all pairs of integers in an integer array. \n    Hamming distance measures the number of positions at which corresponding bits are different between two numbers. \n    The algorithm aims to find the sum of Hamming distances for all possible pairs of integers in the given array.\n\nProblem Statement:\n\n    Given an integer array nums, the task is to calculate the sum of Hamming distances between all the pairs of integers in nums. \n    The goal is to determine the total count of differing bits at each position for all possible pairs of integers in the array.\n    \nHamming Distance : \n\n    Hamming distance is a metric for comparing two binary data strings. \n    While comparing two binary strings of equal length, Hamming distance is the number of bit positions in which the two bits are different.\n\nSample Input    : [4,14,2]\nexpected Output :  6\n\nExplaination    :   In binary representation, the 4 is 0100, 14 is 1110, and 2 is 0010 (just showing the four bits relevant in this case).\nTotal Hamming distance = HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6.\n\nMethod 1 : \n\n    (Brute Force Method) We can iterate over the whole array and find all pairs calculate Hamming distance and add all the distances.\n    Time complexity  :  O(n^2) \n    Space Complexity :  O(1)\n\nMethod 2 :\n\n    1. Initialize a variable `totalDistance` to store the sum of Hamming distances.\n    2. Iterate over each bit position from 0 to 31 (assuming integers are 32-bit).\n    3. For each bit position `i`, initialize two variables: `countZeros` and `countOnes` to keep track of the count of zeros and ones at that position.\n    4. Iterate over each element `num` in `nums`.\n       a. Right shift `num` by `i` positions and perform a bitwise AND with 1 to check the value at bit position `i`.\n       b. If the result is 0, increment `countZeros` by 1; otherwise, increment `countOnes` by 1.\n    5. Add `countZeros * countOnes` to `totalDistance`. This calculates the Hamming distance for the current bit position and adds it to the running total.\n    6. Repeat steps 3-5 for all bit positions.\n    7. Return `totalDistance` as the sum of Hamming distances between all pairs of integers in `nums`.\n\n    Time Complexity  : O(k*n) where ,\n    k = maximum number of bits required to represent a number in the array\n    n = size of array\n\n    Space Complexity : O(1)\n\n\nExplaination :\n\n    Number  ==>   Binary Representation\n     4              0 1 0 0\n     14             1 1 1 0\n     2              0 0 1 0\n\n    The idea is to count differences at individual bit positions. We traverse from 0 to 31 and count numbers with i’th bit set. \n    Let this count be ‘c'. There would be “n-c” numbers with i’th bit not set. \n    So count of differences at i’th bit would be “count * (n-count)”, the reason for this formula is as every pair having one element \n    which has set bit at i’th position and second element having unset bit at i’th position contributes exactly 1 to sum.\n\n    1st bit = 2*1 = 2 \n    2nd bit = 2*1 = 2\n    3rd bit = 2*1 = 2\n    4th bit = 3*0 = 0\n--------------------------\n    Total =         6\n\n\n*/\n\n//  CODE : \n\n// #include<bits/stdc++.h>\n#include <iostream>\n#include <vector>\nusing namespace std;\n\nint totalHammingDistance(vector<int>& nums) {\n        int totalDistance=0;\n        int n=nums.size();\n        // Here we are assuing that the 32 bits are sufficient to represent all the numbers in the array\n        for(int i=0;i<32;i++){\n            int c=0;// c represents number of set bits of a particular position in the whole array.\n            for(int j=0;j<n;j++){\n\t\t\t\t\tif((nums[j]&(1<<i)))\n                    c++;     //Checking if i'th bit is set ot not.\n            }\n            totalDistance+=(c*(n-c));      //Adding count of differences\n        }\n        return totalDistance;\n    }\n\n\nint main()\n{\n    int n ;\n    cin >> n;\n    vector<int> nums(n);\n    for(int i=0;i<n;i++)\n    {\n        cin >> nums[i];\n    }\n    int total_hamming_distance = totalHammingDistance(nums);\n    cout << total_hamming_distance << endl;\n    return 0;\n}"
  },
  {
    "path": "Arrays/tournament_winner.go",
    "content": "/*\n  There's an algorithms tournament taking place in which teams of programmers\n  compete against each other to solve algorithmic problems as fast as possible.\n  Teams compete in a round robin, where each team faces off against all other\n  teams. Only two teams compete against each other at a time, and for each\n  competition, one team is designated the home team, while the other team is the\n  away team. In each competition there's always one winner and one loser; there\n  are no ties. A team receives 3 points if it wins and 0 points if it loses. The\n  winner of the tournament is the team that receives the most amount of points.\n\n  Given an array of pairs representing the teams that have competed against each\n  other and an array containing the results of each competition, write a\n  function that returns the winner of the tournament. The input arrays are named\n  competitions and results, respectively. The competitions  array has elements in the\n  form of [homeTeam, awayTeam], where each team is a string of at most 30\n  characters representing the name of the team. The array\n  contains information about the winner of each corresponding competition in the\n  competitions  array. Specifically, results[i]  denotes the winner of competitions[i]\n  , where a 1 in the results  array means that the home team in the corresponding\n  competition won and a 0  means that the away team won.\n\n\n  It's guaranteed that exactly one team will win the tournament and that each\n  team will compete against all other teams exactly once. It's also guaranteed\n  that the tournament will always have at least two teams.\n  Sample Input :\n  {\n  \"competitions\": [\n    [\"HTML\", \"C#\"],\n    [\"C#\", \"Python\"],\n    [\"Python\", \"HTML\"]\n  ],\n  \"results\": [0, 0, 1]\n  }\n  Output: Python\n\n  O(n) time | O(k) space - where n is the number of competitions and k is the number of teams\n\n*/\npackage main\n\nimport \"fmt\"\n\nconst HOME_TEAM_WON = 1\nconst AWAY_TEAM_WON = 0\n\nfunc TournamentWinner(competitions [][]string, results []int) string {\n\t// construct a hashmap which will keep track of team with number of matches won\n\t// if name already exist in hashmap then add 1 to it\n\t// if it doesn't then add new entry\n\tmp := make(map[string]int)\n\twinner := \"\"\n\tmax := 0\n\tfor i := 0; i < len(results); i++ {\n\t\tif results[i] == HOME_TEAM_WON {\n\t\t\tmp[competitions[i][0]]++\n\t\t\tif mp[competitions[i][0]] > max {\n\t\t\t\t// keep track of max value and winner\n\t\t\t\tmax = mp[competitions[i][0]]\n\t\t\t\twinner = competitions[i][0]\n\t\t\t}\n\t\t} else {\n\t\t\tmp[competitions[i][1]]++\n\t\t\t// keep track of max value and winner\n\t\t\tif mp[competitions[i][1]] > max {\n\t\t\t\tmax = mp[competitions[i][1]]\n\t\t\t\twinner = competitions[i][1]\n\t\t\t}\n\t\t}\n\t}\n\treturn winner\n}\n\nfunc main() {\n\tcompetitions := [][]string{{\"HTML\", \"C#\"}, {\"C#\", \"Python\"}, {\"Python\", \"HTML\"}}\n\tresult := []int{0, 0, 1}\n\tmsg := TournamentWinner(competitions, result)\n\tfmt.Println(msg)\n\tcompetitions = [][]string{{\"HTML\", \"Java\"},{\"Java\", \"Python\"},{\"Python\", \"HTML\"},{\"C#\", \"Python\"},{\"Java\", \"C#\"},{\"C#\", \"HTML\"}}\n\tresult = []int{0, 1, 1, 1, 0, 1}\n\tmsg = TournamentWinner(competitions, result)\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Arrays/triplet_sum.cpp",
    "content": "/*\nGiven an array of integers, nums, and an integer value, target,\ndetermine if there are any three integers in nums whose sum equals the target.\nReturn TRUE if three such integers are found in the array. Otherwise, return FALSE.\n*/\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n/*\n    This implementation uses the two pointer technique to find all triplets in the input array that sum up to the target sum. \n    We first sort the input array in non-decreasing order to simplify the process of finding triplets. We then loop through \n    the array and use two pointers, one starting from the left and one starting from the right, to find triplets that sum up \n    to the target sum. For each iteration of the loop, we set the left pointer to the index immediately to the right of the \n    current index, and the right pointer to the index of the last element in the array. We then move the left and right pointers \n    towards the center, checking at each step whether the triplet formed by the current indices sums up to the target sum. \n    If it does, we add the triplet to the result vector and continue searching for other triplets. \n    If the sum is less than the target sum, we move the left pointer towards the center to find larger numbers. \n    If the sum is greater than the target sum, we move the right pointer towards the center to find smaller numbers.\n*/\nstd::vector<std::vector<int>> threeNumberSum(std::vector<int>& nums, int targetSum) {\n    // Sort the input array in non-decreasing order\n    std::sort(nums.begin(), nums.end());\n    \n    std::vector<std::vector<int>> triplets;\n    \n    // Loop through the array\n    for (int i = 0; i < nums.size() - 2; i++) {\n        int left = i + 1;\n        int right = nums.size() - 1;\n        \n        // While the left index is less than the right index\n        while (left < right) {\n            int currentSum = nums[i] + nums[left] + nums[right];\n            \n            if (currentSum == targetSum) {\n                // If the current triplet sums up to the target sum, add it to the result vector\n                triplets.push_back({ nums[i], nums[left], nums[right] });\n                \n                // Move the left and right indices towards the center to find other triplets\n                left++;\n                right--;\n            } else if (currentSum < targetSum) {\n                // If the current triplet sums up to less than the target sum, move the left index towards the center to find larger numbers\n                left++;\n            } else {\n                // If the current triplet sums up to more than the target sum, move the right index towards the center to find smaller numbers\n                right--;\n            }\n        }\n    }\n    \n    return triplets;\n}\n\nint main() {\n    // Example usage\n    std::vector<int> nums = { 12, 3, 1, 2, -6, 5, -8, 6 };\n    int targetSum = 0;\n    \n    std::vector<std::vector<int>> triplets = threeNumberSum(nums, targetSum);\n    \n    for (std::vector<int>& triplet : triplets) {\n        std::cout << \"[\";\n        for (int i = 0; i < triplet.size(); i++) {\n            std::cout << triplet[i];\n            if (i < triplet.size() - 1) {\n                std::cout << \", \";\n            }\n        }\n        std::cout << \"]\" << std::endl;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "Arrays/triplet_sum.go",
    "content": "/*\nGiven an array of integers, nums, and an integer value, target,\ndetermine if there are any three integers in nums whose sum equals the target.\nReturn TRUE if three such integers are found in the array. Otherwise, return FALSE.\n*/\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n)\n\n// Time complexity : Sorting the array O(n log(n)) and Nested loop to find triplet O(n^{2}) which can be simplified to O(n^{2})\n// Space complexity is O(1) since we use a fixed amount of extra space in memory.\n// FindSumOfThree is our challenge function\nfunc findSumOfThree(nums []int, target int) bool {\n\t// Sorting the input vector\n\tsort.Sort(sort.IntSlice(nums))\n\n\t// We create two pointers to track our indices and, variable to store our triple sum\n\tlow, high, triple := 0, 0, 0\n\n\t// Fix one element at a time and find the other two\n\tfor i := 0; i < len(nums) - 2; i++ {\n\t\t// Set the indices of the two pointers\n\t\t// Index of the first of the remaining elements\n\t\tlow = i + 1\n\n\t\t// Last index\n\t\thigh = len(nums) - 1\n\n\t\tfor low < high {\n\t\t\t// Check if the sum of the triple is equal to the sum\n\t\t\ttriple = nums[i] + nums[low] + nums[high]\n\n\t\t\t// Found a triple whose sum equals the target\n\t\t\tif triple == target {\n\t\t\t\treturn true\n\n\t\t\t// Move low pointer forward if the triple sum is less than the required sum\n\t\t\t} else if triple < target {\n\t\t\t\tlow += 1\n\t\t\t} else {\n\t\t\t\t// Move the high pointer backwards if the triple sum is greater than the required sum\n\t\t\t\thigh -= 1\n\t\t\t}\n\t\t}\n\t}\n\treturn false\n}\n\n// Driver code\nfunc main() {\n\tnumsLists := [][]int {\n\t\t{3, 7, 1, 2, 8, 4, 5},\n\t\t{-1, 2, 1, -4, 5, -3},\n\t\t{2, 3, 4, 1, 7, 9},\n\t\t{1, -1, 0},\n\t\t{2, 4, 2, 7, 6, 3, 1},\n\t}\n\ttestLists := [][]int {\n\t\t{10, 20, 21},\n\t\t{-8, 0, 7},\n\t\t{8, 10, 20},\n\t\t{1, -1, 0},\n\t\t{8, 11, 15},\n\t}\n\tfor i, nList := range numsLists {\n\t\tfmt.Printf(\"%d. Input array: %s\\n\", i + 1, strings.Replace(fmt.Sprint(nList), \" \", \", \", -1))\n\t\tfor _, tList := range testLists[i] {\n\t\t\tif findSumOfThree(nList, tList) {\n\t\t\t\tfmt.Printf(\"   Sum for %d exists\\n\", tList)\n\t\t\t} else {\n\t\t\t\tfmt.Printf(\"   Sum for %d does not exist\\n\", tList)\n\t\t\t}\n\t\t}\n\t\tfmt.Printf(\"%s\\n\", strings.Repeat(\"-\", 100))\n\t}\n}"
  },
  {
    "path": "Arrays/triplet_sum.java",
    "content": "/*\nGiven an array of integers, nums, and an integer value, target,\ndetermine if there are any three integers in nums whose sum equals the target.\nReturn TRUE if three such integers are found in the array. Otherwise, return FALSE.\n*/\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\n/*\nWe sort the input array in non-decreasing order using the Arrays.sort() method, and then loop through \nthe array using a for loop. We use two pointers, one starting from the left and one starting from the right, \nto find triplets that sum up to the target sum. For each iteration of the loop, we set the left pointer to \nthe index immediately to the right of the current index, and the right pointer to the index of the last \nelement in the array. We then move the left and right pointers towards the center, checking at each step \nwhether the triplet formed by the current indices sums up to the target sum. If it does, we add the triplet \nto the result list and continue searching for other triplets. If the sum is less than the target sum, we \nmove the left pointer towards the center to find larger numbers. If the sum is greater than the target \nsum, we move the right pointer towards the center to find smaller numbers.\nFinally, we print out the result list using a nested for loop to iterate through each triplet and each element in each triplet.\n*/\npublic class ThreeNumberSum {\n\n    public static List<List<Integer>> threeNumberSum(int[] nums, int targetSum) {\n        Arrays.sort(nums); // Sort the input array in non-decreasing order\n        List<List<Integer>> triplets = new ArrayList<>();\n        \n        // Loop through the array\n        for (int i = 0; i < nums.length - 2; i++) {\n            int left = i + 1;\n            int right = nums.length - 1;\n            \n            // While the left index is less than the right index\n            while (left < right) {\n                int currentSum = nums[i] + nums[left] + nums[right];\n                \n                if (currentSum == targetSum) {\n                    // If the current triplet sums up to the target sum, add it to the result list\n                    triplets.add(Arrays.asList(nums[i], nums[left], nums[right]));\n                    \n                    // Move the left and right indices towards the center to find other triplets\n                    left++;\n                    right--;\n                } else if (currentSum < targetSum) {\n                    // If the current triplet sums up to less than the target sum, move the left index towards the center to find larger numbers\n                    left++;\n                } else {\n                    // If the current triplet sums up to more than the target sum, move the right index towards the center to find smaller numbers\n                    right--;\n                }\n            }\n        }\n        \n        return triplets;\n    }\n\n    public static void main(String[] args) {\n        // Example usage\n        int[] nums = { 12, 3, 1, 2, -6, 5, -8, 6 };\n        int targetSum = 0;\n        \n        List<List<Integer>> triplets = threeNumberSum(nums, targetSum);\n        \n        for (List<Integer> triplet : triplets) {\n            System.out.print(\"[\");\n            for (int i = 0; i < triplet.size(); i++) {\n                System.out.print(triplet.get(i));\n                if (i < triplet.size() - 1) {\n                    System.out.print(\", \");\n                }\n            }\n            System.out.println(\"]\");\n        }\n    }\n}\n"
  },
  {
    "path": "Arrays/triplet_sum.js",
    "content": "/*\nGiven an array of integers, nums, and an integer value, target,\ndetermine if there are any three integers in nums whose sum equals the target.\nReturn TRUE if three such integers are found in the array. Otherwise, return FALSE.\n\nSample Input : 3, 7, 1, 2, 8, 4, 5 Target : 18\nOutput : True\nSample Input : 0 -1 1 Target : 2\nOutput : False\n\nAPPROACH:\n\n1) We need to sort the array for our strategy to work.\n2) Iterating from index 0, we check three numbers:\n  - value at index i (starting at 0)\n  - low: value at index i + 1\n  - high: value at index nums.length - 1 (the last value, also the highest)\n3) Take the sum of these three values.\n  - If sum equals target, return true\n  - If sum is less than the target, increment \"low\" and run this step again\n  - If sum is higher than the target, decrement \"high\" and run this step again\n4) If low meets high, we ran out of numbers to try. Back to step 2.\n5) Return false at the end of everything because we found no matching sums\n\nFor a similar problem:\nhttps://leetcode.com/problems/3sum/\n\n*/\n\n\nconst sumOfThree = (nums, target) => {\n  // function only applies to arrays with at least 3 values\n  if (nums.length < 3) return false\n\n  // Sort the array\n  nums.sort()\n\n  let low, high\n\n  // Iterate through each value (up to 3rd from last)\n  for (let i = 0; i < nums.length - 2; i++) {\n\n    //Assign pointers and check the sum\n    low = i + 1\n    high = nums.length - 1\n\n    while (low < high) {\n\n      let sum = nums[i] + nums[low] + nums[high]\n\n      // match found, return true\n      if (sum === target) {\n        return true\n\n        // sum is too low, increase low pointer\n      } else if (sum < target) {\n        low++\n\n        // sum is too high, decrease high pointer\n      } else {\n        high--\n      }\n    }\n  }\n\n  return false\n}\n\nconsole.log(sumOfThree([3, 7, 1, 2, 8, 4, 5], 18)) // true\nconsole.log(sumOfThree([3, 7, 1, 2, 8, 4, 5], 50)) // false\nconsole.log(sumOfThree([0, -1, 1], 2)) // false\nconsole.log(sumOfThree([0, -1, 1], 0)) // true\n\n"
  },
  {
    "path": "Arrays/triplet_sum.py",
    "content": "'''\nGiven an array of integers, nums, and an integer value, target,\ndetermine if there are any three integers in nums whose sum equals the target.\nReturn TRUE if three such integers are found in the array. Otherwise, return FALSE.\n'''\n\ndef find3Numbers(A, arr_size, sum):\n\n\t# Sort the elements\n\tA.sort()\n\n\t# Now fix the first element\n\t# one by one and find the\n\t# other two elements\n\tfor i in range(0, arr_size-2):\n\t\t\n\t\t# index of the first element\n\t\t# in the remaining elements\n\t\tl = i + 1\n\t\t\n\t\t# index of the last element\n\t\tr = arr_size-1\n\t\twhile (l < r):\n\t\t\n\t\t\tif( A[i] + A[l] + A[r] == sum):\n\t\t\t\treturn True\n\t\t\telif (A[i] + A[l] + A[r] < sum):\n\t\t\t\tl += 1\n\t\t\telse: # A[i] + A[l] + A[r] > sum\n\t\t\t\tr -= 1\n\n\t# If we reach here, then\n\t# no triplet was found\n\treturn False\n\n# Driver program to test above function\nA = [1, 2, 3, 4, 5, 6]\nsum = 9\narr_size = len(A)\n\nprint(find3Numbers(A, arr_size, sum))"
  },
  {
    "path": "Arrays/urlify.go",
    "content": "// Implement an algorithm to replace all spaces with %20, assumew we have extra buffer at the end.\n// Input : Mr Ashish Lala Output: Mr%20Ashish%20Lala\n// Program Author : Abhisek Kumar Gupta\n// Time complexity : O(n) Space complexity O(n)\npackage main\n\nimport \"fmt\"\n\nfunc Urlify(s string, length int) string {\n\tspaceCount := 0\n\tr := []rune{}\n\t// compute spaces, \n\tfor i := 0; i < length; i++ {\n\t\tif s[i] == ' ' {\n\t\t\tspaceCount++\n\t\t}\n\t}\n\t// string to rune\n\tfor _, v := range s {\n\t\tr = append(r, v)\n\t}\n\t// triple space count and find out how many extra characters will be there in final string \n\tindex := length + (spaceCount * 3) // actual length of final string\n\tfor i := length - 1; i >= 0; i-- {\n\t\t// If u encounter space then replace with  %20\n\t\tif r[i] == ' ' {\n\t\t\tr[index - 1] = '0'\n\t\t\tr[index - 2] = '2'\n\t\t\tr[index - 3] = '%'\n\t\t\tindex -= 3\n\t\t} else {\n\t\t\t// If there is no space then copy the original character\n\t\t\tr[index - 1] = r[i]\n\t\t\tindex--\n\t\t}\n\t}\n\treturn string(r[index:])\n}\n\n\nfunc main() {\n\ts := \"Mr John Smith          \";\n\tlength := 13\n\tmsg := Urlify(s, length);\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Backtracking/Generate_Parentheses.py",
    "content": "'''\n    Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.\n    Example 1:\n    Input: n = 3\n    Output: [\"((()))\",\"(()())\",\"(())()\",\"()(())\",\"()()()\"]\n    \n    Example 2:\n    Input: n = 1\n    Output: [\"()\"]\n    Constraints:\n    1 <= n <= 8\n'''\nclass Solution:\n    #reference: GeeksforGeeks for comments\n    '''To form all the sequences of balanced bracket subsequences with n pairs. So there are n opening brackets and n closing brackets. So the subsequence will be of length 2*n. There is a simple idea, the i’th character can be ‘{‘ if and only if the count of ‘{‘ till i’th is less than n and i’th character can be ‘}’ if and only if the count of ‘{‘ is greater than the count of ‘}’ till index i. If these two cases are followed then the resulting subsequence will always be balanced'''\n\n    def generate(self,n,open,close,s,final_arr):\n        if(open==n and close==n):\n            final_arr.append(s)\n            return\n        if(open<n):\n            Solution.generate(self,n,open+1,close,s+\"(\",final_arr)\n        if(close<open):\n            Solution.generate(self,n,open,close+1,s+\")\",final_arr)\n\n    def generateParenthesis(self, n: int) -> List[str]:\n        final_arr = []\n        Solution.generate(self,n,0,0,\"\",final_arr)\n        return final_arr"
  },
  {
    "path": "Backtracking/geenrate_parentheses.go",
    "content": "// Implementation of generating all combinations of well-formed parentheses\n/*\n\tThe generateParenthesis function takes an integer n as input, which represents the number of pairs of \n\tparentheses to generate. It initializes an empty array result to store the valid combinations and calls \n\tthe backtrack helper function to generate all the combinations.\n\n\tThe backtrack function takes four arguments:\n\n\t\ta pointer to the result array to add the valid combinations\n\t\tthe current string cur\n\t\tthe number of open brackets open\n\t\tthe number of closed brackets close\n\t\tthe maximum number of pairs of parentheses max\n\n\tThe function first checks if the current string has reached the maximum length, i.e., len(cur) == max*2. \n\tIf it has, the function appends the current string to the result array and returns.\n\n\tIf there are still open brackets left to add, i.e., open < max, the function appends an open bracket to \n\tthe current string and recursively calls backtrack with open+1 and close. This represents adding an open \n\tbracket to the current combination.\n\n\tIf there are more closed brackets than open brackets, i.e., close < open, the function appends a \n\tclosed bracket to the current string and recursively calls backtrack with open and close+1. \n\tThis represents adding a closed bracket to the current combination.\n\n\tIn the main function, we call generateParenthesis with n=3 and print the resulting array. \n\tThis will output all possible combinations of three pairs of well-formed parentheses.\n\n\tInput: n = 3\n\n\tOutput: [\"((()))\",\"(()())\",\"(())()\",\"()(())\",\"()()()\"]\n\n\tExplanation:\n\n\tThere are 5 valid combinations of well-formed parentheses with 3 pairs of parentheses. \n\tThe output lists all of them.\n\n\tThe time complexity of the above program is O(4^n / sqrt(n)), where n is the number of parentheses. \n\tThis is because there are a total of 2n positions in the output string, and at each position,\n\twe have two choices - either to put an opening or closing parenthesis. Therefore, the total \n\tnumber of possible combinations is 2^(2n). However, not all of these combinations are valid, \n\tas some may violate the well-formedness condition. We can use Catalan number to determine the \n\tactual number of valid combinations. The nth Catalan number is given by (2n)! / (n+1)!n!, which \n\tis approximately equal to 4^n / sqrt(n*pi). Thus, the time complexity is O(4^n / sqrt(n)).\n*/\npackage main\n\nimport \"fmt\"\n\nfunc generateParenthesis(n int) []string {\n    var result []string\n    backtrack(&result, \"\", 0, 0, n)\n    return result\n}\n\n// helper function to backtrack and generate all valid combinations\nfunc backtrack(result *[]string, cur string, open int, close int, max int) {\n    // base case: if the current string has reached the maximum length, add it to the result\n    if len(cur) == max*2 {\n        *result = append(*result, cur)\n        return\n    }\n\n    // if there are still open brackets left to add, add one and recurse\n    if open < max {\n        backtrack(result, cur+\"(\", open+1, close, max)\n    }\n\n    // if there are more closed brackets than open brackets, add a closed bracket and recurse\n    if close < open {\n        backtrack(result, cur+\")\", open, close+1, max)\n    }\n}\n\nfunc main() {\n    result := generateParenthesis(3)\n    fmt.Println(result)\n}\n"
  },
  {
    "path": "Backtracking/n_queen.cpp",
    "content": "#include <iostream>\n#include <vector>\n\nusing namespace std;\n\n// Function to check if it's safe to place a queen at board[row][col]\nbool isSafe(vector<string>& board, int row, int col, int N) {\n    // Check the row on the left side\n    for (int i = 0; i < col; ++i) {\n        if (board[row][i] == 'Q') {\n            return false;\n        }\n    }\n\n    // Check upper diagonal on the left side\n    for (int i = row, j = col; i >= 0 && j >= 0; --i, --j) {\n        if (board[i][j] == 'Q') {\n            return false;\n        }\n    }\n\n    // Check lower diagonal on the left side\n    for (int i = row, j = col; i < N && j >= 0; ++i, --j) {\n        if (board[i][j] == 'Q') {\n            return false;\n        }\n    }\n\n    return true;\n}\n\n// Recursive function to solve N-Queens problem\nbool solveNQueens(vector<string>& board, int col, int N) {\n    if (col == N) {\n        // All queens are placed successfully\n        return true;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (isSafe(board, i, col, N)) {\n            // Place queen\n            board[i][col] = 'Q';\n\n            // Recur to place the rest of the queens\n            if (solveNQueens(board, col + 1, N)) {\n                return true;\n            }\n\n            // If placing queen in board[i][col] doesn't lead to a solution, backtrack\n            board[i][col] = '.';\n        }\n    }\n\n    // If no queen can be placed in this column, return false\n    return false;\n}\n\n// Function to solve N-Queens problem and print the solution\nvoid solveNQueens(int N) {\n    vector<string> board(N, string(N, '.'));\n\n    if (solveNQueens(board, 0, N)) {\n        // Print the solution\n        for (int i = 0; i < N; ++i) {\n            cout << board[i] << endl;\n        }\n    } else {\n        cout << \"No solution exists.\" << endl;\n    }\n}\n\nint main() {\n    int N;\n    cout << \"Enter the number of queens (N): \";\n    cin >> N;\n\n    solveNQueens(N);\n\n    return 0;\n}\n"
  },
  {
    "path": "Backtracking/n_queens.java",
    "content": "/**\n * Problem :- N-Queens\n  https://leetcode.com/problems/n-queens/description/\n \n \n Approach:-\n The approach uses backtracking to generate all possible configurations of queens on the board and checks the validity of each configuration.\n  It maintains a boolean board to represent the placement of queens, where `true` indicates the presence of a queen in a particular cell. \n  The algorithm starts by placing a queen in the first row and proceeds recursively to the next row, checking all possible column positions for the queen. \n  If a valid position is found, the algorithm moves to the next row and repeats the process. If all N queens are placed on the board, \n  a valid solution is found and added to the list of solutions.\n\n\nTo check the validity of a queen's position, the algorithm verifies three conditions:\n1. Vertical Check: It checks the columns of the previous rows to ensure that there are no queens in the same column.\n2. Left Diagonal Check: It checks the diagonal elements on the left side of the current position to ensure that there are no queens present.\n3. Right Diagonal Check: It checks the diagonal elements on the right side of the current position to ensure that there are no queens present.\n\nThe algorithm continues this process, backtracking whenever it encounters an invalid position or explores all possibilities. Once all valid configurations are found, they are converted into a list of strings representing the board configurations, and the list of solutions is returned.\n\n\n\n\nTime Complexity: O(N!)\n In the worst case, the backtracking algorithm explores all possible configurations,. However, with pruning techniques, the actual runtime is significantly lower.\n\nSpace Complexity:  O(N^2)\n because the boolean board of size NxN is used to represent the placement of queens, and the list of solutions also occupies additional space.\n\n */\n\nclass Solution {\n    public List<List<String>> solveNQueens(int n) {\n        List<List<String>> list = new ArrayList<>();\n        \n        // If the board size is 2 or 3, no solution is possible, so return an empty list\n        if (n == 2 || n == 3) {\n            return list;\n        }\n        \n        // If the board size is 1, there is only one solution with a single queen in the only cell\n        if (n == 1) {\n            String ans = \"Q\";\n            ArrayList<String> a = new ArrayList<>();\n            a.add(ans);\n            list.add(a);\n            return list;\n        }\n        \n        boolean arr[][] = new boolean[n][n]; // Create a boolean board to represent the placement of queens\n        queens(arr, 0, list); // Solve the N-queens problem recursively\n        return list; // Return the list of solutions\n    }\n    \n    // Recursive function to solve the N-queens problem\n    static void queens(boolean board[][], int row, List<List<String>> list) {\n        if (row == board.length) {\n            ArrayList<String> arr = new ArrayList<>();\n            \n            // Convert the boolean board to a list of strings representing the board configuration\n            for (int j = 0; j < board.length; j++) {\n                String ans = \"\";\n                for (int i = 0; i < board[j].length; i++) {\n                    if (board[j][i] == false) {\n                        ans += \".\";\n                    } else {\n                        ans += \"Q\";\n                    }\n                }\n                arr.add(ans);\n            }\n            list.add(arr); // Add the board configuration to the list of solutions\n            return;\n        }\n        \n        for (int col = 0; col < board.length; col++) {\n            if (isSafe(board, row, col)) {\n                board[row][col] = true; // Place a queen in the current position\n                queens(board, row + 1, list); // Recursively solve the problem for the next row\n                board[row][col] = false; // Backtrack and remove the queen from the current position\n            }\n        }\n    }\n    \n    // Function to check if it is safe to place a queen in a given position\n    private static boolean isSafe(boolean[][] board, int row, int col) {\n        // Check the vertical column for any previously placed queens\n        for (int i = 1; i <= row; i++) {\n            if (board[row - i][col]) {\n                return false;\n            }\n        }\n        \n        // Check the left diagonal for any previously placed queens\n        int max = Math.min(row, col);\n        for (int i = 1; i <= max; i++) {\n            if (board[row - i][col - i]) {\n                return false;\n            }\n        }\n        \n        // Check the right diagonal for any previously placed queens\n        int maxtimes = Math.min(row, board.length - col - 1);\n        for (int i = 1; i <= maxtimes; i++) {\n            if (board[row - i][col + i]) {\n                return false;\n            }\n        }\n        \n        return true; // It is safe to place a queen in the given position\n    }\n}\n"
  },
  {
    "path": "Backtracking/sudoko_solver.java",
    "content": "/*Write a program to solve a Sudoku puzzle by filling the empty cells.\n\nA sudoku solution must satisfy all of the following rules:\n\nEach of the digits 1-9 must occur exactly once in each row.\nEach of the digits 1-9 must occur exactly once in each column.\nEach of the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.\nThe '.' character indicates empty cells.\n\n \n\nExample 1:\n\n\nInput: board = [[\"5\",\"3\",\".\",\".\",\"7\",\".\",\".\",\".\",\".\"],[\"6\",\".\",\".\",\"1\",\"9\",\"5\",\".\",\".\",\".\"],[\".\",\"9\",\"8\",\".\",\".\",\".\",\".\",\"6\",\".\"],[\"8\",\".\",\".\",\".\",\"6\",\".\",\".\",\".\",\"3\"],[\"4\",\".\",\".\",\"8\",\".\",\"3\",\".\",\".\",\"1\"],[\"7\",\".\",\".\",\".\",\"2\",\".\",\".\",\".\",\"6\"],[\".\",\"6\",\".\",\".\",\".\",\".\",\"2\",\"8\",\".\"],[\".\",\".\",\".\",\"4\",\"1\",\"9\",\".\",\".\",\"5\"],[\".\",\".\",\".\",\".\",\"8\",\".\",\".\",\"7\",\"9\"]]\nOutput: [[\"5\",\"3\",\"4\",\"6\",\"7\",\"8\",\"9\",\"1\",\"2\"],[\"6\",\"7\",\"2\",\"1\",\"9\",\"5\",\"3\",\"4\",\"8\"],[\"1\",\"9\",\"8\",\"3\",\"4\",\"2\",\"5\",\"6\",\"7\"],[\"8\",\"5\",\"9\",\"7\",\"6\",\"1\",\"4\",\"2\",\"3\"],[\"4\",\"2\",\"6\",\"8\",\"5\",\"3\",\"7\",\"9\",\"1\"],[\"7\",\"1\",\"3\",\"9\",\"2\",\"4\",\"8\",\"5\",\"6\"],[\"9\",\"6\",\"1\",\"5\",\"3\",\"7\",\"2\",\"8\",\"4\"],[\"2\",\"8\",\"7\",\"4\",\"1\",\"9\",\"6\",\"3\",\"5\"],[\"3\",\"4\",\"5\",\"2\",\"8\",\"6\",\"1\",\"7\",\"9\"]]\nExplanation: The input board is shown above and the only valid solution is shown below:\n\n */\npackage Backtracking;\n\npublic class sudokoSolver {\n    \n    \n        public void solveSudoku(char[][] board) {\n            Solver(board, 0);\n        }\n    \n         static boolean Solver(char[][] board , int total)\n        {\n            if(total==81)\n            {\n                return true;\n            }\n            int sr = total/9;\n            int sc = total%9;\n             \n            if(board[sr][sc]!='.')\n            {\n                return Solver(board, total+1);\n            }\n            for(int i=1 ; i<=9 ; i++)\n            {\n                char curr = (char) (i+'0');\n                if(canElementBePlaced(board , sr , sc , curr))\n                {\n                board[sr][sc]=curr;\n                if (Solver(board , total+1))\n                {\n                  return true;\n                }\n                board[sr][sc]='.';\n            }\n        }\n        return false;\n        }\n        static void print(char[][] board)\n        {\n          for(int i=0; i<9 ;i++)\n            {\n                for(int j=0 ; j<9 ; j++)\n                {\n                    System.out.print(board[i][j]+\", \");\n                }\n                System.out.println();\n            }\n        }\n         \n        static boolean canElementBePlaced(char[][] board , int r , int c , char k)\n        {\n            for(int i=0 ; i<9 ; i++)\n            {\n                if(board[r][i]==k)\n                {\n                    return false;\n                }\n            }\n            \n            for(int j =0 ; j<9 ; j++)\n            {\n                if(board[j][c]==k)\n                {\n                    return false;\n                }\n            }\n            \n           int sr = r-(r%3);\n           int sc = c-(c%3);\n           \n           for(int i=sr; i<=sr+2;i++)\n           {\n               for(int j=sc ; j<=sc+2; j++)\n               {\n                  if (board[i][j]==k)\n                   {\n                       return false;\n                   }\n               }\n           }\n           return true;\n        }\n\n}\n"
  },
  {
    "path": "Binary Search/BinarySearchRecursive.java",
    "content": "\n/*\n * Problem : Implement Binary Search using Recursion.\n * \n * RECURSION : Function that calls itself is called recursion.\n * \n * Algorithm:\n * 1) Get an sorted array and a target to be found in the array.\n * 2) Find the middle index by dividing the first and last element.\n * 3) If the middle element is equal to target , return the mid index.\n * 4) If the middle element is greater than the target , in the next recursive call make last element as mid-1\n * 5) If the middle element is smaller than the target , in the next recursive call make first element as mid+1\n * 6) If start is less than end ,ie,if the element not found , return -1.\n * \n * Time complexity: worst case: O(logN) , N - size of the array.\n * \n * Space Complexity: O(logN) (since we use stack for function calls)\n * \n */\n\n\npublic class BinarySearchRecursive {\n\n    public static void main(String[] args) {\n        int[] arr = {1,2,5,89,99,101};\n        int target = 1;\n        System.out.println(binarySearch(arr , target,0 , arr.length-1));\n    }\n\n    static int binarySearch(int[] arr ,int target, int start , int end) {\n\n       int mid = (start + end)/2;\n\n       if (start > end) {\n           return -1;\n       }\n       if (arr[mid] == target) {\n           return mid;\n       }\n\n       else if (arr[mid] > target) {\n           return binarySearch(arr , target , start , mid-1);\n       }\n\n       return  binarySearch(arr ,target , mid+1, end);\n\n    }\n}\n"
  },
  {
    "path": "Binary Search/binary_search.cpp",
    "content": "/*\n    The binarySearch function takes in a sorted vector of integers arr and a target value target to search for.\n    The function initializes the left and right pointers to the first and last indices of the array respectively.\n    The function uses a while loop to keep searching until the left and right pointers meet.\n    Inside the loop, the function calculates the middle index by adding the left and right indices and dividing by 2.\n    If the middle element is equal to the target, the function returns the middle index.\n    If the target is greater than the middle element, the function discards the left half of the array and moves the left pointer to the middle + 1 index.\n    If the target is smaller than the middle element, the function discards the right half of the array and moves the right pointer to the middle - 1 index.\n    If the target is not found in the array, the function returns -1.\n    The driver code initializes a sorted array and a target value, and calls the binarySearch function to search for the target value.\n    The function returns the index of the target value, or -1 if it is not found.\n    The driver code prints the result of the search to the console.\n*/\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\n// Binary search function\n// Takes in a sorted vector of integers and a target value to search for\n// Returns the index of the target value if found, -1 otherwise\nint binarySearch(vector<int> arr, int target) {\n    int left = 0;\n    int right = arr.size() - 1;\n    \n    // Loop until left and right pointers meet\n    while (left <= right) {\n        int mid = left + (right - left) / 2;\n        \n        // If the target is found, return the index\n        if (arr[mid] == target) {\n            return mid;\n        }\n        // If target is greater than the middle element, discard the left half\n        else if (arr[mid] < target) {\n            left = mid + 1;\n        }\n        // If target is smaller than the middle element, discard the right half\n        else {\n            right = mid - 1;\n        }\n    }\n    \n    // Target not found\n    return -1;\n}\n\n// Driver code to test binary search function\nint main() {\n    vector<int> arr = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};\n    int target = 12;\n    int result = binarySearch(arr, target);\n    \n    if (result == -1) {\n        cout << \"Element not found\" << endl;\n    }\n    else {\n        cout << \"Element found at index \" << result << endl;\n    }\n    return 0;\n}\n"
  },
  {
    "path": "Binary Search/binary_search.js",
    "content": "/**\n * Finds the first and last occurrence of a target value in a sorted array.\n *\n * @param {number[]} N - The sorted array of numbers.\n * @param {number} T - The target value to search for.\n * @returns {number[]} An array containing the first and last index of the target value, or [-1,-1] if not found.\n */\nconst searchRange = function(N, T) {\n    // Helper function to perform binary search on the array\n    const find = (target, arr, left=0, right=arr.length) => {\n      while (left <= right) {\n        // Calculate the middle index\n        let mid = left + right >> 1;\n        // If the middle element is less than the target, move the left pointer to mid + 1\n        if (arr[mid] < target) left = mid + 1;\n        // If the middle element is greater than or equal to the target, move the right pointer to mid - 1\n        else right = mid - 1;\n      }\n      // Return the left pointer, which will be the index of the target or the insertion point if not found\n      return left;\n    }; \n  \n    // Find the leftmost index of the target value\n    let Tleft = find(T, N);\n    // If the target value is not found in the array, return [-1,-1]\n    if (N[Tleft] !== T) return [-1,-1];\n    // Find the rightmost index of the target value\n    return [Tleft, find(T+1, N, Tleft) - 1];\n  };\n  "
  },
  {
    "path": "Binary Search/binary_search.py",
    "content": "\"\"\"\n    Intuition:\n        If you have to guess a magic number from 1-100, the best first attempt would be to guess '50'\n        or in other words, the middle. If I tell you that the magic number is higher,\n        you now don't need to consider all numbers 1-50,\n        and if it is lower you wouldn't need to consider numbers 50-100!!\n\n        In Binary Search, we follow the same idea,\n        1. Compar the target with the middle element.\n        2. If the target is higher, then the target can only lie in the right (greater) subarray. We re-calculate mid and repeat step 1.\n        3. If the target is lower, the target  can only lie in the left (lower) half. We re-calculate mid and repeat step 1.\n\n        Binary search can only operate on a sorted array.\n        Further reading: https://en.wikipedia.org/wiki/Binary_search_algorithm\n\"\"\"\n\n\n\n\nimport math\n\ndef binary_search(lst, target):\n    if not lst:\n        return -1\n    lo = 0\n    hi = len(lst)-1\n\n    while lo <= hi:\n        mid = math.floor(lo + (hi - lo) / 2)  # Find mid. math.floor is used to round floats down.\n        if lst[mid] < target:  # Element in mid is lower than target.\n            lo = mid + 1  # Our low (start) becomes the element after mid.\n        elif lst[mid] > target:  # Element in mid is higher than target.\n            hi = mid - 1  # Our high (end) becomes the element before mid.\n        elif lst[mid] == target:\n            print(f\"Found {target} at index {mid}.\")\n            return mid\n    print(f\"Target {target} not found.\")\n    return -1\n\n\narr = [10, 20, 30, 50, 60, 80, 110, 130, 140, 170]\nbinary_search(arr, 80)\nbinary_search(arr, 10)\nbinary_search(arr, 110)\nbinary_search(arr, 20)\nbinary_search(arr, 140)\nbinary_search(arr, 2)\nbinary_search(arr, 1)\n"
  },
  {
    "path": "Binary Search/binary_search_iterative.go",
    "content": "/*\n  Write a function that takes in a sorted array of integers as well as a target\n  integer. The function should use the Binary Search algorithm to determine if\n  the target integer is contained in the array and should return its index if it\n  is, otherwise -1\n  Sample Input : [0, 1, 44, 66, 77] target = 66\n  Output : 3\n  Sample Input : [0, 1, 44, 66, 77] target = 101\n  Output : -1\n*/\npackage main\n\nimport \"fmt\"\n\nfunc BinarySearch(array []int, target int) int {\n\t// mark start and end\n\tstart := 0\n\tend := len(array) - 1\n\t// idea behind bs is, since array is already sorted we can use it to our advantage\n\t// 1 compute mid\n\t// 2 if mid value is less than target then we only need to search index less than mid \n\t// 3 if mid value is greater than target then we only need to search index greater than mid \n\t// and keep repeating from step 1\n\t// make sure start and end dont cross each other\n\tfor start <= end {\n\t\t// compute mid, prevent overflow of integer\n\t\tmid := start + (end - start) / 2\n\t\tif array[mid] == target {\n\t\t\treturn mid\n\t\t} else if array[mid] > target { // Element in mid is higher than target.\n\t\t\tend = mid - 1 // # Our (end) becomes the element before mid.\n\t\t} else if array[mid] < target { // Element in mid is lower than target.\n\t\t\tstart = mid + 1 // # Our (start) becomes the element after mid.\n\t\t}\n\t}\n\treturn -1\n}\n\nfunc main() {\n\tarr := []int{-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 33, 44, 55}\n\ttarget := 7\n\tmsg := BinarySearch(arr, target)\n\tfmt.Println(msg)\n\tmsg = BinarySearch(arr, 700)\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Binary Search/binary_search_recursive.go",
    "content": "/*\n\tImplelemtation of Recursive Binary Search\n\n\tIn computer science, binary search, also known as half-interval search,\n\tlogarithmic search, or binary chop, is a search algorithm that\n\tfinds the position of a target value within a sorted array.\n\tBinary search compares the target value to the middle element of the array.\n\tIf they are not equal, the half in which the target cannot lie is eliminated\n\tand the search continues on the remaining half,\n\tagain taking the middle element to compare to the target value,\n\tand repeating this until the target value is found.\n\tIf the search ends with the remaining half being empty, the target is not in the array.\n\tSource(https://en.wikipedia.org/wiki/Binary_search_algorithm)\n*/\npackage main\n\nimport \"fmt\"\n\nfunc BinarySearchRecursive(Arr []int, key int) bool {\n\tlow := 0\n\thigh := len(Arr) - 1\n\tif low <= high {\n\t\tmid := low + (high - low) / 2 // prevent overflow\n\t\tif Arr[mid] > key { // Element in mid is higher than target.\n\t\t\treturn BinarySearchRecursive(Arr[:mid], key) // search from start to mid \n\t\t} else if Arr[mid] < key { // Element in mid is lower than target.\n\t\t\treturn BinarySearchRecursive(Arr[mid + 1:], key) // search from mid + 1 to last\n\t\t} else {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunc main() {\n\tArr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}\n\tfmt.Println(BinarySearchRecursive(Arr, 5))\n\tfmt.Println(BinarySearchRecursive(Arr, 6))\n\tfmt.Println(BinarySearchRecursive(Arr, -1))\n\tfmt.Println(BinarySearchRecursive(Arr, -10))\n\tfmt.Println(BinarySearchRecursive(Arr, 70))\n}"
  },
  {
    "path": "Binary Search/binary_serach_first_and_last_occurence.py",
    "content": "class Solution:\n    def __init__(self):\n        self.start_index=-1\n        self.end_index=-1\n    \n    ''' Time complexity - O(logn), Space complexity - O(1)''''\n    '''Once the binary Search is implemented, to find the start_index, we store the current index where we find the target and implement search again on the left side of the array'''\n    def binarySearchFirst(self,arr,low,high,target):\n        if(low>high):\n            return \n        mid=(low+high)//2\n        if(arr[mid]>target):\n            Solution.binarySearchFirst(self,arr,low,mid-1,target)\n        elif(arr[mid]<target):\n            Solution.binarySearchFirst(self,arr,mid+1,high,target)\n        else:\n            self.start_index = mid\n            Solution.binarySearchFirst(self,arr,low,mid-1,target)\n    \n    '''Once the binary Search is implemented, to find the end_index, we store the current index where we find the target and implement search again on the right side of the array'''\n    def binarySearchLast(self,arr,low,high,target):\n        if(low>high):\n            return \n        mid=(low+high)//2\n        if(arr[mid]>target):\n            Solution.binarySearchLast(self,arr,low,mid-1,target)\n        elif(arr[mid]<target):\n            Solution.binarySearchLast(self,arr,mid+1,high,target)\n        else:\n            self.end_index = mid\n            Solution.binarySearchLast(self,arr,mid+1,high,target)\n    \n    def searchRange(self, nums: List[int], target: int) -> List[int]:\n\n        #implementing binarySearchLast to populate the self.end_index\n        Solution.binarySearchLast(self,nums,0,len(nums)-1,target)\n\n        #implementing binarySearchFirst to populate the self.start_index\n        Solution.binarySearchFirst(self,nums,0,len(nums)-1,target)\n        return [self.start_index, self.end_index]"
  },
  {
    "path": "Binary Search/first_and_last_pos.js",
    "content": "/* \n                                            -----------QUESTION--------------\n\nGiven an array of integers nums sorted in non-decreasing order, find the starting and ending position of a given target value.\nIf target is not found in the array, return [-1, -1]. Devise an algorithm with O(log n) runtime complexity.\n\nExample 1:\n    Input: nums = [5,7,7,8,8,10], target = 8\n    Output: [3,4]\n\nExample 2:\n    Input: nums = [5,7,7,8,8,10], target = 6\n    Output: [-1,-1]\n\nExample 3:\n    Input: nums = [], target = 0\n    Output: [-1,-1]\n\n\nConstraints:\n        0 <= nums.length <= 105\n        -109 <= nums[i] <= 109\n        nums is a non-decreasing array (increasing order)\n        -109 <= target <= 109\n*/\n\n\n//                                       ------------SOLUTION-------------\n\n/* \nAn intuitive Binary Search algorithm is used to find target value indices of occurence since it is given an increasing array. We perform two searches one for first occurence and second for last occurence.\n\nTwo pointer start and end for 0th and (N-1)th index to iteratively find the mid of array.  \n\nFirst follow the common left-based binary search to find the target value first occurence. \nIf found we proceed further check in left subarray as target may still be presnt either to left or right of mid.\n\nTo find last occurence index we again iterate to right subarray from start as the current value but reset last to N-1.\n\n(start does not require to begin again from 0th index as in first pass we have covered upto start index. This does not affect overall complexity but reduces number of comparisions.)\n*/\n\n\n/*\n\nTime Complexity: \n    O(log N) - Each time the sub-array reduces to half as\n    N/2 -> N/4 -> N/8 ... after k iterations this results to O(1)\n    N/ 2^k = 1\n    N = 2^k   (take a log) \n    k = log(N) (the complexity is defined by how many times the loop executes which is k times)\n\n    T.C = O(log N)\n\nSpace Complexity: \n    O(1) - Constant space for storing variables\n \n*/\n\nvar searchRange = function(nums, target) {\n    \n    let ans = [-1, -1];\n    // array of resulting indices pre-initialised with -1 in case the target is not found\n\n    let start = 0, end = nums.length - 1, mid;\n\n\n    //First Occurence\n    while (start <= end) {\n        mid = Math.floor((start + end) / 2);\n\n        if (nums[mid] === target) {\n            ans[0] = mid;\n            end = mid - 1;\n            //we continue to search in left subarray to find the first occurence position of target value\n        }\n        else if (nums[mid] > target) {\n            end = mid - 1;\n        }\n        else {\n            start = mid + 1;\n        }\n    }\n\n\n    //Last Occurence\n    end = nums.length - 1;\n    while (start <= end) {\n        mid = Math.floor((start + end) / 2);\n\n        if (nums[mid] === target) {\n            ans[1] = mid;\n            start = mid + 1;\n            //for last occurence we search the subarray right to the middle index \n        }\n        else if (nums[mid] > target) {\n            end = mid - 1;\n        }\n        else {\n            start = mid + 1;\n        }\n    }\n\n    return ans;\n};"
  },
  {
    "path": "Binary Search/first_and_last_pos_of_element.cpp",
    "content": "/*\nGiven an array of integers nums sorted in non-decreasing order, find the starting and ending position of a given target value.\n\nIf target is not found in the array, return [-1, -1].\n\nYou must write an algorithm with O(log n) runtime complexity.\n\n \n\nExample 1:\n\nInput: nums = [5,7,7,8,8,10], target = 8\nOutput: [3,4]\nExample 2:\n\nInput: nums = [5,7,7,8,8,10], target = 6\nOutput: [-1,-1]\nExample 3:\n\nInput: nums = [], target = 0\nOutput: [-1,-1]\n \n\nConstraints:\n\n0 <= nums.length <= 105\n-109 <= nums[i] <= 109\nnums is a non-decreasing array.\n-109 <= target <= 109\n\n*/\n#include<bits/stdc++.h>\nclass Solution {\npublic:\n    int get_index(vector<int>& nums, int target, bool found){\n        int ans = -1;\n        int start = 0, end = nums.size() - 1;\n        while(start <= end){\n            int mid = start + (end - start) / 2;\n            if(nums[mid] == target){\n                ans = mid;\n                if(found){\n                    end = mid - 1; // search in left part\n                }\n                else{\n                    start = mid + 1; // search in right part\n                }\n            }\n            else if(nums[mid] > target){\n                end = mid - 1;\n            }\n            else{\n                start = mid + 1;\n            }\n        }\n        return ans;\n    }\n    vector<int> searchRange(vector<int>& nums, int target) {\n        vector<int> ans(2, -1);\n        int first = get_index(nums, target, true);\n        if(first == -1)\n            return ans;\n        int last = get_index(nums, target, false);\n        //ans.push_back(first);\n        //ans.push_back(last);\n        ans[0] = first;\n        ans[1] = last;\n        return ans;\n    }\n};"
  },
  {
    "path": "Binary Search/first_and_last_position.java",
    "content": "/*\n Given an array of integers nums sorted in non-decreasing order, find the starting and ending position of a given target value\nIf target is not found in the array, return [-1, -1].\n\nYou must write an algorithm with O(log n) runtime complexity.\n\nExample 1:\n\nInput: nums = [5,7,7,8,8,10], target = 8\nOutput: [3,4]\nExample 2:\n\nInput: nums = [5,7,7,8,8,10], target = 6\nOutput: [-1,-1]\n\nHow this Code Works?\nThe firstPos method will give the starting position of the target element. We will find the mid and check if the mid element  is equals to the target we will check if previous element is equal to target or not if it is then place low to mid-1 if not   just update the high to mid-1. Next condition is if the element is greater then target it means we have to search in the left side of array hence high=mid-1.And last condition if the element is less than the target do low=mid-1. If this method returns Integer.MAX_VALUE if means element is not present. Hence return {-1,-1} as answer.\n\nThe lastPost method works same way as the above method. Passed extra paramter of low because it's now already clear that from  where we have to start as we already got the first index.\n */\nclass FirstandLastPosition {\n    public int[] searchRange(int[] nums, int target) {\n        if(nums.length==0) return new int[]{-1,-1};\n    int a=firstPos(nums, target);\n    int b=0;\n    if(a!=Integer.MAX_VALUE){\n      b=lastPos(nums,target,a);\n    }else{\n        return new int[]{-1,-1};\n    }\n    return new int[]{a,b};\n  }\n  private  int firstPos(int[] arr,int target){\n    int ans=Integer.MAX_VALUE,low=0,high=arr.length-1;\n\n    while(low<=high){\n      int mid=low+(high-low)/2;\n\n      if(arr[mid]==target){\n        ans=Math.min(ans,mid);\n        if(mid>0 && arr[mid-1]==target) low=mid-1;\n         high=mid-1;\n      }else if(arr[mid]>target){\n         high=mid-1;\n      }else if(arr[mid]<target){\n         low=mid+1;\n      }\n    }\n    return ans;\n  }\n  private  int lastPos(int[] arr,int target,int low){\n    int ans=Integer.MIN_VALUE,high=arr.length-1;\n    while(low<=high){\n      int mid=low+(high-low)/2;\n      if(arr[mid]==target){\n        ans=Math.max(ans,mid);\n        if(mid+1<arr.length && arr[mid+1]==target) high=mid+1;\n        low=mid+1;\n      }else if(arr[mid]>target){\n        high=mid-1;\n      }else{\n        low=mid+1;\n      }\n    }\n     return ans;\n  } \n}\n"
  },
  {
    "path": "Binary Search/first_last_pos.java",
    "content": "/* Given a sorted array arr containing n elements with possibly duplicate elements, \nthe task is to find indexes of first and last occurrences of an element x in the given array. \n\nExample 1: Input: arr [] = [ 1, 3, 5, 5, 5, 5, 67, 123, 125 ] , target = 5\nOUTPUT: [2 5]\nExplanation: First occurrence of 5 is at index 2 and last occurrence of 5 is at index 5.\n\nExample 2: Input: arr[] = [1,2,3,,5,6,7,8],target = 4\nOUTPUT: [-1,-1]\n\nAPPROACH:\n    #We will separately write methods for first occurence and last occurence of the element \n\n    # Follows the standard binary search algorithm with little moddification for first and last occurence\n    # For the first occurence , return the start index at the end of the loop\n    # For the last occurence , return the end index at the end of loop*/\nimport java.util.*;\npublic class FirstLastPos{\n    public static int firstOccurence(int[] arr,int target){\n        int start = 0,end=arr.length-1;\n        while(start <= end){\n            int mid = start + (end-start)/2;\n            if (arr[mid]== target){\n                end = mid -1;\n            }\n            else if(arr[mid] > target){\n                end = mid -1;\n            }\n            else if(arr[mid] < target){\n                start = mid + 1;\n            }\n        }\n        if(start < arr.length && arr[start] == target){\n            return start;\n        }\n        else{\n            return -1;\n        }\n    }\n\n    public static int lastOccurence(int[] arr,int target){\n        int start = 0,end=arr.length-1;\n        while(start <= end){\n            int mid = start + (end-start)/2;\n            if (arr[mid]== target){\n                start = mid + 1;\n            }\n            else if(arr[mid] > target){\n                end = mid -1;\n            }\n            else if(arr[mid] < target){\n                start = mid + 1;\n            }\n        }\n        if(end >= 0 && arr[end] == target){\n            return end;\n        }\n        else{\n            return -1;\n        }\n    }\n\n    public static void main(String[] args){\n        int[] arr = {1,5,7,7,7,9,11,14};\n        int target = 7;\n        int[] result = new int[2];\n        result[0] = firstOccurence(arr,target);\n        result[1] = lastOccurence(arr,target);\n        System.out.println(Arrays.toString(result));\n\n    }\n}"
  },
  {
    "path": "Binary Search/first_occurance.go",
    "content": "// Search of first occurance of element using Binary search\n// Sample Input {0, 1, 1, 4, 5} key 1\n// Output 1\n// Time conplexity O(log n)\npackage main\n\nimport \"fmt\"\n\nfunc FirstOccurance(Arr []int, key int) int {\n\tstart, end, result := 0, len(Arr)-1, -1\n\n\tfor start <= end {\n\t\tmid := start + (end-start)/2\n\t\tif Arr[mid] > key {\n\t\t\tend = mid - 1\n\t\t} else if Arr[mid] < key {\n\t\t\tstart = mid + 1\n\t\t} else {\n\t\t\tresult = mid // update result\n\t\t\tend = mid - 1 // move to left side to search for occurance\n\t\t}\n\t}\n\treturn result\n}\n\nfunc main() {\n\tArr := []int{0, 1, 1, 4, 5}\n\tfmt.Println(FirstOccurance(Arr, 1))\n}"
  },
  {
    "path": "Binary Search/first_occurence.java",
    "content": "/* Finding the index of the first occurence of a number in a sorted array: \nGiven a sorted array and a number x,find the first occurence of x in the \narray. If the element is not found , return -1.\n\nSolve it in O(logN) complexity\n\nExample :\n\nINPUT :  nums = [1,5,7,7,7,9,11,14],  target = 7\nOUTPUT: 2\n\nINPUT :  nums = [1,2,4,6,45,55],  target = 20\nOUTPUT: -1\n\nApproach:\n\n  # Approach will be similar to other binary search problems, but there is a need to find first occurence,\n    So ,if the element found is equal to target, make the end pointer point before of the mid value.\n\n  # Once the condition violates and loop terminates ,check if the target value is equal to the start pointer value.\n    if it is equal, return the start pointer. if it is not return -1;\n\n*/\n\n\n\npublic class FirstOccurence{\n    public static int firstOccurence(int[] arr,int target){\n        int start = 0,end=arr.length-1;\n        while(start <= end){\n            int mid = start + (end-start)/2;\n            if (arr[mid]== target){\n                end = mid -1;\n            }\n            else if(arr[mid] > target){\n                end = mid -1;\n            }\n            else if(arr[mid] < target){\n                start = mid + 1;\n            }\n        }\n        if(start < arr.length && arr[start] == target){\n            return start;\n        }\n        else{\n            return -1;\n        }\n    }\n\n    public static void main(String[] args){\n        int[] arr = {1,5,7,7,7,9,11,14};\n        int target = 7;\n        System.out.print(firstOccurence(arr,target));\n\n    }\n}"
  },
  {
    "path": "Binary Search/first_true.cpp",
    "content": "/*\n    An array of boolean values is divided into two sections; the left section consists of all false and the \n    right section consists of all true. Find the First True in a Sorted Boolean Array of the \n    right section, i.e. the index of the first true element. If there is no true element, return -1.\n    \n    Input: arr = [false, false, true, true, true]\n    Output: 2\n\n    Explanation: first true's index is 2.\n*/\n#include <iostream>\n#include <vector>\n\nint findBoundary(std::vector<bool>& arr) {\n    int low = 0;                // Initialize the low pointer to the beginning of the vector.\n    int high = arr.size() - 1;  // Initialize the high pointer to the end of the vector.\n    int bv = -1;                // Initialize bv (boundary value) to -1.\n\n    while (low <= high) {\n        int mid = low + (high - low) / 2;  // Calculate the middle index.\n\n        if (!arr[mid]) {\n            // If the element at the middle index is 'false',\n            // it means that the last 'true' value should be on the right side.\n            low = mid + 1;               // Move the low pointer to the right of mid.\n        } else {\n            // If the element at the middle index is 'true',\n            // update bv to the current middle index and continue searching on the left side.\n            bv = mid;                    // Update bv to the current middle index.\n            high = mid - 1;              // Move the high pointer to the left of mid.\n        }\n    }\n\n    // The loop ends when low > high, indicating that the search is complete.\n    // bv contains the index of the last 'true' value encountered.\n    return bv;\n}\n\nint main() {\n    std::vector<bool> arr = {false, false, false, true, true, true, true};\n    int boundary = findBoundary(arr);\n    std::cout << \"Boundary Index: \" << boundary << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "Binary Search/first_true.go",
    "content": "/*\n    An array of boolean values is divided into two sections; the left section consists of all false and the \n    right section consists of all true. Find the First True in a Sorted Boolean Array of the \n    right section, i.e. the index of the first true element. If there is no true element, return -1.\n    \n    Input: arr = [false, false, true, true, true]\n    Output: 2\n\n    Explanation: first true's index is 2.\n*/\n\npackage main\n\nimport (\n    \"fmt\"\n)\n\nfunc findBoundary(arr []bool) int {\n    low := 0               // Initialize the low pointer to the beginning of the slice.\n    high := len(arr) - 1   // Initialize the high pointer to the end of the slice.\n    bv := -1               // Initialize bv (boundary value) to -1.\n\n    for low <= high {\n        mid := low + (high - low) / 2  // Calculate the middle index.\n\n        if !arr[mid] {\n            // If the element at the middle index is 'false',\n            // it means that the last 'true' value should be on the right side.\n            low = mid + 1               // Move the low pointer to the right of mid.\n        } else {\n            // If the element at the middle index is 'true',\n            // update bv to the current middle index and continue searching on the left side.\n            bv = mid                    // Update bv to the current middle index.\n            high = mid - 1              // Move the high pointer to the left of mid.\n        }\n    }\n\n    // The loop ends when low > high, indicating that the search is complete.\n    // bv contains the index of the last 'true' value encountered.\n    return bv\n}\n\nfunc main() {\n    arr := []bool{false, false, false, true, true, true, true}\n    boundary := findBoundary(arr)\n    fmt.Println(\"Boundary Index:\", boundary)\n}\n"
  },
  {
    "path": "Binary Search/first_true.java",
    "content": "/*\n    An array of boolean values is divided into two sections; the left section consists of all false and the \n    right section consists of all true. Find the First True in a Sorted Boolean Array of the \n    right section, i.e. the index of the first true element. If there is no true element, return -1.\n    \n    Input: arr = [false, false, true, true, true]\n    Output: 2\n\n    Explanation: first true's index is 2.\n*/\npublic import java.util.Arrays;\nimport java.util.List;\nimport java.util.Scanner;\nimport java.util.stream.Collectors;\n\nclass Solution {\n    public static int findBoundary(List<Boolean> arr) {\n        int low = 0;                // Initialize the low pointer to the beginning of the list.\n        int high = arr.size() - 1;  // Initialize the high pointer to the end of the list.\n        int bv = -1;                // Initialize bv (boundary value) to -1.\n\n        while (low <= high) {\n            int mid = low + (high - low) / 2;  // Calculate the middle index.\n\n            if (arr.get(mid) == false) {\n                // If the element at the middle index is 'false',\n                // it means that the last 'true' value should be on the right side.\n                low = mid + 1;  // Move the low pointer to the right of mid.\n            } else {\n                // If the element at the middle index is 'true',\n                // update bv to the current middle index and continue searching on the left side.\n                bv = mid;       // Update bv to the current middle index.\n                high = mid - 1; // Move the high pointer to the left of mid.\n            }\n        }\n\n        // The loop ends when low > high, indicating that the search is complete.\n        // bv contains the index of the last 'true' value encountered.\n        return bv;\n    }\n}\n"
  },
  {
    "path": "Binary Search/first_true.js",
    "content": "/*\n    An array of boolean values is divided into two sections; the left section consists of all false and the \n    right section consists of all true. Find the First True in a Sorted Boolean Array of the \n    right section, i.e. the index of the first true element. If there is no true element, return -1.\n    \n    Input: arr = [false, false, true, true, true]\n    Output: 2\n\n    Explanation: first true's index is 2.\n*/\nfunction findBoundary(arr) {\n  let low = 0; // Initialize the low pointer to the beginning of the array.\n  let high = arr.length - 1; // Initialize the high pointer to the end of the array.\n  let bv = -1; // Initialize bv (boundary value) to -1.\n\n  while (low <= high) {\n    let mid = low + Math.floor((high - low) / 2); // Calculate the middle index.\n\n    if (!arr[mid]) {\n      // If the element at the middle index is 'false',\n      // it means that the last 'true' value should be on the right side.\n      low = mid + 1; // Move the low pointer to the right of mid.\n    } else {\n      // If the element at the middle index is 'true',\n      // update bv to the current middle index and continue searching on the left side.\n      bv = mid; // Update bv to the current middle index.\n      high = mid - 1; // Move the high pointer to the left of mid.\n    }\n  }\n\n  // The loop ends when low > high, indicating that the search is complete.\n  // bv contains the index of the last 'true' value encountered.\n  return bv;\n}\n\nconst arr = [false, false, false, true, true, true, true];\nconst boundary = findBoundary(arr);\nconsole.log(\"Boundary Index:\", boundary);\n"
  },
  {
    "path": "Binary Search/first_true.py",
    "content": "'''\n    An array of boolean values is divided into two sections; the left section consists of all false and the \n    right section consists of all true. Find the First True in a Sorted Boolean Array of the \n    right section, i.e. the index of the first true element. If there is no true element, return -1.\n    \n    Input: arr = [false, false, true, true, true]\n    Output: 2\n\n    Explanation: first true's index is 2.\n'''\ndef findBoundary(arr):\n    low = 0               # Initialize the low pointer to the beginning of the list.\n    high = len(arr) - 1   # Initialize the high pointer to the end of the list.\n    bv = -1               # Initialize bv (boundary value) to -1.\n\n    while low <= high:\n        mid = low + (high - low) // 2  # Calculate the middle index.\n\n        if not arr[mid]:\n            # If the element at the middle index is 'false',\n            # it means that the last 'true' value should be on the right side.\n            low = mid + 1               # Move the low pointer to the right of mid.\n        else:\n            # If the element at the middle index is 'true',\n            # update bv to the current middle index and continue searching on the left side.\n            bv = mid                    # Update bv to the current middle index.\n            high = mid - 1              # Move the high pointer to the left of mid.\n\n    # The loop ends when low > high, indicating that the search is complete.\n    # bv contains the index of the last 'true' value encountered.\n    return bv\n\narr = [False, False, False, True, True, True, True]\nboundary = findBoundary(arr)\nprint(\"Boundary Index:\", boundary)\n"
  },
  {
    "path": "Binary Search/floor_of_target.java",
    "content": "/* Floor of an element in a sorted array\n    You are given a sorted array nums and a target . \n    Find the index of the greatest element that is less than or equal to target\n\n    EXAMPLES:\n        INPUT :  nums = [2,4,5,7,9,11,18,25],  target = 18\n        OUTPUT: 6\n\n        INPUT :  nums = [2,4,5,7,9,11,18,25],  target = 10\n        OUTPUT: 4\n\n    APPROACH :\n        We will implement this problem using BinarySearch since the array is sorted and will be similar to ceil\n        but with slight modification\n        \n  */\n\n  \npublic class FloorOfTarget{\n\n    public static int search_floor(int[] nums,int target){\n        int start = 0,end = nums.length-1;\n        while(start <=end){\n        int mid = start +(end-start)/2;\n        if(nums[mid]==target){\n            return mid;  // returns the target\n        }\n        else if(nums[mid] > target){\n            end = mid-1;\n        }\n        else{\n            start = mid +1;\n        }\n    }\n    return end; // returns the nearest element to target if the target is not found\n    }\n    public static void main(String[] args){\n        int[] nums = {2,4,5,7,9,11,18,25};\n        int target = 10;  // output will be 4 in this case.\n        System.out.print(search_floor(nums,target));\n}\n}\n"
  },
  {
    "path": "Binary Search/index_position.java",
    "content": "/* BINARY SEARCH\n   Problem Statement:\n   Given an array of integers nums sorted in ascending order and a target ,\n   You need to search the target in the array nums.\n   If the target is found ,return the index position,else return -1\n\n   Time complexity:\n   WorstCase: O(log N)  N--> length of the array\n   BestCase:  O(1)\n\n   Example :\n    Input: nums = [-5,-2,0,2,5,30], target = 2\n    Output: 3\n    Explanation : target 2 is found at index 3\n*/\n\npublic class IndexPosition {\n\n    // method for implementation of binary search\n    public static int search(int[] nums, int target) {\n        int start=0,end=nums.length-1;\n        while(start<=end){\n            int mid = start + (end-start)/2;\n            // if middle value is equal to target return the mid index\n            if(nums[mid] == target){\n                return mid;\n            }\n            // if mid value is greater than the target, search the left sub array\n            else if(nums[mid] > target){\n                end = mid - 1;\n            }\n            // if mid value is lesser than the target, search the right sub array\n            else if(nums[mid] < target){\n                start = mid + 1;\n            }\n        }\n        return -1;  \n    }\n    public static void main(String[] args){\n        //get input array and target value\n        // you can also get input dynamically using Scanner class\n        int [] array = {-5,-2,0,2,5,30};\n        int target = 2;\n        System.out.print(search(array,target));\n    }\n}"
  },
  {
    "path": "Binary Search/infinity_array.java",
    "content": "/*Binary Search in an Infinite array in Java\n * Given an array whose size is not fixed,find the index of the target element in the array.\n * EXAMPLE: [5,15,34,56,77,87...] (array can be of any size)\n * Target = 56;\n * Output: 3;\n * \n * APPROACH:\n * The approach will be similar to normal binary search but in reverse order \n * ie; For the  start and end value, find the range which will be taking the target in the range.\n * We will not specify the array length since the array size is infinity.\n * Send the start and end value to the search function and return the position of the element.\n * \n */\n\npublic class InfinityArray {\n    public static void main(String[] args){\n        int[] nums = {2,5,7,9,14,45,56,77,89,101};// can be of any size\n        int target = 56;\n        System.out.println(range(nums,target));\n    }\n\n    public static int range(int[] nums,int target){\n        int start=0,end=1;\n        while(target > nums[end]){\n            int temp = end +1;\n            end = end + (end-start)*2;\n            start = temp;\n        }\n        return search(nums,target,start,end);\n    }\n    public static int search(int[] nums, int target,int start,int end) {\n        while(start<=end){\n            int mid = start + (end-start)/2;\n            // if middle value is equal to target return the mid index\n            if(nums[mid] == target){\n                return mid;\n            }\n            // if mid value is greater than the target, search the left sub array\n            else if(nums[mid] > target){\n                end = mid - 1;\n            }\n            // if mid value is lesser than the target, search the right sub array\n            else if(nums[mid] < target){\n                start = mid + 1;\n            }\n        }\n        return -1;  \n    }\n}\n"
  },
  {
    "path": "Binary Search/last_occurance.go",
    "content": "// Search of last occurance of element using Binary search\n// Sample Input {0, 1, 1, 4, 5} key 1\n// Output 1\n// Time conplexity O(log n)\npackage main\n\nimport \"fmt\"\n\nfunc LastOccurance(Arr []int, key int) int {\n\tstart, end, result := 0, len(Arr)-1, -1\n\n\tfor start <= end {\n\t\tmid := start + (end-start)/2\n\t\tif Arr[mid] > key {\n\t\t\tend = mid - 1\n\t\t} else if Arr[mid] < key {\n\t\t\tstart = mid + 1\n\t\t} else {\n\t\t\tresult = mid // update result\n\t\t\tstart = mid + 1 // move to RIGHT side to search for occurance\n\t\t}\n\t}\n\treturn result\n}\n\nfunc main() {\n\tArr := []int{0, 1, 1, 1, 2, 2, 3, 3, 4, 5}\n\tfmt.Println(LastOccurance(Arr, 1)) // 3\n\tfmt.Println(LastOccurance(Arr, 2)) // 5\n\tfmt.Println(LastOccurance(Arr, 3)) // 7\n}"
  },
  {
    "path": "Binary Search/median_of_two_sorted_arrays.cpp",
    "content": "/*\nApproach: \n    let nums1 = [1, 3, 4, 7, 10, 12], nums2 = [2, 3, 6, 15]\n\n    In order to find the median, we need a single sorted array. So a naive approach is that, just merge the 2 sorted arrays and find the median of that array.\n    This will have a time Complexity of O(n1 + n2), Space Complexity of O(n1 + n2)\n\n    Now, lets optimise it.\n    So, the sorted form of the given array is arr = [1, 2, 3, 3, 4, 6, 7, 10, 12, 15]. To find the median of the array, we need to select the 2 mid elements and average it out.\n    If we observe the sorted array carefully, then we notice that the 2 middle elements are arr[4] = 4 and arr[5] = 6, => arr[4] <= arr[5].\n    \n    Thought process:\n    Now, since the arrays are sorted, so the binary searh may be able to solve the problem.\n    Observation 1: If we partition the sorted array arr into 2 halves, then for sure we know that there would be 5 elements on left half and 5 elements on right half.\n        Now, we can select 5 elements for right half from nums1 and nums2 combinedly and similarly the rest of the elements for the left half.\n        Example:\n            1. left => [1, 3, 4, 7, 2], right => [10, 12, 3, 6, 15]\n            2. left => [1, 3, 4, 2, 3], right => [7, 10, 12, 6, 15]\n            3. left => [1, 3, 2, 3, 6], right => [4, 7, 10, 12, 15]\n    \n    Observation 2: All the elements on left half is lesser than all the elements on the right half.\n        Now, according to the observation, I have to check that all the elements in the left <= all the elements in the right. This can be done by just comparing the maximum of left half <= minimum of right half.\n    \n    Hence, the problem boils down to a searching problem; but how to identify the binary search approach??\n        Suppose, we partition the element as example 1, then the max of left[] = 7 and min of right[] = 3, but according to the 2nd observation, it is not valid. So, in order to have a correct max in left, I need to reduce its value and consequestly, the min of right[] should be increased. That means, I have to move leftwards in nums1 to have a correct max value in left half.\n*/\n\n// Leetcode link: https://leetcode.com/problems/median-of-two-sorted-arrays/\n\n#include<bits/stdc++.h>\n\nclass Solution {\npublic:\n    double findMedianSortedArrays(std::vector<int>& nums1, std::vector<int>& nums2) {\n        int n1 = nums1.size(); // stores the length of nums1 array\n        int n2 = nums2.size(); // stores the length of nums2 array\n\n        if(n2 > n1) return findMedianSortedArrays(nums2, nums1);\n\n        // according to approach described above, I am applying binary search on nums1 array\n        int lo = 0, hi = n1;\n        while(lo <= hi){\n            int mid1 = (lo+hi)/2; // mid of nums1\n            int mid2 = (n1 + n2 + 1)/2 - mid1;\n\n            std::pair<int, int> maxleft, minright;\n            maxleft.first = mid1 == 0 ? INT_MIN : nums1[mid1-1];\n            maxleft.second = mid2 == 0 ? INT_MIN : nums2[mid2-1];\n\n            minright.first = mid1 == n1 ? INT_MAX : nums1[mid1];\n            minright.second = mid2 == n2 ? INT_MAX : nums2[mid2];\n\n            if(maxleft.first <= minright.second and maxleft.second <= minright.first){\n                if((n1+n2)%2 == 1){\n                    return std::max(maxleft.first, maxleft.second);\n                } else {\n                    return (std::max(maxleft.first, maxleft.second) + std::min(minright.first, minright.second))/2.0;\n                }\n            } else if (maxleft.first > minright.second){\n                hi = mid1-1;\n            } else {\n                lo = mid1+1;\n            }\n        }\n    }\n};\n\nint main(int argc, char const *argv[])\n{\n    int n;\n\n    std::cin>>n;\n    std::vector<int> arr1(n, 0);\n    for(int i=0;i<n;i++){\n        std::cin>>arr1[i];\n    }\n\n    std::cin>>n;\n    std::vector<int> arr2(n, 0);\n    for(int i=0;i<n;i++){\n        std::cin>>arr2[i];\n    }\n\n    Solution sol = Solution();\n    double res = sol.findMedianSortedArrays(arr1, arr2);\n\n    std::cout<<res<<\"\\n\";\n    return 0;\n}\n"
  },
  {
    "path": "Binary Search/median_of_two_sorted_arrays.js",
    "content": "/*\nGiven two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.\n\n  The overall run time complexity should be O(log (m+n)).\n\n  Example 1:\n  Input: nums1 = [1,3], nums2 = [2]\n  Output: 2.00000\n  Explanation: merged array = [1,2,3] and median is 2.\n\n  Example 2:\n  Input: nums1 = [1,2], nums2 = [3,4]\n  Output: 2.50000\n  Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.\n  \n  Constraints:\n  nums1.length == m\n  nums2.length == n\n  0 <= m <= 1000\n  0 <= n <= 1000\n  1 <= m + n <= 2000\n  -106 <= nums1[i], nums2[i] <= 106\n*/\n\n// Approach 1: Brute force\nfunction findMedianSortedArrays(arr1, arr2) {\n  const merged = arr1.concat(arr2).sort((a, b) => a - b);\n  const n = merged.length;\n  if (n % 2 === 0) {\n    const middle = n / 2;\n    return (merged[middle - 1] + merged[middle]) / 2;\n  } else {\n    const middle = Math.floor(n / 2);\n    return merged[middle];\n  }\n}\n\n// Approach 2:  Binary Search\nfunction findMedianSortedArrays(arr1, arr2) {\n  // If arr1 is longer than arr2, swap them to ensure arr1 is shorter\n  if (arr1.length > arr2.length) {\n    [arr1, arr2] = [arr2, arr1];\n  }\n\n  const m = arr1.length;\n  const n = arr2.length;\n  let left = 0;\n  let right = m;\n\n  while (left <= right) {\n    // Partition arr1 and arr2\n    const partition1 = Math.floor((left + right) / 2);\n    const partition2 = Math.floor((m + n + 1) / 2) - partition1;\n\n    // Calculate the max and min elements of the left and right partitions\n    const maxLeft1 = partition1 === 0 ? -Infinity : arr1[partition1 - 1];\n    const minRight1 = partition1 === m ? Infinity : arr1[partition1];\n    const maxLeft2 = partition2 === 0 ? -Infinity : arr2[partition2 - 1];\n    const minRight2 = partition2 === n ? Infinity : arr2[partition2];\n\n    // If the partitions are correctly balanced, return the median\n    if (maxLeft1 <= minRight2 && maxLeft2 <= minRight1) {\n      if ((m + n) % 2 === 0) {\n        return (\n          (Math.max(maxLeft1, maxLeft2) + Math.min(minRight1, minRight2)) / 2\n        );\n      } else {\n        return Math.max(maxLeft1, maxLeft2);\n      }\n    } else if (maxLeft1 > minRight2) {\n      // If maxLeft1 is too big, move partition1 to the left\n      right = partition1 - 1;\n    } else {\n      // If maxLeft2 is too big, move partition1 to the right\n      left = partition1 + 1;\n    }\n  }\n}\n"
  },
  {
    "path": "Binary Search/minimum_in_rotated_sorted_array.cpp",
    "content": "/*\n    Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:\n\n    [4,5,6,7,0,1,2] if it was rotated 4 times.\n    [0,1,2,4,5,6,7] if it was rotated 7 times.\n    Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]].\n\n    Given the sorted rotated array nums of unique elements, return the minimum element of this array.\n\n    You must write an algorithm that runs in O(log n) time.\n\n    Example 1:\n    Input: nums = [3,4,5,1,2]\n    Output: 1\n    Explanation: The original array was [1,2,3,4,5] rotated 3 times.\n    \n    Example 2:\n    Input: nums = [4,5,6,7,0,1,2]\n    Output: 0\n    Explanation: The original array was [0,1,2,4,5,6,7] and it was rotated 4 times.\n    \n    Example 3:\n    Input: nums = [11,13,15,17]\n    Output: 11\n    Explanation: The original array was [11,13,15,17] and it was rotated 4 times. \n    \n    Constraints:\n    n == nums.length\n    1 <= n <= 5000\n    -5000 <= nums[i] <= 5000\n    All the integers of nums are unique.\n    nums is sorted and rotated between 1 and n times.\n*/\n\nclass Solution {\npublic:\n    int findMin(vector<int>& nums) {\n        int n = nums.size();\n        int start = 0, end = n - 1;\n        while(start <= end){\n            int mid = start + (end - start) / 2;\n            int next = (mid + 1) % n;\n            int prev = (mid - 1 + n) % n;\n            if(nums[mid] <= nums[prev] && nums[mid] <= nums[next])\n                return nums[mid];\n            if(nums[mid] <= nums[end]){\n                end = mid - 1;\n            }\n            else if(nums[mid] >= nums[start]){\n                start = mid + 1;\n            }\n        }\n        return -1;\n    }\n};"
  },
  {
    "path": "Binary Search/perfect_square.java",
    "content": "/* finding the perfect square\nGiven a positive integer num, return true if num is a perfect square or false otherwise.\n\nA perfect square is an integer that is the square of an integer. \nIn other words, it is the product of some integer with itself.\n\nExamples:\nInput: num = 25\nOutput: true\nExplanation: We return true because 5 * 5 = 25 and 5 is an integer.\n\nInput: num = 14\nOutput: false\nExplanation: We return false because 3.742 * 3.742 = 14 and 3.742 is not an integer.\n\nAPPROACH:\n    As we know square of a squareroot of a number is that number itself. for example if the number is 36 \n    and the square root of 36 is 6 , we can say that 6*6 =36 (our number).\n    We use this logic with binary search algorithm\n\n*/\n\nclass PerfectSquare {\n    public static boolean isPerfectSquare(int num) {\n            // Binary Search\n            long start =1,end=num;\n            while(start<=end){\n                long mid = start + (end-start)/2;\n                if(mid*mid == num){\n                    return true;\n                }\n                else if(mid*mid > num){\n                    end = mid-1;\n                }\n                else if(mid*mid < num){\n                    start = mid+1;\n                }\n            }\n            return false;\n    }\n    public static void main(String[] args){\n        // you can also get input dynamically using Scanner class\n        int number = 100;\n        System.out.print(isPerfectSquare(number));\n    \n    }}"
  },
  {
    "path": "Binary Search/search_in_rotated_sorted_array.cpp",
    "content": "/*\n\tGiven the array nums after the possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.\n\tYou must write an algorithm with O(log n) runtime complexity.\n\n\tInput: nums = [4,5,6,7,0,1,2], target = 0\n\tOutput: 4\n\t\n\tInput: nums = [4,5,6,7,0,1,2], target = 3\n\tOutput: -1\n\t\n\tInput: nums = [1], target = 0\n\tOutput: -1\n\n\tConstraints:\n\t>  1 <= nums.length <= 5000\n\t>  -104 <= nums[i] <= 104\n\t>  All values of nums are unique.\n\t>  nums is an ascending array that is possibly rotated.\n\t>  -104 <= target <= 104\n\n\tAPPROACH\n\t1. Find the index at which the array has been rotated with the help of Binary Search.\n\t2. Store the index of rotation as INDX and find the range where target might be found using the following comparision:\n\t\t\tRANGE = {INDX+1, HIGH} if TARGET < NUMS[LOW]\n\t\t\tRANGE = {LOW, INDX-1}  if TARGET > NUMS{HIGH]\n\t3. Perform Binary Search for TARGET in the required range.\n\t4. If target is not found return -1.\n\n\tTIME COMPLEXITY : O(NlogN)  SPACE COMPLEXITY: O(1)\n*/\nclass Solution {\npublic:\n    int search(vector<int>& nums, int target) {\n        // Initialize Variable for later Usage\n        int n=nums.size();\n        int low=0;\n        int high=n-1;\n\n        //Find the Rotation Point in the Rotated Array\n        while(low<=high){\n            int mid=(low+high)/2;\n            if(mid==0 || mid==n-1){\n                low=mid;\n                break;\n            }\n            if(nums[mid-1]>nums[mid] && nums[mid+1]>nums[mid]){\n                low=mid;\n                break;\n            }\n            else if(nums[mid]>nums[low] && nums[mid]>nums[high]){\n                low=mid+1;\n            }\n            else{\n                high=mid-1;\n            }\n        }\n\n        // Re-initialize Variables Needed\n        int indx=low;\n        low=0, high=n-1;\n        if(target==nums[indx]){\n            return indx;\n        }\n        else if(target>nums[high]){\n            high=indx-1;\n        }\n        else if(target<nums[low]){\n            low=indx+1;\n        }\n\n        // Binary  Search for Target in range low-high\n        while(low<=high){\n            int mid=(low+high)/2;\n            if(nums[mid]==target){\n                return mid;\n            }\n            else if(target>nums[mid]){\n                low=mid+1;\n            }\n            else{\n                high=mid-1;\n            }\n        }\n\n        // If target not found return -1\n        return -1;\n    }\n};"
  },
  {
    "path": "Binary Search/search_in_sorted_rotated_array.cpp",
    "content": "/*\n    There is an integer array nums sorted in ascending order (with distinct values).\n\n    Prior to being passed to your function, nums is possibly rotated at an unknown pivot index k (1 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed). For example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become [4,5,6,7,0,1,2].\n\n    Given the array nums after the possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.\n\n    You must write an algorithm with O(log n) runtime complexity.\n\n    Example 1:\n    Input: nums = [4,5,6,7,0,1,2], target = 0\n    Output: 4\n\n    Example 2:\n    Input: nums = [4,5,6,7,0,1,2], target = 3\n    Output: -1\n\n    Example 3:\n    Input: nums = [1], target = 0\n    Output: -1\n    \n    Constraints:\n    1 <= nums.length <= 5000\n    -104 <= nums[i] <= 104\n    All values of nums are unique.\n    nums is an ascending array that is possibly rotated.\n    -104 <= target <= 104\n\n*/\n\nclass Solution {\npublic:\n    int search(vector<int>& nums, int target) {\n        int start = 0, end = nums.size() - 1;\n        int ans = -1;\n        while(start <= end){\n            int mid = start + (end - start) / 2;\n            if(target == nums[mid]){\n                return mid;\n            }\n            if(nums[start] <= nums[mid]){\n                if(target >= nums[start] && target <= nums[mid]){\n                    end = mid - 1;\n                }\n                else{\n                    start = mid + 1;\n                }\n            }\n            else{\n                if(target >= nums[mid] && target <= nums[end]){\n                    start = mid + 1;\n                }\n                else {\n                    end = mid - 1;\n                }\n            }\n        }\n        return ans;\n    }\n};"
  },
  {
    "path": "Binary Search/search_in_sorted_rotated_array.go",
    "content": "/*\n\tThe code snippet represents a function `SearchInSortedMatrix` that searches for a target value in a sorted matrix and returns the position (row and column) of the target if found, or [-1, -1] if not found.\n\n\tHere's how the code works:\n\n\t1. Initialize the starting position at the top-right corner of the matrix, i.e., `row = 0` and `col = len(matrix[0]) - 1`.\n\n\t2. Enter a loop that continues as long as the current position is within the matrix bounds, i.e., `row < len(matrix)` and `col >= 0`.\n\n\t3. Inside the loop, compare the value at the current position (`matrix[row][col]`) with the target value:\n\t- If the value is greater than the target, it means the target value must be in a lower column, so decrement the column\n\t   index (`col--`).\n\t- If the value is less than the target, it means the target value must be in a higher row, so increment the row index\n\t  (`row++`).\n\t- If the value is equal to the target, it means the target value is found. Return the position as [row, col].\n\n\t4. If the loop completes without finding the target value, it means the target is not present in the matrix. Return [-1, -1]\n\t   to indicate that the target was not found.\n\n\tThe code takes advantage of the sorted nature of the matrix to perform an efficient search. By starting at the top-right\n\tcorner and comparing the current value with the target, it eliminates rows and columns in each iteration, narrowing down the search space until the target is found or the entire matrix is traversed.\n\n\tOverall, the code has a time complexity of O(N + M), where N is the number of rows in the matrix and M is the number of\n\tcolumns, as it performs a linear search through the matrix.\n\n\tTime complexity: O(n + m) time where n is the length of the matrix's rows and m is the length of the matrix's columns\n\tSpace complexity: O(1)\n*/\npackage main\n\nimport \"fmt\"\n\nfunc SearchInSortedMatrix(matrix [][]int, target int) []int {\n\t// Initialize the starting position at the top-right corner of the matrix\n\trow, col := 0, len(matrix[0])-1\n\n\t// Continue the loop as long as the current position is within the matrix bounds\n\tfor row < len(matrix) && col >= 0 {\n\t\t// Compare the value at the current position with the target value\n\t\tif matrix[row][col] > target {\n\t\t\t// If the value is greater than the target, move to the left column\n\t\t\tcol--\n\t\t} else if matrix[row][col] < target {\n\t\t\t// If the value is less than the target, move to the next row\n\t\t\trow++\n\t\t} else {\n\t\t\t// If the value is equal to the target, return the position [row, col]\n\t\t\treturn []int{row, col}\n\t\t}\n\t}\n\n\t// If the loop completes without finding the target, return [-1, -1]\n\treturn []int{-1, -1}\n}\n\n\nfunc main() {\n\tmatrix := [][]int{\n\t\t{1, 4, 7, 12, 15, 1000},\n\t\t{2, 5, 19, 31, 32, 1001},\n\t\t{3, 8, 24, 33, 35, 1002},\n\t\t{40, 41, 42, 44, 45, 1003},\n\t\t{99, 100, 103, 106, 128, 1004},\n\t}\n\n\ttarget := 33\n\n\tresult := SearchInSortedMatrix(matrix, target)\n\tif result[0] == -1 && result[1] == -1 {\n\t\tfmt.Println(\"Target not found in the matrix\")\n\t} else {\n\t\tfmt.Println(\"Target found at position:\", result)\n\t}\n}"
  },
  {
    "path": "Binary Search/search_in_sorted_rotated_array.java",
    "content": "/*There is an integer array nums sorted in ascending order (with distinct values).\n\nPrior to being passed to your function, nums is possibly rotated at an unknown pivot index k (1 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed). For example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become [4,5,6,7,0,1,2].\n\nGiven the array nums after the possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.\n\nYou must write an algorithm with O(log n) runtime complexity.\n\n \n\nExample 1:\n\nInput: nums = [4,5,6,7,0,1,2], target = 0\nOutput: 4\nExample 2:\n\nInput: nums = [4,5,6,7,0,1,2], target = 3\nOutput: -1\nExample 3:\n\nInput: nums = [1], target = 0\nOutput: -1\n  */\n\n\npublic class searchInRotatedArray {\n\n    //Brute force solution \n    \n        public static int searchTarget(int nums[] , int target)\n        {\n            int result = -1;\n            for(int i=0 ; i<nums.length ; i++)\n            {\n               if(nums[i]==target)\n               {\n                result = i;\n               } \n            }\n            return result ;\n        }\n    \n    // Optimized Solution\n    public static int search(int nums[], int l, int h, int target)\n    {\n        // l: The starting index\n        // h: The ending index, you have to search the key in this range\n        \n        int start = 0;\n        int end = nums.length-1;\n        int result = -1;\n        \n        while(start <=end)\n        {\n        int mid = start +(end -start)/2;\n        \n        if(nums[mid]==target)\n        {\n            result = mid;\n        } \n        \n        \n        if(nums[start]<=nums[mid])\n        {\n       if(nums[start]<=target && nums[mid]>=target)\n        {\n            end = mid-1;\n        }\n        \n        else\n        {\n            start =mid+1;\n        }\n        }\n        \n        \n       else\n       {\n       if(nums[mid]<=target && target<nums[end])\n        {\n          start=  mid+1;\n        }\n        else \n        {\n            end = mid-1;\n        }\n        }\n        }\n        return result;\n    }\n   \n    public static void main(String[] args)\n    {\n        int[] nums = {4,5,6,7,0,1,2};\n        int target = 0;\n        System.out.println(search(nums , 0 , 7 , target));\n    }\n}\n"
  },
  {
    "path": "Binary Search/search_in_sorted_rotated_array.py",
    "content": "'''\n    There is an integer array nums sorted in ascending order (with distinct values).\n\n    Prior to being passed to your function, nums is possibly rotated at an unknown pivot index k (1 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed). For example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become [4,5,6,7,0,1,2].\n\n    Given the array nums after the possible rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.\n\n    You must write an algorithm with O(log n) runtime complexity.\n\n    \n\n    Example 1:\n    Input: nums = [4,5,6,7,0,1,2], target = 0\n    Output: 4\n\n    Example 2:\n    Input: nums = [4,5,6,7,0,1,2], target = 3\n    Output: -1\n\n    Example 3:\n    Input: nums = [1], target = 0\n    Output: -1\n\n'''\nclass Solution:\n    def binarySearch(nums,low,high,target):\n        if(low>high):\n            return -1\n        mid = (low+high)//2\n        if(nums[mid]<target):\n            return Solution.binarySearch(nums,mid+1,high,target)\n        elif(nums[mid]>target):\n            return Solution.binarySearch(nums,low,mid-1,target)\n        else:\n            return mid\n    \n    def search(self, nums: List[int], target: int) -> int:\n        #Finding the index where the array was rotated and binary searching the first and second parts for the target value.\n        rotated_index = -1\n        for i in range(len(nums)-1):\n            if(nums[i]>nums[i+1]):\n                rotated_index = i\n                break\n            \n        return Solution.binarySearch(nums,0,rotated_index,target) & Solution.binarySearch(nums,rotated_index+1,len(nums)-1,target)\n        "
  },
  {
    "path": "Binary Search/search_insert_position.js",
    "content": "// https://leetcode.com/problems/search-insert-position/description/\n\n/*\n\nGiven a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.\n\nYou must write an algorithm with O(log n) runtime complexity.\n\nExample 1:\n\nInput: nums = [1,3,5,6], target = 5\nOutput: 2\nExample 2:\n\nInput: nums = [1,3,5,6], target = 2\nOutput: 1\nExample 3:\n\nInput: nums = [1,3,5,6], target = 7\nOutput: 4\n\nExplanation:\n    In a given sorted array this code uses binary search where we divide the array into two parts and check if the number is present then we return the index of element otherwise we return what should be index of that target in the given array.\n    The loops iterates until the start index and end index of array is same.\n    We calculate the middle index on each iteration of loop as start index / end index might change on the basis of last iteration result.\n    If the middle index element is the target element then we return middle index otherwise we loop through the entire array until last one or two elements left.\n    On the basis of last one or two elements we decide what is going to be the index of target in the array.\n*/\n\nfunction findSearchPosition(nums, target) {\n    let startIndex = 0;\n    let endIndex = nums.length - 1;\n\n    while (startIndex <= endIndex) {\n        const midIndex = startIndex + Math.floor((endIndex - startIndex) / 2);\n\n        // Base case if middle index element is our target then we will return the middle index\n        if (nums[midIndex] === target) {\n            return midIndex;\n        }\n\n        // In case if element is not present in the given array then in the final iteration when only last one or two elements are remaining we will check what should be our target number index in the given array\n        if (startIndex === endIndex || startIndex + 1 === endIndex) {\n            // If element at start index is greater then target then target then start index will be assigned to target\n            if (nums[startIndex] > target) {\n                return startIndex;\n                // if target is greater then end index element then end index + 1 will be assigned to target\n            } else if (nums[endIndex] < target) {\n                return endIndex + 1;\n            } else {\n                return startIndex + 1;\n            }\n        }\n\n        // if the target element is greater then the middle index element then we will change the start index next to middle index otherwise we will change last index to middle index - 1\n        if (nums[midIndex] < target) {\n            startIndex = midIndex + 1;\n        } else {\n            endIndex = midIndex - 1;\n        }\n    }\n}\n\n//driver code\nvar nums = [1, 3, 5, 6];\nconsole.log(findSearchPosition(nums, 8));\n\n//Input: nums = [1,3,5,6], target = 8\n// Output: 4\n"
  },
  {
    "path": "Binary Search/square_root.java",
    "content": "/* Square root of a number\nGiven a non-negative integer x, return the square root of x rounded down to the nearest integer. \nThe returned integer should be non-negative as well.\n\nExamples:\n    Input: x = 36\n    Output: 6\n    Explanation: The square root of 36 is 6, so we return 6.\n\n    Input: x = 8\n    Output: 2\n    Explanation: The square root of 8 is 2.82842..., and since we round it down to the nearest integer, \n                 2 is returned.\n \n\nHOW TO SOLVE:\n    This is similar to finding perfect square of number but to return the square root.\n    We use Binary Search for this problem.\n*/\n\npublic class SquareRoot{\n    public static int sqrt(int x){\n        int start = 1, end=x;\n        while(start<=end){\n            int mid = (start+end)/2;\n            if(x/mid==mid){\n                return mid;\n            }\n            else if(mid< x/mid){\n                start = mid+1;\n            }\n            else if(mid > x/mid){\n                end = mid-1;\n            }\n            \n        }\n        return end;\n    }\n     public static void main(String[] args){\n        // you can also get input dynamically using Scanner class\n        int number = 36;\n        System.out.print(sqrt(number));\n    }\n    }"
  },
  {
    "path": "Bit Manipulation/bloom_filter.cpp",
    "content": "// Bloom Filter Implementation\r\n// Question: How does the Bloom filter work, and how is it implemented in the C++\r\n\r\n// Approach and Explanation\r\n\r\n// 1.Hash Functions: The Bloom filter uses four hash functions (`h1`, `h2`, `h3`, `h4`) to map input strings to positions in the bit array. These hash functions generate different indexes based on the input string and the size of the bit array.\r\n\r\n// 2. Bit Array: The Bloom filter uses a `std::bitset<1000000>` called `bitarray` to represent the filter. It is a fixed-size bit array where each bit represents a position that can be set (1) or unset (0).\r\n\r\n// 3. Lookup Operation: The `lookup` function takes a reference to the `bitarray` and a string `s` as input. It calculates the hash values for `s` using the four hash functions and checks if the corresponding positions in the `bitarray` are all set (1). If all positions are set, it returns `true`, indicating that the element is possibly present in the filter. Otherwise, it returns `false`.\r\n\r\n// 4. Insert Operation: The `insert` function takes a reference to the `bitarray` and a string `s` as input. It first checks if the element is already present in the filter by calling the `lookup` function. If the element is already present, it prints a message indicating that it is probably already present. Otherwise, it calculates the hash values for `s` using the four hash functions and sets the corresponding positions in the `bitarray` to 1, indicating the insertion of the element.\r\n\r\n// 5. Main Function: In the `main` function, a `bitarray` of size 1000000 is created. A set of strings (`sarray`) is defined, representing the elements to be added to the filter. For each string `s` in `sarray`, it checks if `s` is already present in the filter using the `lookup` function. If it is present, it prints a message indicating that it is already present. Otherwise, it inserts `s` into the filter using the `insert` function.\r\n\r\n// The Bloom filter provides a probabilistic way to test whether an element is possibly in a set. It may return false positives, indicating that an element is possibly in the set when it's not, but it will never give false negatives. The accuracy of the filter depends on the size of the bit array, the number of hash functions used, and the number of elements inserted.\r\n\r\n// In this implementation, the size of the bit array is fixed at 1000000, and four hash functions are used. The elements are inserted by setting the corresponding positions in the bit array to 1. The `lookup` function checks if all the positions for an element are set (1), indicating its possible presence in the filter.\r\n\r\n// Time Complexity->\tO(1) on average, O(n) in the worst case\r\n// Space Complexity->\tO(n)\r\n\r\n#include <iostream>\r\n#include <bitset>\r\n#include <cmath>\r\n#define ll long long\r\n\r\n// Hash function 1\r\n// This function calculates the hash value of a string using a simple additive approach.\r\nint h1(std::string s, int arrSize)\r\n{\r\n    ll int hash = 0;\r\n    for (int i = 0; i < s.size(); i++)\r\n    {\r\n        hash = (hash + ((int)s[i])); // Add the ASCII value of each character to the hash\r\n        hash = hash % arrSize;       // Take the modulus to ensure the hash value is within the array size\r\n    }\r\n    return hash;\r\n}\r\n\r\n// Hash function 2\r\n// This function calculates the hash value of a string using an exponential approach.\r\nint h2(std::string s, int arrSize)\r\n{\r\n    ll int hash = 1;\r\n    for (int i = 0; i < s.size(); i++)\r\n    {\r\n        hash = hash + pow(19, i) * s[i]; // Multiply each character by a power of 19 and add to the hash\r\n        hash = hash % arrSize;           // Take the modulus to ensure the hash value is within the array size\r\n    }\r\n    return hash % arrSize;\r\n}\r\n\r\n// Hash function 3\r\n// This function calculates the hash value of a string using a polynomial approach.\r\nint h3(std::string s, int arrSize)\r\n{\r\n    ll int hash = 7;\r\n    for (int i = 0; i < s.size(); i++)\r\n    {\r\n        hash = (hash * 31 + s[i]) % arrSize; // Multiply the hash by 31, add the character, and take the modulus\r\n    }\r\n    return hash % arrSize;\r\n}\r\n\r\n// Hash function 4\r\n// This function calculates the hash value of a string using a combination of multiplication and exponentiation.\r\nint h4(std::string s, int arrSize)\r\n{\r\n    ll int hash = 3;\r\n    int p = 7;\r\n    for (int i = 0; i < s.size(); i++)\r\n    {\r\n        hash += hash * 7 + s[i] * pow(p, i); // Multiply the hash by 7, add the character multiplied by a power of 7\r\n        hash = hash % arrSize;               // Take the modulus to ensure the hash value is within the array size\r\n    }\r\n    return hash;\r\n}\r\n\r\n// Lookup operation\r\n// This function checks if a given string is present in the bit array.\r\nbool lookup(std::bitset<1000000> &bitarray, std::string s)\r\n{\r\n    int a = h1(s, bitarray.size()); // Calculate hash using h1\r\n    int b = h2(s, bitarray.size()); // Calculate hash using h2\r\n    int c = h3(s, bitarray.size()); // Calculate hash using h3\r\n    int d = h4(s, bitarray.size()); // Calculate hash using h4\r\n\r\n    return bitarray[a] && bitarray[b] && bitarray[c] && bitarray[d]; // Check if all corresponding bits are set in the bit array\r\n}\r\n\r\n// Insert operation\r\n// This function inserts a string into the bit array.\r\nvoid insert(std::bitset<1000000> &bitarray, std::string s)\r\n{\r\n    // Check if the element is already present or not\r\n    if (lookup(bitarray, s))\r\n    {\r\n        std::cout << s << \" is probably already present\" << std::endl;\r\n    }\r\n    else\r\n    {\r\n        int a = h1(s, bitarray.size()); // Calculate hash using h1\r\n        int b = h2(s, bitarray.size()); // Calculate hash using h2\r\n        int c = h3(s, bitarray.size()); // Calculate hash using h3\r\n        int d = h4(s, bitarray.size()); // Calculate hash using h4\r\n\r\n        bitarray[a] = true; // Set corresponding bit in the bit array for hash a\r\n        bitarray[b] = true; // Set corresponding bit in the bit array for hash b\r\n        bitarray[c] = true; // Set corresponding bit in the bit array for hash c\r\n        bitarray[d] = true; // Set corresponding bit in the bit array for hash d\r\n\r\n        std::cout << s << \" inserted\" << std::endl;\r\n    }\r\n}\r\n\r\nint main()\r\n{\r\n    std::bitset<1000000> bitarray;\r\n    std::string sarray[] = {\"apple\", \"banana\", \"cherry\", \"orange\", \"grape\", \"kiwi\"};\r\n\r\n    for (const auto &s : sarray)\r\n    {\r\n        if (lookup(bitarray, s))\r\n        {\r\n            std::cout << s << \" is already present\" << std::endl;\r\n        }\r\n        else\r\n        {\r\n            insert(bitarray, s);\r\n        }\r\n    }\r\n\r\n    return 0;\r\n}\r\n"
  },
  {
    "path": "Bit Manipulation/bloom_filter.py",
    "content": "# Bloom Filter Implementation\r\n# Question: How can I implement a Bloom filter in Python?\r\n\r\n#  explanation of the approach:\r\n\r\n# 1. The `BloomFilter` class is defined to encapsulate the functionality of the Bloom filter. It takes two parameters during initialization: `capacity` (expected number of elements to be added to the filter) and `false_positive_rate` (desired false positive rate).\r\n\r\n# 2. The `calculate_size()` method is used to calculate the size of the bit array based on the capacity and false positive rate. It uses the formula `- (capacity * log(false_positive_rate)) / (log(2) ** 2)` to determine the size.\r\n\r\n# 3. The `calculate_num_hashes()` method calculates the number of hash functions to be used based on the size of the bit array and the capacity. It uses the formula `(size / capacity) * log(2)` to determine the number of hashes.\r\n\r\n# 4. The `bit_array` attribute is created using the `bitarray` library and initialized with the calculated size. All bits in the array are initially set to 0.\r\n\r\n# 5. The `add()` method is used to add an item to the Bloom filter. It iterates over the range of `num_hashes` and calculates the index for each hash function using the `mmh3.hash()` function. The index is obtained by taking the modulo of the hash value with the size of the bit array. The corresponding bit in the bit array is set to 1.\r\n\r\n# 6. The `contains()` method is used to check if an item is present in the Bloom filter. It follows a similar process as the `add()` method, iterating over the range of `num_hashes` and calculating the index for each hash function. If any of the corresponding bits in the bit array are 0, it indicates that the item is not present and False is returned. If all the bits are 1, it means the item might be present (false positive) and True is returned.\r\n\r\n# 7. In the example usage, a `BloomFilter` object is created with a capacity of 1000 and a false positive rate of 0.01.\r\n\r\n# 8. Three items (\"apple\", \"banana\", \"cherry\") are added to the Bloom filter using the `add()` method.\r\n\r\n# 9. The `contains()` method is used to check if certain items (\"apple\", \"banana\", \"cherry\", \"orange\") are present in the Bloom filter. The result is printed for each item.\r\n\r\n# The Bloom filter uses the MurmurHash3 hash function (`mmh3.hash()`) to generate hash values for the items. The number of hash functions and the size of the bit array are calculated based on the desired false positive rate and capacity. The Bloom filter provides a probabilistic check for membership, with a possibility of false positives but no false negatives.\r\n\r\n\r\nimport math\r\nimport mmh3\r\nfrom bitarray import bitarray\r\n\r\n\r\nclass BloomFilter:\r\n    def __init__(self, capacity, false_positive_rate):\r\n        self.capacity = capacity\r\n        self.false_positive_rate = false_positive_rate\r\n        self.size = self.calculate_size()\r\n        self.num_hashes = self.calculate_num_hashes()\r\n        self.bit_array = bitarray(self.size)\r\n        self.bit_array.setall(0)\r\n\r\n    def calculate_size(self):\r\n        # Calculate the size of the bit array based on the capacity and false positive rate\r\n        size = - (self.capacity * math.log(self.false_positive_rate)\r\n                  ) / (math.log(2) ** 2)\r\n        return int(size)\r\n\r\n    def calculate_num_hashes(self):\r\n        # Calculate the number of hash functions based on the size and capacity\r\n        num_hashes = (self.size / self.capacity) * math.log(2)\r\n        return int(num_hashes)\r\n\r\n    def add(self, item):\r\n        # Add an item to the Bloom filter\r\n        for seed in range(self.num_hashes):\r\n            # Generate a hash value using the MurmurHash3 algorithm with different seeds\r\n            index = mmh3.hash(item, seed) % self.size\r\n            self.bit_array[index] = 1\r\n\r\n    def contains(self, item):\r\n        # Check if an item is possibly in the Bloom filter\r\n        for seed in range(self.num_hashes):\r\n            # Generate a hash value using the MurmurHash3 algorithm with different seeds\r\n            index = mmh3.hash(item, seed) % self.size\r\n            if self.bit_array[index] == 0:\r\n                return False\r\n        return True\r\n\r\n\r\n# Create a Bloom filter with a capacity of 1000 items and a false positive rate of 0.01\r\nbloom_filter = BloomFilter(capacity=1000, false_positive_rate=0.01)\r\n\r\n# Add items to the filter\r\nbloom_filter.add(\"apple\")\r\nbloom_filter.add(\"banana\")\r\nbloom_filter.add(\"cherry\")\r\n\r\n# Check if items are in the filter\r\nprint(bloom_filter.contains(\"apple\"))    # Expected output: True\r\nprint(bloom_filter.contains(\"banana\"))   # Expected output: True\r\nprint(bloom_filter.contains(\"cherry\"))   # Expected output: True\r\nprint(bloom_filter.contains(\"orange\"))   # Expected output: False\r\n"
  },
  {
    "path": "Bit Manipulation/count_bits.go",
    "content": "// Program to count the number of bits that are set to 1 in an integer\n// The following program tests bits one at a time starting with the least-significant bit.\n// Since we perform O(1) computation per bit, the time complexity is O(n) where n is number of bits in the integer\n// Best case time complexity is O(1), if the input io 0\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\nfunc CountBits(x int) (int, error) {\n\tif x < 0 {\n\t\treturn x, errors.New(\"Negative number\")\n\t}\n\tnumBits := 0\n\tfor x > 0{\n\t\tnumBits += x & 1\n\t\tx >>= 1\n\t}\n\treturn numBits, nil\n}\n\nfunc main() {\n\tres, err := CountBits(7)\n\tfmt.Println(res)\n\tfmt.Println(err)\n\t\n}"
  },
  {
    "path": "Bit Manipulation/interesting_array.java",
    "content": "package BitManipulation;\n\nimport com.google.common.base.Stopwatch;\n\npublic class InterestingArray {\n    public static void main(String[] args) {\n        Stopwatch timer = Stopwatch.createStarted();\n\n        int[] array = {9, 14, 27, 81, 197, 0, 1};\n        String ans = solve(array);\n        System.out.println(ans);\n\n        System.out.println(\"Runtime \" + timer);\n    }\n\n    public static String solve(int[] array) {\n        // O(N) time | O(1) space\n        int oddCount = 0;\n\n        for (var num : array)\n            if (num % 2 != 0)\n                oddCount += 1;\n\n        return oddCount % 2 != 0 ? \"No\" : \"Yes\";\n    }\n}\n"
  },
  {
    "path": "Bit Manipulation/mod_array.java",
    "content": "/**\n * You are given a large number in the form of a array A of size N where each element denotes a digit of the number.\n * You are also given a number B. You have to find out the value of A % B and return it.\n *\n *\n *\n * Problem Constraints\n * 1 <= N <= 105\n * 0 <= Ai <= 9\n * 1 <= B <= 109\n *\n *\n * Input Format\n * The first argument is an integer array A.\n * The second argument is an integer B.\n *\n *\n * Output Format\n * Return a single integer denoting the value of A % B.\n *\n *\n * Example Input\n * Input 1:\n * A = [1, 4, 3]\n * B = 2\n * Input 2:\n *\n * A = [4, 3, 5, 3, 5, 3, 2, 1]\n * B = 47\n *\n *\n * Example Output\n * Output 1:\n * 1\n * Output 2:\n *\n * 20\n *\n *\n * Example Explanation\n * Explanation 1:\n * 143 is an odd number so 143 % 2 = 1.\n * Explanation 2:\n *\n * 43535321 % 47 = 20\n */\n\n/**\n * You are given a large number in the form of a array A of size N where each element denotes a digit of the number.\n * You are also given a number B. You have to find out the value of A % B and return it.\n *\n *\n *\n * Problem Constraints\n * 1 <= N <= 105\n * 0 <= Ai <= 9\n * 1 <= B <= 109\n *\n *\n * Input Format\n * The first argument is an integer array A.\n * The second argument is an integer B.\n *\n *\n * Output Format\n * Return a single integer denoting the value of A % B.\n *\n *\n * Example Input\n * Input 1:\n * A = [1, 4, 3]\n * B = 2\n * Input 2:\n *\n * A = [4, 3, 5, 3, 5, 3, 2, 1]\n * B = 47\n *\n *\n * Example Output\n * Output 1:\n * 1\n * Output 2:\n *\n * 20\n *\n *\n * Example Explanation\n * Explanation 1:\n * 143 is an odd number so 143 % 2 = 1.\n * Explanation 2:\n *\n * 43535321 % 47 = 20\n */\n\n\npackage ModularArithmetic;\n\npublic class ModArray {\n    public static void main(String[] args) {\n        int[] array = {4, 3, 5, 3, 5, 3, 2, 1};\n        int divisor = 47;\n        int ans = solve(array, divisor);\n        System.out.println(ans);\n    }\n    public static int solve(int[] array, int divisor) {\n        // O(N) time | O(1) space\n        long res = 0;\n        int len = array.length - 1;\n        long POWER_10 = 1;\n        long MOD = divisor;\n\n        for (int i = len; i > -1; i--) {\n            long currentDigit = array[i];\n            long currentValue = (currentDigit * POWER_10) % MOD;\n            res = (res + currentValue) % MOD;\n            POWER_10 = (POWER_10 * 10) % MOD;\n        }\n        return (int) res;\n    }\n}\n"
  },
  {
    "path": "Bit Manipulation/number_of_1_bits.java",
    "content": "/**\n * Write a function that takes an integer and returns the number of 1 bits it has.\n *\n *\n * Problem Constraints\n * 1 <= A <= 109\n *\n *\n * Input Format\n * First and only argument contains integer A\n *\n *\n * Output Format\n * Return an integer as the answer\n *\n *\n * Example Input\n * Input 1:\n * 11\n * Input 2:\n * 6\n *\n *\n * Example Output\n * Output 1:\n * 3\n * Output 2:\n * 2\n *\n *\n * Example Explanation\n * Explaination 1:\n * 11 is represented as 1011 in binary.\n * Explaination 2:\n * 6 is represented as 110 in binary.\n */\n\npackage BitManipulation;\n\npublic class NumberOf1Bits {\n    public static void main(String[] args) {\n        int num = 11;\n        int ans = solve(num);\n        System.out.println(ans);\n    }\n    public static int solve(int num) {\n        // O(Log(N)) tine | O(1) space\n        int currentNum = num, count = 0;\n\n        while (currentNum != 0) {\n            if ( (currentNum & 1) == 1) count++;\n            currentNum = currentNum >> 1;\n        }\n        return count;\n    }\n}\n"
  },
  {
    "path": "Bit Manipulation/parity_of_a_word.go",
    "content": "// Computing the parity of a word\n// The parity of a binary word is 1 if the number of 1s in the word is odd\n// The parity of a binary word is 0 if the number of 1s in the word is even\n\n// Input : 11\n// Output : 1\n\n// Input : 12\n// Output : 0\n\npackage main\n\nimport \"fmt\"\n\n// This algorithm iteratively tests the value of each bit while\n// tacking the number of 1's seen so far (Brute Force)\nfunc Parity(x int) int {\n\tresult := 0\n\tfor x > 0 {\n\t\tresult ^= (x & 1)\n\t\tx >>= 1\n\t}\n\treturn result\n}\n\nfunc ParityImproved(x int) int {\n\tresult := 0\n\tfor x > 0 {\n\t\tresult ^= 1\n\t\t// This can be used to improve the performance in the best and average cases.\n\t\tx &= (x - 1) // erase lowest set bit in a word in a single operation\n\t}\n\treturn result\n}\n\nfunc main() {\n\tfmt.Println(\"*********Brute Force*********\")\n\tmsg := Parity(11)\n\tfmt.Println(msg)\n\tmsg = Parity(12)\n\tfmt.Println(msg)\n\tfmt.Println(\"*********Improved*********\")\n\tmsg = ParityImproved(11)\n\tfmt.Println(msg)\n\tmsg = ParityImproved(12)\n\tfmt.Println(msg)\n}\n// The time complexity is O(n) where n is word size"
  },
  {
    "path": "Bit Manipulation/power_of_2.cpp",
    "content": "/*\n    Given an integer n, return true if it is a power of two. Otherwise, return false.\n\n    An integer n is a power of two, if there exists an integer x such that n == 2x.\n\n    Example 1:\n    Input: n = 1\n    Output: true\n    Explanation: 20 = 1\n    \n    Example 2:\n    Input: n = 16\n    Output: true\n    Explanation: 24 = 16\n    \n    Example 3:\n    Input: n = 3\n    Output: false\n    \n    Constraints:\n\n    -231 <= n <= 231 - 1\n    \n    Follow up: Could you solve it without loops/recursion?\n\n*/\n\n\nclass Solution {\npublic:\n    bool isPowerOfTwo(int n) {\n        return n > 0 && !(n &(n - 1));\n    }          \n};"
  },
  {
    "path": "Bit Manipulation/reduce_to_zero.cpp",
    "content": "/*\nGiven an integer num, return the number of steps to reduce it to zero.\n\nIn one step, if the current number is even, you have to divide it by 2, otherwise, you have to subtract 1 from it.\n\n \n\nExample 1:\n\nInput: num = 14\nOutput: 6\nExplanation: \nStep 1) 14 is even; divide by 2 and obtain 7. \nStep 2) 7 is odd; subtract 1 and obtain 6.\nStep 3) 6 is even; divide by 2 and obtain 3. \nStep 4) 3 is odd; subtract 1 and obtain 2. \nStep 5) 2 is even; divide by 2 and obtain 1. \nStep 6) 1 is odd; subtract 1 and obtain 0.\nExample 2:\n\nInput: num = 8\nOutput: 4\nExplanation: \nStep 1) 8 is even; divide by 2 and obtain 4. \nStep 2) 4 is even; divide by 2 and obtain 2. \nStep 3) 2 is even; divide by 2 and obtain 1. \nStep 4) 1 is odd; subtract 1 and obtain 0.\nExample 3:\n\nInput: num = 123\nOutput: 12\n \n\nConstraints:\n\n0 <= num <= 106\n*/\n\n#include<bits/stdc++.h>\nclass Solution {\npublic:\n    int numberOfSteps (int num) {\n        int count = 0;\n        while(num){\n            if(!(num & 1)){\n                num = num >> 1;\n            }\n            else{\n                num--;\n            }\n            count++;\n        }    \n        return count;\n    }\n};"
  },
  {
    "path": "Bit Manipulation/setbits.cpp",
    "content": "// Program to count the number of bits that are set to 1 in an integer\n// The following program tests bits one at a time starting with the least-significant bit.\n// Since we perform O(1) computation per bit, the time complexity is O(n) where n is number of bits in the integer\n// Best case time complexity is O(1), if the input io 0\n#include<bits/stdc++.h>\nusing namespace std;\nint find_set_bits(int n){\n    int set_bits = 0;\n    while(n){\n        set_bits += (n & 1);\n        n >>= 1;\n    }\n    return set_bits;\n}\nint main(){\n    cout << find_set_bits(4) << endl;\n    return 0;\n}\n"
  },
  {
    "path": "Bit Manipulation/single_number.java",
    "content": "/**\n * Given an array of integers A, every element appears twice except for one. Find that integer that occurs once.\n *\n * NOTE: Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?\n *\n *\n *\n * Problem Constraints\n * 1 <= |A| <= 2000000\n *\n * 0 <= A[i] <= INTMAX\n *\n *\n *\n * Input Format\n * The first and only argument of input contains an integer array A.\n *\n *\n *\n * Output Format\n * Return a single integer denoting the single element.\n *\n *\n *\n * Example Input\n * Input 1:\n *\n *  A = [1, 2, 2, 3, 1]\n * Input 2:\n *\n *  A = [1, 2, 2]\n *\n *\n * Example Output\n * Output 1:\n *\n *  3\n * Output 2:\n *\n *  1\n *\n *\n * Example Explanation\n * Explanation 1:\n *\n * 3 occurs once.\n * Explanation 2:\n *\n * 1 occurs once.\n */\npackage BitManipulation;\n\nimport com.google.common.base.Stopwatch;\n\npublic class SingleNumber {\n    public static void main(String[] args) {\n        Stopwatch timer = Stopwatch.createStarted();\n\n        int[] arr = {1, 2, 2, 3, 1};\n        int ans = solve(arr);\n        System.out.println(ans);\n\n        System.out.println(\"Runtime \" + timer);\n    }\n    public static int solve(int[] array) {\n         // O(N) time | O(1) space\n        int ans = 0;\n\n        for (int num : array) ans ^= num;\n\n        return ans;\n    }\n}\n"
  },
  {
    "path": "Bit Manipulation/subarrays_with_bitwise_OR_1.java",
    "content": "/**\n * Problem Description\n * Given an array B of length A with elements 1 or 0. Find the number of subarrays such that the bitwise OR of all the elements present in the subarray is 1.\n *\n *\n * Problem Constraints\n * 1 <= A <= 105\n *\n *\n * Input Format\n * The first argument is a single integer A.\n * The second argument is an integer array B.\n *\n *\n * Output Format\n * Return the number of subarrays with bitwise array 1.\n *\n *\n * Example Input\n * Input 1:\n *  A = 3\n * B = [1, 0, 1]\n * Input 2:\n *  A = 2\n * B = [1, 0]\n *\n *\n * Example Output\n * Output 1:\n * 5\n * Output2:\n * 2\n *\n *\n * Example Explanation\n * Explanation 1:\n * The subarrays are :- [1], [0], [1], [1, 0], [0, 1], [1, 0, 1]\n * Except the subarray [0] all the other subarrays has a Bitwise OR = 1\n * Explanation 2:\n * The subarrays are :- [1], [0], [1, 0]\n * Except the subarray [0] all the other subarrays has a Bitwise OR = 1\n */\n\npackage BitManipulation;\n\npublic class subArrayWithBitwiseOR1 {\n    public static void main(String[] args) {\n        int[] array = {1, 0, 1};\n        int n = 3;\n        int ans = solve(array, n);\n        System.out.println(ans);\n    }\n    public static int solve(int[] array, int len) {\n        // O(N) time | O(1) space\n        int possibleSubarraysWithThisIdx = 0;\n        int ans = 0;\n\n        for (int i = 0; i < len; i++) {\n            int currentNum = array[i];\n            if (currentNum == 1)\n                possibleSubarraysWithThisIdx = i + 1;\n\n            ans += possibleSubarraysWithThisIdx;\n        }\n\n        return ans;\n    }\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Conflict resolution\n\nWhen multiple contributors disagree on the direction for a particular patch or the general direction of the project, the conflict should be resolved by communication. The people who disagree should get together, try to understand each other's points of view, and work to find a design that addresses everyone's concerns.\n\nThis is usually sufficient to resolve issues. If you cannot come to an agreement, ask for the advice of a more senior member of the project.\n\nBe wary of agreement by attrition, where one person argues a point repeatedly until other participants give up in the interests of moving on. This is not conflict resolution, as it does not address everyone's concerns. Be wary of agreement by compromise, where two good competing solutions are merged into one mediocre solution. A conflict is addressed when the participants agree that the final solution is better than all the conflicting proposals. Sometimes the solution is more work than either of the proposals. Embrace the yak shave.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n- Demonstrating empathy and kindness toward other people\n- Being respectful of differing opinions, viewpoints, and experiences\n- Giving and gracefully accepting constructive feedback\n- Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n- Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n- The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n- Trolling, insulting or derogatory comments, and personal or political attacks\n- Public or private harassment\n- Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n- Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\n.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior, harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Contributing\n\n## Fork this repository\n\nGet involved! Fork this repository by clicking on the fork button on the top of this page. This will create a copy of this repository in your account.\n\n- [How to Fork a repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo)\n\nBefore you get started, we encourage you to read these documents which describe some of our community norms:\n\nOur [code of conduct](https://github.com/akgmage/data-structures-and-algorithms/blob/main/CODE_OF_CONDUCT.md), which stipulates explicitly that everyone must be gracious, respectful, and professional. This also documents our conflict resolution policy and encourages people to ask questions.\n\nContributions are always welcome!\n\n- Pick any good first issue and add comment on it (Example: \"I'll take this up\"), or Add classic DSA problem which is currently not present in this repo\n- Read description on the issue (Mostly it will be the link to the question)\n- Add question on top of file\n- Add sample input and output\n- Explain approach with comments\n- Add Time and Space complexity\n- Take care of Readability (Code is written once and read multiple times, so keep this in mind)\n- Provide link for further reading (optional)\n- Send a Pull Request (PR) against main branch and mention issue number in the request format (#ISSUENUMBER)\n\n# Example program\n\n```go\n/*\n\tWrite a function that takes in two non-empty arrays of integers, finds the pair of numbers (one from each array)\n\twhose absolute difference is closest to zero, and returns an array containing these two numbers, with the number from\n\tthe first array in the first position.\n\n\tNote that the absolute difference of two integers is the distance between them on the real number line.\n\tFor example, the absolute difference of -5 and 5 is 10, and the absolute difference of -5 and -4 is 1.\n\n  \tYou can assume that there will only be one pair of numbers with the smallest difference.\n\n\tSample Input Array1 = [-1, 5, 10, 20, 28, 3]\n\tSample Input Array2 = [26, 134, 135, 15, 17]\n\n\tSample Output = [28, 26]\n\n    Explanation :\n\n\tThis code implements the Smallest Difference problem which takes two arrays of integers as input and returns a pair of integers,\n\tone from each array, with the smallest absolute difference between them.\n\n\tThe function first initializes two variables current and smallest to the maximum integer value. It then sorts both input arrays\n\tin ascending order using the sort.Ints function from the sort package.\n\n\tThe function then iterates through both arrays using two pointers, idx1 and idx2, initialized to 0. Inside the loop, it compares\n\tthe elements at the current indices of the two arrays, first and second, and calculates the absolute difference between\n\tthem in the current variable.\n\n\tIf current is smaller than the smallest variable, it updates smallest to current and assigns the current pair of integers\n\tto the result variable.\n\n\tThe function returns the result variable, which contains the pair of integers with the smallest absolute difference.\n\n\tIf there are identical integers in the two input arrays, the function will return them immediately, without any further comparisons.\n\n\tO(nlog(n) + mlog(m)) time | O(1) space - where n is the length of the first input array and m is the length of the second input array\n*/\n\npackage main\n\nimport (\n\t\"math\"\n\t\"sort\"\n)\n\n// SmallestDifference takes two integer slices as input and returns a slice with two integers.\n// The two integers in the returned slice have the smallest absolute difference among all pairs\n// of integers from the two input slices.\nfunc SmallestDifference(array1, array2 []int) []int {\n\t// Initialize variables for the smallest difference and the current difference being calculated\n\tcurrent, smallest := math.MaxInt32, math.MaxInt32\n\t// Sort the input slices\n\tsort.Ints(array1)\n\tsort.Ints(array2)\n\t// Initialize variables for the indices for the two slices\n\tidx1, idx2 := 0, 0\n\t// Initialize an empty slice for the result\n\tresult := []int{}\n\t// Loop through the two slices until we reach the end of one of the slices\n\tfor idx1 < len(array1) && idx2 < len(array2) {\n\t\t// Get the values at the current indices for the two slices\n\t\tfirst, second := array1[idx1], array2[idx2]\n\t\t// Calculate the current difference between the two values\n\t\tif first < second {\n\t\t\tcurrent = second - first\n\t\t\tidx1++\n\t\t} else if second < first {\n\t\t\tcurrent = first - second\n\t\t\tidx2++\n\t\t} else {\n\t\t\t// If the two values are equal, we can return the pair\n\t\t\treturn []int{first, second}\n\t\t}\n\t\t// Update the smallest difference and result slice if the current difference is smaller\n\t\tif smallest > current {\n\t\t\tsmallest = current\n\t\t\tresult = []int{first, second}\n\t\t}\n\t}\n\t// Return the pair with the smallest absolute difference\n\treturn result\n}\n\n```\n"
  },
  {
    "path": "Dynamic Programming/best_time_to_buy_and_sell_stock.cpp",
    "content": "// Best Time to buy and sell stock\n/*\n\tExplanation:\n\tWe start by initializing the minimum price to the maximum integer value and the maximum profit to 0.\n\tWe loop through the prices array, and for each price:\n\tIf the price is less than the current minimum price, we update the minimum price.\n\tOtherwise, if the difference between the price and the minimum price is greater than the current maximum profit, we update the maximum profit.\n\tFinally, we return the maximum profit\n\n    Sample Input [7, 1, 5, 3, 6, 4]\n    Output: 5 buy at 1 sell at 6\n    \n\tTime Complexity: O(n), where n is the length of the prices array.\n\tSpace Complexity: O(1), as we are only using two variables to keep track of the minimum price and maximum profit\n*/\n#include <iostream>\n#include <vector>\n#include <climits>\n\nusing namespace std;\n\nint maxProfit(vector<int>& prices) {\n    int minPrice = INT_MAX; // initialize to maximum value to start with\n    int maxProfit = 0;// initialize to 0\n\n    for (int price : prices) {\n        minPrice = min(minPrice, price); // update minimum price seen so far\n        maxProfit = max(maxProfit, price - minPrice); // update maximum profit seen so far\n    }\n\n    return maxProfit;\n}\n\nint main() {\n    // example usage\n    vector<int> prices {7, 1, 5, 3, 6, 4};\n    int max_profit = maxProfit(prices);\n    cout << \"Max profit: \" << max_profit << endl;\n\n    return 0;\n}\n\n"
  },
  {
    "path": "Dynamic Programming/best_time_to_buy_and_sell_stock.go",
    "content": "// Best Time to buy and sell stock\n/*\n\tExplanation:\n\tWe start by initializing the minimum price to the maximum integer value and the maximum profit to 0.\n\tWe loop through the prices array, and for each price:\n\tIf the price is less than the current minimum price, we update the minimum price.\n\tOtherwise, if the difference between the price and the minimum price is greater than the current maximum profit, we update the maximum profit.\n\tFinally, we return the maximum profit\n\t\n\tSample Input [7, 1, 5, 3, 6, 4]\n\tOutput: 5 buy at 1 sell at 6\n\t\n\tTime Complexity: O(n), where n is the length of the prices array.\n\tSpace Complexity: O(1), as we are only using two variables to keep track of the minimum price and maximum profit\n*/\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\nfunc maxProfit(prices []int) int {\n\tminPrice := math.MaxInt32 // Initialize minimum price to maximum integer value\n\tmaxProfit := 0            // Initialize maximum profit to 0\n\tfor _, price := range prices {\n\t\tif price < minPrice {\n\t\t\tminPrice = price // Update minimum price\n\t\t} else if price-minPrice > maxProfit {\n\t\t\tmaxProfit = price - minPrice // Update maximum profit\n\t\t}\n\t}\n\treturn maxProfit // Return maximum profit\n}\n\nfunc main() {\n\tprices := []int{7, 1, 5, 3, 6, 4}\n\tfmt.Println(maxProfit(prices)) // Output: 5\n}"
  },
  {
    "path": "Dynamic Programming/best_time_to_buy_and_sell_stock.java",
    "content": "// Best Time to buy and sell stock\n/*\n\tExplanation:\n\tWe start by initializing the minimum price to the maximum integer value and the maximum profit to 0.\n\tWe loop through the prices array, and for each price:\n\tIf the price is less than the current minimum price, we update the minimum price.\n\tOtherwise, if the difference between the price and the minimum price is greater than the current maximum profit, we update the maximum profit.\n\tFinally, we return the maximum profit\n      \n    Sample Input [7, 1, 5, 3, 6, 4]\n    Output: 5 buy at 1 sell at 6\n    \n\tTime Complexity: O(n), where n is the length of the prices array.\n\tSpace Complexity: O(1), as we are only using two variables to keep track of the minimum price and maximum profit\n*/\npublic class Solution {\n    public int maxProfit(int[] prices) {\n        // Initialize variables to track the minimum price seen so far and the maximum profit\n        int minPrice = Integer.MAX_VALUE;\n        int maxProfit = 0;\n        \n        // Loop through the prices array\n        for (int i = 0; i < prices.length; i++) {\n            // If the current price is less than the minimum price seen so far, update the minimum price\n            if (prices[i] < minPrice) {\n                minPrice = prices[i];\n            }\n            // If the difference between the current price and the minimum price is greater than the maximum profit seen so far, update the maximum profit\n            else if (prices[i] - minPrice > maxProfit) {\n                maxProfit = prices[i] - minPrice;\n            }\n        }\n        \n        return maxProfit; // Return the maximum profit\n    }\n\n    public static void main(String[] args) {\n        int[] prices = {7, 1, 5, 3, 6, 4};\n        int maxProfit = maxProfit(prices);\n        System.out.println(\"Max Profit: \" + maxProfit);\n    }\n}\n\n"
  },
  {
    "path": "Dynamic Programming/best_time_to_buy_and_sell_stock.js",
    "content": "// Best Time to buy and sell stock\n/*\n\tExplanation:\n\tWe start by initializing the minimum price to the maximum integer value and the maximum profit to 0.\n\tWe loop through the prices array, and for each price:\n\tIf the price is less than the current minimum price, we update the minimum price.\n\tOtherwise, if the difference between the price and the minimum price is greater than the current maximum profit, we update the maximum profit.\n\tFinally, we return the maximum profit\n\n  Sample Input [7, 1, 5, 3, 6, 4]\n  Output: 5 buy at 1 sell at 6\n    \n\tTime Complexity: O(n), where n is the length of the prices array.\n\tSpace Complexity: O(1), as we are only using two variables to keep track of the minimum price and maximum profit\n*/\n/**\n * @param {number[]} prices\n * @return {number}\n */\nvar maxProfit = function (prices) {\n  let minPrice = Infinity; // keep track of minimum price seen so far\n  let maxProfit = 0; // keep track of maximum profit seen so far\n\n  for (let i = 0; i < prices.length; i++) {\n    if (prices[i] < minPrice) {\n      minPrice = prices[i]; // update minimum price seen so far\n    } else if (prices[i] - minPrice > maxProfit) {\n      maxProfit = prices[i] - minPrice; // update maximum profit seen so far\n    }\n  }\n\n  return maxProfit;\n};\n\nconst prices = [7, 1, 5, 3, 6, 4];\nconsole.log(maxProfit(prices)); // Output: 5\n"
  },
  {
    "path": "Dynamic Programming/best_time_to_buy_and_sell_stock.py",
    "content": "# Best Time to buy and sell stock\n'''\n    The function maxProfit takes a list of integers prices and returns the maximum profit that can be \n    made from buying and selling the stock represented by prices. The function works by initializing \n    the minimum price to a very large number (sys.maxsize) and the maximum profit to 0.\n\n    It then loops through the prices, updating the minimum price if the current price is less than the current minimum \n    price, and updating the maximum profit if the difference between the current price and the minimum \n    price is greater than the current maximum profit. Finally, it returns the maximum profit.\n\n    \n    Sample Input [7, 1, 5, 3, 6, 4]  \n    Output: 5 buy at 1 sell at 6\n\n    Time Complexity: O(n), where n is the length of the prices array.\n\tSpace Complexity: O(1), as we are only using two variables to keep track of the minimum price and maximum profit\n'''\n\n\ndef maxProfit(prices: List[int]) -> int:\n    # initialize the minimum price as maximum integer value\n    min_price = sys.maxsize\n    \n    # initialize the maximum profit as 0\n    max_profit = 0\n    \n    # loop through the prices\n    for price in prices:\n        # if the current price is less than the minimum price, update the minimum price\n        if price < min_price:\n            min_price = price\n        # else if the difference between the current price and the minimum price is greater than the maximum profit,\n        # update the maximum profit\n        elif price - min_price > max_profit:\n            max_profit = price - min_price\n    \n    # return the maximum profit\n    return max_profit\n\nprices = [7, 1, 5, 3, 6, 4]\nprofit = maxProfit(prices)\nprint(profit)  # Output: 5"
  },
  {
    "path": "Dynamic Programming/climb_stairs.cpp",
    "content": "// A child is climbing a stair case. It takes n steps to reach to the top. Each time child can either climb 1\n// or 2 steps. In how many distinct ways can the child climb to the top?\n#include <iostream>\nusing namespace std;\n\n// ClimbStairs: returns the number of ways in which a child can climb stairs\n// Approach: Number of ways to reach kth stair = Number of ways to reach k − 1th stair + Number of ways to reach k − 2th stair\n// ClimbStairs(k) = ClimbStairs(k-1) + ClimbStairs(k-2)\nint climbStairs(int n) {\n    // Base case\n    if (n < 3) {\n        return n;\n    }\n    int cache[n];\n    // Initialize initial 2 values\n    cache[0] = 1;\n    cache[1] = 2;\n    for (int i = 2; i < n; i++) {\n        // Add previous 2 values\n        cache[i] = cache[i - 1] + cache[i - 2];\n    }\n    return cache[n - 1];\n}\n\n// Variation: A child is climbing up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time.\n// Implement a method to count how many possible ways the child can jump up the stairs.\n// Approach similar to the above problem\nint climbStairsVariation(int n) {\n    // Base case\n    if (n < 3) {\n        return n;\n    }\n    int cache[n];\n    // Initialize initial 3 values\n    cache[0] = 1;\n    cache[1] = 2;\n    cache[2] = 4;\n    for (int i = 3; i < n; i++) {\n        // Add previous 3 values\n        cache[i] = cache[i - 1] + cache[i - 2] + cache[i - 3];\n    }\n    return cache[n - 1];\n}\n\nint main() {\n    cout << climbStairs(5) << endl;\n    cout << climbStairsVariation(5) << endl;\n    return 0;\n}\n"
  },
  {
    "path": "Dynamic Programming/climb_stairs.go",
    "content": "package main\n\n// A child is climbing a stair case. It takes n steps to reach to the top. Each time child can either climb 1\n// or 2 steps. In how many distinct ways can the child climb to the top?\nimport \"fmt\"\n\n// ClimbStairs: returns the number of ways in which a child can climb stairs\n// Approach: Number of ways to reach kth stair = Number of ways to reach k − 1th stair + Number of ways to reach k − 2th stair\n// ClimbStairs(k) = ClimbStairs(k-1) + ClimbStairs(k-2)\nfunc ClimbStairs(n int) int {\n\t// base case\n\tif n < 3 {\n\t\treturn n\n\t}\n\tcache := make([]int, n)\n\t// initialize initial 2 values\n\tcache[0], cache[1] = 1, 2\n\tfor i := 2; i < n; i++ {\n\t\t// add previous 2 values\n\t\tcache[i] = cache[i-1] + cache[i-2]\n\t}\n\treturn cache[n-1]\n}\n\n// Variatiom: A child is climbing up a staircase with 􀝊 steps, and can hop either 1 step, 2 steps, or 3 steps at a time.\n// Implement a method to count how many possible ways the child can jump up the stairs.\n// Approach similar to above problem\nfunc ClimbStairs2(n int) int {\n\t// base case\n\tif n < 3 {\n\t\treturn n\n\t}\n\tcache := make([]int, n)\n\t// initialize initial 3 values\n\tcache[0], cache[1], cache[2] = 1, 2, 4\n\tfor i := 3; i < n; i++ {\n\t\t// add previous 3 values\n\t\tcache[i] = cache[i-1] + cache[i-2] + cache[i - 3]\n\t}\n\treturn cache[n-1]\n}\nfunc main() {\n\tfmt.Println(ClimbStairs(5))\n\tfmt.Println(ClimbStairs2(5))\n}"
  },
  {
    "path": "Dynamic Programming/climb_stairs.java",
    "content": "// A child is climbing a stair case. It takes n steps to reach to the top. Each time child can either climb 1\n// or 2 steps. In how many distinct ways can the child climb to the top?\npublic class StairClimbing {\n    // ClimbStairs: returns the number of ways in which a child can climb stairs\n    // Approach: Number of ways to reach kth stair = Number of ways to reach k − 1th stair + Number of ways to reach k − 2th stair\n    // ClimbStairs(k) = ClimbStairs(k-1) + ClimbStairs(k-2)\n    public static int climbStairs(int n) {\n        // Base case\n        if (n < 3) {\n            return n;\n        }\n        int[] cache = new int[n];\n        // Initialize initial 2 values\n        cache[0] = 1;\n        cache[1] = 2;\n        for (int i = 2; i < n; i++) {\n            // Add previous 2 values\n            cache[i] = cache[i - 1] + cache[i - 2];\n        }\n        return cache[n - 1];\n    }\n\n    // Variatiom: A child is climbing up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time.\n    // Implement a method to count how many possible ways the child can jump up the stairs.\n    // Approach similar to the above problem\n    public static int climbStairsVariation(int n) {\n        // Base case\n        if (n < 3) {\n            return n;\n        }\n        int[] cache = new int[n];\n        // Initialize initial 3 values\n        cache[0] = 1;\n        cache[1] = 2;\n        cache[2] = 4;\n        for (int i = 3; i < n; i++) {\n            // Add previous 3 values\n            cache[i] = cache[i - 1] + cache[i - 2] + cache[i - 3];\n        }\n        return cache[n - 1];\n    }\n\n    public static void main(String[] args) {\n        System.out.println(climbStairs(5));\n        System.out.println(climbStairsVariation(5));\n    }\n}\n"
  },
  {
    "path": "Dynamic Programming/climb_stairs.js",
    "content": "// A child is climbing a stair case. It takes n steps to reach to the top. Each time child can either climb 1\n// or 2 steps. In how many distinct ways can the child climb to the top?\n\n// ClimbStairs: returns the number of ways in which a child can climb stairs\n// Approach: Number of ways to reach kth stair = Number of ways to reach k − 1th stair + Number of ways to reach k − 2th stair\n// ClimbStairs(k) = ClimbStairs(k-1) + ClimbStairs(k-2)\nfunction climbStairs(n) {\n  // Base case\n  if (n < 3) {\n    return n;\n  }\n  const cache = new Array(n);\n  // Initialize initial 2 values\n  cache[0] = 1;\n  cache[1] = 2;\n  for (let i = 2; i < n; i++) {\n    // Add previous 2 values\n    cache[i] = cache[i - 1] + cache[i - 2];\n  }\n  return cache[n - 1];\n}\n\n// Variation: A child is climbing up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time.\n// Implement a method to count how many possible ways the child can jump up the stairs.\n// Approach similar to the above problem\nfunction climbStairsVariation(n) {\n  // Base case\n  if (n < 3) {\n    return n;\n  }\n  const cache = new Array(n);\n  // Initialize initial 3 values\n  cache[0] = 1;\n  cache[1] = 2;\n  cache[2] = 4;\n  for (let i = 3; i < n; i++) {\n    // Add previous 3 values\n    cache[i] = cache[i - 1] + cache[i - 2] + cache[i - 3];\n  }\n  return cache[n - 1];\n}\n\nconsole.log(climbStairs(5));\nconsole.log(climbStairsVariation(5));\n"
  },
  {
    "path": "Dynamic Programming/climb_stairs.py",
    "content": "'''\nA child is climbing a stair case. It takes n steps to reach to the top. Each time child can either climb 1 \\\nor 2 steps. In how many distinct ways can the child climb to the top?\n'''\n# ClimbStairs: returns the number of ways in which a child can climb stairs\n# Approach: Number of ways to reach kth stair = Number of ways to reach k − 1th stair + Number of ways to reach k − 2th stair\n# ClimbStairs(k) = ClimbStairs(k-1) + ClimbStairs(k-2)\ndef climb_stairs(n):\n    # Base case\n    if n < 3:\n        return n\n    cache = [0] * n\n    # Initialize initial 2 values\n    cache[0], cache[1] = 1, 2\n    for i in range(2, n):\n        # Add previous 2 values\n        cache[i] = cache[i - 1] + cache[i - 2]\n    return cache[n - 1]\n\n# Variation: A child is climbing up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time.\n# Implement a method to count how many possible ways the child can jump up the stairs.\n# Approach similar to the above problem\ndef climb_stairs_variation(n):\n    # Base case\n    if n < 3:\n        return n\n    cache = [0] * n\n    # Initialize initial 3 values\n    cache[0], cache[1], cache[2] = 1, 2, 4\n    for i in range(3, n):\n        # Add previous 3 values\n        cache[i] = cache[i - 1] + cache[i - 2] + cache[i - 3]\n    return cache[n - 1]\n\nif __name__ == \"__main__\":\n    print(climb_stairs(5))\n    print(climb_stairs_variation(5))\n"
  },
  {
    "path": "Dynamic Programming/coin_change.cpp",
    "content": "/*\n    Coin Change Problem\n    You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount\n    of money.Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any \n    combination of the coins, return -1.You may assume that you have an infinite number of each kind of coin.\n\n    The code uses a dynamic programming approach to solve the coin change problem. The dp vector is used to \n    store the minimum number of coins needed to make each amount from 0 to amount. The minimum number \n    of coins needed to make an amount of 0 is 0. Then, for each coin, the code iterates through each \n    amount from the coin value to the target amount. If the current amount minus the coin value is a \n    valid amount, the code updates the minimum number of coins needed to make that amount by taking \n    the minimum of the current value and the value of dp[i - coin] + 1. Finally, if the minimum \n    number of coins needed to make the target amount is still INT_MAX, it is not possible to make \n    the amount and the code returns -1. Otherwise, the code returns the minimum number of coins \n    needed to make the target amount.\n\n    Sample Input : [1, 2, 5] target : 11\n\tOutput 3 (5, 5, 1)\n\n    The time complexity is O(n * V), where n is the number of coins and V is the value we want to make change for. \n    The space complexity is also O(n * V) as we need to store the minimum number of coins required to make \n    change for every value up to V for every coin.\n\n    In the worst case, when we have a large number of coins and a large value V, the time and space complexity \n    can become quite large. However, this approach can efficiently handle a wide range of input values and is \n    guaranteed to give the optimal solution.\n*/\n#include <iostream>\n#include <vector>\n#include <climits>\nusing namespace std;\n\nint coinChange(vector<int>& coins, int amount) {\n    // Create a vector to store the minimum number of coins needed to make each amount from 0 to amount\n    vector<int> dp(amount + 1, INT_MAX);\n    \n    // The minimum number of coins needed to make an amount of 0 is 0\n    dp[0] = 0;\n    \n    // Iterate through each coin\n    for (int coin : coins) {\n        // Iterate through each amount from the coin value to the target amount\n        for (int i = coin; i <= amount; i++) {\n            // If the current amount minus the coin value is a valid amount, update the minimum number of coins needed\n            if (dp[i - coin] != INT_MAX) {\n                dp[i] = min(dp[i], dp[i - coin] + 1);\n            }\n        }\n    }\n    \n    // If the minimum number of coins needed to make the target amount is still INT_MAX, it is not possible to make the amount\n    if (dp[amount] == INT_MAX) {\n        return -1;\n    }\n    \n    // Return the minimum number of coins needed to make the target amount\n    return dp[amount];\n}\n\nint main() {\n    vector<int> coins = {1, 2, 5};\n    int amount = 11;\n    cout << \"Minimum number of coins needed: \" << coinChange(coins, amount) << endl;\n    return 0;\n}\n"
  },
  {
    "path": "Dynamic Programming/coin_change.go",
    "content": "/*\n\tCoin Change Problem\n    You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount\n    of money.Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any \n    combination of the coins, return -1.You may assume that you have an infinite number of each kind of coin.\n\n\tThis implementation uses a bottom-up approach to fill in a 2D table of minimum coin counts for each amount \n\tup to the target amount. The table is initialized with the base cases (0 coins for an amount of 0, infinity \n\tfor an amount greater than 0) and then filled in using the recurrence relation:\n\t\n\tdp[i][j] = min(dp[i-1][j], dp[i][j-coins[i-1]]+1)\n\t\n\twhere dp[i][j] is the minimum number of coins needed to make an amount of j using the first i coins. \n\tIf the current coin value coins[i-1] is greater than the current amount j, then we can't use that coin, \n\tso we take the minimum number of coins we need to make the amount using only the first i-1 coins (dp[i-1][j]). \n\tOtherwise, we can use the current coin, so we take the minimum of the number of coins we need to make the \n\tamount using only the first i-1 coins (dp[i-1][j]) and the number of coins we need to make the amount minus \n\tthe value of the current coin, plus one (dp[i][j-coins[i-1]]+1).\n\n\tThe final result is dp[len(coins)][amount], which gives us the minimum number of coins needed to make the \n\ttarget amount. If this value is infinity, then it's not possible to make the amount using the given coins, \n\tso we return -1.\n\n\tSample Input : [1, 2, 5] target : 11\n\tOutput 3 (5, 5, 1)\n\n\tThe time complexity of this implementation is O(nm), where n is the number of coins and m is the target amount. \n\tThe space complexity is also O(nm) because we're storing a 2D table of size (n+1) x (m+1).\n\n*/\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\nfunc coinChange(coins []int, amount int) int {\n\t// create a 2D slice to store the minimum number of coins needed for each subproblem\n\tdp := make([][]int, len(coins)+1)\n\tfor i := range dp {\n\t\tdp[i] = make([]int, amount+1)\n\t}\n\n\t// initialize the first row to infinity and the first column to 0\n\tfor j := 1; j <= amount; j++ {\n\t\tdp[0][j] = math.MaxInt32\n\t}\n\tfor i := 0; i <= len(coins); i++ {\n\t\tdp[i][0] = 0\n\t}\n\n\t// fill in the rest of the table\n\tfor i := 1; i <= len(coins); i++ {\n\t\tfor j := 1; j <= amount; j++ {\n\t\t\tif j < coins[i-1] {\n\t\t\t\tdp[i][j] = dp[i-1][j]\n\t\t\t} else {\n\t\t\t\tdp[i][j] = min(dp[i-1][j], dp[i][j-coins[i-1]]+1)\n\t\t\t}\n\t\t}\n\t}\n\n\t// return the result\n\tif dp[len(coins)][amount] == math.MaxInt32 {\n\t\treturn -1\n\t}\n\treturn dp[len(coins)][amount]\n}\n\nfunc min(a, b int) int {\n\tif a < b {\n\t\treturn a\n\t}\n\treturn b\n}\n\nfunc main() {\n\tcoins := []int{1, 2, 5}\n\tamount := 11\n\tfmt.Println(coinChange(coins, amount))\n}\n"
  },
  {
    "path": "Dynamic Programming/coin_change.java",
    "content": "/* \n    Coin Change Problem\n    You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount\n    of money.Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any \n    combination of the coins, return -1.You may assume that you have an infinite number of each kind of coin.\n\n    Example 1:\n\n    Input: coins = [1,2,5], amount = 11\n    Output: 3\n    Explanation: 11 = 5 + 5 + 1\n\n    Example 2:\n    Input: coins = [2], amount = 3\n    Output: -1\n\n    Example 3:\n    Input: coins = [1], amount = 0\n    Output: 0\n\n    Constraints:\n\n    1 <= coins.length <= 12\n    1 <= coins[i] <= 231 - 1\n    0 <= amount <= 104 */\n\n//SOLUTION\n//EXPLANATION OF CODE\n/*Using unbounded knapsack in Dynamic programming \n * The minimal number of coins required to make up a specific sum using a certain number of coins is stored in a 2D array.\n *  The array's dimensions are n+1 and amount+1, where n is the length of the coins array.\n * Initialisation 1\n * t[i][j] is set to Integer when i = 0.MAX_VALUE-1 indicates that the amount j cannot be calculated using 0 coins. For j = 0, \n * t[i][j] is set to 0, suggesting that the amount 0 can be made up of any number of coins.\n * Initialisation 2\n * If the amount j is a multiple of the first coin denomination, then the minimum number of coins required to make up the amount j is j/coins[0]. \n * Otherwise, it is not possible to make up the amount j using only the first coin denomination, so the value of t[1][j] is set to \n * Integer.MAX_VALUE-1.\n * \n * main code\n * The third loop fills in the t array for all other cases. If the current coin denomination coins[i-1] is less than or equal to the current amount\n *  j, then we can either include or exclude the current coin denomination to make up the amount j. If we include the current coin denomination, \n * then the minimum number of coins required is 1 + t[i][j-coins[i-1]]. If we exclude the current coin denomination, then the minimum number of \n * coins required is t[i-1][j]. We take the minimum of these two values to get the minimum number of coins required to make up the amount j using \n * the first i coin denominations.\nFinally, if the value of t[n][amount] is still Integer.MAX_VALUE-1, then it is not possible to make up the amount amount using the coin \ndenominations in coins, so we return -1. Otherwise, we return the value of t[n][amount], which represents the minimum number of coins required to \nmake up the amount amount using all the coin denominations in coins.\n*/\n\n//Code:\nclass Solution {\n    public int coinChange(int[] coins, int amount) {\n        int n=coins.length;\n\n        int t[][]= new int[n+1][amount+1];  \n        for(int i=0; i<n+1; i++){                         //Initialisation 1 \n            for(int j=0; j<amount+1;j++){\n                if(i==0){\n                    t[i][j]=Integer.MAX_VALUE-1;\n                }\n                if(j==0){\n                    t[i][j]=0;\n                }\n                \n            }\n        }\n        for(int j=1; j<amount+1; j++){                 //Initialisation 2\n            if(j%coins[0]==0){\n                t[1][j]=j/coins[0];\n            }\n            else{\n                t[1][j]=Integer.MAX_VALUE-1; \n            }\n        }\n        for(int i=2; i<n+1; i++){                                  //Main code\n            for(int j=1; j<amount+1;j++){\n                if(coins[i-1]<=j){\n                    t[i][j]=Math.min(1+t[i][j-coins[i-1]],t[i-1][j]);\n                }\n                else{\n                    t[i][j]=t[i-1][j];\n                }\n            }\n        }\n        if(t[n][amount]==Integer.MAX_VALUE-1){\n            return -1;\n        }\n                return t[n][amount];       //answer\n    }\n}"
  },
  {
    "path": "Dynamic Programming/coin_change.js",
    "content": "/*\n    Coin Change Problem:-\n\n\n    Question:-\n    You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount\n    of money.Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any \n    combination of the coins, return -1.You may assume that you have an infinite number of each kind of coin.\n\n    Example 1:\n    Input: coins = [1,2,5], amount = 11\n    Output: 3\n    Explanation: 11 = 5 + 5 + 1\n\n    Example 2:\n    Input: coins = [2], amount = 3\n    Output: -1\n\n    Example 3:\n    Input: coins = [1], amount = 0\n    Output: 0\n    \n    Constraints:\n    1 <= coins.length <= 12\n    1 <= coins[i] <= 231 - 1\n    0 <= amount <= 104\n\n\n    Approach Explanation:-\n\n    The code uses a dynamic programming approach to solve the coin change problem. The dp array is used to \n    store the minimum number of coins needed to make each amount from 0 to amount. The minimum number \n    of coins needed to make an amount of 0 is 0. Then, for each coin, the code iterates through each \n    amount from the coin value to the target amount. If the current amount minus the coin value is a \n    valid amount, the code updates the minimum number of coins needed to make that amount by taking \n    the minimum of the current value and the value of dp[i - coin] + 1. Finally, if the minimum \n    number of coins needed to make the target amount is still Infinity, it is not possible to make \n    the amount and the code returns -1. Otherwise, the code returns the minimum number of coins \n    needed to make the target amount.\n\n    The time complexity is O(n * V), where n is the number of coins and V is the value we want to make change for. \n    The space complexity is also O(n * V) as we need to store the minimum number of coins required to make \n    change for every value up to V for every coin.\n\n    In the worst case, when we have a large number of coins and a large value V, the time and space complexity \n    can become quite large. However, this approach can efficiently handle a wide range of input values and is \n    guaranteed to give the optimal solution.\n*/\n\n/**\n * @param {number[]} coins\n * @param {number} amount\n * @return {number}\n */\n\n\nvar coinChange = function(coins, amount) {\n\n    // Create a array to store the minimum number of coins needed to make each amount from 0 to amount\n    const dp=Array(amount+1).fill(Infinity);\n\n    // The minimum number of coins needed to make an amount of 0 is 0\n    dp[0]=0;\n\n    // Iterate through each coin\n    for(const coin of coins){\n        // Iterate through each amount from the coin value to the target amount\n        for(let i=coin;i<=amount;i++){\n            // If the current amount minus the coin value is a valid amount, update the minimum number of coins needed\n            if(dp[i-coin]!=Infinity)\n            {\n                dp[i]=Math.min(dp[i],dp[i-coin]+1);\n            }\n        }\n    }\n\n    // If the minimum number of coins needed to make the target amount is still Infinity, it is not possible to make the amount\n    if(dp[amount]===Infinity)\n    {\n        return -1;\n    }\n\n    // Return the minimum number of coins needed to make the target amount\n    return dp[amount];\n};\n"
  },
  {
    "path": "Dynamic Programming/coin_change.py",
    "content": "'''\n    Coin Change Problem\n    You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount\n    of money.Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any \n    combination of the coins, return -1.You may assume that you have an infinite number of each kind of coin.\n\n    The coin change problem is a dynamic programming solution that takes a list of coin denominations and a \n    target value as inputs, and returns the minimum number of coins required to reach the target value. \n    It uses a bottom-up approach to build a table of minimum coin counts for each target value up to the \n    input target. \n\n    Sample Input : [1, 2, 5] target : 11\n\tOutput 3 (5, 5, 1)\n    \n    The time complexity of this implementation is O(amount * n), where n is the number of coins. \n    The space complexity is O(amount).\n\n    Note that this implementation assumes that there are infinite coins of each denomination. \n    If the number of coins is limited, then the implementation can be modified to keep track of the number of coins used as well.\n'''\ndef coin_change(coins, amount):\n    # Initialize the DP table with float('inf') values for all amounts\n    dp = [float('inf') for _ in range(amount+1)]\n    # DP value for 0 amount is always 0\n    dp[0] = 0\n    \n    # Iterate through each coin denomination\n    for coin in coins:\n        # Update DP values for all amounts that can be obtained using the current coin\n        for i in range(coin, amount+1):\n            # Choose the minimum between the current DP value and the DP value obtained\n            # by subtracting the current coin from the current amount and adding 1 to it\n            dp[i] = min(dp[i], dp[i-coin]+1)\n    \n    # If the DP value for the target amount is still float('inf'), then it's not possible to make change\n    if dp[amount] == float('inf'):\n        return -1\n    else:\n        return dp[amount]\n"
  },
  {
    "path": "Dynamic Programming/dice_throws.go",
    "content": "/*\n\n    You're given a set of numDice  dice, each with numSides  sides, and a target  integer, which represents a target sum to obtain when\n\trolling all of the dice and summing their values. Write a function that returns the total number of dice-roll permutations that sum\n\tup to exactly that target value. All three input values will always be positive integers. Each of the dice has an equal probability\n\tof landing on any number from 1 to numSides . Identical total dice rolls obtained from different individual dice rolls (for example,\n\t[2, 3] vs [3, 2] ) count as different dice-roll permutations. If there's no possible dice-roll combination that sums up to the target\n\tgiven the input dice, your function should return 0.\n\n\tSample Input : numDice = 2 numSides = 6 target = 7\n\tOutput:  6  [1, 6], [2, 5], [3, 4], [4, 3], [5, 2], [6, 1]\n\n\tExplanation:\n\n\tThe provided code is a Go implementation of a function called `DiceThrows`, which calculates the number of possible ways to obtain a specific target sum by rolling a given number of dice with a certain number of sides.\n\n\tLet's walk through the code:\n\n\t1. `DiceThrows` function: This is the main function that initiates the process of calculating the number of ways to reach the target sum.\n\n\t- `numDice`: The number of dice available.\n\t- `numSides`: The number of sides on each die.\n\t- `target`: The target sum to achieve.\n\n\t2. `storedResults`: This is a 2D slice used to store the intermediate results of the recursive calls to avoid redundant calculations. It stores the number of ways to reach the target sum for a specific number of dice and target.\n\n\t3. `diceThrowsHelper` function: This is a helper function that performs the recursive calculations to find the number of ways to reach the target sum.\n\n\t- `numDice`, `numSides`, and `target`: The same variables as in the main function.\n\t- `storedResults`: The 2D slice to store the intermediate results.\n\n\t4. Base case: The function checks if `numDice` is 0. If so, it means there are no dice left, and it checks if the `target` is also 0. If yes, it returns 1 (a valid way to reach the target sum using no dice). Otherwise, it returns 0 (no valid way to reach the target sum).\n\n\t5. Memoization: Before starting the actual calculations, the function checks if the result for the current number of dice and target sum is already calculated and stored in `storedResults`. If so, it directly returns the stored value, avoiding redundant calculations.\n\n\t6. Recursive calculation: If the result is not stored, the function proceeds to calculate the number of ways to reach the target sum using the current number of dice.\n\n\t- It iterates over all the possible target sums for the current number of dice (`numDice`) based on the possible outcomes from rolling one die (`max(0, target-numSides)` to `target-1`).\n\t- For each possible target sum (`currentTarget`), it makes a recursive call to `diceThrowsHelper` with `numDice-1` dice, `numSides` sides, and `currentTarget` as the new target sum.\n\t- It adds up the number of ways to reach `currentTarget` using `numDice-1` dice.\n\n\t7. Storing and returning the result: After calculating the total number of ways to reach the target sum, it stores the result in `storedResults` for future use and returns the result.\n\n\t8. `max` function: A helper function to find the maximum of two integers.\n*/\npackage main\n\n// DiceThrows calculates the number of ways to obtain a specific target sum\n// by rolling a given number of dice with a certain number of sides.\n// It calls the helper function diceThrowsHelper for recursive calculations.\nfunc DiceThrows(numDice int, numSides int, target int) int {\n\t// Create a 2D slice to store intermediate results of recursive calls.\n\tstoredResults := make([][]int, numDice+1)\n\tfor i := range storedResults {\n\t\tstoredResults[i] = make([]int, target+1)\n\t\tfor j := range storedResults[i] {\n\t\t\t// Initialize all values to -1 to indicate that they have not been computed yet.\n\t\t\tstoredResults[i][j] = -1\n\t\t}\n\t}\n\t// Call the helper function to perform the actual calculations.\n\treturn diceThrowsHelper(numDice, numSides, target, storedResults)\n}\n\n// diceThrowsHelper is a recursive helper function that calculates the number\n// of ways to reach the target sum using a specific number of dice.\nfunc diceThrowsHelper(numDice, numSides, target int, storedResults [][]int) int {\n\t// Base case: If there are no dice left, check if the target sum is also 0.\n\tif numDice == 0 {\n\t\tif target == 0 {\n\t\t\t// Return 1 if the target sum is 0 (a valid way to reach the target sum using no dice).\n\t\t\treturn 1\n\t\t}\n\t\t// Return 0 if the target sum is not 0 (no valid way to reach the target sum).\n\t\treturn 0\n\t}\n\n\t// Memoization: Check if the result is already computed and stored in storedResults.\n\tif storedResults[numDice][target] > -1 {\n\t\t// If the result is already stored, return it to avoid redundant calculations.\n\t\treturn storedResults[numDice][target]\n\t}\n\n\t// Recursive calculation: Find the number of ways to reach the target sum using numDice dice.\n\tnumWaysToReachTarget := 0\n\tfor currentTarget := max(0, target-numSides); currentTarget < target; currentTarget++ {\n\t\t// Recursively calculate the number of ways to reach the currentTarget using numDice-1 dice.\n\t\tnumWaysToReachTarget += diceThrowsHelper(numDice-1, numSides, currentTarget, storedResults)\n\t}\n\n\t// Store the result in storedResults for future use.\n\tstoredResults[numDice][target] = numWaysToReachTarget\n\n\t// Return the total number of ways to reach the target sum.\n\treturn numWaysToReachTarget\n}\n\n// max is a helper function to find the maximum of two integers.\nfunc max(a, b int) int {\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n"
  },
  {
    "path": "Dynamic Programming/disk_stacking.go",
    "content": "/*\n\tYou're given a non-empty array of arrays where each subarray holds three integers and represents a disk.\n\tThese integers denote each disk's width, depth, and height, respectively. Your goal is to stack up the\n\tdisks and to maximize the total height of the stack. A disk must have a strictly smaller width, depth,\n\tand height than any other disk below it.\n\n\tWrite a function that returns an array of the disks in the final stack, starting with the top disk and\n\tending with the bottom disk. Note that you can't rotate disks; in other words, the integers in each subarray must\n\trepresent [width, depth, height] at all times\n\n\tSample input :  = [[2, 1, 2], [3, 2, 3], [2, 2, 8], [2, 3, 4], [1, 3, 1], [4, 4, 5]]\n\tOutput: [[2, 1, 2], [3, 2, 3], [4, 4, 5]] // 10 (2 + 3 + 5) is the tallest height we can get by\n\n\tExplanation:\n\tThis code snippet implements the \"Disk Stacking\" problem, which is a classic dynamic programming problem. The goal is to\n\tfind the maximum height that can be achieved by stacking disks on top of each other while adhering to certain conditions.\n\n\tThe problem is defined as follows:\n\tGiven a list of disks represented by their dimensions (width, depth, height), you need to find a stack of disks with the\n\tmaximum height. You can only stack a disk on top of another if its width, depth, and height are all strictly smaller than\n\tthose of the disk below it.\n\n\tNow, let's go through the code step by step:\n\n\t1. `Disk` and `Disks` types: These are custom types defined to simplify the code and make it more readable. `Disk` represents\n\ta single disk's dimensions, and `Disks` is a slice of `Disk`, representing a collection of disks.\n\n\t2. Implementing sort interface for `Disks`: The `Disks` type is provided with three methods - `Len`, `Swap`, and `Less`.\n\tThese methods are part of the `sort.Interface`, which allows us to sort the disks based on their height (the third dimension).\n\n\t3. `DiskStacking` function: This is the main function that solves the disk stacking problem. It takes a 2D slice `input`,\n\trepresenting the dimensions of the disks, and returns a 2D slice representing the sequence of disks to stack to achieve\n\tthe maximum height.\n\n\t4. Creating `disks` slice and sorting: The function first converts the input to a `Disks` slice and then sorts it based on\n\tthe third dimension (height) in increasing order. Sorting will allow us to consider disks in a specific order while building\n\tthe stack.\n\n\t5. Initializing `heights` and `sequences` slices: The function initializes two slices, `heights` and `sequences`, both with\n\tthe same length as the number of disks. `heights` will keep track of the maximum height achievable with the current disk at\n\teach position, and `sequences` will store the index of the previous disk that contributes to the current disk's maximum height.\n\n\t6. Dynamic programming loop: The function iterates over each disk and calculates the maximum height that can be achieved by\n\tconsidering the current disk and all the disks before it. It checks if the conditions (`areValidDimensions`) for placing the\n\tcurrent disk on top of another are met, and if so, it updates the maximum height and the contributing disk index in `heights`\n\tand `sequences`.\n\n\t7. Finding the maximum height and the sequence: After the dynamic programming loop, it finds the index with the maximum\n\theight in the `heights` slice. This index represents the topmost disk in the stack, which contributes to the maximum height.\n\n\t8. Building the sequence: The function calls the `buildSequence` function to create the sequence of disks contributing to\n\tthe maximum height. It starts from the topmost disk (found in the previous step) and follows the sequence of disks using the\n\t`sequences` slice.\n\n\t9. Reversing the sequence: The sequence is built in reverse order, starting from the topmost disk. Since the problem requires\n\tthe disks to be stacked from bottom to top, the `reverse` function is used to reverse the order of elements in the sequence.\n\n\t10. Returning the result: Finally, the function returns the sequence of disks that should be stacked to achieve the maximum height.\n\n\tO(n^2) time | O(n) space - where n is the number of disks\n*/\npackage main\n\nimport \"sort\"\n\n// Custom type for representing a single disk's dimensions (width, depth, height)\ntype Disk []int\n\n// Custom type for representing a collection of disks\ntype Disks []Disk\n\n// Implementing sort.Interface for Disks to allow sorting based on height (third dimension)\nfunc (disks Disks) Len() int           { return len(disks) }\nfunc (disks Disks) Swap(i, j int)      { disks[i], disks[j] = disks[j], disks[i] }\nfunc (disks Disks) Less(i, j int) bool { return disks[i][2] < disks[j][2] }\n\n// Main function to solve the Disk Stacking problem\nfunc DiskStacking(input [][]int) [][]int {\n    // Convert input to Disks slice and sort it based on height in increasing order\n    disks := make(Disks, len(input))\n    for i, disk := range input {\n        disks[i] = disk\n    }\n    sort.Sort(disks)\n\n    // Initialize slices to store the maximum height and the sequence of disks\n    heights := make([]int, len(disks))\n    sequences := make([]int, len(disks))\n    for i := range disks {\n        heights[i] = disks[i][2]\n        sequences[i] = -1\n    }\n\n    // Dynamic programming loop to find the maximum height and contributing disks\n    for i := 1; i < len(disks); i++ {\n        currentDisk := disks[i]\n        for j := 0; j < i; j++ {\n            other := disks[j]\n\n            // Check if conditions are met to stack currentDisk on top of other\n            if areValidDimensions(other, currentDisk) {\n                // Update maximum height and contributing disk index if needed\n                if heights[i] <= currentDisk[2]+heights[j] {\n                    heights[i] = currentDisk[2] + heights[j]\n                    sequences[i] = j\n                }\n            }\n        }\n    }\n\n    // Find the index with the maximum height (topmost disk in the stack)\n    maxIndex := 0\n    for i, height := range heights {\n        if height > heights[maxIndex] {\n            maxIndex = i\n        }\n    }\n\n    // Build the sequence of disks contributing to the maximum height\n    sequence := buildSequence(disks, sequences, maxIndex)\n\n    // Return the sequence of disks that should be stacked to achieve the maximum height\n    return sequence\n}\n\n// Function to check if the conditions are met for placing current disk on top of other\nfunc areValidDimensions(o Disk, c Disk) bool {\n    return o[0] < c[0] && o[1] < c[1] && o[2] < c[2]\n}\n\n// Function to build the sequence of disks contributing to the maximum height\nfunc buildSequence(disks []Disk, sequences []int, index int) [][]int {\n    sequence := [][]int{}\n    for index != -1 {\n        sequence = append(sequence, disks[index])\n        index = sequences[index]\n    }\n    // Since the sequence is built in reverse order (top to bottom), reverse it to get correct order\n    reverse(sequence)\n    return sequence\n}\n\n// Function to reverse the order of elements in a 2D slice\nfunc reverse(numbers [][]int) {\n    for i, j := 0, len(numbers)-1; i < j; i, j = i+1, j-1 {\n        numbers[i], numbers[j] = numbers[j], numbers[i]\n    }\n}\n"
  },
  {
    "path": "Dynamic Programming/disk_stacking.py",
    "content": "'''\n\tYou're given a non-empty array of arrays where each subarray holds three integers and represents a disk.\n\tThese integers denote each disk's width, depth, and height, respectively. Your goal is to stack up the\n\tdisks and to maximize the total height of the stack. A disk must have a strictly smaller width, depth,\n\tand height than any other disk below it.\n\n\tWrite a function that returns an array of the disks in the final stack, starting with the top disk and\n\tending with the bottom disk. Note that you can't rotate disks; in other words, the integers in each subarray must\n\trepresent [width, depth, height] at all times\n\n\tSample input :  = [[2, 1, 2], [3, 2, 3], [2, 2, 8], [2, 3, 4], [1, 3, 1], [4, 4, 5]]\n\tOutput: [[2, 1, 2], [3, 2, 3], [4, 4, 5]] // 10 (2 + 3 + 5) is the tallest height we can get by\n\n\tExplanation:\n\tThis code snippet implements the \"Disk Stacking\" problem, which is a classic dynamic programming problem. The goal is to\n\tfind the maximum height that can be achieved by stacking disks on top of each other while adhering to certain conditions.\n\n\tThe problem is defined as follows:\n\tGiven a list of disks represented by their dimensions (width, depth, height), you need to find a stack of disks with the\n\tmaximum height. You can only stack a disk on top of another if its width, depth, and height are all strictly smaller than\n\tthose of the disk below it.\n\n\tNow, let's go through the code step by step:\n\n\t1. `Disk` and `Disks` types: These are custom types defined to simplify the code and make it more readable. `Disk` represents\n\ta single disk's dimensions, and `Disks` is a slice of `Disk`, representing a collection of disks.\n\n\t2. Implementing sort interface for `Disks`: The `Disks` type is provided with three methods - `Len`, `Swap`, and `Less`.\n\tThese methods are part of the `sort.Interface`, which allows us to sort the disks based on their height (the third dimension).\n\n\t3. `DiskStacking` function: This is the main function that solves the disk stacking problem. It takes a 2D slice `input`,\n\trepresenting the dimensions of the disks, and returns a 2D slice representing the sequence of disks to stack to achieve\n\tthe maximum height.\n\n\t4. Creating `disks` slice and sorting: The function first converts the input to a `Disks` slice and then sorts it based on\n\tthe third dimension (height) in increasing order. Sorting will allow us to consider disks in a specific order while building\n\tthe stack.\n\n\t5. Initializing `heights` and `sequences` slices: The function initializes two slices, `heights` and `sequences`, both with\n\tthe same length as the number of disks. `heights` will keep track of the maximum height achievable with the current disk at\n\teach position, and `sequences` will store the index of the previous disk that contributes to the current disk's maximum height.\n\n\t6. Dynamic programming loop: The function iterates over each disk and calculates the maximum height that can be achieved by\n\tconsidering the current disk and all the disks before it. It checks if the conditions (`areValidDimensions`) for placing the\n\tcurrent disk on top of another are met, and if so, it updates the maximum height and the contributing disk index in `heights`\n\tand `sequences`.\n\n\t7. Finding the maximum height and the sequence: After the dynamic programming loop, it finds the index with the maximum\n\theight in the `heights` slice. This index represents the topmost disk in the stack, which contributes to the maximum height.\n\n\t8. Building the sequence: The function calls the `buildSequence` function to create the sequence of disks contributing to\n\tthe maximum height. It starts from the topmost disk (found in the previous step) and follows the sequence of disks using the\n\t`sequences` slice.\n\n\t9. Reversing the sequence: The sequence is built in reverse order, starting from the topmost disk. Since the problem requires\n\tthe disks to be stacked from bottom to top, the `reverse` function is used to reverse the order of elements in the sequence.\n\n\t10. Returning the result: Finally, the function returns the sequence of disks that should be stacked to achieve the maximum height.\n\n\tO(n^2) time | O(n) space - where n is the number of disks\n'''\ndef DiskStacking(disks):\n    # Sort the disks based on their height\n    disks.sort(key=lambda x: x[2])\n    \n    # Initialize arrays to store heights and sequences\n    heights = [disk[2] for disk in disks]  # Heights of each disk\n    sequences = [-1 for _ in disks]  # Index sequence for each disk\n    \n    # Loop through each disk and calculate the maximum height\n    for i in range(1, len(disks)):\n        current_disk = disks[i]\n        for j in range(i):\n            other_disk = disks[j]\n            # Check if the dimensions of the other_disk are valid for stacking\n            if are_valid_dimensions(other_disk, current_disk):\n                # Update the height and sequence if the condition is met\n                if heights[i] <= current_disk[2] + heights[j]:\n                    heights[i] = current_disk[2] + heights[j]\n                    sequences[i] = j\n    \n    # Find the index of the maximum height\n    max_index = heights.index(max(heights))\n    \n    # Build and return the sequence of disks for the maximum height\n    sequence = build_sequence(disks, sequences, max_index)\n    return sequence\n\ndef are_valid_dimensions(other_disk, current_disk):\n    # Check if the dimensions of other_disk allow current_disk to be stacked on top\n    return other_disk[0] < current_disk[0] and other_disk[1] < current_disk[1] and other_disk[2] < current_disk[2]\n\ndef build_sequence(disks, sequences, index):\n    sequence = []\n    # Build the sequence of disks for the maximum height\n    while index != -1:\n        sequence.append(disks[index])\n        index = sequences[index]\n    sequence.reverse()  # Reverse the sequence to maintain the correct order\n    return sequence\n"
  },
  {
    "path": "Dynamic Programming/distance_of_nearest_0.cpp",
    "content": "/*Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell.\r\n\r\nThe distance between two adjacent cells is 1.\r\n\r\n \r\n\r\nExample 1:\r\n\r\n\r\nInput: mat = [[0,0,0],[0,1,0],[0,0,0]]\r\nOutput: [[0,0,0],[0,1,0],[0,0,0]]\r\nExample 2:\r\n\r\n\r\nInput: mat = [[0,0,0],[0,1,0],[1,1,1]]\r\nOutput: [[0,0,0],[0,1,0],[1,2,1]]\r\n \r\n\r\nConstraints:\r\n\r\nm == mat.length\r\nn == mat[i].length\r\n1 <= m, n <= 10^4\r\n1 <= m * n <= 10^4\r\nmat[i][j] is either 0 or 1.\r\nThere is at least one 0 in mat.\r\n\r\n\r\nexplanation: \r\n\r\nstepwise explanation of the code: \r\n\r\n1. We start by initializing the dimensions of the input matrix mat as m (number of rows) and n (number of columns). This will be used later in the code.\r\n\r\n2. We create a result matrix called result of size m x n to store the distance of the nearest 0 for each cell. Initially, we set all the values in result to a large value (in this case, INT_MAX) to represent an unreachable distance.\r\n\r\n3. We create a queue called q to store the cell indices that need to be processed during the breadth-first search.\r\n\r\n4. We iterate through the input matrix mat and enqueue the indices of all the cells with value 0 into the queue. Additionally, we mark the distance of these cells in the result matrix as 0. This initialization step ensures that the cells with value 0 are considered as starting points for the breadth-first search.\r\n\r\n5. Now, we perform the breadth-first search using the queue q. While the queue is not empty, we process the cells in a breadth-first manner.\r\n\r\n6. For each cell (row, col) popped from the queue, we check its neighboring cells in four directions: up, down, left, and right. We define the directions as a vector of pairs called directions, where each pair represents the change in row and column indices to move in a specific direction.\r\n\r\n7. If the neighboring cell indices (newRow, newCol) are within the valid range of the matrix and the current distance in the result matrix for (newRow, newCol) is greater than the distance of the current cell plus 1, we update the distance in the result matrix and enqueue the neighboring cell (newRow, newCol) into the queue for further processing.\r\n\r\n8. Once the breadth-first search is completed, the result matrix will contain the distance of the nearest 0 for each cell in the input matrix.\r\n\r\n9. Finally, we return the result matrix.\r\n\r\n*/\r\n\r\n#include <iostream>\r\n#include <vector>\r\n#include <queue>\r\n\r\nusing namespace std;\r\n\r\nclass Solution\r\n{\r\npublic:\r\n    vector<vector<int>> updateMatrix(vector<vector<int>> &mat)\r\n    {\r\n        int m = mat.size();\r\n        int n = mat[0].size();\r\n\r\n        // Create a result matrix and initialize with large values\r\n        vector<vector<int>> result(m, vector<int>(n, INT_MAX));\r\n\r\n        // Create a queue to store cell indices\r\n        queue<pair<int, int>> q;\r\n\r\n        // Initialize the queue with 0 cells and mark their distance as 0\r\n        for (int i = 0; i < m; i++)\r\n        {\r\n            for (int j = 0; j < n; j++)\r\n            {\r\n                if (mat[i][j] == 0)\r\n                {\r\n                    result[i][j] = 0;\r\n                    q.push({i, j});\r\n                }\r\n            }\r\n        }\r\n\r\n        // Perform breadth-first search\r\n        vector<pair<int, int>> directions{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};\r\n        while (!q.empty())\r\n        {\r\n            int row = q.front().first;\r\n            int col = q.front().second;\r\n            q.pop();\r\n\r\n            for (const auto &dir : directions)\r\n            {\r\n                int newRow = row + dir.first;\r\n                int newCol = col + dir.second;\r\n\r\n                if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n)\r\n                {\r\n                    if (result[newRow][newCol] > result[row][col] + 1)\r\n                    {\r\n                        result[newRow][newCol] = result[row][col] + 1;\r\n                        q.push({newRow, newCol});\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n        return result;\r\n    }\r\n};\r\n\r\nint main()\r\n{\r\n    // Example usage\r\n    vector<vector<int>> mat = {{0, 0, 0}, {0, 1, 0}, {0, 0, 0}};\r\n\r\n    Solution s;\r\n    vector<vector<int>> result = s.updateMatrix(mat);\r\n\r\n    // Print the result\r\n    for (const auto &row : result)\r\n    {\r\n        for (int val : row)\r\n        {\r\n            cout << val << \" \";\r\n        }\r\n        cout << endl;\r\n    }\r\n\r\n    return 0;\r\n}\r\n"
  },
  {
    "path": "Dynamic Programming/distance_of_nearest_0.py",
    "content": "'''\nGiven an m x n binary matrix mat, return the distance of the nearest 0 for each cell.\nThe distance between two adjacent cells is 1.\n \nExample 1:\nInput: mat = [[0,0,0],[0,1,0],[0,0,0]]\nOutput: [[0,0,0],[0,1,0],[0,0,0]]\nExample 2:\nInput: mat = [[0,0,0],[0,1,0],[1,1,1]]\nOutput: [[0,0,0],[0,1,0],[1,2,1]]\n \nConstraints:\nm == mat.length\nn == mat[i].length\n1 <= m, n <= 104\n1 <= m * n <= 104\nmat[i][j] is either 0 or 1.\nThere is at least one 0 in mat.\n\nIntuition\nThe goal is to get the nearest 0 for each 1. So how can we get the nearest 0 for each 1? Lets use Multisource BFS and Dynamic Programming.\nApproach\nTo get the nearest 0 for each 1, we should treat every 0 as if they are on the same level, make a BFS on them and keep track of the distance as we go further. Since we are finding the nearest zero, we may need to use pre-calculated distances for the current 1 when all of its neighbours are all 1.\nLets see this with example!\nHere is the given grid.\n    0 0 0         \n    0 1 0         \n    1 1 1   \nThen by taking all zeros and making a BFS on them, the nearest distance becomes 1 for all ones other than the back ticked 1 found on the third row.\n    0 0 0         \n    0 1 0         \n    1 `1` 1  \nThe back ticked '1' is not adjacent to 0, so it should use the precalculated distance of the nearest 1 it get.\nSo, in here we are using precalculated values to get the nearest distance. This technique is called Dynamic programming.\nThen we will get this grid by using the values we calculated for its adjacent 1\n    0 0 0         \n    0 1 0         \n    1 2 1  \nComplexity\nTime complexity: O(N)\nSpace complexity: O(V + E)\nCode\nsample input and output:\n\n1. Input: mat = [[0,0,0],[0,1,0],[0,0,0]]\n   Output: [[0,0,0],[0,1,0],[0,0,0]]\n\n'''\nclass Solution:\n    def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:\n        \n        # it a Multi-source BFS like 994. Rotting Oranges\n        # treat every 0 as if they are on the same level and make BFS on them\n        def isvalid(row, col):\n            if row >= len(mat) or row < 0 or col >= len(mat[0]) or col < 0:\n                return False\n            return True\n        \n        # get every zero and add them to a queue\n        q, visited = deque(), set()\n        for row in range( len(mat)):\n            for col in range( len(mat[0])):\n                if mat[row][col] == 0:\n                    q.append([row, col])\n                    visited.add((row, col))\n        \n        level = 1 # the distance to the nearest zero starts from 1\n        while q:\n            size = len(q)\n            for _ in range( size ):\n                row, col =q.popleft()\n                for r, c in [ [1, 0], [-1, 0], [0, 1], [0, -1]]:\n                    newRow, newCol = row + r, col + c\n                    if (newRow, newCol) not in visited and isvalid(newRow, newCol):\n                        mat[newRow][newCol] = level\n                        q.append([newRow, newCol])\n                        visited.add( (newRow, newCol))\n            level += 1\n        \n        return mat"
  },
  {
    "path": "Dynamic Programming/distane_of_nearest_0.go",
    "content": "// Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell in Java\n\n// Solution\n// // This solution uses a breadth-first search (BFS) approach to calculate the distance of the nearest 0 for each cell in the matrix.\n// // The idea is to initialize a distances matrix with all values set to the maximum integer value, except for the cells that contain 0s,\n// // which are set to 0 and added to a queue. We then perform a BFS on the queue, updating the distances of neighboring cells as we go.\n// // Finally, we return the updated distances matrix.\n\n// Time Complexity:\n\n// We traverse the entire matrix in the worst case to fill the distances matrix with initial values, which takes O(m * n) time.\n// We use Breadth-First Search (BFS) to update the distances matrix, which in the worst case can visit each cell once, taking O(m * n) time.\n// Therefore, the total time complexity of this solution is O(m * n).\n\n// Space Complexity:\n\n// We store the distances matrix, which requires O(m * n) space.\n// We use a queue to implement the BFS algorithm, which can store at most m * n cells in the worst case, taking O(m * n) space.\n// Therefore, the total space complexity of this solution is O(m * n).\n\npackage main\n\nimport (\n\t\"container/list\"\n\t\"math\"\n)\n\nvar directions = [][2]int{{-1, 0}, {0, 1}, {1, 0}, {0, -1}}\n\nfunc updateMatrix(mat [][]int) [][]int {\n\tm := len(mat)\n\tn := len(mat[0])\n\tdistances := make([][]int, m) // Initialize a distances matrix\n\n\t// Initialize distances to math.MaxInt32 except for cells with 0\n\tfor i := range distances {\n\t\tdistances[i] = make([]int, n)\n\t\tfor j := range distances[i] {\n\t\t\tdistances[i][j] = math.MaxInt32\n\t\t\tif mat[i][j] == 0 {\n\t\t\t\tdistances[i][j] = 0\n\t\t\t}\n\t\t}\n\t}\n\n\tqueue := list.New() // Initialize a queue for BFS\n\n\t// Perform BFS\n\tfor i := 0; i < m; i++ {\n\t\tfor j := 0; j < n; j++ {\n\t\t\tif mat[i][j] == 0 {\n\t\t\t\tqueue.PushBack([2]int{i, j}) // Add the cell to the queue\n\t\t\t}\n\t\t}\n\t}\n\n\tfor queue.Len() > 0 {\n\t\telement := queue.Front()\n\t\tqueue.Remove(element)\n\t\tcell := element.Value.([2]int)\n\t\ti, j := cell[0], cell[1]\n\n\t\tfor _, direction := range directions {\n\t\t\tx, y := i+direction[0], j+direction[1]\n\n\t\t\t// Check if cell is out of bounds\n\t\t\tif x < 0 || x >= m || y < 0 || y >= n {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Check if distance is already smaller\n\t\t\tif distances[x][y] <= distances[i][j]+1 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tdistances[x][y] = distances[i][j] + 1 // Update the distance\n\t\t\tqueue.PushBack([2]int{x, y})         // Add the cell to the queue\n\t\t}\n\t}\n\n\treturn distances // Return the updated distances matrix\n}\n"
  },
  {
    "path": "Dynamic Programming/distane_of_nearest_0.java",
    "content": "// Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell in Java\n\n\n// Solution\n// // This solution uses a breadth-first search (BFS) approach to calculate the distance of the nearest 0 for each cell in the matrix. \n// // The idea is to initialize a distances matrix with all values set to the maximum integer value, except for the cells that contain 0s,\n// // which are set to 0 and added to a queue. We then perform a BFS on the queue, updating the distances of neighboring cells as we go.\n// // Finally, we return the updated distances matrix.\n\n\n// Time Complexity:\n\n// We traverse the entire matrix in the worst case to fill the distances matrix with initial values, which takes O(m * n) time.\n// We use Breadth-First Search (BFS) to update the distances matrix, which in the worst case can visit each cell once, taking O(m * n) time.\n// Therefore, the total time complexity of this solution is O(m * n).\n\n// Space Complexity:\n\n// We store the distances matrix, which requires O(m * n) space.\n// We use a queue to implement the BFS algorithm, which can store at most m * n cells in the worst case, taking O(m * n) space.\n// Therefore, the total space complexity of this solution is O(m * n).\n\nclass Solution {\n    private static final int[][] DIRECTIONS = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};\n    \n    public int[][] updateMatrix(int[][] mat) {\n        int m = mat.length;\n        int n = mat[0].length;\n        int[][] distances = new int[m][n]; // Initialize a distances matrix\n        Queue<int[]> queue = new LinkedList<>(); // Initialize a queue for BFS\n\n         // Loop through the matrix and set distances to MAX_VALUE except for cells with 0\n        for (int i = 0; i < m; i++) {\n            Arrays.fill(distances[i], Integer.MAX_VALUE);\n            for (int j = 0; j < n; j++) {\n                if (mat[i][j] == 0) {\n                    distances[i][j] = 0;\n                    queue.offer(new int[]{i, j});  // Add the cell to the queue \n                }\n            }\n        }\n\n        // Perform BFS\n        while (!queue.isEmpty()) {\n            int[] cell = queue.poll();\n            int i = cell[0];\n            int j = cell[1];\n            for (int[] direction : DIRECTIONS) {\n                int x = i + direction[0];\n                int y = j + direction[1];\n                if (x < 0 || x >= m || y < 0 || y >= n) { // Check if cell is out of bounds\n                    continue;\n                }\n                if (distances[x][y] <= distances[i][j] + 1) {// Check if distance is already smaller\n                    continue;\n                }\n                distances[x][y] = distances[i][j] + 1; // Update the distance\n                queue.offer(new int[]{x, y});// Add the cell to the queue\n            }\n        }\n        return distances; // Return the updated distances matrix \n    }\n}\n\n\n//Input\n// mat =\n// [[0,0,0],[0,1,0],[0,0,0]]\n\n// Output\n// [[0,0,0],[0,1,0],[0,0,0]]"
  },
  {
    "path": "Dynamic Programming/distane_of_nearest_0.js",
    "content": "// Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell in Java\n\n\n// Solution\n// // This solution uses a breadth-first search (BFS) approach to calculate the distance of the nearest 0 for each cell in the matrix. \n// // The idea is to initialize a distances matrix with all values set to the maximum integer value, except for the cells that contain 0s,\n// // which are set to 0 and added to a queue. We then perform a BFS on the queue, updating the distances of neighboring cells as we go.\n// // Finally, we return the updated distances matrix.\n\n\n// Time Complexity:\n\n// We traverse the entire matrix in the worst case to fill the distances matrix with initial values, which takes O(m * n) time.\n// We use Breadth-First Search (BFS) to update the distances matrix, which in the worst case can visit each cell once, taking O(m * n) time.\n// Therefore, the total time complexity of this solution is O(m * n).\n\n// Space Complexity:\n\n// We store the distances matrix, which requires O(m * n) space.\n// We use a queue to implement the BFS algorithm, which can store at most m * n cells in the worst case, taking O(m * n) space.\n// Therefore, the total space complexity of this solution is O(m * n).\n\nfunction updateMatrix(mat) {\n  const m = mat.length;\n  const n = mat[0].length;\n  const queue = [];\n  \n  // Initialize distance matrix with maximum possible values\n  const dist = new Array(m).fill().map(() => new Array(n).fill(Number.MAX_VALUE));\n  \n  // Initialize the queue with all cells containing 0\n  for (let i = 0; i < m; i++) {\n    for (let j = 0; j < n; j++) {\n      if (mat[i][j] === 0) {\n        dist[i][j] = 0;\n        queue.push([i, j]);\n      }\n    }\n  }\n  \n  // Perform a BFS starting from the cells containing 0\n  while (queue.length > 0) {\n    const [i, j] = queue.shift();\n    \n    // Check the neighbors of the current cell\n    const neighbors = [[i - 1, j], [i + 1, j], [i, j - 1], [i, j + 1]];\n    for (const [ni, nj] of neighbors) {\n      // Check if the neighbor is within bounds\n      if (ni >= 0 && ni < m && nj >= 0 && nj < n) {\n        // If the distance to the neighbor can be updated\n        if (dist[ni][nj] > dist[i][j] + 1) {\n          dist[ni][nj] = dist[i][j] + 1;\n          queue.push([ni, nj]);\n        }\n      }\n    }\n  }\n  \n  return dist;\n}\n\n\nThe updateMatrix function takes a binary matrix mat as input and returns a matrix dist with the distance of the nearest 0 for each cell.\nThe algorithm first initializes the dist matrix with maximum possible values and adds all cells containing 0 to a queue. \nThen, it performs a BFS starting from the cells in the queue and updates the distances of the neighboring cells if they can be improved. \nFinally, it returns the dist matrix with the updated distances.\n"
  },
  {
    "path": "Dynamic Programming/edit_distance_dp.cpp",
    "content": "/*\n    Given two strings str1 and str2 and following three operations that can performed on str1. \n    1) Insert\n    2) Remove\n    3) Replace\n    Find minimum number of operations required to convert ‘str1’ into ‘str2’. \n    For example if input strings are CAT AND CAR the edit distance is 1.\n\n    Input  :  s1 : saturday  s2 : sunday \n    Output :  3  \n*/\n// Dynamic Programming Solution : TC O(n^2)\n// Porgram Author : Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\n\n// Function to find the minimum edit distance between two strings\nint find_edit_distance(string s1, string s2, int l1, int l2){ \n    // Create a 2D array dp to store the edit distances\n    int dp[100][100] = {};\n\n    // Initialize the base cases for empty strings\n    for(int i = 0; i <= l1; i++){\n        dp[i][0] = i; // Minimum edit distance for transforming s1[0...i] to an empty string\n    }\n    for(int i = 0; i <= l2; i++){\n        dp[0][i] = i; // Minimum edit distance for transforming an empty string to s2[0...i]\n    }\n\n    // Calculate the edit distance for the rest of the strings\n    for(int i = 1; i <= l1; i++){\n        for(int j = 1; j <= l2; j++){\n            if(s1[i] == s2[j])\n                dp[i][j] = dp[i - 1][j - 1]; // No edit required if characters match\n            else{\n                int del = dp[i][j - 1];    // Deletion (from s2)\n                int replace = dp[i - 1][j - 1]; // Replacement (of s1[i] with s2[j])\n                int insert = dp[i - 1][j];  // Insertion (into s1)\n                dp[i][j] = min(del, min(replace, insert)) + 1; // Choose the minimum of the three operations\n            }\n        }\n    }\n\n    // Print the edit distance matrix (optional)\n    for(int i = 0; i <= l1; i++){\n        for(int j = 0; j <= l2; j++){\n            cout << setw(5) << dp[i][j] << \" \";\n        }\n        cout << \"\\n\";\n    }\n\n    return dp[l1][l2]; // Return the minimum edit distance\n}\n\nint main(){\n    string s1 = \"abhisek\";\n    string s2 = \"tsunade\";\n    int l1 = s1.length() - 1;\n    int l2 = s2.length() - 1;\n\n    int result = find_edit_distance(s1, s2, l1, l2);\n    cout << \"Minimum Edit Distance: \" << result;\n    return 0;\n}\n"
  },
  {
    "path": "Dynamic Programming/edit_distance_dp.go",
    "content": "/*\n   Given two strings str1 and str2 and following three operations that can performed on str1.\n   1) Insert\n   2) Remove\n   3) Replace\n   Find minimum number of operations required to convert ‘str1’ into ‘str2’.\n   For example if input strings are CAT AND CAR the edit distance is 1.\n\n   Input  :  s1 : saturday  s2 : sunday\n   Output :  3\n*/\n// Dynamic Programming Solution : TC O(n^2)\npackage main\n\nimport (\n\t\"fmt\"\n)\n\n// findEditDistance finds the minimum edit distance between two strings.\nfunc findEditDistance(s1, s2 string) int {\n\tl1, l2 := len(s1), len(s2)\n\n\t// Create a 2D array dp to store the edit distances.\n\tdp := make([][]int, l1+1)\n\tfor i := range dp {\n\t\tdp[i] = make([]int, l2+1)\n\t}\n\n\t// Initialize the base cases for empty strings.\n\tfor i := 0; i <= l1; i++ {\n\t\tdp[i][0] = i // Minimum edit distance for transforming s1[0...i] to an empty string.\n\t}\n\tfor i := 0; i <= l2; i++ {\n\t\tdp[0][i] = i // Minimum edit distance for transforming an empty string to s2[0...i].\n\t}\n\n\t// Calculate the edit distance for the rest of the strings.\n\tfor i := 1; i <= l1; i++ {\n\t\tfor j := 1; j <= l2; j++ {\n\t\t\tif s1[i-1] == s2[j-1] {\n\t\t\t\tdp[i][j] = dp[i-1][j-1] // No edit required if characters match.\n\t\t\t} else {\n\t\t\t\tdel := dp[i][j-1]      // Deletion (from s2).\n\t\t\t\treplace := dp[i-1][j-1] // Replacement (of s1[i] with s2[j]).\n\t\t\t\tinsert := dp[i-1][j]   // Insertion (into s1).\n\t\t\t\tdp[i][j] = min(del, min(replace, insert)) + 1 // Choose the minimum of the three operations.\n\t\t\t}\n\t\t}\n\t}\n\n\t// Print the edit distance matrix (optional).\n\tfor i := 0; i <= l1; i++ {\n\t\tfor j := 0; j <= l2; j++ {\n\t\t\tfmt.Printf(\"%5d \", dp[i][j])\n\t\t}\n\t\tfmt.Println()\n\t}\n\n\treturn dp[l1][l2] // Return the minimum edit distance.\n}\n\nfunc main() {\n\ts1 := \"abhisek\"\n\ts2 := \"tsunade\"\n\n\tresult := findEditDistance(s1, s2)\n\tfmt.Printf(\"Minimum Edit Distance: %d\\n\", result)\n}\n"
  },
  {
    "path": "Dynamic Programming/edit_distance_dp.java",
    "content": "/*\n   Given two strings str1 and str2 and following three operations that can performed on str1.\n   1) Insert\n   2) Remove\n   3) Replace\n   Find minimum number of operations required to convert ‘str1’ into ‘str2’.\n   For example if input strings are CAT AND CAR the edit distance is 1.\n\n   Input  :  s1 : saturday  s2 : sunday\n   Output :  3\n*/\n// Dynamic Programming Solution : TC O(n^2)\npublic class EditDistance {\n\n    // Function to find the minimum edit distance between two strings\n    public static int findEditDistance(String s1, String s2) {\n        int l1 = s1.length();\n        int l2 = s2.length();\n\n        // Create a 2D array dp to store the edit distances\n        int[][] dp = new int[l1 + 1][l2 + 1];\n\n        // Initialize the base cases for empty strings\n        for (int i = 0; i <= l1; i++) {\n            dp[i][0] = i; // Minimum edit distance for transforming s1[0...i] to an empty string\n        }\n        for (int i = 0; i <= l2; i++) {\n            dp[0][i] = i; // Minimum edit distance for transforming an empty string to s2[0...i]\n        }\n\n        // Calculate the edit distance for the rest of the strings\n        for (int i = 1; i <= l1; i++) {\n            for (int j = 1; j <= l2; j++) {\n                if (s1.charAt(i - 1) == s2.charAt(j - 1)) {\n                    dp[i][j] = dp[i - 1][j - 1]; // No edit required if characters match\n                } else {\n                    int del = dp[i][j - 1];    // Deletion (from s2)\n                    int replace = dp[i - 1][j - 1]; // Replacement (of s1[i] with s2[j])\n                    int insert = dp[i - 1][j];  // Insertion (into s1)\n                    dp[i][j] = Math.min(del, Math.min(replace, insert)) + 1; // Choose the minimum of the three operations\n                }\n            }\n        }\n\n        // Print the edit distance matrix (optional)\n        for (int i = 0; i <= l1; i++) {\n            for (int j = 0; j <= l2; j++) {\n                System.out.printf(\"%5d \", dp[i][j]);\n            }\n            System.out.println();\n        }\n\n        return dp[l1][l2]; // Return the minimum edit distance\n    }\n\n    public static void main(String[] args) {\n        String s1 = \"abhisek\";\n        String s2 = \"tsunade\";\n\n        int result = findEditDistance(s1, s2);\n        System.out.println(\"Minimum Edit Distance: \" + result);\n    }\n}\n"
  },
  {
    "path": "Dynamic Programming/edit_distance_dp.js",
    "content": "/*\n   Given two strings str1 and str2 and following three operations that can performed on str1.\n   1) Insert\n   2) Remove\n   3) Replace\n   Find minimum number of operations required to convert ‘str1’ into ‘str2’.\n   For example if input strings are CAT AND CAR the edit distance is 1.\n\n   Input  :  s1 : saturday  s2 : sunday\n   Output :  3\n*/\n// Dynamic Programming Solution : TC O(n^2)\n// Function to find the minimum edit distance between two strings\nfunction findEditDistance(s1, s2) {\n  const l1 = s1.length;\n  const l2 = s2.length;\n\n  // Create a 2D array dp to store the edit distances\n  const dp = Array.from({ length: l1 + 1 }, () => Array(l2 + 1).fill(0));\n\n  // Initialize the base cases for empty strings\n  for (let i = 0; i <= l1; i++) {\n    dp[i][0] = i; // Minimum edit distance for transforming s1[0...i] to an empty string\n  }\n  for (let i = 0; i <= l2; i++) {\n    dp[0][i] = i; // Minimum edit distance for transforming an empty string to s2[0...i]\n  }\n\n  // Calculate the edit distance for the rest of the strings\n  for (let i = 1; i <= l1; i++) {\n    for (let j = 1; j <= l2; j++) {\n      if (s1[i - 1] === s2[j - 1]) {\n        dp[i][j] = dp[i - 1][j - 1]; // No edit required if characters match\n      } else {\n        const del = dp[i][j - 1]; // Deletion (from s2)\n        const replace = dp[i - 1][j - 1]; // Replacement (of s1[i] with s2[j])\n        const insert = dp[i - 1][j]; // Insertion (into s1)\n        dp[i][j] = Math.min(del, Math.min(replace, insert)) + 1; // Choose the minimum of the three operations\n      }\n    }\n  }\n\n  // Print the edit distance matrix (optional)\n  for (let i = 0; i <= l1; i++) {\n    console.log(\n      dp[i].map((value) => value.toString().padStart(5, \" \")).join(\" \")\n    );\n  }\n\n  return dp[l1][l2]; // Return the minimum edit distance\n}\n\n// Example usage\nconst s1 = \"abhisek\";\nconst s2 = \"tsunade\";\n\nconst result = findEditDistance(s1, s2);\nconsole.log(\"Minimum Edit Distance:\", result);\n"
  },
  {
    "path": "Dynamic Programming/edit_distance_dp.py",
    "content": "'''\n   Given two strings str1 and str2 and following three operations that can performed on str1.\n   1) Insert\n   2) Remove\n   3) Replace\n   Find minimum number of operations required to convert ‘str1’ into ‘str2’.\n   For example if input strings are CAT AND CAR the edit distance is 1.\n\n   Input  :  s1 : saturday  s2 : sunday\n   Output :  3\n*/\n// Dynamic Programming Solution : TC O(n^2)\n'''\n# Function to find the minimum edit distance between two strings\ndef find_edit_distance(s1, s2):\n    l1, l2 = len(s1), len(s2)\n\n    # Create a 2D list dp to store the edit distances\n    dp = [[0] * (l2 + 1) for _ in range(l1 + 1)]\n\n    # Initialize the base cases for empty strings\n    for i in range(l1 + 1):\n        dp[i][0] = i  # Minimum edit distance for transforming s1[0...i] to an empty string\n    for i in range(l2 + 1):\n        dp[0][i] = i  # Minimum edit distance for transforming an empty string to s2[0...i]\n\n    # Calculate the edit distance for the rest of the strings\n    for i in range(1, l1 + 1):\n        for j in range(1, l2 + 1):\n            if s1[i - 1] == s2[j - 1]:\n                dp[i][j] = dp[i - 1][j - 1]  # No edit required if characters match\n            else:\n                del_op = dp[i][j - 1]  # Deletion (from s2)\n                replace_op = dp[i - 1][j - 1]  # Replacement (of s1[i] with s2[j])\n                insert_op = dp[i - 1][j]  # Insertion (into s1)\n                dp[i][j] = min(del_op, min(replace_op, insert_op)) + 1  # Choose the minimum of the three operations\n\n    # Print the edit distance matrix (optional)\n    for i in range(l1 + 1):\n        print(\" \".join(map(lambda value: f\"{value:5}\", dp[i])))\n\n    return dp[l1][l2]  # Return the minimum edit distance\n\n# Example usage\ns1 = \"abhisek\"\ns2 = \"tsunade\"\n\nresult = find_edit_distance(s1, s2)\nprint(\"Minimum Edit Distance:\", result)\n"
  },
  {
    "path": "Dynamic Programming/edit_distance_memoized.cpp",
    "content": "/*\n    Given two strings str1 and str2 and following three operations that can performed on str1. \n    1) Insert\n    2) Remove\n    3) Replace\n    Find minimum number of operations required to convert ‘str1’ into ‘str2’. \n    For example if input strings are CAT AND CAR the edit distance is 1.\n\n    Input  : s1 : saturday  s2 : sunday \n    Output : 3  \n*/\n// Memoized Solution : TC O(n^2)\n// Porgram Author : Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\nint calls = 0;\nint memoize[1009][1009];\nint find_edit_distance(string s1, string s2, int l1, int l2){\n    calls++;\n    if(l1 == 0)\n        return l2;\n    if(l2 == 0)\n        return l1;\n    if(memoize[l1][l2] != -1) return memoize[l1][l2];          \n    if(s1[l1] == s2[l2]){\n        return find_edit_distance(s1, s2, l1 - 1, l2 - 1);\n    }\n    int del = find_edit_distance(s1, s2, l1, l2 - 1);\n    int replace = find_edit_distance(s1, s2, l1 - 1, l2 - 1);\n    int insert = find_edit_distance(s1, s2, l1 - 1, l2);\n    memoize[l1][l2] = min (del, min(replace, insert)) + 1;\n    return min (del, min(replace, insert)) + 1;\n}\nint main(){\n    memset(memoize, -1, sizeof(memoize));\n    string s1 = \"abhisek\";\n    string s2 = \"tsunade\";\n    int l1 = s1.length() - 1;\n    int l2 = s2.length() - 1;\n    int result = find_edit_distance(s1, s2, l1, l2);\n    cout << result;\n    cout << \"\\n\" << calls;\n    return 0;\n}"
  },
  {
    "path": "Dynamic Programming/edit_distance_recursive.cpp",
    "content": "/*\n    Given two strings str1 and str2 and following three operations that can performed on str1. \n    1) Insert\n    2) Remove\n    3) Replace\n    Find minimum number of operations required to convert ‘str1’ into ‘str2’. \n    For example if input strings are CAT AND CAR the edit distance is 1.\n\n    Input  : s1 : saturday  s2 : sunday \n    Output : 3  \n*/\n// Recursive Solution : TC Exponential\n// Porgram Author : Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\nint calls = 0;\nint find_edit_distance(string s1, string s2, int l1, int l2){\n    calls++;\n    if(l1 == 0)\n        return l2;\n    if(l2 == 0)\n        return l1;     \n    if(s1[l1] == s2[l2]){\n        return find_edit_distance(s1, s2, l1 - 1, l2 - 1);\n    }\n    int del = find_edit_distance(s1, s2, l1, l2 - 1);\n    int replace = find_edit_distance(s1, s2, l1 - 1, l2 - 1);\n    int insert = find_edit_distance(s1, s2, l1 - 1, l2);\n    return min (del, min(replace, insert)) + 1;\n}\nint main(){\n    string s1 = \"abhisek\";\n    string s2 = \"tsunade\";\n    int l1 = s1.length() - 1;\n    int l2 = s2.length() - 1;\n    int result = find_edit_distance(s1, s2, l1, l2);\n    cout << result;\n    cout << \"\\n\" << calls;\n    return 0;\n}"
  },
  {
    "path": "Dynamic Programming/house_robber.cpp",
    "content": "/*\nYou are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.\n\nGiven an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.\n\n \n\nExample 1:\n\nInput: nums = [1,2,3,1]\nOutput: 4\nExplanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).\nTotal amount you can rob = 1 + 3 = 4.\nExample 2:\n\nInput: nums = [2,7,9,3,1]\nOutput: 12\nExplanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).\nTotal amount you can rob = 2 + 9 + 1 = 12.\n \n\nConstraints:\n\n1 <= nums.length <= 100\n0 <= nums[i] <= 400\n*/\n\n#include<bits/stdc++.h>\n\nclass Solution {\npublic:\n    int rob(vector<int>& nums) {\n        int len = nums.size();\n       /*\n        if(len == 0) return 0;\n        if(len == 1) return nums[0];\n        if(len == 2) return max(nums[0], nums[1]);\n        int dp[len];\n        dp[0] = nums[0];\n        dp[1] = max(nums[0], nums[1]);\n        for(int i = 2; i < len; i++){\n            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);\n        }\n        return dp[len-1];\n        */\n        int prev = 0, curr = 0, temp = 0;\n        for(int i = 0; i < len; i++){\n            temp = max(nums[i] + prev, curr);\n            prev = curr;\n            curr = temp;\n        }\n        return curr;\n    }\n};"
  },
  {
    "path": "Dynamic Programming/juice_bottling.cpp",
    "content": "/*\n\n\nExplanation:\n\n1. The function `JuiceBottling` takes an array `prices` as input, where `prices[i]` represents the price of a juice bottle of size `i`.\n\n2. It initializes two arrays, `maxProfit` and `dividingPoints`, both of size `numSizes` (the number of bottle sizes).\nThese arrays will be used to store information about maximum profit and dividing points.\n\n3. The outer loop iterates through each possible bottle size, from 0 to `numSizes - 1`.\n\n4. The inner loop iterates through possible dividing points for the current bottle size. For each combination of bottle size\nand dividing point, it calculates the possible profit by adding the maximum profit from the previous bottle sizes and the\nprice of the bottle at the current dividing point.\n\n5. If the calculated possible profit is greater than the current maximum profit for the bottle size, it updates both `maxProfit`\nand `dividingPoints` arrays.\n\n6. After completing the loops, the function reconstructs the solution by backtracking from the last bottle size to the first.\nIt appends the recorded dividing points to the `solution` array, which represents the optimal way to divide the bottles.\n\n7. The function returns the `solution` array, which contains the indices of the dividing points that maximize profit.\n\nIn summary, the code uses dynamic programming to determine the optimal division of juice bottles to maximize profit.\nIt calculates the maximum profit for each bottle size and keeps track of the dividing points that lead to the maximum profit.\nThe solution is then reconstructed by backtracking from the end using the recorded dividing points.\n*/\n\n#include <iostream>\n#include <vector>\n\nstd::vector<int> juiceBottling(std::vector<int>& prices) {\n    int numSizes = prices.size();\n    std::vector<int> maxProfit(numSizes);         // Vector to store the maximum profit for each bottle size\n    std::vector<int> dividingPoints(numSizes);    // Vector to store the dividing points that maximize profit\n\n    // Loop through each bottle size\n    for (int size = 0; size < numSizes; size++) {\n        // Loop through possible dividing points for the current size\n        for (int dividingPoint = 0; dividingPoint < size + 1; dividingPoint++) {\n            // Calculate the possible profit by combining the previous maximum profit\n            // with the price at the current dividing point\n            int possibleProfit = maxProfit[size - dividingPoint] + prices[dividingPoint];\n\n            // Update maxProfit and dividingPoints if the new possible profit is greater\n            if (possibleProfit > maxProfit[size]) {\n                maxProfit[size] = possibleProfit;\n                dividingPoints[size] = dividingPoint;\n            }\n        }\n    }\n\n    std::vector<int> solution;\n    int currentDividingPoint = numSizes - 1;\n    // Reconstruct the solution by tracing back from the end\n    // using the dividing points information\n    while (currentDividingPoint > 0) {\n        solution.push_back(dividingPoints[currentDividingPoint]);\n        currentDividingPoint -= dividingPoints[currentDividingPoint];\n    }\n    return solution;\n}\n\nint main() {\n    std::vector<int> prices = {3, 5, 8, 9, 10, 17, 17, 20};\n    std::vector<int> result = juiceBottling(prices);\n\n    std::cout << \"Dividing Points for Maximum Profit:\";\n    for (int point : result) {\n        std::cout << \" \" << point;\n    }\n    std::cout << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Dynamic Programming/juice_bottling.go",
    "content": "/*\n\n\nExplanation:\n\n1. The function `JuiceBottling` takes an array `prices` as input, where `prices[i]` represents the price of a juice bottle of size `i`.\n\n2. It initializes two arrays, `maxProfit` and `dividingPoints`, both of size `numSizes` (the number of bottle sizes).\nThese arrays will be used to store information about maximum profit and dividing points.\n\n3. The outer loop iterates through each possible bottle size, from 0 to `numSizes - 1`.\n\n4. The inner loop iterates through possible dividing points for the current bottle size. For each combination of bottle size\nand dividing point, it calculates the possible profit by adding the maximum profit from the previous bottle sizes and the\nprice of the bottle at the current dividing point.\n\n5. If the calculated possible profit is greater than the current maximum profit for the bottle size, it updates both `maxProfit`\nand `dividingPoints` arrays.\n\n6. After completing the loops, the function reconstructs the solution by backtracking from the last bottle size to the first.\nIt appends the recorded dividing points to the `solution` array, which represents the optimal way to divide the bottles.\n\n7. The function returns the `solution` array, which contains the indices of the dividing points that maximize profit.\n\nIn summary, the code uses dynamic programming to determine the optimal division of juice bottles to maximize profit.\nIt calculates the maximum profit for each bottle size and keeps track of the dividing points that lead to the maximum profit.\nThe solution is then reconstructed by backtracking from the end using the recorded dividing points.\n*/\npackage main\n\nfunc JuiceBottling(prices []int) []int {\n\tnumSizes := len(prices)\n\tmaxProfit := make([]int, numSizes)      // Array to store the maximum profit for each bottle size\n\tdividingPoints := make([]int, numSizes) // Array to store the dividing points that maximize profit\n\n\t// Loop through each bottle size\n\tfor size := 0; size < numSizes; size++ {\n\t\t// Loop through possible dividing points for the current size\n\t\tfor dividingPoint := 0; dividingPoint < size+1; dividingPoint++ {\n\t\t\t// Calculate the possible profit by combining the previous maximum profit\n\t\t\t// with the price at the current dividing point\n\t\t\tpossibleProfit := maxProfit[size-dividingPoint] + prices[dividingPoint]\n\n\t\t\t// Update maxProfit and dividingPoints if the new possible profit is greater\n\t\t\tif possibleProfit > maxProfit[size] {\n\t\t\t\tmaxProfit[size] = possibleProfit\n\t\t\t\tdividingPoints[size] = dividingPoint\n\t\t\t}\n\t\t}\n\t}\n\n\tsolution := []int{}\n\tcurrentDividingPoint := numSizes - 1\n\t// Reconstruct the solution by tracing back from the end\n\t// using the dividing points information\n\tfor currentDividingPoint > 0 {\n\t\tsolution = append(solution, dividingPoints[currentDividingPoint])\n\t\tcurrentDividingPoint -= dividingPoints[currentDividingPoint]\n\t}\n\treturn solution\n}\n"
  },
  {
    "path": "Dynamic Programming/juice_bottling.java",
    "content": "/*\n\n\nExplanation:\n\n1. The function `JuiceBottling` takes an array `prices` as input, where `prices[i]` represents the price of a juice bottle of size `i`.\n\n2. It initializes two arrays, `maxProfit` and `dividingPoints`, both of size `numSizes` (the number of bottle sizes).\nThese arrays will be used to store information about maximum profit and dividing points.\n\n3. The outer loop iterates through each possible bottle size, from 0 to `numSizes - 1`.\n\n4. The inner loop iterates through possible dividing points for the current bottle size. For each combination of bottle size\nand dividing point, it calculates the possible profit by adding the maximum profit from the previous bottle sizes and the\nprice of the bottle at the current dividing point.\n\n5. If the calculated possible profit is greater than the current maximum profit for the bottle size, it updates both `maxProfit`\nand `dividingPoints` arrays.\n\n6. After completing the loops, the function reconstructs the solution by backtracking from the last bottle size to the first.\nIt appends the recorded dividing points to the `solution` array, which represents the optimal way to divide the bottles.\n\n7. The function returns the `solution` array, which contains the indices of the dividing points that maximize profit.\n\nIn summary, the code uses dynamic programming to determine the optimal division of juice bottles to maximize profit.\nIt calculates the maximum profit for each bottle size and keeps track of the dividing points that lead to the maximum profit.\nThe solution is then reconstructed by backtracking from the end using the recorded dividing points.\n*/\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class JuiceBottling {\n\n    public static List<Integer> juiceBottling(int[] prices) {\n        int numSizes = prices.length;\n        int[] maxProfit = new int[numSizes];        // Array to store the maximum profit for each bottle size\n        int[] dividingPoints = new int[numSizes];   // Array to store the dividing points that maximize profit\n\n        // Loop through each bottle size\n        for (int size = 0; size < numSizes; size++) {\n            // Loop through possible dividing points for the current size\n            for (int dividingPoint = 0; dividingPoint < size + 1; dividingPoint++) {\n                // Calculate the possible profit by combining the previous maximum profit\n                // with the price at the current dividing point\n                int possibleProfit = maxProfit[size - dividingPoint] + prices[dividingPoint];\n\n                // Update maxProfit and dividingPoints if the new possible profit is greater\n                if (possibleProfit > maxProfit[size]) {\n                    maxProfit[size] = possibleProfit;\n                    dividingPoints[size] = dividingPoint;\n                }\n            }\n        }\n\n        List<Integer> solution = new ArrayList<>();\n        int currentDividingPoint = numSizes - 1;\n        // Reconstruct the solution by tracing back from the end\n        // using the dividing points information\n        while (currentDividingPoint > 0) {\n            solution.add(dividingPoints[currentDividingPoint]);\n            currentDividingPoint -= dividingPoints[currentDividingPoint];\n        }\n        return solution;\n    }\n\n    public static void main(String[] args) {\n        int[] prices = {3, 5, 8, 9, 10, 17, 17, 20};\n        List<Integer> result = juiceBottling(prices);\n\n        System.out.println(\"Dividing Points for Maximum Profit: \" + result);\n    }\n}\n"
  },
  {
    "path": "Dynamic Programming/juice_bottling.js",
    "content": "/*\n\n\nExplanation:\n\n1. The function `JuiceBottling` takes an array `prices` as input, where `prices[i]` represents the price of a juice bottle of size `i`.\n\n2. It initializes two arrays, `maxProfit` and `dividingPoints`, both of size `numSizes` (the number of bottle sizes).\nThese arrays will be used to store information about maximum profit and dividing points.\n\n3. The outer loop iterates through each possible bottle size, from 0 to `numSizes - 1`.\n\n4. The inner loop iterates through possible dividing points for the current bottle size. For each combination of bottle size\nand dividing point, it calculates the possible profit by adding the maximum profit from the previous bottle sizes and the\nprice of the bottle at the current dividing point.\n\n5. If the calculated possible profit is greater than the current maximum profit for the bottle size, it updates both `maxProfit`\nand `dividingPoints` arrays.\n\n6. After completing the loops, the function reconstructs the solution by backtracking from the last bottle size to the first.\nIt appends the recorded dividing points to the `solution` array, which represents the optimal way to divide the bottles.\n\n7. The function returns the `solution` array, which contains the indices of the dividing points that maximize profit.\n\nIn summary, the code uses dynamic programming to determine the optimal division of juice bottles to maximize profit.\nIt calculates the maximum profit for each bottle size and keeps track of the dividing points that lead to the maximum profit.\nThe solution is then reconstructed by backtracking from the end using the recorded dividing points.\n*/\nfunction juiceBottling(prices) {\n  const numSizes = prices.length;\n  const maxProfit = new Array(numSizes).fill(0); // Array to store the maximum profit for each bottle size\n  const dividingPoints = new Array(numSizes).fill(0); // Array to store the dividing points that maximize profit\n\n  // Loop through each bottle size\n  for (let size = 0; size < numSizes; size++) {\n    // Loop through possible dividing points for the current size\n    for (let dividingPoint = 0; dividingPoint < size + 1; dividingPoint++) {\n      // Calculate the possible profit by combining the previous maximum profit\n      // with the price at the current dividing point\n      const possibleProfit =\n        maxProfit[size - dividingPoint] + prices[dividingPoint];\n\n      // Update maxProfit and dividingPoints if the new possible profit is greater\n      if (possibleProfit > maxProfit[size]) {\n        maxProfit[size] = possibleProfit;\n        dividingPoints[size] = dividingPoint;\n      }\n    }\n  }\n\n  const solution = [];\n  let currentDividingPoint = numSizes - 1;\n  // Reconstruct the solution by tracing back from the end\n  // using the dividing points information\n  while (currentDividingPoint > 0) {\n    solution.push(dividingPoints[currentDividingPoint]);\n    currentDividingPoint -= dividingPoints[currentDividingPoint];\n  }\n  return solution;\n}\n\n// Example usage:\nconst prices = [3, 5, 8, 9, 10, 17, 17, 20];\nconst result = juiceBottling(prices);\nconsole.log(\"Dividing Points for Maximum Profit:\", result);\n"
  },
  {
    "path": "Dynamic Programming/juice_bottling.py",
    "content": "'''\nExplanation:\n\n1. The function `JuiceBottling` takes an array `prices` as input, where `prices[i]` represents the price of a juice bottle of size `i`.\n\n2. It initializes two arrays, `maxProfit` and `dividingPoints`, both of size `numSizes` (the number of bottle sizes).\nThese arrays will be used to store information about maximum profit and dividing points.\n\n3. The outer loop iterates through each possible bottle size, from 0 to `numSizes - 1`.\n\n4. The inner loop iterates through possible dividing points for the current bottle size. For each combination of bottle size\nand dividing point, it calculates the possible profit by adding the maximum profit from the previous bottle sizes and the\nprice of the bottle at the current dividing point.\n\n5. If the calculated possible profit is greater than the current maximum profit for the bottle size, it updates both `maxProfit`\nand `dividingPoints` arrays.\n\n6. After completing the loops, the function reconstructs the solution by backtracking from the last bottle size to the first.\nIt appends the recorded dividing points to the `solution` array, which represents the optimal way to divide the bottles.\n\n7. The function returns the `solution` array, which contains the indices of the dividing points that maximize profit.\n\nIn summary, the code uses dynamic programming to determine the optimal division of juice bottles to maximize profit.\nIt calculates the maximum profit for each bottle size and keeps track of the dividing points that lead to the maximum profit.\nThe solution is then reconstructed by backtracking from the end using the recorded dividing points.\n\n'''\ndef juice_bottling(prices):\n    num_sizes = len(prices)\n    max_profit = [0] * num_sizes         # List to store the maximum profit for each bottle size\n    dividing_points = [0] * num_sizes    # List to store the dividing points that maximize profit\n\n    # Loop through each bottle size\n    for size in range(num_sizes):\n        # Loop through possible dividing points for the current size\n        for dividing_point in range(size + 1):\n            # Calculate the possible profit by combining the previous maximum profit\n            # with the price at the current dividing point\n            possible_profit = max_profit[size - dividing_point] + prices[dividing_point]\n\n            # Update max_profit and dividing_points if the new possible profit is greater\n            if possible_profit > max_profit[size]:\n                max_profit[size] = possible_profit\n                dividing_points[size] = dividing_point\n\n    solution = []\n    current_dividing_point = num_sizes - 1\n    # Reconstruct the solution by tracing back from the end\n    # using the dividing points information\n    while current_dividing_point > 0:\n        solution.append(dividing_points[current_dividing_point])\n        current_dividing_point -= dividing_points[current_dividing_point]\n    return solution\n\n# Example usage:\nprices = [3, 5, 8, 9, 10, 17, 17, 20]\nresult = juice_bottling(prices)\nprint(\"Dividing Points for Maximum Profit:\", result)\n"
  },
  {
    "path": "Dynamic Programming/knapsack.cpp",
    "content": "/*\n\tYou're given an array of arrays where each subarray holds two integer values and represents an item;\n\tthe first integer is the item's value, and the second integer is the item's weight.\n\tYou're also given an integer representing the maximum capacity of a knapsack that you have.\n\n\tYour goal is to fit items in your knapsack without having the sum of their weights exceed the knapsack's\n\tcapacity, all the while maximizing their combined value. Note that you only have one of each item at your disposal.\n\n\tWrite a function that returns the maximized combined value of the items that you should pick as well as an array of\n\tthe indices of each item picked.\n\n\tSample Input:= [[1, 2], [4, 3], [5, 6], [6, 7]]\n\tOutput:= [10, [1, 3]] // items [4, 3] and [6, 7]\n\n\tExplanation:\n\n\tSure! Let's break down the code step by step:\n\n\t1. `KnapsackProblem` function: This function takes in two arguments - `items`, a 2D slice representing the\n\t   list of items with their values and weights, and `capacity`, an integer representing the maximum weight\n\t   capacity of the knapsack. It returns an interface slice containing the maximum value that can be achieved\n\t   and the sequence of items included in the knapsack to achieve that maximum value.\n\n\t2. Initializing the `values` array: The function creates a 2D slice called `values` to store the maximum\n\t   achievable values for different knapsack configurations. The size of this array is `(len(items)+1) x (capacity+1)`,\n\t   where `(len(items)+1)` represents the number of items, and `(capacity+1)` represents the weight capacity of the knapsack.\n\t   The `values` array will be filled during the dynamic programming process.\n\n\t3. Filling the `values` array: The function iterates through the `items` array and fills the `values`\n\t   array using dynamic programming. For each item at index `i`, the function calculates the maximum achievable\n\t   value for all possible capacities from `0` to `capacity`.\n\n\t4. Inner loop: The inner loop iterates from `0` to `capacity` and calculates the maximum achievable value for\n\t   the current item at index `i` and the current capacity `c`.\n\n\t5. Updating the `values` array: There are two possibilities for each item:\n\t\ta. If the weight of the current item `items[i-1][1]` is greater than the current capacity `c`, we cannot\n\t\t   include the item in the knapsack at this capacity. So, we use the value from the previous row `values[i-1][c]`\n\t\t   for the current cell `values[i][c]`.\n\t\tb. If we can include the current item, we have two choices:\n\t\t\ti. Not include the current item, so the value remains the same as in the previous row `values[i-1][c]`.\n\t\t\tii. Include the current item, which adds its value `items[i-1][0]` to the value of the knapsack at capacity `c - items[i-1][1]`.\n\t\t\t    We choose the maximum of these two options and update the current cell `values[i][c]`.\n\n\t6. Finding the maximum value: Once the `values` array is filled, the maximum achievable value for the knapsack is stored in the\n\tbottom-right cell `values[len(items)][capacity]`.\n\n\t7. Calling `getKnapSackItems` function: The function calls the `getKnapSackItems` function to find the sequence of items included in\n\tthe knapsack to achieve the maximum value.\n\n\t8. `getKnapSackItems` function: This function takes in the `values` array and the `items` array as input and returns a slice containing\n\tthe indices of the items included in the knapsack.\n\n\t9. Traversing back to find the items: Starting from the bottom-right cell of the `values` array, the function traverses back to find the\n\titems included in the knapsack. It does this by comparing the value in the current cell `values[i][c]` with the value in the cell above\n\t`values[i-1][c]`. If the values are the same, it means the current item was not included, so it moves to the previous row. Otherwise,\n\tit means the current item was included, so it adds the index of the current item `(i-1)` to the `sequence` slice and updates the capacity `c` accordingly.\n\n\t10. Reversing the `sequence`: The sequence of items is built in reverse order, so the function uses the `reverse` helper function to\n\treverse the order of elements in the `sequence` slice.\n\n\t11. Returning the result: The function returns the maximum value and the sequence of items included in the knapsack as an interface slice.\n\n\t12. Helper functions: The `max` function is a simple helper function that returns the maximum of two integers, and the `reverse`\n\tfunction is used to reverse the order of elements in a slice.\n\n\tTime and Space complexity:\n\tO(nc) time | O(nc) space - where n is the number of items and c is the capacity\n*/\n#include <vector>\n#include <algorithm>\n\nusing namespace std;\n\nvector<int> knapsackProblem(vector<vector<int>>& items, int capacity) {\n    // Create a 2D vector to store the values of different knapsack configurations.\n    vector<vector<int>> values(items.size() + 1, vector<int>(capacity + 1, 0));\n\n    // Iterate through the items and fill the values vector.\n    for (int i = 1; i <= items.size(); i++) {\n        int currentValue = items[i - 1][0];\n        int currentWeight = items[i - 1][1];\n\n        for (int c = 0; c <= capacity; c++) {\n            // If the current item's weight is more than the current capacity (c),\n            // then we cannot include it, so we use the value from the previous row (i - 1).\n            if (currentWeight > c) {\n                values[i][c] = values[i - 1][c];\n            } else {\n                // If we can include the current item, we have two choices:\n                // 1. Not include the current item, so the value remains the same as the previous row.\n                // 2. Include the current item, which adds its value to the value of the knapsack at capacity (c - currentWeight).\n                // We choose the maximum of these two options.\n                values[i][c] = max(values[i - 1][c], values[i - 1][c - currentWeight] + currentValue);\n            }\n        }\n    }\n\n    // The value at the bottom-right corner of the values vector represents the maximum achievable value for the knapsack problem.\n    int value = values[items.size()][capacity];\n\n    // Call the getKnapSackItems function to find the items that were included in the knapsack to achieve the maximum value.\n    vector<int> sequence = getKnapSackItems(values, items);\n\n    // Return the maximum value and the sequence of items included in the knapsack.\n    vector<int> result = {value};\n    result.insert(result.end(), sequence.begin(), sequence.end());\n    return result;\n}\n\n// getKnapSackItems is a helper function to find the sequence of items included in the knapsack.\nvector<int> getKnapSackItems(vector<vector<int>>& values, vector<vector<int>>& items) {\n    vector<int> sequence;\n    int i = values.size() - 1;\n    int c = values[0].size() - 1;\n\n    // Starting from the bottom-right corner of the values vector,\n    // we traverse back to find the items included in the knapsack.\n    while (i > 0) {\n        if (values[i][c] == values[i - 1][c]) {\n            // If the value is the same as in the previous row, it means the current item was not included.\n            // So, we move to the previous row without adding the item to the sequence.\n            i--;\n        } else {\n            // If the value is greater than the value in the previous row, it means the current item was included.\n            // So, we add the index of the current item (i-1) to the sequence and update the capacity (c) accordingly.\n            sequence.push_back(i - 1);\n            c -= items[i - 1][1];\n            i--;\n        }\n        // If the capacity becomes 0, it means we have included all the items needed to achieve the maximum value.\n        if (c == 0) {\n            break;\n        }\n    }\n\n    // The sequence of items is built in reverse order, so we need to reverse it to get the correct order.\n    reverse(sequence.begin(), sequence.end());\n    return sequence;\n}\n"
  },
  {
    "path": "Dynamic Programming/knapsack.go",
    "content": "/*\n\tYou're given an array of arrays where each subarray holds two integer values and represents an item;\n\tthe first integer is the item's value, and the second integer is the item's weight.\n\tYou're also given an integer representing the maximum capacity of a knapsack that you have.\n\n\tYour goal is to fit items in your knapsack without having the sum of their weights exceed the knapsack's\n\tcapacity, all the while maximizing their combined value. Note that you only have one of each item at your disposal.\n\n\tWrite a function that returns the maximized combined value of the items that you should pick as well as an array of\n\tthe indices of each item picked.\n\n\tSample Input:= [[1, 2], [4, 3], [5, 6], [6, 7]]\n\tOutput:= [10, [1, 3]] // items [4, 3] and [6, 7]\n\n\tExplanation:\n\n\tSure! Let's break down the code step by step:\n\n\t1. `KnapsackProblem` function: This function takes in two arguments - `items`, a 2D slice representing the\n\t   list of items with their values and weights, and `capacity`, an integer representing the maximum weight\n\t   capacity of the knapsack. It returns an interface slice containing the maximum value that can be achieved\n\t   and the sequence of items included in the knapsack to achieve that maximum value.\n\n\t2. Initializing the `values` array: The function creates a 2D slice called `values` to store the maximum\n\t   achievable values for different knapsack configurations. The size of this array is `(len(items)+1) x (capacity+1)`,\n\t   where `(len(items)+1)` represents the number of items, and `(capacity+1)` represents the weight capacity of the knapsack.\n\t   The `values` array will be filled during the dynamic programming process.\n\n\t3. Filling the `values` array: The function iterates through the `items` array and fills the `values`\n\t   array using dynamic programming. For each item at index `i`, the function calculates the maximum achievable\n\t   value for all possible capacities from `0` to `capacity`.\n\n\t4. Inner loop: The inner loop iterates from `0` to `capacity` and calculates the maximum achievable value for\n\t   the current item at index `i` and the current capacity `c`.\n\n\t5. Updating the `values` array: There are two possibilities for each item:\n\t\ta. If the weight of the current item `items[i-1][1]` is greater than the current capacity `c`, we cannot\n\t\t   include the item in the knapsack at this capacity. So, we use the value from the previous row `values[i-1][c]`\n\t\t   for the current cell `values[i][c]`.\n\t\tb. If we can include the current item, we have two choices:\n\t\t\ti. Not include the current item, so the value remains the same as in the previous row `values[i-1][c]`.\n\t\t\tii. Include the current item, which adds its value `items[i-1][0]` to the value of the knapsack at capacity `c - items[i-1][1]`.\n\t\t\t    We choose the maximum of these two options and update the current cell `values[i][c]`.\n\n\t6. Finding the maximum value: Once the `values` array is filled, the maximum achievable value for the knapsack is stored in the\n\tbottom-right cell `values[len(items)][capacity]`.\n\n\t7. Calling `getKnapSackItems` function: The function calls the `getKnapSackItems` function to find the sequence of items included in\n\tthe knapsack to achieve the maximum value.\n\n\t8. `getKnapSackItems` function: This function takes in the `values` array and the `items` array as input and returns a slice containing\n\tthe indices of the items included in the knapsack.\n\n\t9. Traversing back to find the items: Starting from the bottom-right cell of the `values` array, the function traverses back to find the\n\titems included in the knapsack. It does this by comparing the value in the current cell `values[i][c]` with the value in the cell above\n\t`values[i-1][c]`. If the values are the same, it means the current item was not included, so it moves to the previous row. Otherwise,\n\tit means the current item was included, so it adds the index of the current item `(i-1)` to the `sequence` slice and updates the capacity `c` accordingly.\n\n\t10. Reversing the `sequence`: The sequence of items is built in reverse order, so the function uses the `reverse` helper function to\n\treverse the order of elements in the `sequence` slice.\n\n\t11. Returning the result: The function returns the maximum value and the sequence of items included in the knapsack as an interface slice.\n\n\t12. Helper functions: The `max` function is a simple helper function that returns the maximum of two integers, and the `reverse`\n\tfunction is used to reverse the order of elements in a slice.\n\n\tTime and Space complexity:\n\tO(nc) time | O(nc) space - where n is the number of items and c is the capacity\n*/\npackage main\n\nfunc KnapsackProblem(items [][]int, capacity int) []interface{} {\n\t// Create a 2D array to store the values of different knapsack configurations.\n\tvalues := make([][]int, len(items)+1)\n\tfor i := range values {\n\t\tvalues[i] = make([]int, capacity+1)\n\t}\n\n\t// Iterate through the items and fill the values array.\n\tfor i := 1; i < len(items)+1; i++ {\n\t\tcurrentValue := items[i-1][0]\n\t\tcurrentWeight := items[i-1][1]\n\n\t\tfor c := 0; c < capacity+1; c++ {\n\t\t\t// If the current item's weight is more than the current capacity (c),\n\t\t\t// then we cannot include it, so we use the value from the previous row (i - 1).\n\t\t\tif currentWeight > c {\n\t\t\t\tvalues[i][c] = values[i-1][c]\n\t\t\t} else {\n\t\t\t\t// If we can include the current item, we have two choices:\n\t\t\t\t// 1. Not include the current item, so the value remains the same as the previous row.\n\t\t\t\t// 2. Include the current item, which adds its value to the value of the knapsack at capacity (c - currentWeight).\n\t\t\t\t// We choose the maximum of these two options.\n\t\t\t\tvalues[i][c] = max(values[i-1][c], values[i-1][c-currentWeight]+currentValue)\n\t\t\t}\n\t\t}\n\t}\n\n\t// The value at the bottom-right corner of the values array represents the maximum achievable value for the knapsack problem.\n\tvalue := values[len(items)][capacity]\n\n\t// Call the getKnapSackItems function to find the items that were included in the knapsack to achieve the maximum value.\n\tsequence := getKnapSackItems(values, items)\n\n\t// Return the maximum value and the sequence of items included in the knapsack as an interface slice.\n\treturn []interface{}{value, sequence}\n}\n\n// getKnapSackItems is a helper function to find the sequence of items included in the knapsack.\nfunc getKnapSackItems(values [][]int, items [][]int) []int {\n\tsequence := []int{}\n\ti, c := len(values)-1, len(values[0])-1\n\n\t// Starting from the bottom-right corner of the values array,\n\t// we traverse back to find the items included in the knapsack.\n\tfor i > 0 {\n\t\tif values[i][c] == values[i-1][c] {\n\t\t\t// If the value is the same as in the previous row, it means the current item was not included.\n\t\t\t// So, we move to the previous row without adding the item to the sequence.\n\t\t\ti--\n\t\t} else {\n\t\t\t// If the value is greater than the value in the previous row, it means the current item was included.\n\t\t\t// So, we add the index of the current item (i-1) to the sequence and update the capacity (c) accordingly.\n\t\t\tsequence = append(sequence, i-1)\n\t\t\tc -= items[i-1][1]\n\t\t\ti--\n\t\t}\n\t\t// If the capacity becomes 0, it means we have included all the items needed to achieve the maximum value.\n\t\tif c == 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// The sequence of items is built in reverse order, so we need to reverse it to get the correct order.\n\treverse(sequence)\n\treturn sequence\n}\n\n// max returns the maximum of two integers.\nfunc max(a, b int) int {\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n\n// reverse reverses the order of elements in the given slice.\nfunc reverse(numbers []int) {\n\tfor i, j := 0, len(numbers)-1; i < j; i, j = i+1, j-1 {\n\t\tnumbers[i], numbers[j] = numbers[j], numbers[i]\n\t}\n}\n"
  },
  {
    "path": "Dynamic Programming/knapsack.java",
    "content": "/*\n\tYou're given an array of arrays where each subarray holds two integer values and represents an item;\n\tthe first integer is the item's value, and the second integer is the item's weight.\n\tYou're also given an integer representing the maximum capacity of a knapsack that you have.\n\n\tYour goal is to fit items in your knapsack without having the sum of their weights exceed the knapsack's\n\tcapacity, all the while maximizing their combined value. Note that you only have one of each item at your disposal.\n\n\tWrite a function that returns the maximized combined value of the items that you should pick as well as an array of\n\tthe indices of each item picked.\n\n\tSample Input:= [[1, 2], [4, 3], [5, 6], [6, 7]]\n\tOutput:= [10, [1, 3]] // items [4, 3] and [6, 7]\n\n\tExplanation:\n\n\tSure! Let's break down the code step by step:\n\n\t1. `KnapsackProblem` function: This function takes in two arguments - `items`, a 2D slice representing the\n\t   list of items with their values and weights, and `capacity`, an integer representing the maximum weight\n\t   capacity of the knapsack. It returns an interface slice containing the maximum value that can be achieved\n\t   and the sequence of items included in the knapsack to achieve that maximum value.\n\n\t2. Initializing the `values` array: The function creates a 2D slice called `values` to store the maximum\n\t   achievable values for different knapsack configurations. The size of this array is `(len(items)+1) x (capacity+1)`,\n\t   where `(len(items)+1)` represents the number of items, and `(capacity+1)` represents the weight capacity of the knapsack.\n\t   The `values` array will be filled during the dynamic programming process.\n\n\t3. Filling the `values` array: The function iterates through the `items` array and fills the `values`\n\t   array using dynamic programming. For each item at index `i`, the function calculates the maximum achievable\n\t   value for all possible capacities from `0` to `capacity`.\n\n\t4. Inner loop: The inner loop iterates from `0` to `capacity` and calculates the maximum achievable value for\n\t   the current item at index `i` and the current capacity `c`.\n\n\t5. Updating the `values` array: There are two possibilities for each item:\n\t\ta. If the weight of the current item `items[i-1][1]` is greater than the current capacity `c`, we cannot\n\t\t   include the item in the knapsack at this capacity. So, we use the value from the previous row `values[i-1][c]`\n\t\t   for the current cell `values[i][c]`.\n\t\tb. If we can include the current item, we have two choices:\n\t\t\ti. Not include the current item, so the value remains the same as in the previous row `values[i-1][c]`.\n\t\t\tii. Include the current item, which adds its value `items[i-1][0]` to the value of the knapsack at capacity `c - items[i-1][1]`.\n\t\t\t    We choose the maximum of these two options and update the current cell `values[i][c]`.\n\n\t6. Finding the maximum value: Once the `values` array is filled, the maximum achievable value for the knapsack is stored in the\n\tbottom-right cell `values[len(items)][capacity]`.\n\n\t7. Calling `getKnapSackItems` function: The function calls the `getKnapSackItems` function to find the sequence of items included in\n\tthe knapsack to achieve the maximum value.\n\n\t8. `getKnapSackItems` function: This function takes in the `values` array and the `items` array as input and returns a slice containing\n\tthe indices of the items included in the knapsack.\n\n\t9. Traversing back to find the items: Starting from the bottom-right cell of the `values` array, the function traverses back to find the\n\titems included in the knapsack. It does this by comparing the value in the current cell `values[i][c]` with the value in the cell above\n\t`values[i-1][c]`. If the values are the same, it means the current item was not included, so it moves to the previous row. Otherwise,\n\tit means the current item was included, so it adds the index of the current item `(i-1)` to the `sequence` slice and updates the capacity `c` accordingly.\n\n\t10. Reversing the `sequence`: The sequence of items is built in reverse order, so the function uses the `reverse` helper function to\n\treverse the order of elements in the `sequence` slice.\n\n\t11. Returning the result: The function returns the maximum value and the sequence of items included in the knapsack as an interface slice.\n\n\t12. Helper functions: The `max` function is a simple helper function that returns the maximum of two integers, and the `reverse`\n\tfunction is used to reverse the order of elements in a slice.\n\n\tTime and Space complexity:\n\tO(nc) time | O(nc) space - where n is the number of items and c is the capacity\n*/\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class KnapsackProblem {\n    public static List<Object> knapsackProblem(int[][] items, int capacity) {\n        // Create a 2D array to store the values of different knapsack configurations.\n        int[][] values = new int[items.length + 1][capacity + 1];\n\n        // Iterate through the items and fill the values array.\n        for (int i = 1; i <= items.length; i++) {\n            int currentValue = items[i - 1][0];\n            int currentWeight = items[i - 1][1];\n\n            for (int c = 0; c <= capacity; c++) {\n                // If the current item's weight is more than the current capacity (c),\n                // then we cannot include it, so we use the value from the previous row (i - 1).\n                if (currentWeight > c) {\n                    values[i][c] = values[i - 1][c];\n                } else {\n                    // If we can include the current item, we have two choices:\n                    // 1. Not include the current item, so the value remains the same as the previous row.\n                    // 2. Include the current item, which adds its value to the value of the knapsack at capacity (c - currentWeight).\n                    // We choose the maximum of these two options.\n                    values[i][c] = Math.max(values[i - 1][c], values[i - 1][c - currentWeight] + currentValue);\n                }\n            }\n        }\n\n        // The value at the bottom-right corner of the values array represents the maximum achievable value for the knapsack problem.\n        int value = values[items.length][capacity];\n\n        // Call the getKnapSackItems function to find the items that were included in the knapsack to achieve the maximum value.\n        List<Integer> sequence = getKnapSackItems(values, items);\n\n        // Return the maximum value and the sequence of items included in the knapsack as a list of objects.\n        List<Object> result = new ArrayList<>();\n        result.add(value);\n        result.add(sequence);\n        return result;\n    }\n\n    // getKnapSackItems is a helper function to find the sequence of items included in the knapsack.\n    private static List<Integer> getKnapSackItems(int[][] values, int[][] items) {\n        List<Integer> sequence = new ArrayList<>();\n        int i = values.length - 1;\n        int c = values[0].length - 1;\n\n        // Starting from the bottom-right corner of the values array,\n        // we traverse back to find the items included in the knapsack.\n        while (i > 0) {\n            if (values[i][c] == values[i - 1][c]) {\n                // If the value is the same as in the previous row, it means the current item was not included.\n                // So, we move to the previous row without adding the item to the sequence.\n                i--;\n            } else {\n                // If the value is greater than the value in the previous row, it means the current item was included.\n                // So, we add the index of the current item (i-1) to the sequence and update the capacity (c) accordingly.\n                sequence.add(i - 1);\n                c -= items[i - 1][1];\n                i--;\n            }\n            // If the capacity becomes 0, it means we have included all the items needed to achieve the maximum value.\n            if (c == 0) {\n                break;\n            }\n        }\n\n        // The sequence of items is built in reverse order, so we need to reverse it to get the correct order.\n        reverseList(sequence);\n        return sequence;\n    }\n\n    // max returns the maximum of two integers.\n    private static int max(int a, int b) {\n        return Math.max(a, b);\n    }\n\n    // reverseList reverses the order of elements in the given list.\n    private static void reverseList(List<Integer> list) {\n        int left = 0;\n        int right = list.size() - 1;\n        while (left < right) {\n            int temp = list.get(left);\n            list.set(left, list.get(right));\n            list.set(right, temp);\n            left++;\n            right--;\n        }\n    }\n}\n"
  },
  {
    "path": "Dynamic Programming/knapsack.js",
    "content": "/*\n\tYou're given an array of arrays where each subarray holds two integer values and represents an item;\n\tthe first integer is the item's value, and the second integer is the item's weight.\n\tYou're also given an integer representing the maximum capacity of a knapsack that you have.\n\n\tYour goal is to fit items in your knapsack without having the sum of their weights exceed the knapsack's\n\tcapacity, all the while maximizing their combined value. Note that you only have one of each item at your disposal.\n\n\tWrite a function that returns the maximized combined value of the items that you should pick as well as an array of\n\tthe indices of each item picked.\n\n\tSample Input:= [[1, 2], [4, 3], [5, 6], [6, 7]]\n\tOutput:= [10, [1, 3]] // items [4, 3] and [6, 7]\n\n\tExplanation:\n\n\tSure! Let's break down the code step by step:\n\n\t1. `KnapsackProblem` function: This function takes in two arguments - `items`, a 2D slice representing the\n\t   list of items with their values and weights, and `capacity`, an integer representing the maximum weight\n\t   capacity of the knapsack. It returns an interface slice containing the maximum value that can be achieved\n\t   and the sequence of items included in the knapsack to achieve that maximum value.\n\n\t2. Initializing the `values` array: The function creates a 2D slice called `values` to store the maximum\n\t   achievable values for different knapsack configurations. The size of this array is `(len(items)+1) x (capacity+1)`,\n\t   where `(len(items)+1)` represents the number of items, and `(capacity+1)` represents the weight capacity of the knapsack.\n\t   The `values` array will be filled during the dynamic programming process.\n\n\t3. Filling the `values` array: The function iterates through the `items` array and fills the `values`\n\t   array using dynamic programming. For each item at index `i`, the function calculates the maximum achievable\n\t   value for all possible capacities from `0` to `capacity`.\n\n\t4. Inner loop: The inner loop iterates from `0` to `capacity` and calculates the maximum achievable value for\n\t   the current item at index `i` and the current capacity `c`.\n\n\t5. Updating the `values` array: There are two possibilities for each item:\n\t\ta. If the weight of the current item `items[i-1][1]` is greater than the current capacity `c`, we cannot\n\t\t   include the item in the knapsack at this capacity. So, we use the value from the previous row `values[i-1][c]`\n\t\t   for the current cell `values[i][c]`.\n\t\tb. If we can include the current item, we have two choices:\n\t\t\ti. Not include the current item, so the value remains the same as in the previous row `values[i-1][c]`.\n\t\t\tii. Include the current item, which adds its value `items[i-1][0]` to the value of the knapsack at capacity `c - items[i-1][1]`.\n\t\t\t    We choose the maximum of these two options and update the current cell `values[i][c]`.\n\n\t6. Finding the maximum value: Once the `values` array is filled, the maximum achievable value for the knapsack is stored in the\n\tbottom-right cell `values[len(items)][capacity]`.\n\n\t7. Calling `getKnapSackItems` function: The function calls the `getKnapSackItems` function to find the sequence of items included in\n\tthe knapsack to achieve the maximum value.\n\n\t8. `getKnapSackItems` function: This function takes in the `values` array and the `items` array as input and returns a slice containing\n\tthe indices of the items included in the knapsack.\n\n\t9. Traversing back to find the items: Starting from the bottom-right cell of the `values` array, the function traverses back to find the\n\titems included in the knapsack. It does this by comparing the value in the current cell `values[i][c]` with the value in the cell above\n\t`values[i-1][c]`. If the values are the same, it means the current item was not included, so it moves to the previous row. Otherwise,\n\tit means the current item was included, so it adds the index of the current item `(i-1)` to the `sequence` slice and updates the capacity `c` accordingly.\n\n\t10. Reversing the `sequence`: The sequence of items is built in reverse order, so the function uses the `reverse` helper function to\n\treverse the order of elements in the `sequence` slice.\n\n\t11. Returning the result: The function returns the maximum value and the sequence of items included in the knapsack as an interface slice.\n\n\t12. Helper functions: The `max` function is a simple helper function that returns the maximum of two integers, and the `reverse`\n\tfunction is used to reverse the order of elements in a slice.\n\n\tTime and Space complexity:\n\tO(nc) time | O(nc) space - where n is the number of items and c is the capacity\n*/\nfunction KnapsackProblem(items, capacity) {\n  // Create a 2D array to store the values of different knapsack configurations.\n  const values = new Array(items.length + 1)\n    .fill(0)\n    .map(() => new Array(capacity + 1).fill(0));\n\n  // Iterate through the items and fill the values array.\n  for (let i = 1; i < items.length + 1; i++) {\n    const currentValue = items[i - 1][0];\n    const currentWeight = items[i - 1][1];\n\n    for (let c = 0; c < capacity + 1; c++) {\n      // If the current item's weight is more than the current capacity (c),\n      // then we cannot include it, so we use the value from the previous row (i - 1).\n      if (currentWeight > c) {\n        values[i][c] = values[i - 1][c];\n      } else {\n        // If we can include the current item, we have two choices:\n        // 1. Not include the current item, so the value remains the same as the previous row.\n        // 2. Include the current item, which adds its value to the value of the knapsack at capacity (c - currentWeight).\n        // We choose the maximum of these two options.\n        values[i][c] = Math.max(\n          values[i - 1][c],\n          values[i - 1][c - currentWeight] + currentValue\n        );\n      }\n    }\n  }\n\n  // The value at the bottom-right corner of the values array represents the maximum achievable value for the knapsack problem.\n  const value = values[items.length][capacity];\n\n  // Call the getKnapSackItems function to find the items that were included in the knapsack to achieve the maximum value.\n  const sequence = getKnapSackItems(values, items);\n\n  // Return the maximum value and the sequence of items included in the knapsack as an array.\n  return [value, sequence];\n}\n\n// getKnapSackItems is a helper function to find the sequence of items included in the knapsack.\nfunction getKnapSackItems(values, items) {\n  const sequence = [];\n  let i = values.length - 1;\n  let c = values[0].length - 1;\n\n  // Starting from the bottom-right corner of the values array,\n  // we traverse back to find the items included in the knapsack.\n  while (i > 0) {\n    if (values[i][c] == values[i - 1][c]) {\n      // If the value is the same as in the previous row, it means the current item was not included.\n      // So, we move to the previous row without adding the item to the sequence.\n      i--;\n    } else {\n      // If the value is greater than the value in the previous row, it means the current item was included.\n      // So, we add the index of the current item (i-1) to the sequence and update the capacity (c) accordingly.\n      sequence.push(i - 1);\n      c -= items[i - 1][1];\n      i--;\n    }\n    // If the capacity becomes 0, it means we have included all the items needed to achieve the maximum value.\n    if (c == 0) {\n      break;\n    }\n  }\n\n  // Reverse the sequence of items to get the correct order.\n  sequence.reverse();\n  return sequence;\n}\n\n// max returns the maximum of two integers.\nfunction max(a, b) {\n  return a > b ? a : b;\n}\n"
  },
  {
    "path": "Dynamic Programming/knapsack.py",
    "content": "'''\n\tYou're given an array of arrays where each subarray holds two integer values and represents an item;\n\tthe first integer is the item's value, and the second integer is the item's weight.\n\tYou're also given an integer representing the maximum capacity of a knapsack that you have.\n\n\tYour goal is to fit items in your knapsack without having the sum of their weights exceed the knapsack's\n\tcapacity, all the while maximizing their combined value. Note that you only have one of each item at your disposal.\n\n\tWrite a function that returns the maximized combined value of the items that you should pick as well as an array of\n\tthe indices of each item picked.\n\n\tSample Input:= [[1, 2], [4, 3], [5, 6], [6, 7]]\n\tOutput:= [10, [1, 3]] // items [4, 3] and [6, 7]\n\n\tExplanation:\n\n\tSure! Let's break down the code step by step:\n\n\t1. `KnapsackProblem` function: This function takes in two arguments - `items`, a 2D slice representing the\n\t   list of items with their values and weights, and `capacity`, an integer representing the maximum weight\n\t   capacity of the knapsack. It returns an interface slice containing the maximum value that can be achieved\n\t   and the sequence of items included in the knapsack to achieve that maximum value.\n\n\t2. Initializing the `values` array: The function creates a 2D slice called `values` to store the maximum\n\t   achievable values for different knapsack configurations. The size of this array is `(len(items)+1) x (capacity+1)`,\n\t   where `(len(items)+1)` represents the number of items, and `(capacity+1)` represents the weight capacity of the knapsack.\n\t   The `values` array will be filled during the dynamic programming process.\n\n\t3. Filling the `values` array: The function iterates through the `items` array and fills the `values`\n\t   array using dynamic programming. For each item at index `i`, the function calculates the maximum achievable\n\t   value for all possible capacities from `0` to `capacity`.\n\n\t4. Inner loop: The inner loop iterates from `0` to `capacity` and calculates the maximum achievable value for\n\t   the current item at index `i` and the current capacity `c`.\n\n\t5. Updating the `values` array: There are two possibilities for each item:\n\t\ta. If the weight of the current item `items[i-1][1]` is greater than the current capacity `c`, we cannot\n\t\t   include the item in the knapsack at this capacity. So, we use the value from the previous row `values[i-1][c]`\n\t\t   for the current cell `values[i][c]`.\n\t\tb. If we can include the current item, we have two choices:\n\t\t\ti. Not include the current item, so the value remains the same as in the previous row `values[i-1][c]`.\n\t\t\tii. Include the current item, which adds its value `items[i-1][0]` to the value of the knapsack at capacity `c - items[i-1][1]`.\n\t\t\t    We choose the maximum of these two options and update the current cell `values[i][c]`.\n\n\t6. Finding the maximum value: Once the `values` array is filled, the maximum achievable value for the knapsack is stored in the\n\tbottom-right cell `values[len(items)][capacity]`.\n\n\t7. Calling `getKnapSackItems` function: The function calls the `getKnapSackItems` function to find the sequence of items included in\n\tthe knapsack to achieve the maximum value.\n\n\t8. `getKnapSackItems` function: This function takes in the `values` array and the `items` array as input and returns a slice containing\n\tthe indices of the items included in the knapsack.\n\n\t9. Traversing back to find the items: Starting from the bottom-right cell of the `values` array, the function traverses back to find the\n\titems included in the knapsack. It does this by comparing the value in the current cell `values[i][c]` with the value in the cell above\n\t`values[i-1][c]`. If the values are the same, it means the current item was not included, so it moves to the previous row. Otherwise,\n\tit means the current item was included, so it adds the index of the current item `(i-1)` to the `sequence` slice and updates the capacity `c` accordingly.\n\n\t10. Reversing the `sequence`: The sequence of items is built in reverse order, so the function uses the `reverse` helper function to\n\treverse the order of elements in the `sequence` slice.\n\n\t11. Returning the result: The function returns the maximum value and the sequence of items included in the knapsack as an interface slice.\n\n\t12. Helper functions: The `max` function is a simple helper function that returns the maximum of two integers, and the `reverse`\n\tfunction is used to reverse the order of elements in a slice.\n\n\tTime and Space complexity:\n\tO(nc) time | O(nc) space - where n is the number of items and c is the capacity\n'''\ndef knapsack_problem(items, capacity):\n    # Create a 2D list to store the values of different knapsack configurations.\n    values = [[0] * (capacity + 1) for _ in range(len(items) + 1)]\n\n    # Iterate through the items and fill the values list.\n    for i in range(1, len(items) + 1):\n        current_value = items[i - 1][0]\n        current_weight = items[i - 1][1]\n\n        for c in range(capacity + 1):\n            # If the current item's weight is more than the current capacity (c),\n            # then we cannot include it, so we use the value from the previous row (i - 1).\n            if current_weight > c:\n                values[i][c] = values[i - 1][c]\n            else:\n                # If we can include the current item, we have two choices:\n                # 1. Not include the current item, so the value remains the same as the previous row.\n                # 2. Include the current item, which adds its value to the value of the knapsack at capacity (c - current_weight).\n                # We choose the maximum of these two options.\n                values[i][c] = max(values[i - 1][c], values[i - 1][c - current_weight] + current_value)\n\n    # The value at the bottom-right corner of the values list represents the maximum achievable value for the knapsack problem.\n    value = values[len(items)][capacity]\n\n    # Call the get_knapsack_items function to find the items that were included in the knapsack to achieve the maximum value.\n    sequence = get_knapsack_items(values, items)\n\n    # Return the maximum value and the sequence of items included in the knapsack.\n    return [value] + sequence\n\n# get_knapsack_items is a helper function to find the sequence of items included in the knapsack.\ndef get_knapsack_items(values, items):\n    sequence = []\n    i = len(values) - 1\n    c = len(values[0]) - 1\n\n    # Starting from the bottom-right corner of the values list,\n    # we traverse back to find the items included in the knapsack.\n    while i > 0:\n        if values[i][c] == values[i - 1][c]:\n            # If the value is the same as in the previous row, it means the current item was not included.\n            # So, we move to the previous row without adding the item to the sequence.\n            i -= 1\n        else:\n            # If the value is greater than the value in the previous row, it means the current item was included.\n            # So, we add the index of the current item (i-1) to the sequence and update the capacity (c) accordingly.\n            sequence.append(i - 1)\n            c -= items[i - 1][1]\n            i -= 1\n        # If the capacity becomes 0, it means we have included all the items needed to achieve the maximum value.\n        if c == 0:\n            break\n\n    # The sequence of items is built in reverse order, so we need to reverse it to get the correct order.\n    sequence.reverse()\n    return sequence\n"
  },
  {
    "path": "Dynamic Programming/knight_probability_chessboard.cpp",
    "content": "/*\nOn an n x n chessboard, a knight starts at the cell (row, column) and attempts to make exactly k moves. The rows and columns are 0-indexed, so the top-left cell is (0, 0), and the bottom-right cell is (n - 1, n - 1).\n\nA chess knight has eight possible moves it can make, as illustrated below. Each move is two cells in a cardinal direction, then one cell in an orthogonal direction.\n\n\nEach time the knight is to move, it chooses one of eight possible moves uniformly at random (even if the piece would go off the chessboard) and moves there.\n\nThe knight continues moving until it has made exactly k moves or has moved off the chessboard.\n\nReturn the probability that the knight remains on the board after it has stopped moving.\n\n \n\nExample 1:\n\nInput: n = 3, k = 2, row = 0, column = 0\nOutput: 0.06250\nExplanation: There are two moves (to (1,2), (2,1)) that will keep the knight on the board.\nFrom each of those positions, there are also two moves that will keep the knight on the board.\nThe total probability the knight stays on the board is 0.0625.\nExample 2:\n\nInput: n = 1, k = 0, row = 0, column = 0\nOutput: 1.00000\n*/\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nclass Solution {\npublic:\n    double knightProbability(int n, int k, int row, int column) {\n        // Create a 3D vector for memoization\n        vector<vector<vector<double>>> dp(k + 1, vector<vector<double>>(n, vector<double>(n, -1.0)));\n        \n        // Call the DFS function to compute the probability\n        return dfs(n, k, row, column, dp);\n    }\n\n    double dfs(int n, int k, int row, int column, vector<vector<vector<double>>>& dp) {\n        // Base case: Check if the knight goes off the board\n        if (row < 0 || row >= n || column < 0 || column >= n) {\n            return 0.0;\n        }\n        \n        // Base case: If no more moves left, knight remains on the board\n        if (k == 0) {\n            return 1.0;\n        }\n        \n        // If result is already computed, return it\n        if (dp[k][row][column] != -1.0) {\n            return dp[k][row][column];\n        }\n\n        double probability = 0.0;\n        int directions[8][2] = {{-2, -1}, {-1, -2}, {-2, 1}, {-1, 2}, {2, -1}, {1, -2}, {2, 1}, {1, 2}};\n\n        // Try all 8 possible knight moves\n        for (int i = 0; i < 8; ++i) {\n            int newRow = row + directions[i][0];\n            int newColumn = column + directions[i][1];\n            probability += 0.125 * dfs(n, k - 1, newRow, newColumn, dp);\n        }\n\n        // Memoize the result and return it\n        dp[k][row][column] = probability;\n        return probability;\n    }\n};\n\nint main() {\n    Solution solution;\n    \n    // Example 1\n    int n1 = 3, k1 = 2, row1 = 0, column1 = 0;\n    cout << \"Output 1: \" << solution.knightProbability(n1, k1, row1, column1) << endl;\n\n    // Example 2\n    int n2 = 1, k2 = 0, row2 = 0, column2 = 0;\n    cout << \"Output 2: \" << solution.knightProbability(n2, k2, row2, column2) << endl;\n\n    return 0;\n}\n\n"
  },
  {
    "path": "Dynamic Programming/knight_probability_chessboard.go",
    "content": "/*\nOn an n x n chessboard, a knight starts at the cell (row, column) and attempts to make exactly k moves. The rows and columns are 0-indexed, so the top-left cell is (0, 0), and the bottom-right cell is (n - 1, n - 1).\n\nA chess knight has eight possible moves it can make, as illustrated below. Each move is two cells in a cardinal direction, then one cell in an orthogonal direction.\n\n\nEach time the knight is to move, it chooses one of eight possible moves uniformly at random (even if the piece would go off the chessboard) and moves there.\n\nThe knight continues moving until it has made exactly k moves or has moved off the chessboard.\n\nReturn the probability that the knight remains on the board after it has stopped moving.\n\n \n\nExample 1:\n\nInput: n = 3, k = 2, row = 0, column = 0\nOutput: 0.06250\nExplanation: There are two moves (to (1,2), (2,1)) that will keep the knight on the board.\nFrom each of those positions, there are also two moves that will keep the knight on the board.\nThe total probability the knight stays on the board is 0.0625.\nExample 2:\n\nInput: n = 1, k = 0, row = 0, column = 0\nOutput: 1.00000\n*/\nfunc knightProbability(n int, k int, row int, column int) float64 {\n    // Create a 3D grid to store the probabilities\n    dp := make([][][]float64, n)\n    for i := 0; i < n; i++ {\n        dp[i] = make([][]float64, n)\n        for j := 0; j < n; j++ {\n            dp[i][j] = make([]float64, k+1)\n        }\n    }\n    \n    // Define the eight possible knight moves\n    moves := [][]int{{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2, 1}}\n    \n    // Set the initial probability of the knight being on the starting cell to 1\n    dp[row][column][0] = 1.0\n    \n    // Calculate the probabilities for each move\n    for s := 1; s <= k; s++ {\n        for i := 0; i < n; i++ {\n            for j := 0; j < n; j++ {\n                for _, move := range moves {\n                    x := i + move[0]\n                    y := j + move[1]\n                    \n                    // Check if the move is within the chessboard\n                    if x >= 0 && x < n && y >= 0 && y < n {\n                        // Accumulate the probability for the current cell\n                        dp[i][j][s] += dp[x][y][s-1] / 8.0\n                    }\n                }\n            }\n        }\n    }\n    \n    // Calculate the total probability of the knight remaining on the board\n    probability := 0.0\n    for i := 0; i < n; i++ {\n        for j := 0; j < n; j++ {\n            probability += dp[i][j][k]\n        }\n    }\n    \n    return probability\n}\n"
  },
  {
    "path": "Dynamic Programming/knight_probability_chessboard.java",
    "content": "/*\nOn an n x n chessboard, a knight starts at the cell (row, column) and attempts to make exactly k moves. The rows and columns are 0-indexed, so the top-left cell is (0, 0), and the bottom-right cell is (n - 1, n - 1).\n\nA chess knight has eight possible moves it can make, as illustrated below. Each move is two cells in a cardinal direction, then one cell in an orthogonal direction.\n\n\nEach time the knight is to move, it chooses one of eight possible moves uniformly at random (even if the piece would go off the chessboard) and moves there.\n\nThe knight continues moving until it has made exactly k moves or has moved off the chessboard.\n\nReturn the probability that the knight remains on the board after it has stopped moving.\n\n \n\nExample 1:\n\nInput: n = 3, k = 2, row = 0, column = 0\nOutput: 0.06250\nExplanation: There are two moves (to (1,2), (2,1)) that will keep the knight on the board.\nFrom each of those positions, there are also two moves that will keep the knight on the board.\nThe total probability the knight stays on the board is 0.0625.\nExample 2:\n\nInput: n = 1, k = 0, row = 0, column = 0\nOutput: 1.00000\n*/\npublic class KnightProbability {\n    public double knightProbability(int n, int k, int row, int column) {\n        // Create a 3D array for memoization\n        double[][][] dp = new double[k + 1][n][n];\n        \n        // Call the recursive function to compute the probability\n        return dfs(n, k, row, column, dp);\n    }\n\n    private double dfs(int n, int k, int row, int column, double[][][] dp) {\n        // Base case: Check if the knight goes off the board\n        if (row < 0 || row >= n || column < 0 || column >= n) {\n            return 0.0;\n        }\n        \n        // Base case: If no more moves left, knight remains on the board\n        if (k == 0) {\n            return 1.0;\n        }\n        \n        // If result is already computed, return it\n        if (dp[k][row][column] != 0.0) {\n            return dp[k][row][column];\n        }\n\n        double probability = 0.0;\n        int[][] directions = {{-2, -1}, {-1, -2}, {-2, 1}, {-1, 2}, {2, -1}, {1, -2}, {2, 1}, {1, 2}};\n\n        // Try all 8 possible knight moves\n        for (int i = 0; i < 8; ++i) {\n            int newRow = row + directions[i][0];\n            int newColumn = column + directions[i][1];\n            probability += 0.125 * dfs(n, k - 1, newRow, newColumn, dp);\n        }\n\n        // Memoize the result and return it\n        dp[k][row][column] = probability;\n        return probability;\n    }\n\n    public static void main(String[] args) {\n        KnightProbability solution = new KnightProbability();\n\n        // Example 1\n        int n1 = 3, k1 = 2, row1 = 0, column1 = 0;\n        System.out.println(\"Output 1: \" + solution.knightProbability(n1, k1, row1, column1));\n\n        // Example 2\n        int n2 = 1, k2 = 0, row2 = 0, column2 = 0;\n        System.out.println(\"Output 2: \" + solution.knightProbability(n2, k2, row2, column2));\n    }\n}\n"
  },
  {
    "path": "Dynamic Programming/knight_probability_chessboard.js",
    "content": "/*\nOn an n x n chessboard, a knight starts at the cell (row, column) and attempts to make exactly k moves. The rows and columns are 0-indexed, so the top-left cell is (0, 0), and the bottom-right cell is (n - 1, n - 1).\n\nA chess knight has eight possible moves it can make, as illustrated below. Each move is two cells in a cardinal direction, then one cell in an orthogonal direction.\n\n\nEach time the knight is to move, it chooses one of eight possible moves uniformly at random (even if the piece would go off the chessboard) and moves there.\n\nThe knight continues moving until it has made exactly k moves or has moved off the chessboard.\n\nReturn the probability that the knight remains on the board after it has stopped moving.\n\n \n\nExample 1:\n\nInput: n = 3, k = 2, row = 0, column = 0\nOutput: 0.06250\nExplanation: There are two moves (to (1,2), (2,1)) that will keep the knight on the board.\nFrom each of those positions, there are also two moves that will keep the knight on the board.\nThe total probability the knight stays on the board is 0.0625.\nExample 2:\n\nInput: n = 1, k = 0, row = 0, column = 0\nOutput: 1.00000\n*/\nvar knightProbability = function (n, k, row, column) {\n  // Create a 3D grid to store the probabilities\n  let dp = new Array(n)\n    .fill(0)\n    .map(() => new Array(n).fill(0).map(() => new Array(k + 1).fill(0)));\n\n  // Define the eight possible knight moves\n  const moves = [\n    [-2, -1],\n    [-2, 1],\n    [-1, -2],\n    [-1, 2],\n    [1, -2],\n    [1, 2],\n    [2, -1],\n    [2, 1],\n  ];\n\n  // Set the initial probability of the knight being on the starting cell to 1\n  dp[row][column][0] = 1.0;\n\n  // Calculate the probabilities for each move\n  for (let s = 1; s <= k; s++) {\n    for (let i = 0; i < n; i++) {\n      for (let j = 0; j < n; j++) {\n        for (const move of moves) {\n          const x = i + move[0];\n          const y = j + move[1];\n\n          // Check if the move is within the chessboard\n          if (x >= 0 && x < n && y >= 0 && y < n) {\n            // Accumulate the probability for the current cell\n            dp[i][j][s] += dp[x][y][s - 1] / 8.0;\n          }\n        }\n      }\n    }\n  }\n\n  // Calculate the total probability of the knight remaining on the board\n  let probability = 0.0;\n  for (let i = 0; i < n; i++) {\n    for (let j = 0; j < n; j++) {\n      probability += dp[i][j][k];\n    }\n  }\n\n  return probability;\n};\n"
  },
  {
    "path": "Dynamic Programming/knight_probability_chessboard.py",
    "content": "'''\n    On an n x n chessboard, a knight starts at the cell (row, column) and attempts to make exactly k moves. The rows and columns are 0-indexed, so the top-left cell is (0, 0), and the bottom-right cell is (n - 1, n - 1).\n\n    A chess knight has eight possible moves it can make, as illustrated below. Each move is two cells in a cardinal direction, then one cell in an orthogonal direction.\n\n\n    Each time the knight is to move, it chooses one of eight possible moves uniformly at random (even if the piece would go off the chessboard) and moves there.\n\n    The knight continues moving until it has made exactly k moves or has moved off the chessboard.\n\n    Return the probability that the knight remains on the board after it has stopped moving.\n\n    \n\n    Example 1:\n\n    Input: n = 3, k = 2, row = 0, column = 0\n    Output: 0.06250\n    Explanation: There are two moves (to (1,2), (2,1)) that will keep the knight on the board.\n    From each of those positions, there are also two moves that will keep the knight on the board.\n    The total probability the knight stays on the board is 0.0625.\n    Example 2:\n\n    Input: n = 1, k = 0, row = 0, column = 0\n    Output: 1.00000\n'''\nclass Solution:\n    def knightProbability(self, n: int, k: int, row: int, column: int) -> float:\n        # Create a 3D grid to store the probabilities\n        dp = [[[0 for _ in range(k + 1)] for _ in range(n)] for _ in range(n)]\n        \n        # Define the eight possible knight moves\n        moves = [(-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2), (2, -1), (2, 1)]\n        \n        # Set the initial probability of the knight being on the starting cell to 1\n        dp[row][column][0] = 1.0\n        \n        # Calculate the probabilities for each move\n        for s in range(1, k + 1):\n            for i in range(n):\n                for j in range(n):\n                    for move in moves:\n                        x = i + move[0]\n                        y = j + move[1]\n                        \n                        # Check if the move is within the chessboard\n                        if 0 <= x < n and 0 <= y < n:\n                            # Accumulate the probability for the current cell\n                            dp[i][j][s] += dp[x][y][s - 1] / 8.0\n        \n        # Calculate the total probability of the knight remaining on the board\n        probability = 0.0\n        for i in range(n):\n            for j in range(n):\n                probability += dp[i][j][k]\n        \n        return probability\n"
  },
  {
    "path": "Dynamic Programming/kth_closest_point_to origin.java",
    "content": "/*\n K Closest Points to Origin\n\nGiven an array of points where points[i] = [xi, yi] represents a point on the X-Y plane and an integer k, return the k closest points to the origin (0, 0).\nThe distance between two points on the X-Y plane is the Euclidean distance (i.e., √(x1 - x2)2 + (y1 - y2)2).\nYou may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in).\n\n \n\nExample 1:\nInput: points = [[1,3],[-2,2]], k = 1\nOutput: [[-2,2]]\nExplanation:\nThe distance between (1, 3) and the origin is sqrt(10).\nThe distance between (-2, 2) and the origin is sqrt(8).\nSince sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.\nWe only want the closest k = 1 points from the origin, so the answer is just [[-2,2]].\n\nExample 2:\nInput: points = [[3,3],[5,-1],[-2,4]], k = 2\nOutput: [[3,3],[-2,4]]\nExplanation: The answer [[-2,4],[3,3]] would also be accepted.\n \nConstraints:\n\n1 <= k <= points.length <= 104\n-104 < xi, yi < 104\n */\n\n /*\n  SOLUTION:\n\n  Explanation:\n      Solved this question using priority Queue.\n      Created a priority queue with an Integer.comapre() function.\n      The solution uses a max-heap, implemented as a PriorityQueue, to keep track of the k closest points seen so far. \n      We use the Euclidean distance formula to calculate the distance between each point and the origin, \n      which is given by the square root of the sum of the squares of the coordinates. However, to avoid the expensive square root operation, \n      we square the distance formula and compare the squared distances instead.\n\n      The PriorityQueue is initialized with a lambda function that compares the squared distances of two points, p1 and p2, \n      using the Integer.compare() method. This lambda function sorts the points in descending order of their squared distances so that the \n      largest squared distance is at the top of the queue.\n\n      \n\n\n  */\n\n  //code:\n  class Solution {\n    \n    public int[][] kClosest(int[][] points, int k) {\n        \n        Queue<int[]> q = new PriorityQueue<int[]>((p1, p2) -> Integer.compare((p2[0] * p2[0] + p2[1] * p2[1]),(p1[0] * p1[0] + p1[1] * p1[1])));  // Created a priority queue (Implementing max-heap) with a comparison function.\n                                                  \n        for(int i=0; i<points.length; i++){\n            q.add(points[i]);                 /*We then iterate through each point in the input array points and add it to the priority queue. \n                                                 If the size of max-heap exceeds k, we remove the point with the largest squared distance from the queue \n                                                 using the poll() method. */\n            if(q.size() > k){\n                q.poll();\n            }\n\n        }\n        int[][] arr = new int[k][2];\n        while(k>0){\n            arr[--k] = q.poll();        /* Creating a 2D array of size K and storing points  in non decreasing order of their distance (from  ,least-most). */\n        }\n        return arr;         //answer\n    \n    }\n}"
  },
  {
    "path": "Dynamic Programming/largest_rectangle.java",
    "content": "//Program Author : TheCodeVenturer [Niraj Modi]\n/*\n    Problem Definition:\n        Dynamic Programming: Given a rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area in Python\n    Approach:\n        This Problem can be termed as updated version of Largest Rectangle in Histogram\n        If you are given a binary matrix then you can use no.of rows together with one as height\n        Like \n        0 1 1 0\n        1 1 1 1\n        1 1 1 1\n        1 1 0 0\n        If you can Visualise then it will be clear that for \n        first row the histogram row is like [0,1,1,0]\n        second row the histogram row is like [1,2,2,1]\n        third row the histogram row is like [2,3,3,2]\n        fourth row the histogram row is like [3,4,0,0]\n        then by using a monotonic stack for each row we can get The Largest Rectangle in the Binary Matrix\n\n        we are taking here a row list which keeps track of current height of a particular column . Here, ShiftRow\n        we are also using a solution variable to keep track of largest rectangle\n        then first we will iterate through each row \n            and inside each iteration we will go and look for the particular element of that row matrix[i][j]\n            if it is 1 then will increase size of jth entry in the shiftRow else will convert it to zero\n            next will initialize an empty Stack [Monotonic]\n            next we will iterate through the shiftRow and will first check for the list is not empty and (it's top element is greater than or equal to current element or value of current column is equal to row size)\n                then will store it's height from the current row array and will update width of the rectangle with stack's top element and will finally update the sol\n            and will insert the element to the stack\n        Complexity:\n        Time Complexity: O(rows * col) for for traversing through each elements of the array \n                Here in each iteration we are doint three times O(n) => O(3n) ~ O(n)\n        Space Complexity: O(n) for the shiftRow and O(n) for the stack we are using => O(2n) ~ O(n)\n        Sample input/outputs:\n\t\tExample 1:\n\t\tInput: [[0,1,1,0],[1,1,1,1],[1,1,1,1],[1,1,0,0]]\n\t\tOutput: 8\n\n\t\tExample 2:\n\t\tInput: [[0,1,1],[1,1,1],[0,1,1]] \n\t\tOutput: 6\n*/\nimport java.util.*;\n\npublic class Solution {\n    public static int maxArea(int[][] matrix, int rows, int cols) {\n        int[] shiftRow = new int[cols]; // initializing the row which updates after each iteration\n        int sol = 0;\n        \n        for (int[] row : matrix) {\n            for (int i = 0; i < row.length; i++) {\n                // Updating the shiftRow if the value of ele is 1 => shiftRow[i] <- shiftRow[i] + 1\n                // else shiftRow[i] = 0\n                int ele = row[i];\n                if (ele == 1) shiftRow[i]++;\n                else shiftRow[i] = 0;\n            }\n            \n            Deque<Integer> stack = new ArrayDeque<>();\n            \n            for (int i = 0; i < cols + 1; i++) {\n                while (!stack.isEmpty() && (i == cols || shiftRow[stack.peek()] >= shiftRow[i])) {\n                    // checking TOS (top of stack) stack.length - 1\n                    int height = shiftRow[stack.peek()]; // for getting the height of the current index\n                    stack.pop();\n                    int width = i; // setting width to i as it is only smallest from the beginning\n                    if (!stack.isEmpty()) width = i - stack.peek() - 1; // updating width if the stack is not empty as it is not the smallest element\n                    sol = Math.max(height * width, sol); // updating the sol\n                }\n                \n                stack.push(i); // pushing the element's index to the stack\n            }\n        }\n        \n        return sol;\n    }\n    \n    public static void main(String[] args) {\n        int[][] matrix = {\n            {0, 1, 1, 0},\n            {1, 1, 1, 1},\n            {1, 1, 1, 1},\n            {1, 1, 0, 0}\n        };\n        \n        System.out.println(maxArea(matrix, 4, 4));\n    }\n}\n\n  "
  },
  {
    "path": "Dynamic Programming/largest_rectangle.js",
    "content": "//Program Author : TheCodeVenturer [Niraj Modi]\n/*\n    Problem Definition:\n        Dynamic Programming: Given a rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area in Python\n    Approach:\n        This Problem can be termed as updated version of Largest Rectangle in Histogram\n        If you are given a binary matrix then you can use no.of rows together with one as height\n        Like \n        0 1 1 0\n        1 1 1 1\n        1 1 1 1\n        1 1 0 0\n        If you can Visualise then it will be clear that for \n        first row the histogram row is like [0,1,1,0]\n        second row the histogram row is like [1,2,2,1]\n        third row the histogram row is like [2,3,3,2]\n        fourth row the histogram row is like [3,4,0,0]\n        then by using a monotonic stack for each row we can get The Largest Rectangle in the Binary Matrix\n\n        we are taking here a row list which keeps track of current height of a particular column . Here, ShiftRow\n        we are also using a solution variable to keep track of largest rectangle\n        then first we will iterate through each row \n            and inside each iteration we will go and look for the particular element of that row matrix[i][j]\n            if it is 1 then will increase size of jth entry in the shiftRow else will convert it to zero\n            next will initialize an empty Stack [Monotonic]\n            next we will iterate through the shiftRow and will first check for the list is not empty and (it's top element is greater than or equal to current element or value of current column is equal to row size)\n                then will store it's height from the current row array and will update width of the rectangle with stack's top element and will finally update the sol\n            and will insert the element to the stack\n        Complexity:\n        Time Complexity: O(rows * col) for for traversing through each elements of the array \n                Here in each iteration we are doint three times O(n) => O(3n) ~ O(n)\n        Space Complexity: O(n) for the shiftRow and O(n) for the stack we are using => O(2n) ~ O(n)\n        Sample input/outputs:\n\t\tExample 1:\n\t\tInput: [[0,1,1,0],[1,1,1,1],[1,1,1,1],[1,1,0,0]]\n\t\tOutput: 8\n\n\t\tExample 2:\n\t\tInput: [[0,1,1],[1,1,1],[0,1,1]] \n\t\tOutput: 6\n*/\nvar maxArea = function (matrix, rows, cols) {\n  let shiftRow = new Array(cols).fill(0); //initialising the row which update after each iteration\n  var sol = 0;\n  for (let row of matrix) {\n    for (let i = 0; i < row.length; i++) {\n      // Updating the shiftRow if value of ele is 1 => ShiftRow[i] <- shiftRow[i]+1\n      // else shiftRow[i]=0\n      var ele = row[i];\n      if (ele == 1) shiftRow[i]++;\n      else shiftRow[i] = 0;\n    }\n    st = [];\n    for (let i = 0; i < cols + 1; i++) {\n      while (st.length > 0 &&(i == cols || shiftRow[st[st.length - 1]] >= shiftRow[i])) {\n        //checking TOS st.length-1\n        height = shiftRow[st[st.length - 1]]; //for getting height of Current index\n        st.pop();\n        width = i; // setting width to i as it is only smallest from beginning\n        if (st.length > 0) width = i - st[st.length - 1] - 1; // updating width is stack is not empty as it is not the smallest element\n        sol = Math.max(height * width, sol); // Updating the sol\n      }\n      st.push(i); // Pushing the Element's index to the stack\n    }\n  }\n  return sol;\n};\n\nvar matrix = [\n  [0, 1, 1, 0],\n  [1, 1, 1, 1],\n  [1, 1, 1, 1],\n  [1, 1, 0, 0],\n];\nconsole.log(maxArea(matrix, 4, 4));\n"
  },
  {
    "path": "Dynamic Programming/largest_rectangle.py",
    "content": "#Program Author : TheCodeVenturer [Niraj Modi]\n'''\n    Problem Definition:\n        Dynamic Programming: Given a rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area in Python\n    Approach:\n        This Problem can be termed as updated version of Largest Rectangle in Histogram\n        If you are given a binary matrix then you can use no.of rows together with one as height\n        Like \n        0 1 1 0\n        1 1 1 1\n        1 1 1 1\n        1 1 0 0\n        If you can Visualise then it will be clear that for \n        first row the histogram row is like [0,1,1,0]\n        second row the histogram row is like [1,2,2,1]\n        third row the histogram row is like [2,3,3,2]\n        fourth row the histogram row is like [3,4,0,0]\n        then by using a monotonic stack for each row we can get The Largest Rectangle in the Binary Matrix\n\n        we are taking here a row list which keeps track of current height of a particular column . Here, ShiftRow\n        we are also using a solution variable to keep track of largest rectangle\n        then first we will iterate through each row \n            and inside each iteration we will go and look for the particular element of that row matrix[i][j]\n            if it is 1 then will increase size of jth entry in the shiftRow else will convert it to zero\n            next will initialize an empty Stack [Monotonic]\n            next we will iterate through the shiftRow and will first check for the list is not empty and (it's top element is greater than or equal to current element or value of current column is equal to row size)\n                then will store it's height from the current row array and will update width of the rectangle with stack's top element and will finally update the sol\n            and will insert the element to the stack\n        Complexity:\n        Time Complexity: O(rows * col) for for traversing through each elements of the array \n                Here in each iteration we are doint three times O(n) => O(3n) ~ O(n)\n        Space Complexity: O(n) for the shiftRow and O(n) for the stack we are using => O(2n) ~ O(n)\n        Sample input/outputs:\n\t\tExample 1:\n\t\tInput: [[0,1,1,0],[1,1,1,1],[1,1,1,1],[1,1,0,0]]\n\t\tOutput: 8\n\n\t\tExample 2:\n\t\tInput: [[0,1,1],[1,1,1],[0,1,1]] \n\t\tOutput: 6\n'''\nclass Solution:\n    def maxArea(self,matrix, rows, cols):\n        shiftRow = [0]*cols  #initialising the row which update after each iteration\n        sol=0\n        for row in matrix:\n            for i,ele in enumerate(row):       #used enumerate as it will give index as well as element\n                # Updating the shiftRow if value of ele is 1 => ShiftRow[i] <- shiftRow[i]+1\n                # else shiftRow[i]=0\n                if ele==1:\n                    shiftRow[i]+=1\n                else:\n                    shiftRow[i]=0\n            st = []\n            for i in range(cols+1):\n                while(len(st)>0 and(i==cols or shiftRow[st[-1]]>=shiftRow[i])):\n                    height = shiftRow[st[-1]] #for getting height of Current index\n                    st.pop()\n                    width = i # setting width to i as it is only smallest from beginning \n                    if(len(st)>0): \n                        width = i - st[-1] - 1  # updating width is stack is not empty as it is not the smallest element\n                    sol = max(height*width,sol)  # Updating the sol\n                st.append(i)  # Pushing the Element's index to the stack\n        return sol\n\nif __name__ == '__main__':\n    matrix = [[0,1,1,0],[1,1,1,1],[1,1,1,1],[1,1,0,0]]\n    print(Solution().maxArea(matrix, 4, 4)) \n\t\n"
  },
  {
    "path": "Dynamic Programming/longest_common_subsequence_dp.cpp",
    "content": "// DP : Find Longest Common Subsequence of two string\n// Program Author : Abhisek Kumar Gupta\n#include<bits/stdc++.h>\n\nusing namespace std;\nconst int maxi = 10000;\nint find_longest_common_subsequence(string a, string b, int n, int m, int dp[][maxi]){\n    for(int i = 0; i <= n; i++){\n        dp[i][0] = 0;\n    }\n    for(int i = 0; i <= m; i++){\n        dp[0][i] = 0;\n    }    \n    // dp solution builds the table of LCS of substrings and starts\n    // computing the length building on the final solution\n    // we place one string along row and one along the column\n    for(int i = 1; i <= n; i++){\n        for(int j = 1; j <= m; j++){\n            // populating table in row-wise order\n            if(a[i - 1] == b[j - 1]){\n                dp[i][j] = dp[i - 1][j - 1] + 1; \n            }\n            else{\n                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);\n            }\n        }\n    }\n    return dp[m][n];\n}\nint main(){\n    string a = \"DABCEFIHKST\";\n    string b = \"DCEFKAAAQST\";\n    int n = a.length();\n    int m = b.length();\n    int dp[n+1][maxi];\n    memset(dp, -1, sizeof(dp));\n    int result = find_longest_common_subsequence(a, b, n, m, dp);\n    cout << result;\n    return 0;\n}\n// Time complexity O(N * M)  improvement over both \n// Recursion and memoization\n// Space complexity O(N * M)"
  },
  {
    "path": "Dynamic Programming/longest_common_subsequence_memoization.cpp",
    "content": "// Memoization : Find Longest Common Subsequence of two string\n// Program Author : Abhisek Kumar Gupta\n/*\n    To avoid computation of subproblem many times we use memoization\n    here we take 2D array of size n*m memoization[n][m]\n    when length of lcs of first i characters of a and j characters of b is \n    computed for first time it is stored in cell memoization[i][j]\n    if function is called with n = i and m = j then LCS is not computed from scratch\n    and stored value is returned from table\n*/\n#include<bits/stdc++.h>\nusing namespace std;\nconst int maxi = 10000;\nint get_max(int x, int y){\n    return (x > y) ? x : y; \n}\nint find_longest_common_subsequence(string a, string b, int n, int m, int memoization[][maxi]){\n    if(m == 0 || n == 0)\n        return 0;\n    // if value is already computed then return the value    \n    if(memoization[n][m] != -1){\n        return memoization[n][m];\n    }    \n    if(a[n - 1] == b[m - 1]){\n        // memoize the solution in order to avoid recomputation\n        memoization[n][m] =  1 + find_longest_common_subsequence(a, b, n - 1, m - 1, memoization);\n    }\n    else{\n        // memoize the solution in order to avoid recomputation\n        memoization[n][m] = get_max(find_longest_common_subsequence(a, b, n - 1, m, memoization),\n                                    find_longest_common_subsequence(a, b, n, m -1, memoization));\n    }\n    return memoization[n][m];    \n}\nint main(){\n    string a = \"DABCEFIHKST\";\n    string b = \"DCEFKAAAQST\";\n    int n = a.length();\n    int m = b.length();\n    int memoization[n+1][maxi];\n    memset(memoization, -1, sizeof(memoization));\n    int result = find_longest_common_subsequence(a, b, n, m, memoization);\n    cout << result;\n    return 0;\n}\n// Time complexity from exponential to polynomial O(N * M) \n// Space complexity O(N * M)"
  },
  {
    "path": "Dynamic Programming/longest_common_subsequence_recursive.cpp",
    "content": "// Recursion : Find Longest Common Subsequence of two string\n// Program Author : Abhisek Kumar Gupta\n/*\n    This problem exemplify optimal substructure property and the \n    bigger problem can be defined in terms of mini subprobs of same type \n    hence recursion\n*/\n\n#include<bits/stdc++.h>\nusing namespace std;\nint get_max(int x, int y){\n    return (x > y) ? x : y; \n}\nint find_longest_common_subsequence(string a, string b, int n, int m){\n    if(m == 0 || n == 0)\n        return 0;\n    // we start by comparing last two characters of strings and there are two\n    // possibilities \n    // 1) both are same [means we already have found one character in LCS so \n    //    add 1 and make recursive call with modified strings]\n    if(a[n - 1] == b[m - 1]){\n        return 1 + find_longest_common_subsequence(a, b, n-1, m-1);\n    }\n    // 2) both are different [find length of tow lcs, first haveing n-1 character from first string\n    //    and m characters from second string, and another with m characters from first string and \n    //    m - 1 characters from second string and return the max of two]\n    else{\n        return get_max(find_longest_common_subsequence(a, b, n-1,m),\n                        find_longest_common_subsequence(a, b, n, m-1));\n    }    \n}\nint main(){\n    string a = \"ABCEFIHST\";\n    string b = \"DCEFKAAAQST\";\n    int n = a.length();\n    int m = b.length();\n    int result = find_longest_common_subsequence(a, b, n, m);\n    cout << result;\n}\n// Code takes exponential time 2^n in the worst case i.e when all\n// two characters are different\n//                        ACB |  ABC\n//            ACB | AB                   AC | ABC\n//            AC  | A                    A  | AB\n//        A | A       AC |          A | A        | AB\n// BECAUSE WE ARE SOLVING ONE SUB PROBLEM MULTIPLE TIMES SO LCS PROBLEM \n// DEMONSTRATES OPTIMAL SUBSTRUCTURE PROPERTY AND THERE ARE OVERLAPPING\n// SUBPROBLEMS TOO, SO WE WILL USE MEMOIZATION / DP TO SOLVE THIS PROBLEM \n// OPTIMALLY "
  },
  {
    "path": "Dynamic Programming/longest_increasing_subsequence.cpp",
    "content": "/*\n    Longest Increasing Subsequence \n    Input : 1 2 1 3 1 4\n    Output : 4\n*/\n// Dynamic Programming Approach : TC O(n^2)\n// Program Author :  Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\n\nint find_longest_increasing_subsequence(vector<int> V, int n){\n    int dp[1004];\n    for(int i = 0; i < 1000; i++) dp[i] = 1;\n    int best = INT_MIN;\n    for(int i = 1; i < n; i++){\n        for(int j = 0; j < i; j++){\n            if(V[j] <= V[i]){ // this means its in increasing order and we can take value stored at dp[j] and add 1 to it\n                int curr_len = 1 + dp[j];\n                dp[i] = max(curr_len, dp[i]);\n            }\n        }\n        best = max(dp[i], best);\n    }\n    return best;\n}\nint main(){\n    int n;\n    cout << \"Enter a number\";\n    cin >> n;\n    vector<int> V(n);\n    for(int i = 0; i < n; i++){\n        cin >> V[i];\n    }\n    int result = find_longest_increasing_subsequence(V, n);\n    cout << result;\n}\n"
  },
  {
    "path": "Dynamic Programming/longest_pallindromic_substring.cpp",
    "content": "/*\n\tGiven a string s, return the longest palindromic substring in s.\n\n\tExample 1:\n\tInput: s = \"babad\"\n\tOutput: \"bab\"\n\tExplanation: \"aba\" is also a valid answer.\n\n\tExample 2:\n\tInput: s = \"cbbd\"\n\tOutput: \"bb\"\n\n\n\tConstraints:\n\t1 <= s.length <= 1000\n\ts consist of only digits and English letters.\n*/\n#include <iostream>\n#include <vector>\n#include <algorithm>\n\n// Function to find the length of the longest palindromic substring\nint longestPalindromicSubstring(const std::string& Array) {\n    int n = Array.length();\n\n    // Create a 2D boolean array L to store whether substrings are palindromes.\n    std::vector<std::vector<bool>> L(n, std::vector<bool>(n, false));\n\n    int max_length = 1;  // Initialize the maximum palindrome length to 1 (single characters are palindromes)\n\n    // Initialize the base cases for substrings of length 1 and 2.\n    for (int i = 0; i < n - 1; i++) {\n        L[i][i] = true;  // Single characters are palindromes\n        if (Array[i] == Array[i + 1]) {\n            L[i][i + 1] = true;  // Check for palindromes of length 2\n            max_length = 2;     // Update the maximum palindrome length\n        }\n    }\n\n    // Check for palindromes of length 3 and greater.\n    for (int k = 3; k <= n; k++) {\n        for (int i = 0; i < n - k + 1; i++) {\n            int j = i + k - 1;\n\n            // Check if the characters at the ends of the current substring match\n            // and if the substring inside is a palindrome.\n            if (Array[i] == Array[j] && L[i + 1][j - 1]) {\n                L[i][j] = true;      // Mark the current substring as a palindrome\n                max_length = k;      // Update the maximum palindrome length\n            }\n        }\n    }\n\n    return max_length;  // Return the length of the longest palindromic substring\n}\n\nint main() {\n    // Example usage:\n    std::string input = \"babad\";\n    int result = longestPalindromicSubstring(input);\n    std::cout << result << std::endl;  // Output: 3 (\"bab\" or \"aba\" is the longest palindromic substring)\n    return 0;\n}\n"
  },
  {
    "path": "Dynamic Programming/longest_pallindromic_substring.go",
    "content": "/*\n\tGiven a string s, return the longest palindromic substring in s.\n\n\tExample 1:\n\tInput: s = \"babad\"\n\tOutput: \"bab\"\n\tExplanation: \"aba\" is also a valid answer.\n\n\tExample 2:\n\tInput: s = \"cbbd\"\n\tOutput: \"bb\"\n\n\n\tConstraints:\n\t1 <= s.length <= 1000\n\ts consist of only digits and English letters.\n*/\npackage main\n\nimport (\n\t\"fmt\"\n)\n\n// LongestPalindromicSubstring finds the length of the longest palindromic substring in a given string.\nfunc LongestPalindromicSubstring(Array string) int {\n\tn := len(Array)\n\n\t// Create a 2D boolean array L to store whether substrings are palindromes.\n\tL := make([][]bool, n)\n\tfor i := range L {\n\t\tL[i] = make([]bool, n) // Defaults to false\n\t}\n\n\tmax := 1 // Initialize the maximum palindrome length to 1 (single characters are palindromes)\n\n\t// Initialize the base cases for substrings of length 1 and 2.\n\tfor i := 0; i < n-1; i++ {\n\t\tL[i][i] = true // Single characters are palindromes\n\t\tif Array[i] == Array[i+1] {\n\t\t\tL[i][i+1] = true // Check for palindromes of length 2\n\t\t\tmax = 2         // Update the maximum palindrome length\n\t\t}\n\t}\n\n\t// Check for palindromes of length 3 and greater.\n\tfor k := 3; k <= n; k++ {\n\t\tfor i := 0; i < n-k+1; i++ {\n\t\t\tj := i + k - 1\n\n\t\t\t// Check if the characters at the ends of the current substring match and if the substring inside is a palindrome.\n\t\t\tif Array[i] == Array[j] && L[i+1][j-1] {\n\t\t\t\tL[i][j] = true // Mark the current substring as a palindrome\n\t\t\t\tmax = k        // Update the maximum palindrome length\n\t\t\t} else {\n\t\t\t\tL[i][j] = false // Mark the current substring as not a palindrome\n\t\t\t}\n\t\t}\n\t}\n\n\treturn max // Return the length of the longest palindromic substring\n}\n\nfunc main() {\n\t// Example usage:\n\tfmt.Print(LongestPalindromicSubstring(\"babad\"))\n}\n"
  },
  {
    "path": "Dynamic Programming/longest_pallindromic_substring.java",
    "content": "/*\n\tGiven a string s, return the longest palindromic substring in s.\n\n\tExample 1:\n\tInput: s = \"babad\"\n\tOutput: \"bab\"\n\tExplanation: \"aba\" is also a valid answer.\n\n\tExample 2:\n\tInput: s = \"cbbd\"\n\tOutput: \"bb\"\n\n\n\tConstraints:\n\t1 <= s.length <= 1000\n\ts consist of only digits and English letters.\n*/\npublic class LongestPalindromicSubstring {\n    // Function to find the length of the longest palindromic substring\n    public static int longestPalindromicSubstring(String Array) {\n        int n = Array.length();\n\n        // Create a 2D boolean array L to store whether substrings are palindromes.\n        boolean[][] L = new boolean[n][n];\n\n        int max_length = 1;  // Initialize the maximum palindrome length to 1 (single characters are palindromes)\n\n        // Initialize the base cases for substrings of length 1 and 2.\n        for (int i = 0; i < n - 1; i++) {\n            L[i][i] = true;  // Single characters are palindromes\n            if (Array.charAt(i) == Array.charAt(i + 1)) {\n                L[i][i + 1] = true;  // Check for palindromes of length 2\n                max_length = 2;     // Update the maximum palindrome length\n            }\n        }\n\n        // Check for palindromes of length 3 and greater.\n        for (int k = 3; k <= n; k++) {\n            for (int i = 0; i < n - k + 1; i++) {\n                int j = i + k - 1;\n\n                // Check if the characters at the ends of the current substring match\n                // and if the substring inside is a palindrome.\n                if (Array.charAt(i) == Array.charAt(j) && L[i + 1][j - 1]) {\n                    L[i][j] = true;      // Mark the current substring as a palindrome\n                    max_length = k;      // Update the maximum palindrome length\n                }\n            }\n        }\n\n        return max_length;  // Return the length of the longest palindromic substring\n    }\n\n    public static void main(String[] args) {\n        // Example usage:\n        String input = \"babad\";\n        int result = longestPalindromicSubstring(input);\n        System.out.println(result);  // Output: 3 (\"bab\" or \"aba\" is the longest palindromic substring)\n    }\n}\n"
  },
  {
    "path": "Dynamic Programming/longest_pallindromic_substring.js",
    "content": "/*\n\tGiven a string s, return the longest palindromic substring in s.\n\n\tExample 1:\n\tInput: s = \"babad\"\n\tOutput: \"bab\"\n\tExplanation: \"aba\" is also a valid answer.\n\n\tExample 2:\n\tInput: s = \"cbbd\"\n\tOutput: \"bb\"\n\n\n\tConstraints:\n\t1 <= s.length <= 1000\n\ts consist of only digits and English letters.\n*/\nfunction longestPalindromicSubstring(Array) {\n  const n = Array.length;\n\n  // Create a 2D boolean array L to store whether substrings are palindromes.\n  const L = Array.from({ length: n }, () => Array(n).fill(false));\n\n  let max_length = 1; // Initialize the maximum palindrome length to 1 (single characters are palindromes)\n\n  // Initialize the base cases for substrings of length 1 and 2.\n  for (let i = 0; i < n - 1; i++) {\n    L[i][i] = true; // Single characters are palindromes\n    if (Array[i] === Array[i + 1]) {\n      L[i][i + 1] = true; // Check for palindromes of length 2\n      max_length = 2; // Update the maximum palindrome length\n    }\n  }\n\n  // Check for palindromes of length 3 and greater.\n  for (let k = 3; k <= n; k++) {\n    for (let i = 0; i < n - k + 1; i++) {\n      const j = i + k - 1;\n\n      // Check if the characters at the ends of the current substring match\n      // and if the substring inside is a palindrome.\n      if (Array[i] === Array[j] && L[i + 1][j - 1]) {\n        L[i][j] = true; // Mark the current substring as a palindrome\n        max_length = k; // Update the maximum palindrome length\n      }\n    }\n  }\n\n  return max_length; // Return the length of the longest palindromic substring\n}\n\n// Example usage:\nconst result = longestPalindromicSubstring(\"babad\");\nconsole.log(result); // Output: 3 (\"bab\" or \"aba\" is the longest palindromic substring)\n"
  },
  {
    "path": "Dynamic Programming/longest_pallindromic_substring.py",
    "content": "'''\n\tGiven a string s, return the longest palindromic substring in s.\n\n\tExample 1:\n\tInput: s = \"babad\"\n\tOutput: \"bab\"\n\tExplanation: \"aba\" is also a valid answer.\n\n\tExample 2:\n\tInput: s = \"cbbd\"\n\tOutput: \"bb\"\n\n\n\tConstraints:\n\t1 <= s.length <= 1000\n\ts consist of only digits and English letters.\n'''\ndef longest_palindromic_substring(Array):\n    n = len(Array)\n\n    # Create a 2D boolean array L to store whether substrings are palindromes.\n    L = [[False] * n for _ in range(n)]\n\n    max_length = 1  # Initialize the maximum palindrome length to 1 (single characters are palindromes)\n\n    # Initialize the base cases for substrings of length 1 and 2.\n    for i in range(n - 1):\n        L[i][i] = True  # Single characters are palindromes\n        if Array[i] == Array[i + 1]:\n            L[i][i + 1] = True  # Check for palindromes of length 2\n            max_length = 2  # Update the maximum palindrome length\n\n    # Check for palindromes of length 3 and greater.\n    for k in range(3, n + 1):\n        for i in range(n - k + 1):\n            j = i + k - 1\n\n            # Check if the characters at the ends of the current substring match\n            # and if the substring inside is a palindrome.\n            if Array[i] == Array[j] and L[i + 1][j - 1]:\n                L[i][j] = True  # Mark the current substring as a palindrome\n                max_length = k  # Update the maximum palindrome length\n\n    return max_length  # Return the length of the longest palindromic substring\n\n# Example usage:\nresult = longest_palindromic_substring(\"babad\")\nprint(result)  # Output: 3 (\"bab\" or \"aba\" is the longest palindromic substring)\n"
  },
  {
    "path": "Dynamic Programming/max_path_sum.go",
    "content": "/// How would you approach finding the maximum path sum in a binary tree using dynamic programming in Go?\n// Provide a sample input and output, explain your approach using comments, \n//  and analyze the time and space complexity of your solution.\n\n// sample input:         1\n//\t\t\t\t\t\t/ \\\n//\t\t\t\t\t\t2   3\n// sample output: Maximum Path Sum: 6\n\n/// Explanation : \n//   1. Implement a function that calculates the maximum path sum in a binary tree using dynamic programming.\n//   2. Create a struct treeNode to represent each node in the binary tree, including a Val field for the node's value, Left field for the left child, and Right field for the right child.\n//   3. Define a helper function pathMaxSum that takes the root node as input and returns the maximum path sum.\n//   4 Within maxPathSum, initialize a variable maxSum with the minimum integer value to track the maximum path sum.\n//   5. Call the recursive helper function findMaxSum and pass the root node and the maxSum variable as arguments.\n//   6. In the findMaxSum function, handle the base case: if the node is nil, return 0.\n//   7. Recursively find the maximum path sum for the left and right subtrees by calling findMaxSum on the left and right children of the current node.\n//   8. Calculate the maximum path sum that includes the current node:\n\t\t// Check if the left sum is negative (less than 0), assign it as 0.\n\t\t// Check if the right sum is negative (less than 0), assign it as 0.\n\t\t// Update the maxSum by comparing it with the sum of the current node's value, left sum, and right sum.//\n//   9. Return the maximum path sum including the current node (either the current node's value plus the maximum of left or right sum).\n//   10. Finally, return the maxSum from the pathMaxSum function.\n//   11. In the main function, create a sample binary tree and call pathMaxSum to find the maximum path sum. Print the result.\n\n// Time Complexity: The time complexity of this solution is O(N), where N is the number of nodes in the binary tree, as we need to traverse each node once.\n\n// Space Complexity: The space complexity is O(H), where H is the height of the binary tree. This is due to the recursive calls on the stack, which can go up to the height of the tree.\n\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\ntype treenode struct {\n\tVal int\n\tLeft *treenode\n\tRight *treenode\n}\n\n// Function to find the maximum path sum in a binary tree\nfunc pathMaxSum(root *treenode) int{\n\tmaxSum := math.MinInt32\n\tfindMaxSum(root, &maxSum)\n\treturn maxSum\n}\n\n// finding the maximum path sum starting from a given node\nfunc findMaxSum(node *treenode, maxSum *int) int {\n\tif node == nil {\n\t\treturn 0\n\t}\n\n\tleftSum := max(0, findMaxSum(node.Left,maxSum))\n\trightSum := max(0,findMaxSum(node.Right,maxSum))\n\n\t*maxSum = max(*maxSum,node.Val+leftSum+rightSum)\n\n\t// returning the max sum plus the current node\n\treturn node.Val + max(leftSum,rightSum)\n}\n\n// function to find the maximum of two numbers\nfunc max(a,b int) int {\n\tif a >b {\n\t\treturn a\n\t}\n\treturn b\n}\n\nfunc main() {\n\t// creating sample binary tree\n\troot := &treenode{Val: 1}\n\troot.Left = &treenode{Val: 2}\n\troot.Right = &treenode{Val: 3}\n\n\t// Calculate the maximum path sum\n\tmaxSum := pathMaxSum(root)\n\tfmt.Println(\"Maximum Path Sum:\", maxSum)\n}"
  },
  {
    "path": "Dynamic Programming/max_sum_increasing_subsequence.cpp",
    "content": "/*\n\tWrite a function that takes in a non-empty array of integers and returns the greatest sum  that can be generated\n\tfrom a strictly-increasing subsequence in the array as well as an array of the numbers in that subsequence.\n\n\tSample Input:  = [10, 70, 20, 30, 50, 11, 30]\n\tOutput : [110, [10, 20, 30, 50]]\n\t\n\tExplanation:\n\tThe given code snippet implements a function called `MaxSumIncreasingSubsequence`, which finds the maximum sum increasing subsequence in a given array of integers. An increasing subsequence is a sequence of array elements where each element is strictly greater than the previous element.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MaxSumIncreasingSubsequence` takes an input array of integers called `array`.\n\n\t2. Two arrays `sums` and `sequences` are initialized with the same length as the input array. The `sums` array stores the maximum sum of increasing subsequences ending at the corresponding index, and the `sequences` array stores the previous index that contributes to the maximum sum at the current index.\n\n\t3. The `maxSumIndex` variable is used to keep track of the index with the maximum sum of an increasing subsequence.\n\n\t4. The code uses a dynamic programming approach to calculate the maximum sum of increasing subsequences. It iterates through the input array from left to right and, for each element, checks all the previous elements to find the ones that are less than the current element and can form an increasing subsequence with it. If a better sum is found for the current element, it updates the `sums` and `sequences` arrays.\n\n\t5. After iterating through the entire array, the `maxSumIndex` stores the index with the maximum sum of an increasing subsequence.\n\n\t6. The function `buildSequence` is used to reconstruct the actual increasing subsequence from the `sequences` array, starting from the `maxSumIndex` and going backward until it reaches an element with a value of `math.MinInt32`, which is used as a sentinel value to indicate the end of the sequence.\n\n\t7. The `reverse` function is a helper function used to reverse the elements in the `sequence` array since the subsequence was built backward.\n\n\t8. The function returns the maximum sum of the increasing subsequence (`sum`) and the subsequence itself (`sequence`).\n\n\tO(n^2) time | O(n) space - where n is the length of the input array\n*/\n\n#include <vector>\n#include <algorithm>\n\nstd::pair<int, std::vector<int>> MaxSumIncreasingSubsequence(std::vector<int>& array) {\n    int n = array.size();\n    std::vector<int> sums(n);   // Store the maximum increasing sum up to index i.\n    std::vector<int> sequences(n, -1); // Store the previous index of the increasing subsequence.\n\n    for (int i = 0; i < n; i++) {\n        sums[i] = array[i];\n        for (int j = 0; j < i; j++) {\n            if (array[i] > array[j] && sums[j] + array[i] > sums[i]) {\n                sums[i] = sums[j] + array[i];\n                sequences[i] = j;\n            }\n        }\n    }\n\n    // Find the index of the maximum sum in 'sums'.\n    int maxSumIndex = std::max_element(sums.begin(), sums.end()) - sums.begin();\n    int maxSum = sums[maxSumIndex];\n\n    // Build the increasing subsequence using the 'sequences' array.\n    std::vector<int> sequence;\n    while (maxSumIndex != -1) {\n        sequence.push_back(array[maxSumIndex]);\n        maxSumIndex = sequences[maxSumIndex];\n    }\n    std::reverse(sequence.begin(), sequence.end());\n\n    return std::make_pair(maxSum, sequence);\n}\n"
  },
  {
    "path": "Dynamic Programming/max_sum_increasing_subsequence.go",
    "content": "/*\n\tWrite a function that takes in a non-empty array of integers and returns the greatest sum  that can be generated\n\tfrom a strictly-increasing subsequence in the array as well as an array of the numbers in that subsequence.\n\n\tSample Input:  = [10, 70, 20, 30, 50, 11, 30]\n\tOutput : [110, [10, 20, 30, 50]]\n\t\n\tExplanation:\n\tThe given code snippet implements a function called `MaxSumIncreasingSubsequence`, which finds the maximum sum increasing subsequence in a given array of integers. An increasing subsequence is a sequence of array elements where each element is strictly greater than the previous element.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MaxSumIncreasingSubsequence` takes an input array of integers called `array`.\n\n\t2. Two arrays `sums` and `sequences` are initialized with the same length as the input array. The `sums` array stores the maximum sum of increasing subsequences ending at the corresponding index, and the `sequences` array stores the previous index that contributes to the maximum sum at the current index.\n\n\t3. The `maxSumIndex` variable is used to keep track of the index with the maximum sum of an increasing subsequence.\n\n\t4. The code uses a dynamic programming approach to calculate the maximum sum of increasing subsequences. It iterates through the input array from left to right and, for each element, checks all the previous elements to find the ones that are less than the current element and can form an increasing subsequence with it. If a better sum is found for the current element, it updates the `sums` and `sequences` arrays.\n\n\t5. After iterating through the entire array, the `maxSumIndex` stores the index with the maximum sum of an increasing subsequence.\n\n\t6. The function `buildSequence` is used to reconstruct the actual increasing subsequence from the `sequences` array, starting from the `maxSumIndex` and going backward until it reaches an element with a value of `math.MinInt32`, which is used as a sentinel value to indicate the end of the sequence.\n\n\t7. The `reverse` function is a helper function used to reverse the elements in the `sequence` array since the subsequence was built backward.\n\n\t8. The function returns the maximum sum of the increasing subsequence (`sum`) and the subsequence itself (`sequence`).\n\n\tO(n^2) time | O(n) space - where n is the length of the input array\n*/\npackage main\n\nimport \"math\"\n\n// MaxSumIncreasingSubsequence finds the maximum sum increasing subsequence in the given array of integers.\nfunc MaxSumIncreasingSubsequence(array []int) (int, []int) {\n\t// Initialize two arrays to store maximum sums and the previous elements contributing to the sums.\n\tsums := make([]int, len(array))\n\tsequences := make([]int, len(array))\n\n\t// Initialize each element in 'sums' array to its corresponding element in the input array.\n\t// Also, initialize each element in 'sequences' array to a sentinel value 'math.MinInt32'.\n\tfor i := range sequences {\n\t\tsequences[i] = math.MinInt32\n\t\tsums[i] = array[i]\n\t}\n\n\t// Variable to keep track of the index with the maximum sum.\n\tmaxSumIndex := 0\n\n\t// Iterate through the input array and calculate the maximum sum increasing subsequences.\n\tfor i, currNum := range array {\n\t\tfor j := 0; j < i; j++ {\n\t\t\totherNum := array[j]\n\t\t\tif otherNum < currNum && currNum+sums[j] >= sums[i] {\n\t\t\t\t// If the current element can extend the increasing subsequence with a better sum,\n\t\t\t\t// update the 'sums' and 'sequences' arrays accordingly.\n\t\t\t\tsums[i] = currNum + sums[j]\n\t\t\t\tsequences[i] = j\n\t\t\t}\n\t\t}\n\n\t\t// Update the index with the maximum sum if the current sum is greater.\n\t\tif sums[i] > sums[maxSumIndex] {\n\t\t\tmaxSumIndex = i\n\t\t}\n\t}\n\n\t// Get the maximum sum from the 'sums' array and the increasing subsequence from the 'sequences' array.\n\tsum := sums[maxSumIndex]\n\tsequence := buildSequence(array, sequences, maxSumIndex)\n\treturn sum, sequence\n}\n\n// buildSequence reconstructs the increasing subsequence from the 'sequences' array.\nfunc buildSequence(array []int, sequences []int, index int) []int {\n\tsequence := []int{}\n\n\t// Traverse the 'sequences' array starting from the 'index' until reaching the sentinel value 'math.MinInt32'.\n\tfor index != math.MinInt32 {\n\t\t// Add the element at the current index to the 'sequence' array.\n\t\tsequence = append(sequence, array[index])\n\n\t\t// Move to the previous index using 'sequences' array.\n\t\tindex = sequences[index]\n\t}\n\n\t// Reverse the 'sequence' array since it was built backward.\n\treverse(sequence)\n\treturn sequence\n}\n\n// reverse is a helper function used to reverse the elements in the 'sequence' array.\nfunc reverse(numbers []int) {\n\tfor i, j := 0, len(numbers)-1; i < j; i, j = i+1, j-1 {\n\t\tnumbers[i], numbers[j] = numbers[j], numbers[i]\n\t}\n}\n"
  },
  {
    "path": "Dynamic Programming/max_sum_increasing_subsequence.java",
    "content": "/*\n    Write a function that takes in a non-empty array of integers and returns the greatest sum  that can be generated\n\tfrom a strictly-increasing subsequence in the array as well as an array of the numbers in that subsequence.\n\n\tSample Input:  = [10, 70, 20, 30, 50, 11, 30]\n\tOutput : [110, [10, 20, 30, 50]]\n\t\n\tExplanation:\n\tThe given code snippet implements a function called `MaxSumIncreasingSubsequence`, which finds the maximum sum increasing subsequence in a given array of integers. An increasing subsequence is a sequence of array elements where each element is strictly greater than the previous element.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MaxSumIncreasingSubsequence` takes an input array of integers called `array`.\n\n\t2. Two arrays `sums` and `sequences` are initialized with the same length as the input array. The `sums` array stores the maximum sum of increasing subsequences ending at the corresponding index, and the `sequences` array stores the previous index that contributes to the maximum sum at the current index.\n\n\t3. The `maxSumIndex` variable is used to keep track of the index with the maximum sum of an increasing subsequence.\n\n\t4. The code uses a dynamic programming approach to calculate the maximum sum of increasing subsequences. It iterates through the input array from left to right and, for each element, checks all the previous elements to find the ones that are less than the current element and can form an increasing subsequence with it. If a better sum is found for the current element, it updates the `sums` and `sequences` arrays.\n\n\t5. After iterating through the entire array, the `maxSumIndex` stores the index with the maximum sum of an increasing subsequence.\n\n\t6. The function `buildSequence` is used to reconstruct the actual increasing subsequence from the `sequences` array, starting from the `maxSumIndex` and going backward until it reaches an element with a value of `math.MinInt32`, which is used as a sentinel value to indicate the end of the sequence.\n\n\t7. The `reverse` function is a helper function used to reverse the elements in the `sequence` array since the subsequence was built backward.\n\n\t8. The function returns the maximum sum of the increasing subsequence (`sum`) and the subsequence itself (`sequence`).\n\n\tO(n^2) time | O(n) space - where n is the length of the input array\n*/\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.ArrayList;\n\npublic class Main {\n    public static int[] maxSumIncreasingSubsequence(int[] array) {\n        int n = array.length;\n        int[] sums = Arrays.copyOf(array, n); // Store the maximum increasing sum up to index i.\n        int[] sequences = new int[n];\n        Arrays.fill(sequences, -1); // Store the previous index of the increasing subsequence.\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < i; j++) {\n                if (array[i] > array[j] && sums[j] + array[i] > sums[i]) {\n                    sums[i] = sums[j] + array[i];\n                    sequences[i] = j;\n                }\n            }\n        }\n\n        // Find the index of the maximum sum in 'sums'.\n        int maxSumIndex = 0;\n        for (int i = 1; i < n; i++) {\n            if (sums[i] > sums[maxSumIndex]) {\n                maxSumIndex = i;\n            }\n        }\n        int maxSum = sums[maxSumIndex];\n\n        // Build the increasing subsequence using the 'sequences' array.\n        List<Integer> sequenceList = new ArrayList<>();\n        while (maxSumIndex != -1) {\n            sequenceList.add(array[maxSumIndex]);\n            maxSumIndex = sequences[maxSumIndex];\n        }\n\n        // Convert the list to an array and reverse it to get the correct order.\n        int[] sequence = new int[sequenceList.size()];\n        for (int i = 0; i < sequence.length; i++) {\n            sequence[i] = sequenceList.get(sequenceList.size() - i - 1);\n        }\n\n        return new int[]{maxSum, sequence};\n    }\n\n    public static void main(String[] args) {\n        int[] array = {4, 6, 1, 3, 8, 4, 6};\n        int[] result = maxSumIncreasingSubsequence(array);\n        System.out.println(\"Max Sum: \" + result[0]);\n        System.out.println(\"Increasing Subsequence: \" + Arrays.toString(result[1]));\n    }\n}\n"
  },
  {
    "path": "Dynamic Programming/max_sum_increasing_subsequence.js",
    "content": "/*\n\tWrite a function that takes in a non-empty array of integers and returns the greatest sum  that can be generated\n\tfrom a strictly-increasing subsequence in the array as well as an array of the numbers in that subsequence.\n\n\tSample Input:  = [10, 70, 20, 30, 50, 11, 30]\n\tOutput : [110, [10, 20, 30, 50]]\n\t\n\tExplanation:\n\tThe given code snippet implements a function called `MaxSumIncreasingSubsequence`, which finds the maximum sum increasing subsequence in a given array of integers. An increasing subsequence is a sequence of array elements where each element is strictly greater than the previous element.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MaxSumIncreasingSubsequence` takes an input array of integers called `array`.\n\n\t2. Two arrays `sums` and `sequences` are initialized with the same length as the input array. The `sums` array stores the maximum sum of increasing subsequences ending at the corresponding index, and the `sequences` array stores the previous index that contributes to the maximum sum at the current index.\n\n\t3. The `maxSumIndex` variable is used to keep track of the index with the maximum sum of an increasing subsequence.\n\n\t4. The code uses a dynamic programming approach to calculate the maximum sum of increasing subsequences. It iterates through the input array from left to right and, for each element, checks all the previous elements to find the ones that are less than the current element and can form an increasing subsequence with it. If a better sum is found for the current element, it updates the `sums` and `sequences` arrays.\n\n\t5. After iterating through the entire array, the `maxSumIndex` stores the index with the maximum sum of an increasing subsequence.\n\n\t6. The function `buildSequence` is used to reconstruct the actual increasing subsequence from the `sequences` array, starting from the `maxSumIndex` and going backward until it reaches an element with a value of `math.MinInt32`, which is used as a sentinel value to indicate the end of the sequence.\n\n\t7. The `reverse` function is a helper function used to reverse the elements in the `sequence` array since the subsequence was built backward.\n\n\t8. The function returns the maximum sum of the increasing subsequence (`sum`) and the subsequence itself (`sequence`).\n\n\tO(n^2) time | O(n) space - where n is the length of the input array\n*/\n\nfunction maxSumIncreasingSubsequence(array) {\n  const n = array.length;\n  const sums = [...array]; // Store the maximum increasing sum up to index i.\n  const sequences = new Array(n).fill(-1); // Store the previous index of the increasing subsequence.\n\n  for (let i = 0; i < n; i++) {\n    for (let j = 0; j < i; j++) {\n      if (array[i] > array[j] && sums[j] + array[i] > sums[i]) {\n        sums[i] = sums[j] + array[i];\n        sequences[i] = j;\n      }\n    }\n  }\n\n  // Find the index of the maximum sum in 'sums'.\n  let maxSumIndex = 0;\n  for (let i = 1; i < n; i++) {\n    if (sums[i] > sums[maxSumIndex]) {\n      maxSumIndex = i;\n    }\n  }\n  const maxSum = sums[maxSumIndex];\n\n  // Build the increasing subsequence using the 'sequences' array.\n  const sequence = [];\n  while (maxSumIndex !== -1) {\n    sequence.push(array[maxSumIndex]);\n    maxSumIndex = sequences[maxSumIndex];\n  }\n  sequence.reverse();\n\n  return [maxSum, sequence];\n}\n"
  },
  {
    "path": "Dynamic Programming/max_sum_increasing_subsequence.py",
    "content": "'''\n\tWrite a function that takes in a non-empty array of integers and returns the greatest sum  that can be generated\n\tfrom a strictly-increasing subsequence in the array as well as an array of the numbers in that subsequence.\n\n\tSample Input:  = [10, 70, 20, 30, 50, 11, 30]\n\tOutput : [110, [10, 20, 30, 50]]\n\t\n\tExplanation:\n\tThe given code snippet implements a function called `MaxSumIncreasingSubsequence`, which finds the maximum sum increasing subsequence in a given array of integers. An increasing subsequence is a sequence of array elements where each element is strictly greater than the previous element.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MaxSumIncreasingSubsequence` takes an input array of integers called `array`.\n\n\t2. Two arrays `sums` and `sequences` are initialized with the same length as the input array. The `sums` array stores the maximum sum of increasing subsequences ending at the corresponding index, and the `sequences` array stores the previous index that contributes to the maximum sum at the current index.\n\n\t3. The `maxSumIndex` variable is used to keep track of the index with the maximum sum of an increasing subsequence.\n\n\t4. The code uses a dynamic programming approach to calculate the maximum sum of increasing subsequences. It iterates through the input array from left to right and, for each element, checks all the previous elements to find the ones that are less than the current element and can form an increasing subsequence with it. If a better sum is found for the current element, it updates the `sums` and `sequences` arrays.\n\n\t5. After iterating through the entire array, the `maxSumIndex` stores the index with the maximum sum of an increasing subsequence.\n\n\t6. The function `buildSequence` is used to reconstruct the actual increasing subsequence from the `sequences` array, starting from the `maxSumIndex` and going backward until it reaches an element with a value of `math.MinInt32`, which is used as a sentinel value to indicate the end of the sequence.\n\n\t7. The `reverse` function is a helper function used to reverse the elements in the `sequence` array since the subsequence was built backward.\n\n\t8. The function returns the maximum sum of the increasing subsequence (`sum`) and the subsequence itself (`sequence`).\n\n\tO(n^2) time | O(n) space - where n is the length of the input array\n'''\ndef max_sum_increasing_subsequence(array):\n    n = len(array)\n    sums = [num for num in array]   # Store the maximum increasing sum up to index i.\n    sequences = [-1] * n  # Store the previous index of the increasing subsequence.\n\n    for i in range(n):\n        for j in range(i):\n            if array[i] > array[j] and sums[j] + array[i] > sums[i]:\n                sums[i] = sums[j] + array[i]\n                sequences[i] = j\n\n    # Find the index of the maximum sum in 'sums'.\n    max_sum_index = max(range(n), key=lambda i: sums[i])\n    max_sum = sums[max_sum_index]\n\n    # Build the increasing subsequence using the 'sequences' array.\n    sequence = []\n    while max_sum_index != -1:\n        sequence.append(array[max_sum_index])\n        max_sum_index = sequences[max_sum_index]\n    sequence.reverse()\n\n    return max_sum, sequence\n"
  },
  {
    "path": "Dynamic Programming/maximal_sqaure.cpp",
    "content": "/*\r\n    -> The maximalSquare function takes a matrix as input and returns the area of the maximal square found in the matrix.\r\n    -> The function first checks if the matrix is empty (no rows or columns). In such cases, there can't be any squares,\r\n     so it returns 0.\r\n    -> Next, it initializes some variables. rows stores the number of rows in the matrix, cols stores the number of\r\n     columns, and maxSide keeps track of the maximum side length of the square encountered so far.\r\n    -> It creates a new matrix called dp using the Array.from method. This matrix will store the side lengths of squares.\r\n    -> The next step is to initialize the first row and the first column of dp with the values from the input matrix. It \r\n    iterates over each element in the first row and sets the corresponding element in dp to either 0 or 1, depending on \r\n    whether the element in the input matrix is '0' or '1'. It also updates maxSide accordingly.\r\n    -> Similarly, it iterates over each element in the first column and sets the corresponding element in dp to either \r\n    0 or 1, based on the input matrix. Again, maxSide is updated.\r\n    -> Now, the function enters a nested loop to iterate over the remaining elements of the matrix, starting from the\r\n    second row and the second column. For each element at position (i, j), it checks if the corresponding element in the\r\n    input matrix is '1'.\r\n    -> If the element is '1', it calculates the value of dp[i][j] by taking the minimum of the three adjacent elements: \r\n    dp[i-1][j] (above), dp[i][j-1] (left), and dp[i-1][j-1] (diagonally above-left). It adds 1 to the minimum value and \r\n    assigns it to dp[i][j]. Additionally, it updates maxSide if the current dp[i][j] value is greater.\r\n    -> After the nested loop completes, the function has calculated the side lengths of squares for all positions in the \r\n    matrix. It returns the area of the maximal square by squaring the value of maxSide.\r\n    -> Finally, outside the function, an example usage is shown. The matrix variable represents a 2D array with 0s and 1s. \r\n    The maximalSquare function is called with this matrix, and the returned result is logged to the console. In this\r\n    example, the maximal square in the matrix has a side length of 2, so the output is 4 (2 * 2).\r\n\r\nThe code utilizes dynamic programming to efficiently calculate the maximal square in the given matrix by storing the \r\nside lengths of squares in a separate matrix. By using previously calculated values, the algorithm avoids redundant \r\ncalculations and improves performance.\r\n\r\n//Time complexity\r\n\r\nThe time complexity of the provided maximal square algorithm is O(m * n), where m is the number of rows \r\nin the matrix and n is the number of columns. This is because we iterate over each element in the matrix \r\nonce to calculate the side lengths of squares. The nested loops contribute to the linear time complexity.\r\n\r\nThe space complexity is O(m * n) as well. We create an additional matrix, dp, with the same dimensions as \r\nthe input matrix to store the side lengths of squares. Hence, the space required is proportional to the \r\nnumber of elements in the matrix.\r\n\r\nIn summary, the time complexity and space complexity of the maximal square algorithm are both O(m * n), \r\nwhere m is the number of rows and n is the number of columns in the matrix.\r\n*/\r\n\r\n\r\n/*\r\n\r\nExample 1:\r\nInput:\r\n\r\n1 0 1 0 0\r\n1 0 1 1 1\r\n1 1 1 1 1\r\n1 0 0 1 0\r\n\r\nOutput: 4 \r\nThe maximal square in the matrix is a 2x2 square with the top-left corner at position (1, 2) and the bottom-right corner at position (2, 3). The area of this square is 4.\r\n\r\nExample 2:\r\nInput:\r\n0 1 1 1 1\r\n1 1 0 1 0\r\n0 1 1 1 1\r\n1 1 1 1 0\r\n\r\n\r\nOutput: 9\r\nThe maximal square in the matrix is a 3x3 square with the top-left corner at position (0, 1) and the bottom-right corner at position (2, 3). The area of this square is 9.\r\n\r\nExample 3:\r\nInput:\r\n\r\n0 0 0\r\n0 0 0\r\n0 0 0\r\n\r\nOutput: 0\r\nThere are no squares with side length greater than 0 in the matrix. Therefore, the output is 0.\r\n\r\n*/\r\n#include <iostream>\r\n#include <vector>\r\n#include <algorithm>\r\n\r\nint maximalSquare(std::vector<std::vector<char>>& matrix) {\r\n    if (matrix.empty() || matrix[0].empty()) {\r\n        return 0;\r\n    }\r\n\r\n    int rows = matrix.size();\r\n    int cols = matrix[0].size();\r\n    int maxSide = 0;\r\n\r\n    // Create a new matrix to store the side lengths of squares\r\n    std::vector<std::vector<int>> dp(rows, std::vector<int>(cols, 0));\r\n\r\n    // Initialize the first row of the dp matrix\r\n    for (int i = 0; i < rows; i++) {\r\n        dp[i][0] = matrix[i][0] - '0';\r\n        maxSide = std::max(maxSide, dp[i][0]);\r\n    }\r\n\r\n    // Initialize the first column of the dp matrix\r\n    for (int j = 0; j < cols; j++) {\r\n        dp[0][j] = matrix[0][j] - '0';\r\n        maxSide = std::max(maxSide, dp[0][j]);\r\n    }\r\n\r\n    // Iterate over the remaining elements of the matrix\r\n    for (int i = 1; i < rows; i++) {\r\n        for (int j = 1; j < cols; j++) {\r\n            if (matrix[i][j] == '1') {\r\n                // Calculate the minimum of the three adjacent squares and add 1\r\n                dp[i][j] = std::min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]}) + 1;\r\n                maxSide = std::max(maxSide, dp[i][j]);\r\n            }\r\n        }\r\n    }\r\n\r\n    // Return the area of the maximal square\r\n    return maxSide * maxSide;\r\n}"
  },
  {
    "path": "Dynamic Programming/maximal_sqaure.go",
    "content": "/*\r\n    -> The maximalSquare function takes a matrix as input and returns the area of the maximal square found in the matrix.\r\n    -> The function first checks if the matrix is empty (no rows or columns). In such cases, there can't be any squares,\r\n     so it returns 0.\r\n    -> Next, it initializes some variables. rows stores the number of rows in the matrix, cols stores the number of\r\n     columns, and maxSide keeps track of the maximum side length of the square encountered so far.\r\n    -> It creates a new matrix called dp using the Array.from method. This matrix will store the side lengths of squares.\r\n    -> The next step is to initialize the first row and the first column of dp with the values from the input matrix. It \r\n    iterates over each element in the first row and sets the corresponding element in dp to either 0 or 1, depending on \r\n    whether the element in the input matrix is '0' or '1'. It also updates maxSide accordingly.\r\n    -> Similarly, it iterates over each element in the first column and sets the corresponding element in dp to either \r\n    0 or 1, based on the input matrix. Again, maxSide is updated.\r\n    -> Now, the function enters a nested loop to iterate over the remaining elements of the matrix, starting from the\r\n    second row and the second column. For each element at position (i, j), it checks if the corresponding element in the\r\n    input matrix is '1'.\r\n    -> If the element is '1', it calculates the value of dp[i][j] by taking the minimum of the three adjacent elements: \r\n    dp[i-1][j] (above), dp[i][j-1] (left), and dp[i-1][j-1] (diagonally above-left). It adds 1 to the minimum value and \r\n    assigns it to dp[i][j]. Additionally, it updates maxSide if the current dp[i][j] value is greater.\r\n    -> After the nested loop completes, the function has calculated the side lengths of squares for all positions in the \r\n    matrix. It returns the area of the maximal square by squaring the value of maxSide.\r\n    -> Finally, outside the function, an example usage is shown. The matrix variable represents a 2D array with 0s and 1s. \r\n    The maximalSquare function is called with this matrix, and the returned result is logged to the console. In this\r\n    example, the maximal square in the matrix has a side length of 2, so the output is 4 (2 * 2).\r\n\r\nThe code utilizes dynamic programming to efficiently calculate the maximal square in the given matrix by storing the \r\nside lengths of squares in a separate matrix. By using previously calculated values, the algorithm avoids redundant \r\ncalculations and improves performance.\r\n\r\n//Time complexity\r\n\r\nThe time complexity of the provided maximal square algorithm is O(m * n), where m is the number of rows \r\nin the matrix and n is the number of columns. This is because we iterate over each element in the matrix \r\nonce to calculate the side lengths of squares. The nested loops contribute to the linear time complexity.\r\n\r\nThe space complexity is O(m * n) as well. We create an additional matrix, dp, with the same dimensions as \r\nthe input matrix to store the side lengths of squares. Hence, the space required is proportional to the \r\nnumber of elements in the matrix.\r\n\r\nIn summary, the time complexity and space complexity of the maximal square algorithm are both O(m * n), \r\nwhere m is the number of rows and n is the number of columns in the matrix.\r\n*/\r\n\r\n\r\n/*\r\n\r\nExample 1:\r\nInput:\r\n\r\n1 0 1 0 0\r\n1 0 1 1 1\r\n1 1 1 1 1\r\n1 0 0 1 0\r\n\r\nOutput: 4 \r\nThe maximal square in the matrix is a 2x2 square with the top-left corner at position (1, 2) and the bottom-right corner at position (2, 3). The area of this square is 4.\r\n\r\nExample 2:\r\nInput:\r\n0 1 1 1 1\r\n1 1 0 1 0\r\n0 1 1 1 1\r\n1 1 1 1 0\r\n\r\n\r\nOutput: 9\r\nThe maximal square in the matrix is a 3x3 square with the top-left corner at position (0, 1) and the bottom-right corner at position (2, 3). The area of this square is 9.\r\n\r\nExample 3:\r\nInput:\r\n\r\n0 0 0\r\n0 0 0\r\n0 0 0\r\n\r\nOutput: 0\r\nThere are no squares with side length greater than 0 in the matrix. Therefore, the output is 0.\r\n\r\n*/\r\n\r\n\r\npackage main\r\n\r\nimport (\r\n\t\"fmt\"\r\n)\r\n\r\nfunc maximalSquare(matrix [][]byte) int {\r\n\tif len(matrix) == 0 || len(matrix[0]) == 0 {\r\n\t\treturn 0\r\n\t}\r\n\r\n\trows := len(matrix)\r\n\tcols := len(matrix[0])\r\n\tmaxSide := 0\r\n\r\n\t// Create a new matrix to store the side lengths of squares\r\n\tdp := make([][]int, rows)\r\n\tfor i := range dp {\r\n\t\tdp[i] = make([]int, cols)\r\n\t}\r\n\r\n\t// Initialize the first row of the dp matrix\r\n\tfor i := 0; i < rows; i++ {\r\n\t\tdp[i][0] = int(matrix[i][0] - '0')\r\n\t\tmaxSide = max(maxSide, dp[i][0])\r\n\t}\r\n\r\n\t// Initialize the first column of the dp matrix\r\n\tfor j := 0; j < cols; j++ {\r\n\t\tdp[0][j] = int(matrix[0][j] - '0')\r\n\t\tmaxSide = max(maxSide, dp[0][j])\r\n\t}\r\n\r\n\t// Iterate over the remaining elements of the matrix\r\n\tfor i := 1; i < rows; i++ {\r\n\t\tfor j := 1; j < cols; j++ {\r\n\t\t\tif matrix[i][j] == '1' {\r\n\t\t\t\t// Calculate the minimum of the three adjacent squares and add 1\r\n\t\t\t\tdp[i][j] = min(min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1\r\n\t\t\t\tmaxSide = max(maxSide, dp[i][j])\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Return the area of the maximal square\r\n\treturn maxSide * maxSide\r\n}\r\n\r\nfunc max(a, b int) int {\r\n\tif a > b {\r\n\t\treturn a\r\n\t}\r\n\treturn b\r\n}\r\n\r\nfunc min(a, b int) int {\r\n\tif a < b {\r\n\t\treturn a\r\n\t}\r\n\treturn b\r\n}\r\n"
  },
  {
    "path": "Dynamic Programming/maximal_sqaure.js",
    "content": "/*\r\n    -> The maximalSquare function takes a matrix as input and returns the area of the maximal square found in the matrix.\r\n    -> The function first checks if the matrix is empty (no rows or columns). In such cases, there can't be any squares,\r\n     so it returns 0.\r\n    -> Next, it initializes some variables. rows stores the number of rows in the matrix, cols stores the number of\r\n     columns, and maxSide keeps track of the maximum side length of the square encountered so far.\r\n    -> It creates a new matrix called dp using the Array.from method. This matrix will store the side lengths of squares.\r\n    -> The next step is to initialize the first row and the first column of dp with the values from the input matrix. It \r\n    iterates over each element in the first row and sets the corresponding element in dp to either 0 or 1, depending on \r\n    whether the element in the input matrix is '0' or '1'. It also updates maxSide accordingly.\r\n    -> Similarly, it iterates over each element in the first column and sets the corresponding element in dp to either \r\n    0 or 1, based on the input matrix. Again, maxSide is updated.\r\n    -> Now, the function enters a nested loop to iterate over the remaining elements of the matrix, starting from the\r\n    second row and the second column. For each element at position (i, j), it checks if the corresponding element in the\r\n    input matrix is '1'.\r\n    -> If the element is '1', it calculates the value of dp[i][j] by taking the minimum of the three adjacent elements: \r\n    dp[i-1][j] (above), dp[i][j-1] (left), and dp[i-1][j-1] (diagonally above-left). It adds 1 to the minimum value and \r\n    assigns it to dp[i][j]. Additionally, it updates maxSide if the current dp[i][j] value is greater.\r\n    -> After the nested loop completes, the function has calculated the side lengths of squares for all positions in the \r\n    matrix. It returns the area of the maximal square by squaring the value of maxSide.\r\n    -> Finally, outside the function, an example usage is shown. The matrix variable represents a 2D array with 0s and 1s. \r\n    The maximalSquare function is called with this matrix, and the returned result is logged to the console. In this\r\n    example, the maximal square in the matrix has a side length of 2, so the output is 4 (2 * 2).\r\n\r\nThe code utilizes dynamic programming to efficiently calculate the maximal square in the given matrix by storing the \r\nside lengths of squares in a separate matrix. By using previously calculated values, the algorithm avoids redundant \r\ncalculations and improves performance.\r\n\r\n//Time complexity\r\n\r\nThe time complexity of the provided maximal square algorithm is O(m * n), where m is the number of rows \r\nin the matrix and n is the number of columns. This is because we iterate over each element in the matrix \r\nonce to calculate the side lengths of squares. The nested loops contribute to the linear time complexity.\r\n\r\nThe space complexity is O(m * n) as well. We create an additional matrix, dp, with the same dimensions as \r\nthe input matrix to store the side lengths of squares. Hence, the space required is proportional to the \r\nnumber of elements in the matrix.\r\n\r\nIn summary, the time complexity and space complexity of the maximal square algorithm are both O(m * n), \r\nwhere m is the number of rows and n is the number of columns in the matrix.\r\n*/\r\n\r\n/*\r\n\r\nExample 1:\r\nInput:\r\n\r\n1 0 1 0 0\r\n1 0 1 1 1\r\n1 1 1 1 1\r\n1 0 0 1 0\r\n\r\nOutput: 4 \r\nThe maximal square in the matrix is a 2x2 square with the top-left corner at position (1, 2) and the bottom-right corner at position (2, 3). The area of this square is 4.\r\n\r\nExample 2:\r\nInput:\r\n0 1 1 1 1\r\n1 1 0 1 0\r\n0 1 1 1 1\r\n1 1 1 1 0\r\n\r\n\r\nOutput: 9\r\nThe maximal square in the matrix is a 3x3 square with the top-left corner at position (0, 1) and the bottom-right corner at position (2, 3). The area of this square is 9.\r\n\r\nExample 3:\r\nInput:\r\n\r\n0 0 0\r\n0 0 0\r\n0 0 0\r\n\r\nOutput: 0\r\nThere are no squares with side length greater than 0 in the matrix. Therefore, the output is 0.\r\n\r\n*/\r\n\r\nfunction maximalSquare(matrix) {\r\n  if (matrix.length === 0 || matrix[0].length === 0) {\r\n    return 0;\r\n  }\r\n\r\n  const rows = matrix.length;\r\n  const cols = matrix[0].length;\r\n  let maxSide = 0;\r\n\r\n  // Create a new matrix to store the side lengths of squares\r\n  const dp = Array.from({ length: rows }, () => Array(cols).fill(0));\r\n\r\n  // Initialize the first row of the dp matrix\r\n  for (let i = 0; i < rows; i++) {\r\n    dp[i][0] = Number(matrix[i][0]);\r\n    maxSide = Math.max(maxSide, dp[i][0]);\r\n  }\r\n\r\n  // Initialize the first column of the dp matrix\r\n  for (let j = 0; j < cols; j++) {\r\n    dp[0][j] = Number(matrix[0][j]);\r\n    maxSide = Math.max(maxSide, dp[0][j]);\r\n  }\r\n\r\n  // Iterate over the remaining elements of the matrix\r\n  for (let i = 1; i < rows; i++) {\r\n    for (let j = 1; j < cols; j++) {\r\n      if (matrix[i][j] === '1') {\r\n        // Calculate the minimum of the three adjacent squares and add 1\r\n        dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1;\r\n        maxSide = Math.max(maxSide, dp[i][j]);\r\n      }\r\n    }\r\n  }\r\n\r\n  // Return the area of the maximal square\r\n  return maxSide * maxSide;\r\n}\r\n\r\n"
  },
  {
    "path": "Dynamic Programming/maximal_sqaure.py",
    "content": "'''\r\n    -> The maximalSquare function takes a matrix as input and returns the area of the maximal square found in the matrix.\r\n    -> The function first checks if the matrix is empty (no rows or columns). In such cases, there can't be any squares,\r\n     so it returns 0.\r\n    -> Next, it initializes some variables. rows stores the number of rows in the matrix, cols stores the number of\r\n     columns, and maxSide keeps track of the maximum side length of the square encountered so far.\r\n    -> It creates a new matrix called dp using the Array.from method. This matrix will store the side lengths of squares.\r\n    -> The next step is to initialize the first row and the first column of dp with the values from the input matrix. It \r\n    iterates over each element in the first row and sets the corresponding element in dp to either 0 or 1, depending on \r\n    whether the element in the input matrix is '0' or '1'. It also updates maxSide accordingly.\r\n    -> Similarly, it iterates over each element in the first column and sets the corresponding element in dp to either \r\n    0 or 1, based on the input matrix. Again, maxSide is updated.\r\n    -> Now, the function enters a nested loop to iterate over the remaining elements of the matrix, starting from the\r\n    second row and the second column. For each element at position (i, j), it checks if the corresponding element in the\r\n    input matrix is '1'.\r\n    -> If the element is '1', it calculates the value of dp[i][j] by taking the minimum of the three adjacent elements: \r\n    dp[i-1][j] (above), dp[i][j-1] (left), and dp[i-1][j-1] (diagonally above-left). It adds 1 to the minimum value and \r\n    assigns it to dp[i][j]. Additionally, it updates maxSide if the current dp[i][j] value is greater.\r\n    -> After the nested loop completes, the function has calculated the side lengths of squares for all positions in the \r\n    matrix. It returns the area of the maximal square by squaring the value of maxSide.\r\n    -> Finally, outside the function, an example usage is shown. The matrix variable represents a 2D array with 0s and 1s. \r\n    The maximalSquare function is called with this matrix, and the returned result is logged to the console. In this\r\n    example, the maximal square in the matrix has a side length of 2, so the output is 4 (2 * 2).\r\n\r\nThe code utilizes dynamic programming to efficiently calculate the maximal square in the given matrix by storing the \r\nside lengths of squares in a separate matrix. By using previously calculated values, the algorithm avoids redundant \r\ncalculations and improves performance.\r\n\r\n//Time complexity\r\n\r\nThe time complexity of the provided maximal square algorithm is O(m * n), where m is the number of rows \r\nin the matrix and n is the number of columns. This is because we iterate over each element in the matrix \r\nonce to calculate the side lengths of squares. The nested loops contribute to the linear time complexity.\r\n\r\nThe space complexity is O(m * n) as well. We create an additional matrix, dp, with the same dimensions as \r\nthe input matrix to store the side lengths of squares. Hence, the space required is proportional to the \r\nnumber of elements in the matrix.\r\n\r\nIn summary, the time complexity and space complexity of the maximal square algorithm are both O(m * n), \r\nwhere m is the number of rows and n is the number of columns in the matrix.\r\n'''\r\n\r\n\r\n'''\r\n\r\nExample 1:\r\nInput:\r\n\r\n1 0 1 0 0\r\n1 0 1 1 1\r\n1 1 1 1 1\r\n1 0 0 1 0\r\n\r\nOutput: 4 \r\nThe maximal square in the matrix is a 2x2 square with the top-left corner at position (1, 2) and the bottom-right corner at position (2, 3). The area of this square is 4.\r\n\r\nExample 2:\r\nInput:\r\n0 1 1 1 1\r\n1 1 0 1 0\r\n0 1 1 1 1\r\n1 1 1 1 0\r\n\r\n\r\nOutput: 9\r\nThe maximal square in the matrix is a 3x3 square with the top-left corner at position (0, 1) and the bottom-right corner at position (2, 3). The area of this square is 9.\r\n\r\nExample 3:\r\nInput:\r\n\r\n0 0 0\r\n0 0 0\r\n0 0 0\r\n\r\nOutput: 0\r\nThere are no squares with side length greater than 0 in the matrix. Therefore, the output is 0.\r\n\r\n'''\r\n\r\ndef maximalSquare(matrix):\r\n    if len(matrix) == 0 or len(matrix[0]) == 0:\r\n        return 0\r\n\r\n    rows = len(matrix)\r\n    cols = len(matrix[0])\r\n    maxSide = 0\r\n\r\n    # Create a new matrix to store the side lengths of squares\r\n    dp = [[0] * cols for _ in range(rows)]\r\n\r\n    # Initialize the first row of the dp matrix\r\n    for i in range(rows):\r\n        dp[i][0] = int(matrix[i][0])\r\n        maxSide = max(maxSide, dp[i][0])\r\n\r\n    # Initialize the first column of the dp matrix\r\n    for j in range(cols):\r\n        dp[0][j] = int(matrix[0][j])\r\n        maxSide = max(maxSide, dp[0][j])\r\n\r\n    # Iterate over the remaining elements of the matrix\r\n    for i in range(1, rows):\r\n        for j in range(1, cols):\r\n            if matrix[i][j] == '1':\r\n                # Calculate the minimum of the three adjacent squares and add 1\r\n                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1\r\n                maxSide = max(maxSide, dp[i][j])\r\n\r\n    # Return the area of the maximal square\r\n    return maxSide * maxSide\r\n"
  },
  {
    "path": "Dynamic Programming/maximal_square.java",
    "content": "/*\nProblem:\nGiven an m x n binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area.\n\nApproach:\n1. Initialize a variable `maxSide` to 0 to store the maximum side length of the square.\n2. Check if the given matrix is empty, if so, return 0.\n3. Create a dynamic programming array `dp` with dimensions (rows + 1) x (cols + 1), where `rows` and `cols` are the dimensions of the matrix.\n4. Traverse through the matrix starting from index (1, 1) to (rows, cols).\n5. For each cell, if the value is '1', calculate the side length of the square by taking the minimum of the values from the top, left, and diagonal cells in the `dp` array, and add 1.\n6. Update the `maxSide` variable with the maximum side length found so far.\n7. Finally, return the area of the largest square by multiplying `maxSide` with itself.\n\nTime Complexity: O(m*n), where m is the number of rows and n is the number of columns in the matrix.\n\nSpace Complexity: O(m*n), as we use an additional dp array of the same dimensions as the matrix.\n\nSample Input:\nchar[][] matrix = {\n    {'1', '0', '1', '0', '0'},\n    {'1', '0', '1', '1', '1'},\n    {'1', '1', '1', '1', '1'},\n    {'1', '0', '0', '1', '0'}\n};\n\nSample Output:\n4\n\nNote: In the given sample input, the largest square containing only 1's has a side length of 2, so the area is 4.\n*/\n\n\npublic class LargestSquare {\n    public int maximalSquare(char[][] matrix) {\n        int maxSide = 0; // variable to store the maximum side length of the square\n        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {\n            return maxSide; // return 0 if the matrix is empty\n        }\n\n        int rows = matrix.length;\n        int cols = matrix[0].length;\n        int[][] dp = new int[rows + 1][cols + 1]; // create a dynamic programming array to store the side length of the square\n\n        for (int i = 1; i <= rows; i++) {\n            for (int j = 1; j <= cols; j++) {\n                if (matrix[i-1][j-1] == '1') { // if current cell is 1\n                    dp[i][j] = Math.min(Math.min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1; // calculate the side length of the square based on top, left, and diagonal cells\n                    maxSide = Math.max(maxSide, dp[i][j]); // update the maximum side length\n                }\n            }\n        }\n\n        return maxSide * maxSide; // return the area of the largest square\n    }\n}\n\n\n"
  },
  {
    "path": "Dynamic Programming/min_cost_travel_in_a_grid.cpp",
    "content": "/*\n    Given a cost matrix cost[][] and a position (m, n) in cost[][], \n    write a function that returns cost of minimum cost path to reach (m, n) from (0, 0). \n    Each cell of the matrix represents a cost to traverse through that cell. \n    The total cost of a path to reach (m, n) is the sum of all the costs on that path \n    (including both source and destination). You can only traverse down and right\n    from a given cell, i.e., from a given cell (i, j), cells \n    (i+1, j), (i, j+1) can be traversed. You may assume that all \n    costs are positive integers.\n    Input  : {1, 2, 3, 4},\n             {5, 6, 7, 8},\n             {9, 10, 11, 12}\n    Output : 30 [Path : 1->2->3->4->8->12]\n*/\n// Program Author : Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\nint dp[100][100] = {};\nint min_cost_path_in_a_grid(int grid[][100], int m, int n){\n    \n    dp[0][0] = grid[0][0];\n    //row\n    for(int i = 1; i < m; i++){\n        dp[i][0] = grid[i][0] + dp[i - 1][0];\n    }\n    //col\n    for(int i = 1; i < n; i++){\n        dp[0][i] = grid[0][i] + dp[0][i - 1];\n    }\n\n    for(int i = 1; i < m; i++){\n        for(int j = 1; j < n; j++){\n            dp[i][j] = grid[i][j] + min(dp[i - 1][j], dp[i][j - 1]);\n        }\n    }\n    return dp[m-1][n-1];\n}\nint main(){\n    int grid[100][100] = {\n        {1, 2, 3, 4},\n        {5, 6, 7, 8},\n        {9, 10, 11, 12}\n    };\n    int m = 3, n = 4;\n    int result = min_cost_path_in_a_grid(grid, m, n);\n    for(int i = 0; i < m; i++){\n        for(int j = 0; j < n; j++){\n            cout << setw(5) <<dp[i][j] << \" \";\n        }\n        cout << \"\\n\";\n    }\n    cout << result;\n}"
  },
  {
    "path": "Dynamic Programming/min_insertion_steps_for_string_palindrome.java",
    "content": "/*\r\n    Given a string, find the minimum number of insertions needed to make it a palindrome.\r\n\r\n    Sample Input: \"abcde\"\r\n    Sample Output: 4\r\n    Explanation: The minimum insertions required are 'edcb' -> \"abcdecb\", resulting in a palindrome.\r\n\r\n    Approach:\r\n    We can solve this problem using dynamic programming.\r\n    Let's define a 2D table, dp, where dp[i][j] represents the minimum number of insertions needed to make the substring from index i to j a palindrome.\r\n    If the characters at indices i and j are equal, then dp[i][j] = dp[i+1][j-1].\r\n    Otherwise, we have two options:\r\n        1. Insert the character at index i at the end, i.e., dp[i][j] = dp[i][j-1] + 1.\r\n        2. Insert the character at index j at the beginning, i.e., dp[i][j] = dp[i+1][j] + 1.\r\n    We take the minimum of these two options as the minimum number of insertions required for the substring from index i to j.\r\n    Finally, the minimum number of insertions needed for the entire string is dp[0][n-1], where n is the length of the string.\r\n\r\n    Time complexity: O(n^2)\r\n    Space complexity: O(n^2)\r\n*/\r\n\r\npublic class PalindromeInsertion {\r\n    public static int findMinInsertions(String s) {\r\n        int n = s.length();\r\n        int[][] dp = new int[n][n];\r\n\r\n        for (int len = 2; len <= n; len++) {\r\n            for (int i = 0; i <= n - len; i++) {\r\n                int j = i + len - 1;\r\n                if (s.charAt(i) == s.charAt(j))\r\n                    dp[i][j] = dp[i + 1][j - 1];\r\n                else\r\n                    dp[i][j] = Math.min(dp[i][j - 1], dp[i + 1][j]) + 1;\r\n            }\r\n        }\r\n\r\n        return dp[0][n - 1];\r\n    }\r\n\r\n    public static void main(String[] args) {\r\n        String input = \"abcde\";\r\n        int minInsertions = findMinInsertions(input);\r\n        System.out.println(\"Minimum insertions required: \" + minInsertions);\r\n    }\r\n}\r\n"
  },
  {
    "path": "Dynamic Programming/min_number_of_jumps.cpp",
    "content": "/*\n\tThe given code snippet calculates the minimum number of jumps required to reach the end of an array of integers. \n\tEach element in the array represents the maximum distance you can jump from that position.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MinNumberOfJumps` takes an integer array `array` as input and returns the minimum number of jumps \n\trequired to reach the last element.\n\n\t2. The code first checks if the length of the `array` is 1. If so, it means there's only one element, and we don't \n\tneed any jumps to reach the end. In this case, the function returns 0.\n\n\t3. If the array has more than one element, the code proceeds with the jump calculation.\n\n\t4. The variables `jumps`, `maxreach`, and `steps` are initialized. `jumps` keeps track of the total number of jumps \n\ttaken, `maxreach` represents the farthest position that can be reached in a single jump, and `steps` represents the \n\tremaining steps until a new jump is required.\n\n\t5. The loop starts from the second element (index 1) and iterates until the second-to-last element (index `len(array) - 1`). \n\tThe reason for stopping at the second-to-last element is that we don't need to take any additional jumps from there, as \n\twe are already at the end.\n\n\t6. For each iteration, the code checks if the current index plus the value at that index (`i + array[i]`) is greater \n\tthan the current `maxreach`. If so, it updates `maxreach` to the new value, representing the farthest position that \n\tcan be reached in a single jump.\n\n\t7. It then decrements `steps` by 1, representing the steps taken in the current jump.\n\n\t8. If `steps` becomes 0, it means the current jump is completed, and a new jump is required. So, it increments `jumps` \n\tby 1 and updates `steps` with the number of steps required to reach the farthest position (i.e., `maxreach - i`).\n\n\t9. After the loop completes, the function returns `jumps + 1`. The `+1` is added because the loop doesn't consider the \n\tlast element in the array (as we don't need an additional jump from there), so we need to add one more jump to reach the last element.\n\n\tIn summary, the code efficiently calculates the minimum number of jumps required to reach the last element in the array \n\tby simulating the jumps and keeping track of the farthest position that can be reached in each jump. The final result \n\tis the total number of jumps taken to reach the end.\n*/\n#include <vector>\n#include <algorithm>\n\nint MinNumberOfJumpsOptimal(std::vector<int>& array) {\n    // If the array has only one element, no jumps are needed.\n    if (array.size() == 1) {\n        return 0;\n    }\n\n    // Initialize variables to keep track of jumps, maximum reachable position, and remaining steps in a jump.\n    int jumps = 0;\n    int maxreach = array[0];\n    int steps = array[0];\n\n    // Iterate through the array to calculate the minimum number of jumps.\n    // We stop at the second-to-last element as we don't need an additional jump from there.\n    for (int i = 1; i < array.size() - 1; i++) {\n        // Update the maximum reachable position if the current position plus the value at that index is greater.\n        if (i + array[i] > maxreach) {\n            maxreach = i + array[i];\n        }\n\n        // Decrement the remaining steps in the current jump.\n        steps--;\n\n        // If the current jump is completed (steps becomes 0), calculate the new jump.\n        if (steps == 0) {\n            // Increment jumps to count the completed jump.\n            jumps++;\n\n            // Update steps to the number of steps required to reach the farthest position.\n            steps = maxreach - i;\n        }\n    }\n\n    // The minimum number of jumps to reach the last element is the total number of jumps taken plus one\n    // because the loop doesn't consider the last element (as we don't need an additional jump from there).\n    return jumps + 1;\n}\n"
  },
  {
    "path": "Dynamic Programming/min_number_of_jumps.go",
    "content": "/*\n\tThis Go code snippet implements the `MinNumberOfJumps` function, which calculates the minimum number of jumps required to reach the\n\tlast element of the `array` by starting from the first element. Each element of the array represents the maximum number of steps that\n\tcan be taken from that position.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MinNumberOfJumps` takes an array `array` as input and returns the minimum number of jumps required.\n\n\t2. The `ways` array is initialized to store the minimum number of jumps required to reach each position in the input array. The length of\n\tthe `ways` array is the same as the input array, and all values are initialized to `math.MaxInt32`, which represents an unreachable state.\n\n\t3. The base case is set for the first element of the `ways` array. Since we are already at the first element, the minimum number of jumps\n\trequired is 0. So, `ways[0]` is set to 0.\n\n\t4. Starting from the second element (i = 1) to the last element (i = len(array) - 1), the function iterates through the `array`.\n\n\t5. For each element, it iterates through all previous elements (j) up to the current position (i) to check if it is possible to jump from j to i.\n\n\t6. If `array[j] + j >= i`, it means we can jump from position `j` to position `i`.\n\n\t7. The `ways[i]` value is then updated using the minimum between the current `ways[i]` value and `ways[j] + 1`. The `ways[j] + 1` represents\n\tthe minimum number of jumps required to reach position `j`, and then from position `j` to position `i`.\n\n\t8. After all iterations, `ways[len(ways) - 1]` will contain the minimum number of jumps required to reach the last element of the array.\n\n\t9. The `min` function is a helper function that returns the minimum of two integers.\n\n\tThe `MinNumberOfJumps` function uses dynamic programming to find the minimum number of jumps efficiently by keeping track of the minimum number\n\tof jumps required to reach each position from the previous positions. The time complexity of this function is O(n^2), where n is the length of\n\tthe input array. The space complexity is O(n), as the `ways` array is used to store the minimum jumps for each position in the array.\n*/\npackage main\n\nimport \"math\"\n\n// MinNumberOfJumps calculates the minimum number of jumps required to reach the last element of the `array`.\nfunc MinNumberOfJumps(array []int) int {\n\t// Create an array to store the minimum number of jumps required to reach each position in the `array`.\n\tways := make([]int, len(array))\n\t\n\t// Initialize the `ways` array with maximum integer values representing an unreachable state.\n\tfor i := range ways {\n\t\tways[i] = math.MaxInt32\n\t}\n\t\n\t// Base case: The first element requires 0 jumps to reach itself.\n\tways[0] = 0\n\t\n\t// Iterate through the array starting from the second element.\n\tfor i := 1; i < len(array); i++ {\n\t\t// Check all previous elements to see if a jump from j to i is possible.\n\t\tfor j := 0; j < i; j++ {\n\t\t\t// If it is possible to jump from j to i, update the `ways[i]` value.\n\t\t\tif array[j] + j >= i {\n\t\t\t\tways[i] = min(ways[i], ways[j]+1)\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// The value at `ways[len(ways) - 1]` will contain the minimum number of jumps required to reach the last element.\n\treturn ways[len(ways)-1]\n}\n\n// min returns the minimum of two integers.\nfunc min(a, b int) int {\n\tif a < b {\n\t\treturn a\n\t}\n\treturn b\n}\n\n\n/*\n\tThe given code snippet calculates the minimum number of jumps required to reach the end of an array of integers. \n\tEach element in the array represents the maximum distance you can jump from that position.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MinNumberOfJumps` takes an integer array `array` as input and returns the minimum number of jumps \n\trequired to reach the last element.\n\n\t2. The code first checks if the length of the `array` is 1. If so, it means there's only one element, and we don't \n\tneed any jumps to reach the end. In this case, the function returns 0.\n\n\t3. If the array has more than one element, the code proceeds with the jump calculation.\n\n\t4. The variables `jumps`, `maxreach`, and `steps` are initialized. `jumps` keeps track of the total number of jumps \n\ttaken, `maxreach` represents the farthest position that can be reached in a single jump, and `steps` represents the \n\tremaining steps until a new jump is required.\n\n\t5. The loop starts from the second element (index 1) and iterates until the second-to-last element (index `len(array) - 1`). \n\tThe reason for stopping at the second-to-last element is that we don't need to take any additional jumps from there, as \n\twe are already at the end.\n\n\t6. For each iteration, the code checks if the current index plus the value at that index (`i + array[i]`) is greater \n\tthan the current `maxreach`. If so, it updates `maxreach` to the new value, representing the farthest position that \n\tcan be reached in a single jump.\n\n\t7. It then decrements `steps` by 1, representing the steps taken in the current jump.\n\n\t8. If `steps` becomes 0, it means the current jump is completed, and a new jump is required. So, it increments `jumps` \n\tby 1 and updates `steps` with the number of steps required to reach the farthest position (i.e., `maxreach - i`).\n\n\t9. After the loop completes, the function returns `jumps + 1`. The `+1` is added because the loop doesn't consider the \n\tlast element in the array (as we don't need an additional jump from there), so we need to add one more jump to reach the last element.\n\n\tIn summary, the code efficiently calculates the minimum number of jumps required to reach the last element in the array \n\tby simulating the jumps and keeping track of the farthest position that can be reached in each jump. The final result \n\tis the total number of jumps taken to reach the end.\n*/\nfunc MinNumberOfJumpsOptimal(array []int) int {\n\t// If the array has only one element, no jumps are needed.\n\tif len(array) == 1 {\n\t\treturn 0\n\t}\n\n\t// Initialize variables to keep track of jumps, maximum reachable position, and remaining steps in a jump.\n\tjumps := 0\n\tmaxreach, steps := array[0], array[0]\n\n\t// Iterate through the array to calculate the minimum number of jumps.\n\t// We stop at the second-to-last element as we don't need an additional jump from there.\n\tfor i := 1; i < len(array)-1; i++ {\n\t\t// Update the maximum reachable position if the current position plus the value at that index is greater.\n\t\tif i+array[i] > maxreach {\n\t\t\tmaxreach = i + array[i]\n\t\t}\n\n\t\t// Decrement the remaining steps in the current jump.\n\t\tsteps--\n\n\t\t// If the current jump is completed (steps becomes 0), calculate the new jump.\n\t\tif steps == 0 {\n\t\t\t// Increment jumps to count the completed jump.\n\t\t\tjumps++\n\n\t\t\t// Update steps to the number of steps required to reach the farthest position.\n\t\t\tsteps = maxreach - i\n\t\t}\n\t}\n\n\t// The minimum number of jumps to reach the last element is the total number of jumps taken plus one\n\t// because the loop doesn't consider the last element (as we don't need an additional jump from there).\n\treturn jumps + 1\n}\n"
  },
  {
    "path": "Dynamic Programming/min_number_of_jumps.java",
    "content": "public class min_number_of_jumps {\n    \n}\n/*\n\tThe given code snippet calculates the minimum number of jumps required to reach the end of an array of integers. \n\tEach element in the array represents the maximum distance you can jump from that position.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MinNumberOfJumps` takes an integer array `array` as input and returns the minimum number of jumps \n\trequired to reach the last element.\n\n\t2. The code first checks if the length of the `array` is 1. If so, it means there's only one element, and we don't \n\tneed any jumps to reach the end. In this case, the function returns 0.\n\n\t3. If the array has more than one element, the code proceeds with the jump calculation.\n\n\t4. The variables `jumps`, `maxreach`, and `steps` are initialized. `jumps` keeps track of the total number of jumps \n\ttaken, `maxreach` represents the farthest position that can be reached in a single jump, and `steps` represents the \n\tremaining steps until a new jump is required.\n\n\t5. The loop starts from the second element (index 1) and iterates until the second-to-last element (index `len(array) - 1`). \n\tThe reason for stopping at the second-to-last element is that we don't need to take any additional jumps from there, as \n\twe are already at the end.\n\n\t6. For each iteration, the code checks if the current index plus the value at that index (`i + array[i]`) is greater \n\tthan the current `maxreach`. If so, it updates `maxreach` to the new value, representing the farthest position that \n\tcan be reached in a single jump.\n\n\t7. It then decrements `steps` by 1, representing the steps taken in the current jump.\n\n\t8. If `steps` becomes 0, it means the current jump is completed, and a new jump is required. So, it increments `jumps` \n\tby 1 and updates `steps` with the number of steps required to reach the farthest position (i.e., `maxreach - i`).\n\n\t9. After the loop completes, the function returns `jumps + 1`. The `+1` is added because the loop doesn't consider the \n\tlast element in the array (as we don't need an additional jump from there), so we need to add one more jump to reach the last element.\n\n\tIn summary, the code efficiently calculates the minimum number of jumps required to reach the last element in the array \n\tby simulating the jumps and keeping track of the farthest position that can be reached in each jump. The final result \n\tis the total number of jumps taken to reach the end.\n*/\npublic static int minNumberOfJumpsOptimal(int[] array) {\n    // If the array has only one element, no jumps are needed.\n    if (array.length == 1) {\n        return 0;\n    }\n\n    // Initialize variables to keep track of jumps, maximum reachable position, and remaining steps in a jump.\n    int jumps = 0;\n    int maxReach = array[0];\n    int steps = array[0];\n\n    // Iterate through the array to calculate the minimum number of jumps.\n    // We stop at the second-to-last element as we don't need an additional jump from there.\n    for (int i = 1; i < array.length - 1; i++) {\n        // Update the maximum reachable position if the current position plus the value at that index is greater.\n        if (i + array[i] > maxReach) {\n            maxReach = i + array[i];\n        }\n\n        // Decrement the remaining steps in the current jump.\n        steps--;\n\n        // If the current jump is completed (steps becomes 0), calculate the new jump.\n        if (steps == 0) {\n            // Increment jumps to count the completed jump.\n            jumps++;\n\n            // Update steps to the number of steps required to reach the farthest position.\n            steps = maxReach - i;\n        }\n    }\n\n    // The minimum number of jumps to reach the last element is the total number of jumps taken plus one\n    // because the loop doesn't consider the last element (as we don't need an additional jump from there).\n    return jumps + 1;\n}\n"
  },
  {
    "path": "Dynamic Programming/min_number_of_jumps.js",
    "content": "/*\n\tThe given code snippet calculates the minimum number of jumps required to reach the end of an array of integers. \n\tEach element in the array represents the maximum distance you can jump from that position.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MinNumberOfJumps` takes an integer array `array` as input and returns the minimum number of jumps \n\trequired to reach the last element.\n\n\t2. The code first checks if the length of the `array` is 1. If so, it means there's only one element, and we don't \n\tneed any jumps to reach the end. In this case, the function returns 0.\n\n\t3. If the array has more than one element, the code proceeds with the jump calculation.\n\n\t4. The variables `jumps`, `maxreach`, and `steps` are initialized. `jumps` keeps track of the total number of jumps \n\ttaken, `maxreach` represents the farthest position that can be reached in a single jump, and `steps` represents the \n\tremaining steps until a new jump is required.\n\n\t5. The loop starts from the second element (index 1) and iterates until the second-to-last element (index `len(array) - 1`). \n\tThe reason for stopping at the second-to-last element is that we don't need to take any additional jumps from there, as \n\twe are already at the end.\n\n\t6. For each iteration, the code checks if the current index plus the value at that index (`i + array[i]`) is greater \n\tthan the current `maxreach`. If so, it updates `maxreach` to the new value, representing the farthest position that \n\tcan be reached in a single jump.\n\n\t7. It then decrements `steps` by 1, representing the steps taken in the current jump.\n\n\t8. If `steps` becomes 0, it means the current jump is completed, and a new jump is required. So, it increments `jumps` \n\tby 1 and updates `steps` with the number of steps required to reach the farthest position (i.e., `maxreach - i`).\n\n\t9. After the loop completes, the function returns `jumps + 1`. The `+1` is added because the loop doesn't consider the \n\tlast element in the array (as we don't need an additional jump from there), so we need to add one more jump to reach the last element.\n\n\tIn summary, the code efficiently calculates the minimum number of jumps required to reach the last element in the array \n\tby simulating the jumps and keeping track of the farthest position that can be reached in each jump. The final result \n\tis the total number of jumps taken to reach the end.\n*/\nfunction minNumberOfJumpsOptimal(array) {\n  // If the array has only one element, no jumps are needed.\n  if (array.length === 1) {\n    return 0;\n  }\n\n  // Initialize variables to keep track of jumps, maximum reachable position, and remaining steps in a jump.\n  let jumps = 0;\n  let maxReach = array[0];\n  let steps = array[0];\n\n  // Iterate through the array to calculate the minimum number of jumps.\n  // We stop at the second-to-last element as we don't need an additional jump from there.\n  for (let i = 1; i < array.length - 1; i++) {\n    // Update the maximum reachable position if the current position plus the value at that index is greater.\n    if (i + array[i] > maxReach) {\n      maxReach = i + array[i];\n    }\n\n    // Decrement the remaining steps in the current jump.\n    steps--;\n\n    // If the current jump is completed (steps becomes 0), calculate the new jump.\n    if (steps === 0) {\n      // Increment jumps to count the completed jump.\n      jumps++;\n\n      // Update steps to the number of steps required to reach the farthest position.\n      steps = maxReach - i;\n    }\n  }\n\n  // The minimum number of jumps to reach the last element is the total number of jumps taken plus one\n  // because the loop doesn't consider the last element (as we don't need an additional jump from there).\n  return jumps + 1;\n}\n"
  },
  {
    "path": "Dynamic Programming/min_number_of_jumps.py",
    "content": "'''\n\tThe given code snippet calculates the minimum number of jumps required to reach the end of an array of integers. \n\tEach element in the array represents the maximum distance you can jump from that position.\n\n\tHere's a step-by-step explanation of the code:\n\n\t1. The function `MinNumberOfJumps` takes an integer array `array` as input and returns the minimum number of jumps \n\trequired to reach the last element.\n\n\t2. The code first checks if the length of the `array` is 1. If so, it means there's only one element, and we don't \n\tneed any jumps to reach the end. In this case, the function returns 0.\n\n\t3. If the array has more than one element, the code proceeds with the jump calculation.\n\n\t4. The variables `jumps`, `maxreach`, and `steps` are initialized. `jumps` keeps track of the total number of jumps \n\ttaken, `maxreach` represents the farthest position that can be reached in a single jump, and `steps` represents the \n\tremaining steps until a new jump is required.\n\n\t5. The loop starts from the second element (index 1) and iterates until the second-to-last element (index `len(array) - 1`). \n\tThe reason for stopping at the second-to-last element is that we don't need to take any additional jumps from there, as \n\twe are already at the end.\n\n\t6. For each iteration, the code checks if the current index plus the value at that index (`i + array[i]`) is greater \n\tthan the current `maxreach`. If so, it updates `maxreach` to the new value, representing the farthest position that \n\tcan be reached in a single jump.\n\n\t7. It then decrements `steps` by 1, representing the steps taken in the current jump.\n\n\t8. If `steps` becomes 0, it means the current jump is completed, and a new jump is required. So, it increments `jumps` \n\tby 1 and updates `steps` with the number of steps required to reach the farthest position (i.e., `maxreach - i`).\n\n\t9. After the loop completes, the function returns `jumps + 1`. The `+1` is added because the loop doesn't consider the \n\tlast element in the array (as we don't need an additional jump from there), so we need to add one more jump to reach the last element.\n\n\tIn summary, the code efficiently calculates the minimum number of jumps required to reach the last element in the array \n\tby simulating the jumps and keeping track of the farthest position that can be reached in each jump. The final result \n\tis the total number of jumps taken to reach the end.\n'''\ndef min_number_of_jumps_optimal(array):\n    # If the array has only one element, no jumps are needed.\n    if len(array) == 1:\n        return 0\n\n    # Initialize variables to keep track of jumps, maximum reachable position, and remaining steps in a jump.\n    jumps = 0\n    max_reach = array[0]\n    steps = array[0]\n\n    # Iterate through the array to calculate the minimum number of jumps.\n    # We stop at the second-to-last element as we don't need an additional jump from there.\n    for i in range(1, len(array) - 1):\n        # Update the maximum reachable position if the current position plus the value at that index is greater.\n        if i + array[i] > max_reach:\n            max_reach = i + array[i]\n\n        # Decrement the remaining steps in the current jump.\n        steps -= 1\n\n        # If the current jump is completed (steps becomes 0), calculate the new jump.\n        if steps == 0:\n            # Increment jumps to count the completed jump.\n            jumps += 1\n\n            # Update steps to the number of steps required to reach the farthest position.\n            steps = max_reach - i\n\n    # The minimum number of jumps to reach the last element is the total number of jumps taken plus one\n    # because the loop doesn't consider the last element (as we don't need an additional jump from there).\n    return jumps + 1\n"
  },
  {
    "path": "Dynamic Programming/min_steps_to_make_string_palindrome.go",
    "content": "/*\n    Given a string, find the minimum number of insertions needed to make it a palindrome.\n\n    Sample Input: \"abcde\"\n    Sample Output: 4\n    Explanation: The minimum insertions required are 'edcb' -> \"abcdecb\", resulting in a palindrome.\n\n    Approach:\n    We can solve this problem using dynamic programming.\n    Let's define a 2D table, dp, where dp[i][j] represents the minimum number of insertions needed to make the substring from index i to j a palindrome.\n    If the characters at indices i and j are equal, then dp[i][j] = dp[i+1][j-1].\n    Otherwise, we have two options:\n        1. Insert the character at index i at the end, i.e., dp[i][j] = dp[i][j-1] + 1.\n        2. Insert the character at index j at the beginning, i.e., dp[i][j] = dp[i+1][j] + 1.\n    We take the minimum of these two options as the minimum number of insertions required for the substring from index i to j.\n    Finally, the minimum number of insertions needed for the entire string is dp[0][n-1], where n is the length of the string.\n\n    Time complexity: O(n^2)\n    Space complexity: O(n^2)\n*/\n\npackage main\n\nimport (\n\t\"fmt\"\n)\n\nfunc lcs(s1, s2 string) int {\n\tn, m := len(s1), len(s2)\n\tdp := make([][]int, n+1) // Create a 2D matrix dp to store the lengths of LCS\n\tfor i := 0; i <= n; i++ {\n\t\tdp[i] = make([]int, m+1)\n\t}\n\n\tfor i := 1; i <= n; i++ {\n\t\tfor j := 1; j <= m; j++ {\n\t\t\tif s1[i-1] == s2[j-1] { // If characters at the current positions match\n\t\t\t\tdp[i][j] = 1 + dp[i-1][j-1] // Increase the length of LCS by 1\n\t\t\t} else {\n\t\t\t\tdp[i][j] = max(dp[i-1][j], dp[i][j-1]) // Take the maximum length from the previous positions\n\t\t\t}\n\t\t}\n\t}\n\n\treturn dp[n][m] // Return the length of the LCS of s1 and s2\n}\n\nfunc max(a, b int) int {\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n\nfunc minInsertions(s string) int {\n\treverseS := \"\"\n\tfor i := len(s) - 1; i >= 0; i-- {\n\t\treverseS += string(s[i]) // Reverse the string s\n\t}\n\n\tlcsLength := lcs(s, reverseS) // Find the length of the LCS of s and its reverse\n\treturn len(s) - lcsLength // Return the number of insertions required to make s a palindrome\n}\n\nfunc main() {\n\tvar s string\n\tfmt.Scanln(&s) // Read input string\n\tans := minInsertions(s) // Calculate the minimum number of insertions required\n\tfmt.Println(ans) // Print the result\n}\n"
  },
  {
    "path": "Dynamic Programming/min_steps_to_make_string_palindrome.java",
    "content": "/*\n    Given a string, find the minimum number of insertions needed to make it a palindrome.\n\n    Sample Input: \"abcde\"\n    Sample Output: 4\n    Explanation: The minimum insertions required are 'edcb' -> \"abcdecb\", resulting in a palindrome.\n\n    Approach:\n    We can solve this problem using dynamic programming.\n    Let's define a 2D table, dp, where dp[i][j] represents the minimum number of insertions needed to make the substring from index i to j a palindrome.\n    If the characters at indices i and j are equal, then dp[i][j] = dp[i+1][j-1].\n    Otherwise, we have two options:\n        1. Insert the character at index i at the end, i.e., dp[i][j] = dp[i][j-1] + 1.\n        2. Insert the character at index j at the beginning, i.e., dp[i][j] = dp[i+1][j] + 1.\n    We take the minimum of these two options as the minimum number of insertions required for the substring from index i to j.\n    Finally, the minimum number of insertions needed for the entire string is dp[0][n-1], where n is the length of the string.\n\n    Time complexity: O(n^2)\n    Space complexity: O(n^2)\n*/\nimport java.util.Scanner;\n\npublic class Main {\n    \n    // Function to calculate the length of the Longest Common Subsequence (LCS) of two strings\n    public static int lcs(String s1, String s2) {\n        int n = s1.length();\n        int m = s2.length();\n        \n        // Create a 2D array dp to store the lengths of LCS\n        int[][] dp = new int[n+1][m+1];\n        \n        // Initialize the first row and first column to 0\n        for (int i = 0; i <= n; i++) {\n            dp[i][0] = 0;\n        }\n        for (int j = 0; j <= m; j++) {\n            dp[0][j] = 0;\n        }\n        \n        // Fill the dp array using dynamic programming\n        for (int i = 1; i <= n; i++) {\n            for (int j = 1; j <= m; j++) {\n                if (s1.charAt(i-1) == s2.charAt(j-1)) {\n                    // If characters at the current positions match, increase the length of LCS by 1\n                    dp[i][j] = 1 + dp[i-1][j-1];\n                } else {\n                    // Take the maximum length from the previous positions\n                    dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);\n                }\n            }\n        }\n        \n        // Return the length of the LCS of s1 and s2\n        return dp[n][m];\n    }\n\n    // Function to calculate the minimum number of insertions required to make a string palindrome\n    public static int minInsertions(String s) {\n        StringBuilder reverseSb = new StringBuilder(s);\n        reverseSb.reverse(); // Reverse the string s\n        String reverseS = reverseSb.toString();\n\n        int lcsLength = lcs(s, reverseS); // Find the length of the LCS of s and its reverse\n        return s.length() - lcsLength; // Return the number of insertions required to make s a palindrome\n    }\n\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        String s = scanner.nextLine(); // Read input string\n        int ans = minInsertions(s); // Calculate the minimum number of insertions required\n        System.out.println(ans); // Print the result\n        scanner.close();\n    }\n}\n"
  },
  {
    "path": "Dynamic Programming/min_steps_to_make_string_palindrome.py",
    "content": "'''\n    Given a string, find the minimum number of insertions needed to make it a palindrome.\n\n    Sample Input: \"abcde\"\n    Sample Output: 4\n    Explanation: The minimum insertions required are 'edcb' -> \"abcdecb\", resulting in a palindrome.\n\n    Approach:\n    We can solve this problem using dynamic programming.\n    Let's define a 2D table, dp, where dp[i][j] represents the minimum number of insertions needed to make the substring from index i to j a palindrome.\n    If the characters at indices i and j are equal, then dp[i][j] = dp[i+1][j-1].\n    Otherwise, we have two options:\n        1. Insert the character at index i at the end, i.e., dp[i][j] = dp[i][j-1] + 1.\n        2. Insert the character at index j at the beginning, i.e., dp[i][j] = dp[i+1][j] + 1.\n    We take the minimum of these two options as the minimum number of insertions required for the substring from index i to j.\n    Finally, the minimum number of insertions needed for the entire string is dp[0][n-1], where n is the length of the string.\n\n    Time complexity: O(n^2)\n    Space complexity: O(n^2)\n'''\n# Function to calculate the length of the Longest Common Subsequence (LCS) of two strings\ndef lcs(s1, s2):\n    n, m = len(s1), len(s2)\n    \n    # Create a 2D list dp to store the lengths of LCS\n    dp = [[0] * (m + 1) for _ in range(n + 1)]\n    \n    # Fill the dp array using dynamic programming\n    for i in range(1, n + 1):\n        for j in range(1, m + 1):\n            if s1[i - 1] == s2[j - 1]:\n                # If characters at the current positions match, increase the length of LCS by 1\n                dp[i][j] = 1 + dp[i - 1][j - 1]\n            else:\n                # Take the maximum length from the previous positions\n                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])\n    \n    # Return the length of the LCS of s1 and s2\n    return dp[n][m]\n\n# Function to calculate the minimum number of insertions required to make a string palindrome\ndef min_insertions(s):\n    reverse_s = s[::-1]  # Reverse the string s\n    \n    lcs_length = lcs(s, reverse_s)  # Find the length of the LCS of s and its reverse\n    return len(s) - lcs_length  # Return the number of insertions required to make s a palindrome\n\nif __name__ == \"__main__\":\n    s = input()  # Read input string\n    ans = min_insertions(s)  # Calculate the minimum number of insertions required\n    print(ans)  # Print the result\n"
  },
  {
    "path": "Dynamic Programming/min_steps_to_make_string_pallindrome.cpp",
    "content": "/*\n    Given a string, find the minimum number of insertions needed to make it a palindrome.\n\n    Sample Input: \"abcde\"\n    Sample Output: 4\n    Explanation: The minimum insertions required are 'edcb' -> \"abcdecb\", resulting in a palindrome.\n\n    Approach:\n    We can solve this problem using dynamic programming.\n    Let's define a 2D table, dp, where dp[i][j] represents the minimum number of insertions needed to make the substring from index i to j a palindrome.\n    If the characters at indices i and j are equal, then dp[i][j] = dp[i+1][j-1].\n    Otherwise, we have two options:\n        1. Insert the character at index i at the end, i.e., dp[i][j] = dp[i][j-1] + 1.\n        2. Insert the character at index j at the beginning, i.e., dp[i][j] = dp[i+1][j] + 1.\n    We take the minimum of these two options as the minimum number of insertions required for the substring from index i to j.\n    Finally, the minimum number of insertions needed for the entire string is dp[0][n-1], where n is the length of the string.\n\n    Time complexity: O(n^2)\n    Space complexity: O(n^2)\n*/\n\n#include <bits/stdc++.h>\nusing namespace std;\n\nint lcs(string s1,string s2){\n      int n=s1.size(),m=s2.size();\n      vector<vector<int>> dp(n+1,vector<int>(m+1,-1));\n\n      // bottom up approach to calculate lcs\n      // base conditions\n      for(int i=0;i<=n;i++){\n            dp[i][0]=0;\n      }\n\n      for(int i=0;i<=m;i++){\n            dp[0][i]=0;\n      }\n\n      // filling the table to calculate the longest common subsequence \n      for(int i=1;i<=n;i++){\n            for(int j=1;j<=m;j++){\n                  if(s1[i-1]==s2[j-1]){ // checking if the characters at both the string are same \n                        dp[i][j]=1+dp[i-1][j-1];  \n                  }\n                  else{\n                        dp[i][j]=0+max(dp[i-1][j],dp[i][j-1]);\n                  }\n            }\n      }\n\n      return dp[n][m];\n}\n\nint main(){\n      string s;\n      cin>>s;\n      string reverse_s;\n      for(int i=s.size()-1;i>=0;i--){\n            reverse_s.push_back(s[i]);\n      }\n      // the minimum steps to make a string pallindrome will require to calculate the \n      // longest common subsequence in the given string and the reverse of the string\n      int ans=lcs(s,reverse_s);\n      ans=s.size()-ans;\n      cout<<ans;\n}"
  },
  {
    "path": "Dynamic Programming/min_steps_to_make_string_pallindrome.js",
    "content": "/*\n    Given a string, find the minimum number of insertions needed to make it a palindrome.\n\n    Sample Input: \"abcde\"\n    Sample Output: 4\n    Explanation: The minimum insertions required are 'edcb' -> \"abcdecb\", resulting in a palindrome.\n\n    Approach:\n    We can solve this problem using dynamic programming.\n    Let's define a 2D table, dp, where dp[i][j] represents the minimum number of insertions needed to make the substring from index i to j a palindrome.\n    If the characters at indices i and j are equal, then dp[i][j] = dp[i+1][j-1].\n    Otherwise, we have two options:\n        1. Insert the character at index i at the end, i.e., dp[i][j] = dp[i][j-1] + 1.\n        2. Insert the character at index j at the beginning, i.e., dp[i][j] = dp[i+1][j] + 1.\n    We take the minimum of these two options as the minimum number of insertions required for the substring from index i to j.\n    Finally, the minimum number of insertions needed for the entire string is dp[0][n-1], where n is the length of the string.\n\n    Time complexity: O(n^2)\n    Space complexity: O(n^2)\n*/\n// Function to calculate the length of the Longest Common Subsequence (LCS) of two strings\nfunction lcs(s1, s2) {\n  const n = s1.length;\n  const m = s2.length;\n\n  // Create a 2D array dp to store the lengths of LCS\n  const dp = new Array(n + 1).fill(0).map(() => new Array(m + 1).fill(0));\n\n  // Fill the dp array using dynamic programming\n  for (let i = 1; i <= n; i++) {\n    for (let j = 1; j <= m; j++) {\n      if (s1[i - 1] === s2[j - 1]) {\n        // If characters at the current positions match, increase the length of LCS by 1\n        dp[i][j] = 1 + dp[i - 1][j - 1];\n      } else {\n        // Take the maximum length from the previous positions\n        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);\n      }\n    }\n  }\n\n  // Return the length of the LCS of s1 and s2\n  return dp[n][m];\n}\n\n// Function to calculate the minimum number of insertions required to make a string palindrome\nfunction minInsertions(s) {\n  const reverseS = s.split(\"\").reverse().join(\"\"); // Reverse the string s\n\n  const lcsLength = lcs(s, reverseS); // Find the length of the LCS of s and its reverse\n  return s.length - lcsLength; // Return the number of insertions required to make s a palindrome\n}\n\n// Example usage:\nconst input = \"abcde\";\nconst result = minInsertions(input); // Calculate the minimum number of insertions required\nconsole.log(result); // Print the result\n"
  },
  {
    "path": "Dynamic Programming/min_steps_to_reduce_a_number_to_one.cpp",
    "content": "// Minimum steps to reduce a number to one conditions are as follows\n// a)  subtract 1 [one operation] \n// b)  divide by 2 [one operation] \n// c)  divide by 3 [one operation]\n\n// Dynamic Programming solution\n// Program Author : Abhisek Kumar Gupta\n/*\n    Input  : 10\n    Output : 3\n    Explanation : 10 reduced to 9 reduced to 3 reduced to 1 [total 3 operations]\n    Input  : 15\n    Output : 4\n*/\n#include<bits/stdc++.h>\nusing namespace std;\nint dp[10000];\nint find_min_steps(int number){\n    int r1 = INT_MAX, r2 = INT_MAX, r3 = INT_MAX;\n    dp[0] = 0;\n    dp[1] = 0;\n    dp[2] = 1;\n    dp[3] = 1;\n    for(int i = 4; i <= number; i++){\n        r1 = 1 + dp[i - 1];\n        if(i % 2 == 0)\n            r2 = 1 + dp[i / 2];\n        if(i % 3 == 0)\n            r3 = 1 + dp[i / 3];\n        dp[i] = min(r1, min(r2, r3));\n        r1 = INT_MAX, r2 = INT_MAX, r3 = INT_MAX;\n    }\n\n    return dp[number];\n}\n\nint memoized[10004];\nint find_min_steps(int number){\n    if(number == 1)\n        return 0;\n    int r1 = INT_MAX, r2 = INT_MAX, r3 = INT_MAX;\n    if(memoized[number] != -1) return memoized[number];\n        r1 = 1 + find_min_steps(number - 1);\n    if(number % 2 == 0)\n        r2 = 1 + find_min_steps(number / 2);\n    if(number % 3 == 0)\n        r3 = 1 + find_min_steps(number / 3);\n    memoized[number] = min(r1, min(r2, r3));\n    return memoized[number];\n}\n\n\nint main(){\n    int number;\n    cin >> number;\n    memset(dp, 0, sizeof(dp));\n    int result = find_min_steps(number);\n    cout << result;\n    return 0;\n}\n"
  },
  {
    "path": "Dynamic Programming/num_ways_to_make_change.cpp",
    "content": "/*\n\tGiven an array of distinct positive integers representing coin denominations and a single non-negative integer n\n\trepresenting a target amount of money, write a function that returns the number of ways to make change for\n\tthat target amount using the given coin denominations.\n\n\tSample Input: n = 6 denominations : [1, 5]\n\tOutput: 2 (1 * 1 + 1 * 5 and  6 * 1)\n\n\tExplanation:\n\n\tThe given code snippet is implementing the \"NumberOfWaysToMakeChange\" algorithm in Go.\n\tThis algorithm calculates the number of ways to make change for a given amount using a set of denominations.\n\n\tHere's how the algorithm works:\n\n\t1. The function \"NumberOfWaysToMakeChange\" takes two parameters: \"n\" (the target amount to make change for) and \"denoms\"\n\t(an array of coin denominations).\n\n\t2. It initializes an array called \"ways\" of size \"n+1\" to keep track of the number of ways to make change for each amount\n\tfrom 0 to \"n\". The initial value of \"ways[0]\" is set to 1, representing the base case where there is one way to make\n\tchange for zero.\n\n\t3. The algorithm iterates over each denomination in the \"denoms\" array using a for-each loop.\n\n\t4. For each denomination, it further iterates from 1 to \"n+1\" to calculate the number of ways to make change for each\n\tamount.\n\n\t5. Inside the inner loop, it checks if the current denomination is less than or equal to the current amount. If so,\n\tit means that the current denomination can contribute to the change for the current amount.\n\n\t6. It then updates the \"ways[amount]\" value by adding the number of ways to make change for the current amount minus\n\tthe current denomination. This is done to accumulate all the possible ways to make change using the current denomination.\n\n\t7. After completing the nested loops, the algorithm returns the value stored in \"ways[n]\", which represents the total\n\tnumber of ways to make change for the target amount \"n\" using the given denominations.\n\n\tIn summary, this algorithm utilizes dynamic programming to calculate the number of ways to make change for a given\n\tamount using a set of denominations. By iteratively building up the solutions for smaller amounts, it efficiently computes the result in O(n * m) time complexity, where \"n\" is the target amount and \"m\" is the number of denominations. The space complexity is O(n), as the algorithm uses an array of size \"n+1\" to store the intermediate results.\n\n\tTime complexity : O(nd)\n\tSpace complexity : O(n) where n is the target amount and d is the number of coin denominations\n\n*/\n#include <vector>\n\nint NumberOfWaysToMakeChange(int n, const std::vector<int>& denoms) {\n    // Create an array to store the number of ways to make change for each amount from 0 to n.\n    std::vector<int> ways(n + 1, 0);\n\n    // Initialize the base case: There is one way to make change for amount 0 (using no coins).\n    ways[0] = 1;\n\n    // Iterate over each denomination.\n    for (int denom : denoms) {\n        // For each denomination, iterate over each amount from 1 to n.\n        for (int amount = 1; amount < n + 1; amount++) {\n            // Check if the denomination can be used to make change for the current amount.\n            if (denom <= amount) {\n                // Add the number of ways to make change for the current amount\n                // by considering the current denomination.\n                ways[amount] += ways[amount - denom];\n            }\n        }\n    }\n\n    // Return the number of ways to make change for the target amount n.\n    return ways[n];\n}\n"
  },
  {
    "path": "Dynamic Programming/num_ways_to_make_change.go",
    "content": "/*\n\tGiven an array of distinct positive integers representing coin denominations and a single non-negative integer n\n\trepresenting a target amount of money, write a function that returns the number of ways to make change for\n\tthat target amount using the given coin denominations.\n\n\tSample Input: n = 6 denominations : [1, 5]\n\tOutput: 2 (1 * 1 + 1 * 5 and  6 * 1)\n\n\tExplanation:\n\n\tThe given code snippet is implementing the \"NumberOfWaysToMakeChange\" algorithm in Go.\n\tThis algorithm calculates the number of ways to make change for a given amount using a set of denominations.\n\n\tHere's how the algorithm works:\n\n\t1. The function \"NumberOfWaysToMakeChange\" takes two parameters: \"n\" (the target amount to make change for) and \"denoms\"\n\t(an array of coin denominations).\n\n\t2. It initializes an array called \"ways\" of size \"n+1\" to keep track of the number of ways to make change for each amount\n\tfrom 0 to \"n\". The initial value of \"ways[0]\" is set to 1, representing the base case where there is one way to make\n\tchange for zero.\n\n\t3. The algorithm iterates over each denomination in the \"denoms\" array using a for-each loop.\n\n\t4. For each denomination, it further iterates from 1 to \"n+1\" to calculate the number of ways to make change for each\n\tamount.\n\n\t5. Inside the inner loop, it checks if the current denomination is less than or equal to the current amount. If so,\n\tit means that the current denomination can contribute to the change for the current amount.\n\n\t6. It then updates the \"ways[amount]\" value by adding the number of ways to make change for the current amount minus\n\tthe current denomination. This is done to accumulate all the possible ways to make change using the current denomination.\n\n\t7. After completing the nested loops, the algorithm returns the value stored in \"ways[n]\", which represents the total\n\tnumber of ways to make change for the target amount \"n\" using the given denominations.\n\n\tIn summary, this algorithm utilizes dynamic programming to calculate the number of ways to make change for a given\n\tamount using a set of denominations. By iteratively building up the solutions for smaller amounts, it efficiently computes the result in O(n * m) time complexity, where \"n\" is the target amount and \"m\" is the number of denominations. The space complexity is O(n), as the algorithm uses an array of size \"n+1\" to store the intermediate results.\n\n\tTime complexity : O(nd)\n\tSpace complexity : O(n) where n is the target amount and d is the number of coin denominations\n\n*/\npackage main\n\nfunc NumberOfWaysToMakeChange(n int, denoms []int) int {\n\t// Create an array to store the number of ways to make change for each amount from 0 to n.\n\tways := make([]int, n+1)\n\n\t// Initialize the base case: There is one way to make change for amount 0 (using no coins).\n\tways[0] = 1\n\n\t// Iterate over each denomination.\n\tfor _, denom := range denoms {\n\t\t// For each denomination, iterate over each amount from 1 to n.\n\t\tfor amount := 1; amount < n+1; amount++ {\n\t\t\t// Check if the denomination can be used to make change for the current amount.\n\t\t\tif denom <= amount {\n\t\t\t\t// Add the number of ways to make change for the current amount\n\t\t\t\t// by considering the current denomination.\n\t\t\t\tways[amount] += ways[amount-denom]\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the number of ways to make change for the target amount n.\n\treturn ways[n]\n}\n"
  },
  {
    "path": "Dynamic Programming/num_ways_to_make_change.java",
    "content": "/*\n\tGiven an array of distinct positive integers representing coin denominations and a single non-negative integer n\n\trepresenting a target amount of money, write a function that returns the number of ways to make change for\n\tthat target amount using the given coin denominations.\n\n\tSample Input: n = 6 denominations : [1, 5]\n\tOutput: 2 (1 * 1 + 1 * 5 and  6 * 1)\n\n\tExplanation:\n\n\tThe given code snippet is implementing the \"NumberOfWaysToMakeChange\" algorithm in Go.\n\tThis algorithm calculates the number of ways to make change for a given amount using a set of denominations.\n\n\tHere's how the algorithm works:\n\n\t1. The function \"NumberOfWaysToMakeChange\" takes two parameters: \"n\" (the target amount to make change for) and \"denoms\"\n\t(an array of coin denominations).\n\n\t2. It initializes an array called \"ways\" of size \"n+1\" to keep track of the number of ways to make change for each amount\n\tfrom 0 to \"n\". The initial value of \"ways[0]\" is set to 1, representing the base case where there is one way to make\n\tchange for zero.\n\n\t3. The algorithm iterates over each denomination in the \"denoms\" array using a for-each loop.\n\n\t4. For each denomination, it further iterates from 1 to \"n+1\" to calculate the number of ways to make change for each\n\tamount.\n\n\t5. Inside the inner loop, it checks if the current denomination is less than or equal to the current amount. If so,\n\tit means that the current denomination can contribute to the change for the current amount.\n\n\t6. It then updates the \"ways[amount]\" value by adding the number of ways to make change for the current amount minus\n\tthe current denomination. This is done to accumulate all the possible ways to make change using the current denomination.\n\n\t7. After completing the nested loops, the algorithm returns the value stored in \"ways[n]\", which represents the total\n\tnumber of ways to make change for the target amount \"n\" using the given denominations.\n\n\tIn summary, this algorithm utilizes dynamic programming to calculate the number of ways to make change for a given\n\tamount using a set of denominations. By iteratively building up the solutions for smaller amounts, it efficiently computes the result in O(n * m) time complexity, where \"n\" is the target amount and \"m\" is the number of denominations. The space complexity is O(n), as the algorithm uses an array of size \"n+1\" to store the intermediate results.\n\n\tTime complexity : O(nd)\n\tSpace complexity : O(n) where n is the target amount and d is the number of coin denominations\n\n*/\nimport java.util.Arrays;\n\npublic class CoinChange {\n\n    public static int numberOfWaysToMakeChange(int n, int[] denoms) {\n        // Create an array to store the number of ways to make change for each amount from 0 to n.\n        int[] ways = new int[n + 1];\n\n        // Initialize the base case: There is one way to make change for amount 0 (using no coins).\n        ways[0] = 1;\n\n        // Iterate over each denomination.\n        for (int denom : denoms) {\n            // For each denomination, iterate over each amount from 1 to n.\n            for (int amount = 1; amount < n + 1; amount++) {\n                // Check if the denomination can be used to make change for the current amount.\n                if (denom <= amount) {\n                    // Add the number of ways to make change for the current amount\n                    // by considering the current denomination.\n                    ways[amount] += ways[amount - denom];\n                }\n            }\n        }\n\n        // Return the number of ways to make change for the target amount n.\n        return ways[n];\n    }\n\n    public static void main(String[] args) {\n        int n = 10;\n        int[] denoms = {1, 2, 5};\n\n        int numberOfWays = numberOfWaysToMakeChange(n, denoms);\n        System.out.println(\"Number of ways to make change: \" + numberOfWays);\n    }\n}\n"
  },
  {
    "path": "Dynamic Programming/num_ways_to_make_change.js",
    "content": "/*\n\tGiven an array of distinct positive integers representing coin denominations and a single non-negative integer n\n\trepresenting a target amount of money, write a function that returns the number of ways to make change for\n\tthat target amount using the given coin denominations.\n\n\tSample Input: n = 6 denominations : [1, 5]\n\tOutput: 2 (1 * 1 + 1 * 5 and  6 * 1)\n\n\tExplanation:\n\n\tThe given code snippet is implementing the \"NumberOfWaysToMakeChange\" algorithm in Go.\n\tThis algorithm calculates the number of ways to make change for a given amount using a set of denominations.\n\n\tHere's how the algorithm works:\n\n\t1. The function \"NumberOfWaysToMakeChange\" takes two parameters: \"n\" (the target amount to make change for) and \"denoms\"\n\t(an array of coin denominations).\n\n\t2. It initializes an array called \"ways\" of size \"n+1\" to keep track of the number of ways to make change for each amount\n\tfrom 0 to \"n\". The initial value of \"ways[0]\" is set to 1, representing the base case where there is one way to make\n\tchange for zero.\n\n\t3. The algorithm iterates over each denomination in the \"denoms\" array using a for-each loop.\n\n\t4. For each denomination, it further iterates from 1 to \"n+1\" to calculate the number of ways to make change for each\n\tamount.\n\n\t5. Inside the inner loop, it checks if the current denomination is less than or equal to the current amount. If so,\n\tit means that the current denomination can contribute to the change for the current amount.\n\n\t6. It then updates the \"ways[amount]\" value by adding the number of ways to make change for the current amount minus\n\tthe current denomination. This is done to accumulate all the possible ways to make change using the current denomination.\n\n\t7. After completing the nested loops, the algorithm returns the value stored in \"ways[n]\", which represents the total\n\tnumber of ways to make change for the target amount \"n\" using the given denominations.\n\n\tIn summary, this algorithm utilizes dynamic programming to calculate the number of ways to make change for a given\n\tamount using a set of denominations. By iteratively building up the solutions for smaller amounts, it efficiently computes the result in O(n * m) time complexity, where \"n\" is the target amount and \"m\" is the number of denominations. The space complexity is O(n), as the algorithm uses an array of size \"n+1\" to store the intermediate results.\n\n\tTime complexity : O(nd)\n\tSpace complexity : O(n) where n is the target amount and d is the number of coin denominations\n\n*/\nfunction numberOfWaysToMakeChange(n, denoms) {\n  // Create an array to store the number of ways to make change for each amount from 0 to n.\n  const ways = new Array(n + 1).fill(0);\n\n  // Initialize the base case: There is one way to make change for amount 0 (using no coins).\n  ways[0] = 1;\n\n  // Iterate over each denomination.\n  for (const denom of denoms) {\n    // For each denomination, iterate over each amount from 1 to n.\n    for (let amount = 1; amount < n + 1; amount++) {\n      // Check if the denomination can be used to make change for the current amount.\n      if (denom <= amount) {\n        // Add the number of ways to make change for the current amount\n        // by considering the current denomination.\n        ways[amount] += ways[amount - denom];\n      }\n    }\n  }\n\n  // Return the number of ways to make change for the target amount n.\n  return ways[n];\n}\n\n// Example usage\nconst n = 10;\nconst denoms = [1, 2, 5];\n\nconst numberOfWays = numberOfWaysToMakeChange(n, denoms);\nconsole.log(\"Number of ways to make change:\", numberOfWays);\n"
  },
  {
    "path": "Dynamic Programming/num_ways_to_make_change.py",
    "content": "'''\n\tGiven an array of distinct positive integers representing coin denominations and a single non-negative integer n\n\trepresenting a target amount of money, write a function that returns the number of ways to make change for\n\tthat target amount using the given coin denominations.\n\n\tSample Input: n = 6 denominations : [1, 5]\n\tOutput: 2 (1 * 1 + 1 * 5 and  6 * 1)\n\n\tExplanation:\n\n\tThe given code snippet is implementing the \"NumberOfWaysToMakeChange\" algorithm in Go.\n\tThis algorithm calculates the number of ways to make change for a given amount using a set of denominations.\n\n\tHere's how the algorithm works:\n\n\t1. The function \"NumberOfWaysToMakeChange\" takes two parameters: \"n\" (the target amount to make change for) and \"denoms\"\n\t(an array of coin denominations).\n\n\t2. It initializes an array called \"ways\" of size \"n+1\" to keep track of the number of ways to make change for each amount\n\tfrom 0 to \"n\". The initial value of \"ways[0]\" is set to 1, representing the base case where there is one way to make\n\tchange for zero.\n\n\t3. The algorithm iterates over each denomination in the \"denoms\" array using a for-each loop.\n\n\t4. For each denomination, it further iterates from 1 to \"n+1\" to calculate the number of ways to make change for each\n\tamount.\n\n\t5. Inside the inner loop, it checks if the current denomination is less than or equal to the current amount. If so,\n\tit means that the current denomination can contribute to the change for the current amount.\n\n\t6. It then updates the \"ways[amount]\" value by adding the number of ways to make change for the current amount minus\n\tthe current denomination. This is done to accumulate all the possible ways to make change using the current denomination.\n\n\t7. After completing the nested loops, the algorithm returns the value stored in \"ways[n]\", which represents the total\n\tnumber of ways to make change for the target amount \"n\" using the given denominations.\n\n\tIn summary, this algorithm utilizes dynamic programming to calculate the number of ways to make change for a given\n\tamount using a set of denominations. By iteratively building up the solutions for smaller amounts, it efficiently computes the result in O(n * m) time complexity, where \"n\" is the target amount and \"m\" is the number of denominations. The space complexity is O(n), as the algorithm uses an array of size \"n+1\" to store the intermediate results.\n\n\tTime complexity : O(nd)\n\tSpace complexity : O(n) where n is the target amount and d is the number of coin denominations\n'''\ndef number_of_ways_to_make_change(n, denoms):\n    # Create a list to store the number of ways to make change for each amount from 0 to n.\n    ways = [0] * (n + 1)\n\n    # Initialize the base case: There is one way to make change for amount 0 (using no coins).\n    ways[0] = 1\n\n    # Iterate over each denomination.\n    for denom in denoms:\n        # For each denomination, iterate over each amount from 1 to n.\n        for amount in range(1, n + 1):\n            # Check if the denomination can be used to make change for the current amount.\n            if denom <= amount:\n                # Add the number of ways to make change for the current amount\n                # by considering the current denomination.\n                ways[amount] += ways[amount - denom]\n\n    # Return the number of ways to make change for the target amount n.\n    return ways[n]\n\n\n# Example usage\nn = 10\ndenoms = [1, 2, 5]\n\nnumber_of_ways = number_of_ways_to_make_change(n, denoms)\nprint(\"Number of ways to make change:\", number_of_ways)\n"
  },
  {
    "path": "Dynamic Programming/num_ways_to_traverse_graph.cpp",
    "content": "/*\n\n\tYou're given two positive integers representing the width and height of a grid-shaped, rectangular graph.\n\tWrite a function that returns the number of ways to reach the bottom right corner of the graph when starting\n\tat the top left corner. Each move you take must either go down or right. In other words, you can never move up\n\tor left in the graph.\n\n\tFor example, given the graph illustrated below, with width = 2 and height = 3 , there are three ways to\n\treach the bottom right corner when starting at the top left corner:\n\t _ _\n\t|_|_|\n\t|_|_|\n\t|_|_|\n\tDown Down Right\n\tRight Down Down\n\tDown Right Down\n\n\tSample Input: Width : 4 height: 3\n\tOutput: 10\n\n\tExplanation:\n\tThe code snippet implements the `NumberOfWaysToTraverseGraph` function, which calculates the number of ways to\n\ttraverse a 2D graph from the top-left corner to the bottom-right corner. The graph has a given width and height.\n\n\tHere's a breakdown of the code:\n\n\t1. The function takes two parameters: `width` and `height`, representing the dimensions of the graph.\n\n\t2. It initializes a 2D slice called `numberOfWays` with dimensions `(height+1) x (width+1)`. The additional \"+1\" is to\n\t   account for the boundary cases when traversing the graph.\n\n\t3. It enters a nested loop to iterate over the graph cells. The outer loop iterates over the width indices (`widthIdx`),\n\t   and the inner loop iterates over the height indices (`heightIdx`).\n\n\t4. For each cell, it checks if it is on the top row (`heightIdx == 1`) or the leftmost column (`widthIdx == 1`). If so, it\n\t   means that there is only one way to reach that cell, either by moving right or moving down. Therefore, it sets `numberOfWays[heightIdx][widthIdx]` to 1.\n\n\t5. If the cell is not on the top row or the leftmost column, it means that it can be reached by either moving from the\n\t   cell above (up) or the cell to the left (left). The number of ways to reach the current cell is the sum of the number of\n\t   ways to reach the cell above and the number of ways to reach the cell to the left. This value is stored in\n\t  `numberOfWays[heightIdx][widthIdx]`.\n\n\t6. After iterating over all cells, the function returns the value stored in the bottom-right corner of `numberOfWays`,\n\t   which represents the total number of ways to traverse the graph.\n\n\tThe algorithm uses dynamic programming to build the `numberOfWays` matrix iteratively, starting from the top-left corner\n\tand moving towards the bottom-right corner. By calculating the number of ways to reach each cell based on the number of ways to reach its neighboring cells, it avoids redundant calculations and computes the result efficiently.\n\n\tThe time complexity of the algorithm is O(width * height) since it iterates over all cells of the graph.\n\n\tThe space complexity is also O(width * height) since it uses the `numberOfWays` matrix to store intermediate results.\n\n\n*/\n\nint numberOfWaysToTraverseGraph(int width, int height) {\n    // Create a 2D vector to store the number of ways to reach each cell\n    vector<vector<int>> numberOfWays(height, vector<int>(width, 1));\n\n    // Iterate through the cells from top to bottom and left to right\n    for (int i = 1; i < height; i++) {\n        for (int j = 1; j < width; j++) {\n            // Calculate the number of ways to reach the current cell\n            // by summing the number of ways from the cell above and the cell to the left\n            numberOfWays[i][j] = numberOfWays[i - 1][j] + numberOfWays[i][j - 1];\n        }\n    }\n\n    // Return the number of ways to reach the bottom-right corner of the graph\n    return numberOfWays[height - 1][width - 1];\n}\n\n\n/*\n\tCombinatorics Solution\n\n\tThe given code snippet aims to calculate the number of ways to traverse a graph from the top-left corner to the bottom-right \n\tcorner. Let's break down the solution and provide a detailed explanation:\n\n\t1. The `NumberOfWaysToTraverseGraph` function takes two parameters: `width` and `height`, representing the dimensions of \n\t   the graph.\n\n\t2. The variables `xDistanceToCorner` and `yDistanceToCorner` are calculated by subtracting 1 from the `width` and `height` \n\t   respectively. These variables represent the distances from the top-left corner to the bottom-right corner along the x-axis and y-axis.\n\n\t3. The `factorial` function is defined separately to calculate the factorial of a number. It takes a number `num` as input \n\t   and uses an iterative approach to calculate the factorial.\n\n\t4. In the `NumberOfWaysToTraverseGraph` function, the numerator is calculated as the factorial of the sum of \n\t   `xDistanceToCorner` and `yDistanceToCorner`. This represents the total number of possible paths from the top-left \n\t   corner to the bottom-right corner.\n\n\t5. The denominator is calculated as the product of the factorials of `xDistanceToCorner` and `yDistanceToCorner`. \n\t   This represents the number of ways to arrange the steps along the x-axis and y-axis.\n\n\t6. Finally, the function returns the result by dividing the numerator by the denominator, giving the total number of \n\t   ways to traverse the graph.\n\n\tThe solution relies on the concept of combinatorics, specifically the binomial coefficient, to calculate the number of \n\tways to traverse the graph. By using factorials, it accounts for all possible paths and eliminates duplicate paths. \n\tThis approach provides an efficient solution to the problem.\n\n\tO(n + m) time | O(1) space - where n is the width of the graph and m is the height\n*/\n\nint numberOfWaysToTraverseGraphCombinatorics(int width, int height) {\n    // Calculate the distances to the bottom-right corner of the graph\n    int xDistanceToCorner = width - 1;\n    int yDistanceToCorner = height - 1;\n\n    // Calculate the numerator and denominator for the binomial coefficient\n    int numerator = factorial(xDistanceToCorner + yDistanceToCorner);\n    int denominator = factorial(xDistanceToCorner) * factorial(yDistanceToCorner);\n\n    // Return the result by dividing the numerator by the denominator\n    return numerator / denominator;\n}\n\nint factorial(int n) {\n    // Base case: factorial of 0 or 1 is 1\n    if (n <= 1) {\n        return 1;\n    }\n\n    // Recursive case: compute factorial by multiplying n with factorial(n-1)\n    return n * factorial(n - 1);\n}\n\n\n/*\n\tRecursive solution\n\tThe given solution aims to calculate the number of ways to traverse a graph from the top-left corner to the bottom-right \n\tcorner. It uses a recursive approach to break down the problem into smaller subproblems.\n\n\tHere's how the solution works:\n\n\t1. The function `NumberOfWaysToTraverseGraph` takes the width and height of the graph as input and returns the number of ways to traverse it.\n\n\t2. The base case of the recursion is when either the width or height is equal to 1. In this case, there is only one way to traverse the graph: either by moving only horizontally or vertically. Therefore, the function returns 1.\n\n\t3. For other cases where the width and height are both greater than 1, the function recursively calls itself with two smaller subproblems:\n\t- One subproblem is created by reducing the width by 1 and keeping the same height.\n\t- The other subproblem is created by keeping the same width and reducing the height by 1.\n\n\t4. The number of ways to traverse the current graph is calculated by summing up the number of ways from the two subproblems.\n\n\t5. The recursion continues until it reaches the base case, where the width or height becomes 1, and eventually returns the total number of ways to traverse the graph.\n\n\tWhile this recursive approach is conceptually simple, it suffers from efficiency issues due to exponential time complexity and redundant \n\tcalculations. As the graph size increases, the number of recursive calls grows exponentially, leading to a significant increase in computation time. Additionally, without memoization, the function recalculates the same subproblems multiple times, further reducing efficiency.\n\n\tTo address these drawbacks, alternative approaches like dynamic programming or memoization can be employed to store and \n\treuse the results of previously solved subproblems, avoiding redundant calculations and improving efficiency.\n\n\tThe given solution uses a recursive approach to calculate the number of ways to traverse a graph from the top-left corner \n\tto the bottom-right corner. However, this solution has some drawbacks that make it inefficient for larger inputs:\n\n\t1. Exponential Time Complexity: The recursive function makes multiple recursive calls, each with a smaller width or height. \n\tAs a result, the number of function calls grows exponentially with the size of the input. This leads to a high time complexity, making the solution inefficient for larger graphs. The time complexity is O(2^(width+height)), which can quickly become unmanageable.\n\n\t2. Overlapping Subproblems: The recursive function suffers from redundant calculations of the same subproblems. For example,\n\t when calculating the number of ways for a specific width and height, the function may recursively calculate the number of ways for smaller widths and heights multiple times. This leads to redundant work and decreases efficiency.\n\n\t3. Lack of Memoization: The solution does not utilize memoization to store the results of previously solved subproblems. \n\tWithout memoization, the recursive function ends up recalculating the same subproblems multiple times, further reducing efficiency.\n\n\tDue to these reasons, the given recursive solution is considered inefficient and impractical for larger graph sizes. \n\tIt is prone to exponential time complexity and redundant calculations, making it unsuitable for real-world scenarios where efficiency is crucial. Alternative approaches, such as the dynamic programming solution mentioned earlier, can provide better performance by avoiding redundant calculations and improving time complexity.\n*/\n\nint numberOfWaysToTraverseGraphRecursive(int width, int height) {\n    // Base case: when the width or height is 1, there is only one way to reach the destination\n    if (width == 1 || height == 1) {\n        return 1;\n    }\n\n    // Recursive case: sum the number of ways from the cell above and the cell to the left\n    return numberOfWaysToTraverseGraphRecursive(width - 1, height) + numberOfWaysToTraverseGraphRecursive(width, height - 1);\n}\n"
  },
  {
    "path": "Dynamic Programming/num_ways_to_traverse_graph.go",
    "content": "/*\n\n\tYou're given two positive integers representing the width and height of a grid-shaped, rectangular graph.\n\tWrite a function that returns the number of ways to reach the bottom right corner of the graph when starting\n\tat the top left corner. Each move you take must either go down or right. In other words, you can never move up\n\tor left in the graph.\n\n\tFor example, given the graph illustrated below, with width = 2 and height = 3 , there are three ways to\n\treach the bottom right corner when starting at the top left corner:\n\t _ _\n\t|_|_|\n\t|_|_|\n\t|_|_|\n\tDown Down Right\n\tRight Down Down\n\tDown Right Down\n\n\tSample Input: Width : 4 height: 3\n\tOutput: 10\n\n\tExplanation:\n\tThe code snippet implements the `NumberOfWaysToTraverseGraph` function, which calculates the number of ways to\n\ttraverse a 2D graph from the top-left corner to the bottom-right corner. The graph has a given width and height.\n\n\tHere's a breakdown of the code:\n\n\t1. The function takes two parameters: `width` and `height`, representing the dimensions of the graph.\n\n\t2. It initializes a 2D slice called `numberOfWays` with dimensions `(height+1) x (width+1)`. The additional \"+1\" is to\n\t   account for the boundary cases when traversing the graph.\n\n\t3. It enters a nested loop to iterate over the graph cells. The outer loop iterates over the width indices (`widthIdx`),\n\t   and the inner loop iterates over the height indices (`heightIdx`).\n\n\t4. For each cell, it checks if it is on the top row (`heightIdx == 1`) or the leftmost column (`widthIdx == 1`). If so, it\n\t   means that there is only one way to reach that cell, either by moving right or moving down. Therefore, it sets `numberOfWays[heightIdx][widthIdx]` to 1.\n\n\t5. If the cell is not on the top row or the leftmost column, it means that it can be reached by either moving from the\n\t   cell above (up) or the cell to the left (left). The number of ways to reach the current cell is the sum of the number of\n\t   ways to reach the cell above and the number of ways to reach the cell to the left. This value is stored in\n\t  `numberOfWays[heightIdx][widthIdx]`.\n\n\t6. After iterating over all cells, the function returns the value stored in the bottom-right corner of `numberOfWays`,\n\t   which represents the total number of ways to traverse the graph.\n\n\tThe algorithm uses dynamic programming to build the `numberOfWays` matrix iteratively, starting from the top-left corner\n\tand moving towards the bottom-right corner. By calculating the number of ways to reach each cell based on the number of ways to reach its neighboring cells, it avoids redundant calculations and computes the result efficiently.\n\n\tThe time complexity of the algorithm is O(width * height) since it iterates over all cells of the graph.\n\n\tThe space complexity is also O(width * height) since it uses the `numberOfWays` matrix to store intermediate results.\n\n\n*/\npackage main\n\nfunc NumberOfWaysToTraverseGraph(width int, height int) int {\n\t// Initialize the numberOfWays matrix with dimensions (height+1) x (width+1)\n\t// The extra \"+1\" is to account for the boundary cases when traversing the graph\n\tnumberOfWays := make([][]int, height+1)\n\tfor i := range numberOfWays {\n\t\tnumberOfWays[i] = make([]int, width+1)\n\t}\n\n\t// Iterate over the graph cells\n\tfor widthIdx := 1; widthIdx < width+1; widthIdx++ {\n\t\tfor heightIdx := 1; heightIdx < height+1; heightIdx++ {\n\t\t\t// Check if the current cell is on the top row or the leftmost column\n\t\t\tif widthIdx == 1 || heightIdx == 1 {\n\t\t\t\t// If so, there is only one way to reach this cell (moving right or moving down)\n\t\t\t\tnumberOfWays[heightIdx][widthIdx] = 1\n\t\t\t} else {\n\t\t\t\t// If the cell is not on the top row or the leftmost column,\n\t\t\t\t// calculate the number of ways to reach this cell based on the\n\t\t\t\t// number of ways to reach the cell above (up) and the cell to the left (left)\n\t\t\t\twaysLeft := numberOfWays[heightIdx][widthIdx-1]\n\t\t\t\twaysUp := numberOfWays[heightIdx-1][widthIdx]\n\t\t\t\tnumberOfWays[heightIdx][widthIdx] = waysLeft + waysUp\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the number of ways to reach the bottom-right corner of the graph\n\treturn numberOfWays[height][width]\n}\n\n\n/*\n\tCombinatorics Solution\n\n\tThe given code snippet aims to calculate the number of ways to traverse a graph from the top-left corner to the bottom-right \n\tcorner. Let's break down the solution and provide a detailed explanation:\n\n\t1. The `NumberOfWaysToTraverseGraph` function takes two parameters: `width` and `height`, representing the dimensions of \n\t   the graph.\n\n\t2. The variables `xDistanceToCorner` and `yDistanceToCorner` are calculated by subtracting 1 from the `width` and `height` \n\t   respectively. These variables represent the distances from the top-left corner to the bottom-right corner along the x-axis and y-axis.\n\n\t3. The `factorial` function is defined separately to calculate the factorial of a number. It takes a number `num` as input \n\t   and uses an iterative approach to calculate the factorial.\n\n\t4. In the `NumberOfWaysToTraverseGraph` function, the numerator is calculated as the factorial of the sum of \n\t   `xDistanceToCorner` and `yDistanceToCorner`. This represents the total number of possible paths from the top-left \n\t   corner to the bottom-right corner.\n\n\t5. The denominator is calculated as the product of the factorials of `xDistanceToCorner` and `yDistanceToCorner`. \n\t   This represents the number of ways to arrange the steps along the x-axis and y-axis.\n\n\t6. Finally, the function returns the result by dividing the numerator by the denominator, giving the total number of \n\t   ways to traverse the graph.\n\n\tThe solution relies on the concept of combinatorics, specifically the binomial coefficient, to calculate the number of \n\tways to traverse the graph. By using factorials, it accounts for all possible paths and eliminates duplicate paths. \n\tThis approach provides an efficient solution to the problem.\n\n\tO(n + m) time | O(1) space - where n is the width of the graph and m is the height\n*/\nfunc NumberOfWaysToTraverseGraphCombinatorics(width int, height int) int {\n\t// Calculate the distance to the bottom-right corner of the graph\n\txDistanceToCorner := width - 1\n\tyDistanceToCorner := height - 1\n\n\t// Calculate the number of ways to traverse the graph using combinatorics\n\t// by calculating the binomial coefficient of (xDistanceToCorner + yDistanceToCorner) choose xDistanceToCorner\n\t// where (n choose k) = n! / (k! * (n-k)!)\n\tnumerator := factorial(xDistanceToCorner + yDistanceToCorner)\n\tdenominator := factorial(xDistanceToCorner) * factorial(yDistanceToCorner)\n\n\t// Return the result by dividing the numerator by the denominator\n\treturn numerator / denominator\n}\n\nfunc factorial(num int) int {\n\t// Calculate the factorial of a number using an iterative approach\n\tresult := 1\n\tfor n := 2; n <= num; n++ {\n\t\tresult *= n\n\t}\n\treturn result\n}\n\n\n/*\n\tRecursive solution\n\tThe given solution aims to calculate the number of ways to traverse a graph from the top-left corner to the bottom-right \n\tcorner. It uses a recursive approach to break down the problem into smaller subproblems.\n\n\tHere's how the solution works:\n\n\t1. The function `NumberOfWaysToTraverseGraph` takes the width and height of the graph as input and returns the number of ways to traverse it.\n\n\t2. The base case of the recursion is when either the width or height is equal to 1. In this case, there is only one way to traverse the graph: either by moving only horizontally or vertically. Therefore, the function returns 1.\n\n\t3. For other cases where the width and height are both greater than 1, the function recursively calls itself with two smaller subproblems:\n\t- One subproblem is created by reducing the width by 1 and keeping the same height.\n\t- The other subproblem is created by keeping the same width and reducing the height by 1.\n\n\t4. The number of ways to traverse the current graph is calculated by summing up the number of ways from the two subproblems.\n\n\t5. The recursion continues until it reaches the base case, where the width or height becomes 1, and eventually returns the total number of ways to traverse the graph.\n\n\tWhile this recursive approach is conceptually simple, it suffers from efficiency issues due to exponential time complexity and redundant \n\tcalculations. As the graph size increases, the number of recursive calls grows exponentially, leading to a significant increase in computation time. Additionally, without memoization, the function recalculates the same subproblems multiple times, further reducing efficiency.\n\n\tTo address these drawbacks, alternative approaches like dynamic programming or memoization can be employed to store and \n\treuse the results of previously solved subproblems, avoiding redundant calculations and improving efficiency.\n\n\tThe given solution uses a recursive approach to calculate the number of ways to traverse a graph from the top-left corner \n\tto the bottom-right corner. However, this solution has some drawbacks that make it inefficient for larger inputs:\n\n\t1. Exponential Time Complexity: The recursive function makes multiple recursive calls, each with a smaller width or height. \n\tAs a result, the number of function calls grows exponentially with the size of the input. This leads to a high time complexity, making the solution inefficient for larger graphs. The time complexity is O(2^(width+height)), which can quickly become unmanageable.\n\n\t2. Overlapping Subproblems: The recursive function suffers from redundant calculations of the same subproblems. For example,\n\t when calculating the number of ways for a specific width and height, the function may recursively calculate the number of ways for smaller widths and heights multiple times. This leads to redundant work and decreases efficiency.\n\n\t3. Lack of Memoization: The solution does not utilize memoization to store the results of previously solved subproblems. \n\tWithout memoization, the recursive function ends up recalculating the same subproblems multiple times, further reducing efficiency.\n\n\tDue to these reasons, the given recursive solution is considered inefficient and impractical for larger graph sizes. \n\tIt is prone to exponential time complexity and redundant calculations, making it unsuitable for real-world scenarios where efficiency is crucial. Alternative approaches, such as the dynamic programming solution mentioned earlier, can provide better performance by avoiding redundant calculations and improving time complexity.\n*/\nfunc NumberOfWaysToTraverseGraphRecursive(width int, height int) int {\n\tif width == 1  || height == 1 {\n        return 1\n    }\n    return NumberOfWaysToTraverseGraph(width - 1, height) + NumberOfWaysToTraverseGraph(width, height - 1)\n}\n"
  },
  {
    "path": "Dynamic Programming/num_ways_to_traverse_graph.js",
    "content": "/*\n\n\tYou're given two positive integers representing the width and height of a grid-shaped, rectangular graph.\n\tWrite a function that returns the number of ways to reach the bottom right corner of the graph when starting\n\tat the top left corner. Each move you take must either go down or right. In other words, you can never move up\n\tor left in the graph.\n\n\tFor example, given the graph illustrated below, with width = 2 and height = 3 , there are three ways to\n\treach the bottom right corner when starting at the top left corner:\n\t _ _\n\t|_|_|\n\t|_|_|\n\t|_|_|\n\tDown Down Right\n\tRight Down Down\n\tDown Right Down\n\n\tSample Input: Width : 4 height: 3\n\tOutput: 10\n\n\tExplanation:\n\tThe code snippet implements the `NumberOfWaysToTraverseGraph` function, which calculates the number of ways to\n\ttraverse a 2D graph from the top-left corner to the bottom-right corner. The graph has a given width and height.\n\n\tHere's a breakdown of the code:\n\n\t1. The function takes two parameters: `width` and `height`, representing the dimensions of the graph.\n\n\t2. It initializes a 2D slice called `numberOfWays` with dimensions `(height+1) x (width+1)`. The additional \"+1\" is to\n\t   account for the boundary cases when traversing the graph.\n\n\t3. It enters a nested loop to iterate over the graph cells. The outer loop iterates over the width indices (`widthIdx`),\n\t   and the inner loop iterates over the height indices (`heightIdx`).\n\n\t4. For each cell, it checks if it is on the top row (`heightIdx == 1`) or the leftmost column (`widthIdx == 1`). If so, it\n\t   means that there is only one way to reach that cell, either by moving right or moving down. Therefore, it sets `numberOfWays[heightIdx][widthIdx]` to 1.\n\n\t5. If the cell is not on the top row or the leftmost column, it means that it can be reached by either moving from the\n\t   cell above (up) or the cell to the left (left). The number of ways to reach the current cell is the sum of the number of\n\t   ways to reach the cell above and the number of ways to reach the cell to the left. This value is stored in\n\t  `numberOfWays[heightIdx][widthIdx]`.\n\n\t6. After iterating over all cells, the function returns the value stored in the bottom-right corner of `numberOfWays`,\n\t   which represents the total number of ways to traverse the graph.\n\n\tThe algorithm uses dynamic programming to build the `numberOfWays` matrix iteratively, starting from the top-left corner\n\tand moving towards the bottom-right corner. By calculating the number of ways to reach each cell based on the number of ways to reach its neighboring cells, it avoids redundant calculations and computes the result efficiently.\n\n\tThe time complexity of the algorithm is O(width * height) since it iterates over all cells of the graph.\n\n\tThe space complexity is also O(width * height) since it uses the `numberOfWays` matrix to store intermediate results.\n\n\n*/\nfunction numberOfWaysToTraverseGraph(width, height) {\n  // Create a 2D array to store the number of ways to reach each cell\n  const numberOfWays = new Array(height)\n    .fill(1)\n    .map(() => new Array(width).fill(1));\n\n  // Iterate through the cells from top to bottom and left to right\n  for (let i = 1; i < height; i++) {\n    for (let j = 1; j < width; j++) {\n      // Calculate the number of ways to reach the current cell\n      // by summing the number of ways from the cell above and the cell to the left\n      numberOfWays[i][j] = numberOfWays[i - 1][j] + numberOfWays[i][j - 1];\n    }\n  }\n\n  // Return the number of ways to reach the bottom-right corner of the graph\n  return numberOfWays[height - 1][width - 1];\n}\n\n/*\n\tCombinatorics Solution\n\n\tThe given code snippet aims to calculate the number of ways to traverse a graph from the top-left corner to the bottom-right \n\tcorner. Let's break down the solution and provide a detailed explanation:\n\n\t1. The `NumberOfWaysToTraverseGraph` function takes two parameters: `width` and `height`, representing the dimensions of \n\t   the graph.\n\n\t2. The variables `xDistanceToCorner` and `yDistanceToCorner` are calculated by subtracting 1 from the `width` and `height` \n\t   respectively. These variables represent the distances from the top-left corner to the bottom-right corner along the x-axis and y-axis.\n\n\t3. The `factorial` function is defined separately to calculate the factorial of a number. It takes a number `num` as input \n\t   and uses an iterative approach to calculate the factorial.\n\n\t4. In the `NumberOfWaysToTraverseGraph` function, the numerator is calculated as the factorial of the sum of \n\t   `xDistanceToCorner` and `yDistanceToCorner`. This represents the total number of possible paths from the top-left \n\t   corner to the bottom-right corner.\n\n\t5. The denominator is calculated as the product of the factorials of `xDistanceToCorner` and `yDistanceToCorner`. \n\t   This represents the number of ways to arrange the steps along the x-axis and y-axis.\n\n\t6. Finally, the function returns the result by dividing the numerator by the denominator, giving the total number of \n\t   ways to traverse the graph.\n\n\tThe solution relies on the concept of combinatorics, specifically the binomial coefficient, to calculate the number of \n\tways to traverse the graph. By using factorials, it accounts for all possible paths and eliminates duplicate paths. \n\tThis approach provides an efficient solution to the problem.\n\n\tO(n + m) time | O(1) space - where n is the width of the graph and m is the height\n*/\n\nfunction numberOfWaysToTraverseGraphCombinatorics(width, height) {\n  // Calculate the distances to the bottom-right corner of the graph\n  const xDistanceToCorner = width - 1;\n  const yDistanceToCorner = height - 1;\n\n  // Calculate the numerator and denominator for the binomial coefficient\n  const numerator = factorial(xDistanceToCorner + yDistanceToCorner);\n  const denominator =\n    factorial(xDistanceToCorner) * factorial(yDistanceToCorner);\n\n  // Return the result by dividing the numerator by the denominator\n  return numerator / denominator;\n}\n\nfunction factorial(n) {\n  // Base case: factorial of 0 or 1 is 1\n  if (n <= 1) {\n    return 1;\n  }\n\n  // Recursive case: compute factorial by multiplying n with factorial(n-1)\n  return n * factorial(n - 1);\n}\n\n/*\n\tRecursive solution\n\tThe given solution aims to calculate the number of ways to traverse a graph from the top-left corner to the bottom-right \n\tcorner. It uses a recursive approach to break down the problem into smaller subproblems.\n\n\tHere's how the solution works:\n\n\t1. The function `NumberOfWaysToTraverseGraph` takes the width and height of the graph as input and returns the number of ways to traverse it.\n\n\t2. The base case of the recursion is when either the width or height is equal to 1. In this case, there is only one way to traverse the graph: either by moving only horizontally or vertically. Therefore, the function returns 1.\n\n\t3. For other cases where the width and height are both greater than 1, the function recursively calls itself with two smaller subproblems:\n\t- One subproblem is created by reducing the width by 1 and keeping the same height.\n\t- The other subproblem is created by keeping the same width and reducing the height by 1.\n\n\t4. The number of ways to traverse the current graph is calculated by summing up the number of ways from the two subproblems.\n\n\t5. The recursion continues until it reaches the base case, where the width or height becomes 1, and eventually returns the total number of ways to traverse the graph.\n\n\tWhile this recursive approach is conceptually simple, it suffers from efficiency issues due to exponential time complexity and redundant \n\tcalculations. As the graph size increases, the number of recursive calls grows exponentially, leading to a significant increase in computation time. Additionally, without memoization, the function recalculates the same subproblems multiple times, further reducing efficiency.\n\n\tTo address these drawbacks, alternative approaches like dynamic programming or memoization can be employed to store and \n\treuse the results of previously solved subproblems, avoiding redundant calculations and improving efficiency.\n\n\tThe given solution uses a recursive approach to calculate the number of ways to traverse a graph from the top-left corner \n\tto the bottom-right corner. However, this solution has some drawbacks that make it inefficient for larger inputs:\n\n\t1. Exponential Time Complexity: The recursive function makes multiple recursive calls, each with a smaller width or height. \n\tAs a result, the number of function calls grows exponentially with the size of the input. This leads to a high time complexity, making the solution inefficient for larger graphs. The time complexity is O(2^(width+height)), which can quickly become unmanageable.\n\n\t2. Overlapping Subproblems: The recursive function suffers from redundant calculations of the same subproblems. For example,\n\t when calculating the number of ways for a specific width and height, the function may recursively calculate the number of ways for smaller widths and heights multiple times. This leads to redundant work and decreases efficiency.\n\n\t3. Lack of Memoization: The solution does not utilize memoization to store the results of previously solved subproblems. \n\tWithout memoization, the recursive function ends up recalculating the same subproblems multiple times, further reducing efficiency.\n\n\tDue to these reasons, the given recursive solution is considered inefficient and impractical for larger graph sizes. \n\tIt is prone to exponential time complexity and redundant calculations, making it unsuitable for real-world scenarios where efficiency is crucial. Alternative approaches, such as the dynamic programming solution mentioned earlier, can provide better performance by avoiding redundant calculations and improving time complexity.\n*/\n\nfunction numberOfWaysToTraverseGraphRecursive(width, height) {\n  // Base case: when the width or height is 1, there is only one way to reach the destination\n  if (width === 1 || height === 1) {\n    return 1;\n  }\n\n  // Recursive case: sum the number of ways from the cell above and the cell to the left\n  return (\n    numberOfWaysToTraverseGraphRecursive(width - 1, height) +\n    numberOfWaysToTraverseGraphRecursive(width, height - 1)\n  );\n}\n"
  },
  {
    "path": "Dynamic Programming/num_ways_to_traverse_graph.py",
    "content": "'''\n    You're given two positive integers representing the width and height of a grid-shaped, rectangular graph.\n\tWrite a function that returns the number of ways to reach the bottom right corner of the graph when starting\n\tat the top left corner. Each move you take must either go down or right. In other words, you can never move up\n\tor left in the graph.\n\n\tFor example, given the graph illustrated below, with width = 2 and height = 3 , there are three ways to\n\treach the bottom right corner when starting at the top left corner:\n\t _ _\n\t|_|_|\n\t|_|_|\n\t|_|_|\n\tDown Down Right\n\tRight Down Down\n\tDown Right Down\n\n\tSample Input: Width : 4 height: 3\n\tOutput: 10\n\n\tExplanation:\n\tThe code snippet implements the `NumberOfWaysToTraverseGraph` function, which calculates the number of ways to\n\ttraverse a 2D graph from the top-left corner to the bottom-right corner. The graph has a given width and height.\n\n\tHere's a breakdown of the code:\n\n\t1. The function takes two parameters: `width` and `height`, representing the dimensions of the graph.\n\n\t2. It initializes a 2D slice called `numberOfWays` with dimensions `(height+1) x (width+1)`. The additional \"+1\" is to\n\t   account for the boundary cases when traversing the graph.\n\n\t3. It enters a nested loop to iterate over the graph cells. The outer loop iterates over the width indices (`widthIdx`),\n\t   and the inner loop iterates over the height indices (`heightIdx`).\n\n\t4. For each cell, it checks if it is on the top row (`heightIdx == 1`) or the leftmost column (`widthIdx == 1`). If so, it\n\t   means that there is only one way to reach that cell, either by moving right or moving down. Therefore, it sets `numberOfWays[heightIdx][widthIdx]` to 1.\n\n\t5. If the cell is not on the top row or the leftmost column, it means that it can be reached by either moving from the\n\t   cell above (up) or the cell to the left (left). The number of ways to reach the current cell is the sum of the number of\n\t   ways to reach the cell above and the number of ways to reach the cell to the left. This value is stored in\n\t  `numberOfWays[heightIdx][widthIdx]`.\n\n\t6. After iterating over all cells, the function returns the value stored in the bottom-right corner of `numberOfWays`,\n\t   which represents the total number of ways to traverse the graph.\n\n\tThe algorithm uses dynamic programming to build the `numberOfWays` matrix iteratively, starting from the top-left corner\n\tand moving towards the bottom-right corner. By calculating the number of ways to reach each cell based on the number of ways to reach its neighboring cells, it avoids redundant calculations and computes the result efficiently.\n\n\tThe time complexity of the algorithm is O(width * height) since it iterates over all cells of the graph.\n\n\tThe space complexity is also O(width * height) since it uses the `numberOfWays` matrix to store intermediate results.\n\n'''\n\ndef number_of_ways_to_traverse_graph(width, height):\n    # Initialize the numberOfWays matrix with dimensions (height+1) x (width+1)\n    # The extra \"+1\" is to account for the boundary cases when traversing the graph\n    numberOfWays = [[0] * (width + 1) for _ in range(height + 1)]\n\n    # Iterate over the graph cells\n    for widthIdx in range(1, width + 1):\n        for heightIdx in range(1, height + 1):\n            # Check if the current cell is on the top row or the leftmost column\n            if widthIdx == 1 or heightIdx == 1:\n                # If so, there is only one way to reach this cell (moving right or moving down)\n                numberOfWays[heightIdx][widthIdx] = 1\n            else:\n                # If the cell is not on the top row or the leftmost column,\n                # calculate the number of ways to reach this cell based on the\n                # number of ways to reach the cell above (up) and the cell to the left (left)\n                waysLeft = numberOfWays[heightIdx][widthIdx - 1]\n                waysUp = numberOfWays[heightIdx - 1][widthIdx]\n                numberOfWays[heightIdx][widthIdx] = waysLeft + waysUp\n\n    # Return the number of ways to reach the bottom-right corner of the graph\n    return numberOfWays[height][width]\n\n'''\n\tCombinatorics Solution\n\n\tThe given code snippet aims to calculate the number of ways to traverse a graph from the top-left corner to the bottom-right \n\tcorner. Let's break down the solution and provide a detailed explanation:\n\n\t1. The `NumberOfWaysToTraverseGraph` function takes two parameters: `width` and `height`, representing the dimensions of \n\t   the graph.\n\n\t2. The variables `xDistanceToCorner` and `yDistanceToCorner` are calculated by subtracting 1 from the `width` and `height` \n\t   respectively. These variables represent the distances from the top-left corner to the bottom-right corner along the x-axis and y-axis.\n\n\t3. The `factorial` function is defined separately to calculate the factorial of a number. It takes a number `num` as input \n\t   and uses an iterative approach to calculate the factorial.\n\n\t4. In the `NumberOfWaysToTraverseGraph` function, the numerator is calculated as the factorial of the sum of \n\t   `xDistanceToCorner` and `yDistanceToCorner`. This represents the total number of possible paths from the top-left \n\t   corner to the bottom-right corner.\n\n\t5. The denominator is calculated as the product of the factorials of `xDistanceToCorner` and `yDistanceToCorner`. \n\t   This represents the number of ways to arrange the steps along the x-axis and y-axis.\n\n\t6. Finally, the function returns the result by dividing the numerator by the denominator, giving the total number of \n\t   ways to traverse the graph.\n\n\tThe solution relies on the concept of combinatorics, specifically the binomial coefficient, to calculate the number of \n\tways to traverse the graph. By using factorials, it accounts for all possible paths and eliminates duplicate paths. \n\tThis approach provides an efficient solution to the problem.\n\n\tO(n + m) time | O(1) space - where n is the width of the graph and m is the height\n'''\n\nimport math\n\ndef number_of_ways_to_traverse_graph_combinatorics(width, height):\n    # Calculate the distance to the bottom-right corner of the graph\n    x_distance_to_corner = width - 1\n    y_distance_to_corner = height - 1\n\n    # Calculate the number of ways to traverse the graph using combinatorics\n    # by calculating the binomial coefficient of (x_distance_to_corner + y_distance_to_corner) choose x_distance_to_corner\n    # where (n choose k) = n! / (k! * (n-k)!)\n    numerator = math.factorial(x_distance_to_corner + y_distance_to_corner)\n    denominator = math.factorial(x_distance_to_corner) * math.factorial(y_distance_to_corner)\n\n    # Return the result by dividing the numerator by the denominator\n    return numerator // denominator\n\n'''\n\tRecursive solution\n\tThe given solution aims to calculate the number of ways to traverse a graph from the top-left corner to the bottom-right \n\tcorner. It uses a recursive approach to break down the problem into smaller subproblems.\n\n\tHere's how the solution works:\n\n\t1. The function `NumberOfWaysToTraverseGraph` takes the width and height of the graph as input and returns the number of ways to traverse it.\n\n\t2. The base case of the recursion is when either the width or height is equal to 1. In this case, there is only one way to traverse the graph: either by moving only horizontally or vertically. Therefore, the function returns 1.\n\n\t3. For other cases where the width and height are both greater than 1, the function recursively calls itself with two smaller subproblems:\n\t- One subproblem is created by reducing the width by 1 and keeping the same height.\n\t- The other subproblem is created by keeping the same width and reducing the height by 1.\n\n\t4. The number of ways to traverse the current graph is calculated by summing up the number of ways from the two subproblems.\n\n\t5. The recursion continues until it reaches the base case, where the width or height becomes 1, and eventually returns the total number of ways to traverse the graph.\n\n\tWhile this recursive approach is conceptually simple, it suffers from efficiency issues due to exponential time complexity and redundant \n\tcalculations. As the graph size increases, the number of recursive calls grows exponentially, leading to a significant increase in computation time. Additionally, without memoization, the function recalculates the same subproblems multiple times, further reducing efficiency.\n\n\tTo address these drawbacks, alternative approaches like dynamic programming or memoization can be employed to store and \n\treuse the results of previously solved subproblems, avoiding redundant calculations and improving efficiency.\n\n\tThe given solution uses a recursive approach to calculate the number of ways to traverse a graph from the top-left corner \n\tto the bottom-right corner. However, this solution has some drawbacks that make it inefficient for larger inputs:\n\n\t1. Exponential Time Complexity: The recursive function makes multiple recursive calls, each with a smaller width or height. \n\tAs a result, the number of function calls grows exponentially with the size of the input. This leads to a high time complexity, making the solution inefficient for larger graphs. The time complexity is O(2^(width+height)), which can quickly become unmanageable.\n\n\t2. Overlapping Subproblems: The recursive function suffers from redundant calculations of the same subproblems. For example,\n\t when calculating the number of ways for a specific width and height, the function may recursively calculate the number of ways for smaller widths and heights multiple times. This leads to redundant work and decreases efficiency.\n\n\t3. Lack of Memoization: The solution does not utilize memoization to store the results of previously solved subproblems. \n\tWithout memoization, the recursive function ends up recalculating the same subproblems multiple times, further reducing efficiency.\n\n\tDue to these reasons, the given recursive solution is considered inefficient and impractical for larger graph sizes. \n\tIt is prone to exponential time complexity and redundant calculations, making it unsuitable for real-world scenarios where efficiency is crucial. Alternative approaches, such as the dynamic programming solution mentioned earlier, can provide better performance by avoiding redundant calculations and improving time complexity.\n'''\ndef number_of_ways_to_traverse_graph_recursive(width, height):\n    if width == 1 or height == 1:\n        return 1\n    return number_of_ways_to_traverse_graph_recursive(width - 1, height) + number_of_ways_to_traverse_graph_recursive(width, height - 1)\n"
  },
  {
    "path": "Dynamic Programming/numbers_in_pi.go",
    "content": "/*\n\n\tGiven a string representation of the first n digits of Pi and a list of positive integers (all in string format), write a function that returns the\n\tsmallest number of spaces that can be added to the n digits of Pi such that all resulting numbers are found in the list of integers.\n\n\tSample Input pi = \"3141592653589793238462643383279\"\n\tnumbers : [\"314159265358979323846\", \"26433\", \"8\", \"3279\", \"314159265\", \"35897932384626433832\", \"79\"]\n\n\tOutput: 2\n\n\n\tExplanation:\n\n\tThe given code snippet is for solving the \"Numbers in Pi\" problem using a recursive approach with memoization (dynamic programming) to find the minimum number of spaces required to divide the given string representation of pi into valid numbers from a list of given numbers.\n\n\tThe problem is as follows: Given a string representation of the irrational number pi and a list of numbers, find the minimum number of spaces required to divide the string into valid numbers such that each number is present in the given list.\n\n\tLet's go through the code step by step:\n\n\t1. `NumbersInPi` function:\n\t- This is the main function that takes the string representation of pi and a list of numbers as input and returns the minimum number of spaces required. It initializes a `numbersTable` to store the numbers from the input list for quick lookup and then calls the `getMinSpaces` function with initial parameters.\n\n\t2. `getMinSpaces` function:\n\t- This is a recursive function with memoization. It takes the string representation of pi, the `numbersTable`, a `cache` (a map to store previously calculated values to avoid redundant calculations), and the current `idx` (position in the pi string) as input.\n\t- It first checks if the base case has been reached by comparing `idx` with the length of the pi string. If so, it returns -1.\n\t- Next, it checks if the result for the current `idx` is already present in the cache. If yes, it returns the cached result.\n\t- If the base case is not reached and the result is not in the cache, it initializes a variable `minSpaces` to store the minimum spaces required for the current `idx`. It sets `minSpaces` to a large value (initialized as `math.MaxInt32`) to ensure correct comparisons later.\n\t- Then, it iterates from the current `idx` to the end of the pi string and forms a prefix string from `idx` to the current iteration index (`i`).\n\t- If the prefix string is found in the `numbersTable`, it means it is a valid number from the given list. The function then recursively calls itself with the suffix (remaining part) of the pi string starting from index `i+1`.\n\t- The result of the recursive call is stored in `minSpacesInSuffix`.\n\t- The minimum of `minSpaces` and `minSpacesInSuffix + 1` is computed and assigned back to `minSpaces`. The \"+1\" indicates the current valid number prefix, which requires one space.\n\t- The loop continues, trying all possible valid prefixes from the current index.\n\t- Finally, the `minSpaces` value is stored in the `cache` to avoid redundant calculations and returned as the result for the current `idx`.\n\n\t3. `min` function:\n\t- A simple utility function to return the minimum of two integers.\n\n\tThe `NumbersInPi` function is the entry point, and the `getMinSpaces` function handles the recursive computation with memoization.\n\tBy using memoization, the code optimizes and reduces redundant calculations, making it more efficient than a pure\n\trecursive solution. The result returned by `NumbersInPi` is the minimum number of spaces required to divide the pi string\n\tinto valid numbers from the given list. If it is not possible to form valid numbers using the given list,\n\tthe function returns -1.\n*/\npackage main\n\nimport \"math\"\n\n// NumbersInPi finds the minimum number of spaces needed to divide the pi string\n// into valid numbers from the given list of numbers.\nfunc NumbersInPi(pi string, numbers []string) int {\n\tnumbersTable := map[string]bool{}\n\tfor _, number := range numbers {\n\t\tnumbersTable[number] = true\n\t}\n\n\t// Cache to store results of subproblems to avoid redundant calculations\n\tcache := map[int]int{}\n\tminSpaces := getMinSpaces(pi, numbersTable, cache, 0)\n\n\tif minSpaces == math.MaxInt32 {\n\t\treturn -1\n\t}\n\treturn minSpaces\n}\n\n// getMinSpaces calculates the minimum number of spaces needed to divide the remaining\n// suffix of the pi string into valid numbers from the numbersTable.\nfunc getMinSpaces(pi string, numbersTable map[string]bool, cache map[int]int, idx int) int {\n\t// Base case: If the end of the pi string is reached, return -1.\n\t// This indicates that the suffix of the pi string cannot be divided into valid numbers.\n\tif idx == len(pi) {\n\t\treturn -1\n\t} else if val, found := cache[idx]; found {\n\t\t// If the result for the current index is already in the cache, return it.\n\t\treturn val\n\t}\n\n\tminSpaces := math.MaxInt32\n\t// Iterate over possible prefixes starting from the current index.\n\tfor i := idx; i < len(pi); i++ {\n\t\tprefix := pi[idx : i+1]\n\n\t\t// If the prefix is found in the numbersTable, it is a valid number prefix.\n\t\tif _, found := numbersTable[prefix]; found {\n\t\t\t// Recursively calculate the minimum number of spaces in the suffix.\n\t\t\tminSpacesInSuffix := getMinSpaces(pi, numbersTable, cache, i+1)\n\t\t\t// Update the minimum spaces with the current prefix if it leads to a valid number.\n\t\t\tminSpaces = min(minSpaces, minSpacesInSuffix+1)\n\t\t}\n\t}\n\n\t// Cache the result for the current index to avoid redundant calculations.\n\tcache[idx] = minSpaces\n\treturn cache[idx]\n}\n\n// min returns the minimum of two integers.\nfunc min(a, b int) int {\n\tif a < b {\n\t\treturn a\n\t}\n\treturn b\n}\n"
  },
  {
    "path": "Dynamic Programming/reconstruct_bst_in_python.py",
    "content": "class TreeNode:\n    def __init__(self, val):\n        self.val = val\n        self.left = None\n        self.right = None\n\ndef constructBST(preorder):\n    if not preorder:\n        return None\n\n    root = TreeNode(preorder[0])\n\n    i = 1\n    while i < len(preorder) and preorder[i] < root.val:\n        i += 1\n\n    root.left = constructBST(preorder[1:i])\n    root.right = constructBST(preorder[i:])\n\n    return root\n\ndef inorderTraversal(root):\n    if root is None:\n        return []\n\n    return inorderTraversal(root.left) + [root.val] + inorderTraversal(root.right)\n\n# Sample Input\npreorder = [10, 4, 2, 1, 5, 17, 19, 18]\n\n# Construct the BST\nroot = constructBST(preorder)\n\n# Print the inorder traversal of the reconstructed BST\ninorder = inorderTraversal(root)\nprint(inorder)\n"
  },
  {
    "path": "Dynamic Programming/rod_cutting_problem_dp.cpp",
    "content": " /*\n    Given a rod of length n inches and an array of prices that contains prices of all \n    pieces of size smaller than n. Determine the maximum value obtainable by cutting \n    up the rod and selling the pieces. For example, if length of the rod is 8 and the \n    values of different pieces are given as following, then the maximum obtainable \n    value is 22 (by cutting in two pieces of lengths 2 and 6) \n    Input  : 8 \n           : 1   5   8   9  10  17  17  20\n    Output : 22     \n*/\n// Dynamic Programming solution TC : O(n^2)\n// Program Author: Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\nint max_profit(vector<int> profit, int total_length){\n    int dp[100] = {};\n    for(int length = 1; length <= total_length; length++){\n        int best = 0;\n        for(int cut = 1; cut <= length; cut++){\n            best = max(best, profit[cut] + dp[length - cut]);\n        }\n        dp[length] = best;\n    }\n    return dp[total_length];    \n}\nint main(){\n    int total_length;\n    cin >> total_length;\n    vector<int> profit(total_length + 1);\n    for(int length = 1; length <= total_length; length++)\n        cin >> profit[length];\n    int result = max_profit(profit, total_length);  \n    cout << result;      \n    return 0;\n}"
  },
  {
    "path": "Dynamic Programming/rod_cutting_problem_memoized.cpp",
    "content": "/*\n    Given a rod of length n inches and an array of prices that contains prices of all \n    pieces of size smaller than n. Determine the maximum value obtainable by cutting \n    up the rod and selling the pieces. For example, if length of the rod is 8 and the \n    values of different pieces are given as following, then the maximum obtainable \n    value is 22 (by cutting in two pieces of lengths 2 and 6) \n    Input  : 8 \n           : 1   5   8   9  10  17  17  20\n    Output : 22     \n*/\n// Memoized solution TC : O(n^2)\n// Program Author: Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\nint memoized[1000];\nint max_profit(vector<int> length, int n){\n    if(n == 0) return 0;\n    int best = 0;\n    if(memoized[n] != -1) return memoized[n];\n    for(int i = 0; i < n; i++){\n        int total_profit = length[i] + max_profit(length, n - (i + 1));\n        best = max(best, total_profit);\n        memoized[n] = best;\n    }\n    return memoized[n];\n}\nint main(){\n    memset(memoized, -1, sizeof(memoized));\n    int n;\n    cin >> n;\n    vector<int> length(n);\n    for(int i = 0; i < n; i++)\n        cin >> length[i];\n    int result = max_profit(length, n);  \n    cout << result;      \n    return 0;\n}"
  },
  {
    "path": "Dynamic Programming/rod_cutting_problem_recursive.cpp",
    "content": "/*\n    Given a rod of length n inches and an array of prices that contains prices of all \n    pieces of size smaller than n. Determine the maximum value obtainable by cutting \n    up the rod and selling the pieces. For example, if length of the rod is 8 and the \n    values of different pieces are given as following, then the maximum obtainable \n    value is 22 (by cutting in two pieces of lengths 2 and 6) \n    Input  : 8 \n           : 1   5   8   9  10  17  17  20\n    Output : 22     \n*/\n// Recursive solution TC : O(2^n)\n// Program Author: Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\nint max_profit(vector<int> length, int n){\n    if(n == 0) return 0;\n    int best = 0;\n    for(int i = 0; i < n; i++){\n        int total_profit = length[i] + max_profit(length, n - (i + 1));\n        best = max(best, total_profit);\n    }\n    return best;\n}\nint main(){\n    int n;\n    cin >> n;\n    vector<int> length(n);\n    for(int i = 0; i < n; i++)\n        cin >> length[i];\n    int result = max_profit(length, n);  \n    cout << result;      \n    return 0;\n}\n"
  },
  {
    "path": "Dynamic Programming/trapping_rain_water.cpp",
    "content": "\n/*\nGiven n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.\n\nExample 1:\n\nInput: height = [0,1,0,2,1,0,1,3,2,1,2,1]\nOutput: 6\n\nExplanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.\nExample 2:\n\nInput: height = [4,2,0,3,2,5]\nOutput: 9\n \nConstraints:\n\nn == height.length\n1 <= n <= 2 * 104\n0 <= height[i] <= 105\n*/\n#include<bits/stdc++.h>\n\nclass Solution {\npublic:\n    int trap(vector<int>& height) {    \n        int len = height.size(), result = 0;\n        if(len == 0) return 0;\n        int low = 0, high = len - 1, leftmax = 0, rightmax = 0;\n        while(low <= high){\n            if(height[low] < height[high]){\n                if(height[low] > leftmax)\n                    leftmax = height[low];\n                else\n                    result += leftmax - height[low];\n                low++;\n            }\n            else{\n                if(height[high] > rightmax)\n                    rightmax = height[high];\n                else\n                    result += rightmax - height[high];\n                high--;\n            }    \n        }\n        return result;\n    }    \n};"
  },
  {
    "path": "Dynamic Programming/unique_paths_with_obstacles.cpp",
    "content": "/*\n    You are given an m x n integer array grid. There is a robot initially located at the top-left corner (i.e., grid[0][0]). The robot tries to move to the bottom-right corner (i.e., grid[m - 1][n - 1]). The robot can only move either down or right at any point in time.\n\n    An obstacle and space are marked as 1 or 0 respectively in grid. A path that the robot takes cannot include any square that is an obstacle.\n\n    Return the number of possible unique paths that the robot can take to reach the bottom-right corner.\n\n    The testcases are generated so that the answer will be less than or equal to 2 * 109.\n\n    Example 1:\n    Input: obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]\n    Output: 2\n    Explanation: There is one obstacle in the middle of the 3x3 grid above.\n    There are two ways to reach the bottom-right corner:\n    1. Right -> Right -> Down -> Down\n    2. Down -> Down -> Right -> Right\n*/\n\nclass Solution {\npublic:\n    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {\n        int m = obstacleGrid.size(), n = obstacleGrid[0].size();\n        vector<vector<int> >dp(m + 1, vector<int> (n + 1, 0));\n        dp[0][1] = 1;\n        for(int i = 1; i<= m; i++){\n            for(int j = 1; j <= n; j++){\n                if(!obstacleGrid[i - 1][j - 1]){\n                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];\n                }       \n            }\n        }\n        return dp[m][n];\n    }\n};"
  },
  {
    "path": "Dynamic Programming/wine_selling_problem_dp.cpp",
    "content": "/*\n    Given n wines in a row, with integers denoting the cost of each wine respectively. \n    Each year you can sale the first or the last wine in the row. However, the price \n    of wines increases over time. Let the initial profits from the wines be P1, P2, P3…Pn. \n    On the Yth year, the profit from the ith wine will be Y*Pi.\n    Calculate the maximum profit from all the wines.\n\n    Input  : 5\n           : 2 4 6 2 5\n    Output : 64 \n*/\n// Dynamic Programming Approach TC : O(N^2)\n// Program Author :  Abhisek Kumar Gupta\n\n#include<bits/stdc++.h>\nusing namespace std;\nint find_max_profit(int *A, int n){\n    int dp[100][100] = {};\n    int year = n;\n    for(int i = 0; i < n; i++){\n        dp[i][i] = year * A[i];\n    }\n    year--;\n    for(int i = 2; i <= n; i++){\n        int start = 0;\n        int end = n - i;\n        while(start <= end){\n            int end_window = start + i - 1;\n            int x = A[start] * year + dp[start + 1][end_window];\n            int y = A[end_window]* year + dp[start][end_window - 1];\n            dp[start][end_window] = max(x, y);\n            start++;\n        }\n        year--;\n    }\n  /*  for(int i = 0; i < n; i++){\n        for(int j = 0; j < n; j++){\n            cout << setw(5) << dp[i][j] << \" \";\n        }\n        cout << \"\\n\";\n    }\n  */  \n    return dp[0][n-1];\n}\nint main(){\n    int n;\n    cin >> n;\n    int *A;\n    for(int i = 0; i < n; i++)\n        cin >> A[i];\n    int start = 0;\n    int end = n - 1; \n    int year = 1;   \n    int result = find_max_profit(A, n);    \n    cout << result;\n    return 0;\n}\n"
  },
  {
    "path": "Dynamic Programming/wine_selling_problem_memoized.cpp",
    "content": "/*\n    Given n wines in a row, with integers denoting the cost of each wine respectively. \n    Each year you can sale the first or the last wine in the row. However, the price \n    of wines increases over time. Let the initial profits from the wines be P1, P2, P3…Pn. \n    On the Yth year, the profit from the ith wine will be Y*Pi.\n    Calculate the maximum profit from all the wines.\n\n    Input  : 5\n           : 2 4 6 2 5\n    Output : 64 \n*/\n// Memoized Approach TC : O(N^2)\n// Program Author :  Abhisek Kumar Gupta\n\n#include<bits/stdc++.h>\nusing namespace std;\nint memoized[1000][1000];\nint find_max_profit(int *A, int start, int end, int year){\n    if(start > end)\n        return 0;\n    if(memoized[start][end] != -1)\n        return memoized[start][end];\n    int r1 = A[start] * year + find_max_profit(A, start + 1, end, year + 1);\n    int r2 = A[end] * year + find_max_profit(A, start, end - 1, year + 1);\n    int answer = max(r1, r2); ;\n    memoized[start][end] = answer;\n    return memoized[start][end];    \n}\nint main(){\n    memset(memoized, -1, sizeof(memoized));\n    int n;\n    cin >> n;\n    int *A;\n    for(int i = 0; i < n; i++)\n        cin >> A[i];\n    int start = 0;\n    int end = n - 1; \n    int year = 1;   \n    int result = find_max_profit(A, start, end, year);    \n    cout << result;\n    return 0;\n}"
  },
  {
    "path": "Dynamic Programming/wine_selling_problem_recursive.cpp",
    "content": "/*\n    Given n wines in a row, with integers denoting the cost of each wine respectively. \n    Each year you can sale the first or the last wine in the row. However, the price \n    of wines increases over time. Let the initial profits from the wines be P1, P2, P3…Pn. \n    On the Yth year, the profit from the ith wine will be Y*Pi.\n    Calculate the maximum profit from all the wines.\n\n    Input  : 5\n           : 2 4 6 2 5\n    Output : 64 \n*/\n// Recursive Approach TC : O(2^n)\n// Program Author :  Abhisek Kumar Gupta\n\n#include<bits/stdc++.h>\nusing namespace std;\nint find_max_profit(int *A, int start, int end, int year){\n    if(start > end)\n        return 0;\n    int r1 = A[start] * year + find_max_profit(A, start + 1, end, year + 1);\n    int r2 = A[end] * year + find_max_profit(A, start, end - 1, year + 1);\n    return max(r1, r2);    \n}\nint main(){\n    int n;\n    cin >> n;\n    int *A;\n    for(int i = 0; i < n; i++)\n        cin >> A[i];\n    int start = 0;\n    int end = n - 1; \n    int year = 1;   \n    int result = find_max_profit(A, start, end, year);    \n    cout << result;\n    return 0;\n}"
  },
  {
    "path": "Famous Algorithms/N_queen.js",
    "content": "function solveNQueens(n) {\n  const board = new Array(n).fill().map(() => new Array(n).fill('.')); // Create an empty NxN chessboard\n  \n  const solutions = [];\n  \n  function isSafe(row, col) {\n    // Check if no other queens are in the same column\n    for (let i = 0; i < row; i++) {\n      if (board[i][col] === 'Q') {\n        return false;\n      }\n    }\n    \n    // Check upper-left diagonal\n    for (let i = row, j = col; i >= 0 && j >= 0; i--, j--) {\n      if (board[i][j] === 'Q') {\n        return false;\n      }\n    }\n    \n    // Check upper-right diagonal\n    for (let i = row, j = col; i >= 0 && j < n; i--, j++) {\n      if (board[i][j] === 'Q') {\n        return false;\n      }\n    }\n    \n    return true;\n  }\n  \n  function solve(row) {\n    if (row === n) {\n      // Found a valid solution, push a copy of the board to the solutions array\n      solutions.push(board.map(row => row.join('')));\n      return;\n    }\n    \n    for (let col = 0; col < n; col++) {\n      if (isSafe(row, col)) {\n        board[row][col] = 'Q'; // Place a queen\n        solve(row + 1); // Recursively move to the next row\n        board[row][col] = '.'; // Backtrack by removing the queen\n      }\n    }\n  }\n  \n  solve(0); // Start solving from the first row\n  \n  return solutions;\n}\n\n// Example usage:\nconst n = 4; // Change this to the desired board size\nconst solutions = solveNQueens(n);\n\nconsole.log(`Solutions for ${n}-Queens:`);\nfor (const solution of solutions) {\n  console.log(solution);\n}\n"
  },
  {
    "path": "Famous Algorithms/euclidean_algorithm.java",
    "content": "//extended version of Euclid's algorithm to find GCD of 2 numbers\n//runs in O(log N) time/space complexity for GCD of numbers a and b \n//in comparison, the standard Euclidean algorithm runs in O (log (min (a,b)))\n\npublic class euclidean_algorithm {\n    public static int euclid(int a, int b, int c, int d){\n        if(a == 0){\n            c = 0;\n            d = 0;\n            return b;\n        }\n        int c1 = 1,d1 = 1;\n        int result = euclid(b%a, a, c1, d1);\n        //update with recursive call\n        c = d1 - (b / a) * c1;\n        d = c1;\n        return result;\n    }\n    //driver\n    public static void main(String[] args) {\n        int c =1, d = 1;\n        int a = 45;\n        int b = 10;\n        int gcd = euclid(a, b, c, d);\n        System.out.print(\"gcd of \"+ a+\",\" +b +\" is equal to: \" + gcd);\n    }\n}\n"
  },
  {
    "path": "Famous Algorithms/euclidean_algorithm.js",
    "content": "//extended version of Euclid's algorithm to find GCD of 2 numbers\n//runs in O(log N) time/space complexity for GCD of numbers a and b \n//in comparison, the standard Euclidean algorithm runs in O (log (min (a,b)))\n\n\nfunction euclid(a,b,c,d){\n    if(a == 0){\n        c = 0;\n        d = 1;\n        return b;\n    }\n    let result = euclid(b%a,a,c,d);\n    //update with recursive values\n    c = d- (b / a) * c;\n    d = c;\n    return result;\n}\n//modify a and b to find gcd of any 2 numbers\nlet a = 450;\nlet b = 100;\nlet gcd = euclid(a,b,0,0);\nconsole.log(`GCD of ${a}, ${b} is equal to ${gcd}`);\n"
  },
  {
    "path": "Famous Algorithms/euclidean_algorithm.py",
    "content": "#extended version of Euclid's algorithm to find GCD of 2 numbers\n#runs in O(log N) time/space complexity for GCD of numbers a and b \n#in comparison, the standard Euclidean algorithm runs in O (log (min (a,b)))\n\ndef euclidExtended(a,b):\n    if a==0:\n        return b,0, 1 \n    result, a1, b1 = euclidExtended(b%a,a)\n    \n    a2 = b1- (b//a) *a1\n    b2 = a1\n    return result, a2, b2 #used as input to recursive call, \n\n#example driver, change a and b as desired\n\na,b = 45,10\ng,x,y = euclidExtended(a,b)\nprint(\"gcd of\", a,\",\" ,b ,\"is equal to: \" , g)\n    \n    \n        \n"
  },
  {
    "path": "Famous Algorithms/kadanes_algorithm.c++",
    "content": "/* Name : Rajeev Kumar\nGithub username : Tonystark121\nRepository name : data-structures-and-algorithms\nProblem : Kadane's algorithm in C++\nIssue Number : #1179\nProblem statement : Given an integer array nums, find the subarray with the largest sum, and return its sum.\n\nSample testcases: \n\nTestcase 1 --> \n\nInput: number of elements in array = 8\nnums = [-2,-3,5,-1,-2,1,5,-3]\nOutput: 8\n\nTestcase 2 -->\nInput: number of elements in array = 5\nnums = [5,4,-1,7,8]\nOutput: 23\n\nTime Complexity = O(n)\nSpace Complexity = O(1)\n\n\nExplanation:\nThis code asks the user to enter the number of elements in an array,\nand then prompts them to enter each element of the array one at a time.\nOnce the array is complete, the code applies the Kadane's algorithm to\nfind the maximum sum of any subarray within the array, and then prints \nthe result to the console.\n\nKadane's algorithm is a way of finding the maximum sum of a contiguous subarray within an array,\nand it does so by keeping track of the maximum sum seen so far as it iterates through the array.\nAt each step, it adds the current element to a running sum, and if that sum becomes negative,\nit resets the running sum to zero. If the running sum is ever greater than the maximum seen so far,\nit updates the maximum. Finally, it returns the maximum sum.\n*/\n\n// ----------------------------------------------------------------------------- code begins now!\n\n\n#include<bits/stdc++.h>\nusing namespace std;\n\nint main(){\n\n    // taking input number of array elements.\n    int n; \n    cin>>n;\n\n    // taking input array elements.\n    int arr[n];\n    for(int i=0;i<n;i++){\n        cin>>arr[i];\n    }\n\n    // declare current maximum and maximum so far variable.\n    int curr_max=0,max_so_far=INT_MIN;\n\n    for(int i=0;i<n;i++){\n        \n        curr_max += arr[i];\n\n        if(curr_max<0){\n            curr_max=0;\n        }\n\n        if(curr_max>max_so_far){\n            max_so_far = curr_max;\n        }\n    }\n\n    // output result.\n    cout<<max_so_far<<endl;\n    return 0;\n}"
  },
  {
    "path": "Famous Algorithms/kadanes_algorithm.go",
    "content": "/*\n\tWrite a function that takes in a non-empty array of integers and returns the\n\tmaximum sum that can be obtained by summing up all of the integers in a\n\tnon-empty subarray of the input array. A subarray must only contain adjacent\n\tnumbers (numbers next to each other in the input array).\n\n\tSample Input: [3, 5, -9, 1, 3, -2, 3, 4, 7, 2, -9, 6, 3, 1, -5, 4]\n\tOutput: 19\n\n\tExplanation:\n\n\tThe function takes an array of integers as input, and initializes two variables: `maxEndingHere` and `maxSoFar`. \n\t`maxEndingHere` keeps track of the maximum subarray sum that ends at the current element, and `maxSoFar` keeps track \n\tof the maximum subarray sum seen so far.\n\n\tThe function then iterates through the array starting at the second element, and for each element, it calculates the \n\tmaximum subarray sum that ends at that element by adding the current element to the maximum subarray sum that ends at \n\tthe previous element (`maxEndingHere + num`). If this sum is greater than the current element itself (`num`), then `maxEndingHere` is updated to the sum. Otherwise, `maxEndingHere` is updated to `num`.\n\n\tAfter each iteration, `maxSoFar` is updated to the maximum value seen so far, which is either `maxEndingHere` or `maxSoFar`.\n\n\tThe function finally returns `maxSoFar`, which represents the maximum subarray sum of the input array. The `max` function \n\tis a helper function used to compare two integers and return the maximum of the two.\n\n\tO(n) time | O(1) space - where n is the length of the input array\n\n*/\npackage main\n\n// KadanesAlgorithm computes the maximum sum subarray using Kadane's algorithm\nfunc KadanesAlgorithm(array []int) int {\n\t// Initialize maxEndingHere and maxSoFar to the first element of the array\n\tmaxEndingHere, maxSoFar := array[0], array[0]\n\n\t// Loop through the array starting from the second element\n\tfor _, num := range array[1:] {\n\t\t// Compute the maximum subarray sum ending at the current element\n\t\tmaxEndingHere = max(maxEndingHere+num, num)\n\n\t\t// Update maxSoFar if the current maximum subarray sum is greater\n\t\tmaxSoFar = max(maxEndingHere, maxSoFar)\n\t}\n\n\t// Return the maximum subarray sum\n\treturn maxSoFar\n}\n\n// max returns the maximum of two integers\nfunc max(a, b int) int {\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n q"
  },
  {
    "path": "Famous Algorithms/kadanes_algorithm.java",
    "content": "/* Name : Aneesh\nGithub username : 007aneesh\nRepository name : data-structures-and-algorithms\nProblem : Kadane's algorithm in Java\nIssue Number : #1180\nProblem statement : Given an integer array nums, find the subarray with the largest sum, and return its sum.\n\nSample testcases: \n\nTestcase 1 --> \n\nInput: number of elements in array = 9\nnums = [-2,1,-3,4,-1,2,1,-5,4]\nOutput: 6\n\nTestcase 2 -->\nInput: number of elements in array\nnums = [5,4,-1,7,8]\nOutput: 23\n\nTime Complexity = O(n)\nSpace Complexity = O(1)\n\n\nExplanation:\nThis code asks the user to enter the number of elements in an array,\nand then prompts them to enter each element of the array one at a time.\nOnce the array is complete, the code applies the Kadane's algorithm to\nfind the maximum sum of any subarray within the array, and then prints \nthe result to the console.\n\nKadane's algorithm is a way of finding the maximum sum of a contiguous subarray within an array,\nand it does so by keeping track of the maximum sum seen so far as it iterates through the array.\nAt each step, it adds the current element to a running sum, and if that sum becomes negative,\nit resets the running sum to zero. If the running sum is ever greater than the maximum seen so far,\nit updates the maximum. Finally, it returns the maximum sum.\n*/\n\n// ----------------------------------------------------------------------------- code begins now!\nimport java.util.Scanner;\n\npublic class kadanes_algo {\n\tpublic static int maxSubArraySum(int[] arr) {\n        if (arr == null || arr.length == 0) {\n            return 0;\n        }\n\n        int max = 0;\n        int sum = Integer.MIN_VALUE;\n\n        for (int i = 0; i < arr.length; i++) {\n            max += arr[i];\n\n            if (max < arr[i]) {\n                max = arr[i];\n            }\n\n            if (sum < max) {\n                sum = max;\n            }\n        }\n\n        return sum;\n    }\n\n    public static void main(String[] args) {\n        Scanner sc = new Scanner(System.in);\n        System.out.print(\"Enter the number of elements in the array: \");\n        int n = sc.nextInt();\n        int[] arr = new int[n];\n        System.out.println(\"Enter the elements of the array:\");\n        for (int i = 0; i < n; i++) {\n            arr[i] = sc.nextInt();\n        }\n\n        int maxSum = maxSubArraySum(arr);\n        System.out.println(\"The maximum subarray sum is \" + maxSum);\n    }\n\n}\n"
  },
  {
    "path": "Famous Algorithms/kadanes_algorithm.py",
    "content": "\"\"\"\nWhat is Kadane's Algorithm?\nKadane's Algorithm is a way to find the maximum subarray sum in an array with a runtime of O(n).\nIt is a dynamic programming algorithm that uses the fact that the maximum subarray sum ending at index i is either the value at index i or the maximum subarray sum ending at index i-1 plus the value at index i.\n\nNote: The subarray must be contiguous, all the values in the subarray must be next to each other in the original array.\n\nHow does it work?\nThe algorithm works by iterating through the array and keeping track of the maximum subarray sum seen so far and the maximum subarray sum ending at the current index.\nThe maximum subarray sum ending at the current index is either the value at the current index or the maximum subarray sum ending at the previous index plus the value at the current index.\n\nLets take the example: {-2, -3, 4, -1, -2, 1, 5, -3}\n    max_so_far = INT_MIN\n    max_ending_here = 0\n\n    for i=0,  a[0] =  -2\n    max_ending_here = max_ending_here + (-2)\n    Set max_ending_here = 0 because max_ending_here < 0\n    and set max_so_far = -2\n\n    for i=1,  a[1] =  -3\n    max_ending_here = max_ending_here + (-3)\n    Since max_ending_here = -3 and max_so_far = -2, max_so_far will remain -2\n    Set max_ending_here = 0 because max_ending_here < 0\n\n    for i=2,  a[2] =  4\n    max_ending_here = max_ending_here + (4)\n    max_ending_here = 4\n    max_so_far is updated to 4 because max_ending_here greater \n    than max_so_far which was -2 till now\n\n    for i=3,  a[3] =  -1\n    max_ending_here = max_ending_here + (-1)\n    max_ending_here = 3\n\n    for i=4,  a[4] =  -2\n    max_ending_here = max_ending_here + (-2)\n    max_ending_here = 1\n\n    for i=5,  a[5] =  1\n    max_ending_here = max_ending_here + (1)\n    max_ending_here = 2\n\n    for i=6,  a[6] =  5\n    max_ending_here = max_ending_here + (5)\n    max_ending_here = 7\n    max_so_far is updated to 7 because max_ending_here is \n    greater than max_so_far\n\n    for i=7,  a[7] =  -3\n    max_ending_here = max_ending_here + (-3)\n    max_ending_here = 4\n    \n    Time Complexity: O(n)\n    Space Complexity: O(1)\n\"\"\"\n\nfrom sys import maxint\n\n# maxint is a constant that holds the maximum possible value for an integer in Python.\n\n\ndef maxSubArraySum(a, size):\n    # we take the max_so_far to be the smallest possible integer value\n    max_so_far = -maxint - 1\n\n    # initialize max_ending_here to 0\n    max_ending_here = 0\n\n    for i in range(0, size):\n        max_ending_here = max_ending_here + a[i]\n        if max_so_far < max_ending_here:\n            max_so_far = max_ending_here\n\n        # if max_ending_here is negative, we set it to 0\n        if max_ending_here < 0:\n            max_ending_here = 0\n\n    return max_so_far\n\n\n# Driver function to check the above function\n\n\na = [-2, -3, 4, -1, -2, 1, 5, -3]\n\nprint(\"Maximum contiguous sum is\", maxSubArraySum(a, len(a)))\n"
  },
  {
    "path": "Famous Algorithms/kadenes_algorithm.js",
    "content": "/* What is Kadane's Algorithm?\nKadane's Algorithm is a way to find the maximum subarray sum in an array with a runtime of O(n).\nIt is a dynamic programming algorithm that uses the fact that the maximum subarray sum ending at index i is either the value at index i or the maximum subarray sum ending at index i-1 plus the value at index i.\n\nNote: The subarray must be contiguous, all the values in the subarray must be next to each other in the original array.\n\nHow does it work?\nIn this algorithim we maintain two variables, one will hold the maximum sum of contagious subarray and the other variable will hold sum of next element + current sum from previous iteration.\nIf at any point the current sum + next element sum is less then 0 then we will reset the current sum to 0 and current sum + next element sum will start again from the next element.\nIf the current sum + next element sum is greater then 0 and it is also greater then the maximum sum of contagious subarray then the variable of maximum sum of contagious subarray will be updated with current sum + next element sum\n\n\nLets take the example: {-2, -3, 4, -1, -2, 1, 5, -3}\n    In this example maxLargestSumTillNow holds the maximum sum of contagious subarray and newLargestSum hold the value of current sum + next element\n    On initalizing max so far will be the max -ve number\n    maxLargestSumTillNow = INT_MIN\n    newLargestSum = 0\n\n    for i=0,  a[0] =  -2\n    newLargestSum = newLargestSum + (-2)\n    Set newLargestSum = 0 because newLargestSum < 0\n    and set maxLargestSumTillNow = -2\n\n    for i=1,  a[1] =  -3\n    newLargestSum = newLargestSum + (-3)\n    Since newLargestSum = -3 and maxLargestSumTillNow = -2, maxLargestSumTillNow will remain -2\n    Set newLargestSum = 0 because newLargestSum < 0\n\n    for i=2,  a[2] =  4\n    newLargestSum = newLargestSum + (4)\n    newLargestSum = 4\n    maxLargestSumTillNow is updated to 4 because newLargestSum greater \n    than maxLargestSumTillNow which was -2 till now\n\n    for i=3,  a[3] =  -1\n    newLargestSum = newLargestSum + (-1)\n    newLargestSum = 3\n\n    for i=4,  a[4] =  -2\n    newLargestSum = newLargestSum + (-2)\n    newLargestSum = 1\n\n    for i=5,  a[5] =  1\n    newLargestSum = newLargestSum + (1)\n    newLargestSum = 2\n\n    for i=6,  a[6] =  5\n    newLargestSum = newLargestSum + (5)\n    newLargestSum = 7\n    maxLargestSumTillNow is updated to 7 because newLargestSum is \n    greater than maxLargestSumTillNow\n\n    for i=7,  a[7] =  -3\n    newLargestSum = newLargestSum + (-3)\n    newLargestSum = 4\n    \n    Time Complexity: O(n)\n    Space Complexity: O(1)\n*/\n\nfunction largestSumOfSubArray(arr) {\n    if (arr.lenth == 1) {\n        return arr[0];\n    }\n\n    // Variable for maintaining Maximum sum of the subarray\n    var maxint = Math.pow(2, 53);\n    var maxLargestSumTillNow = -maxint - 1;\n\n    // Variable to calclate the sum of subarray after each iteration\n    var newLargestSum = 0;\n\n    // Looping through the entire array\n    for (i = 0; i < arr.length - 1; i++) {\n        // Calculating the largest sum on each iteration\n        newLargestSum += arr[i];\n\n        // If the largest sum value is greater then the maximum largest subarray value we have maintained then we will assign new value to maintained maximum largest subarray\n        if (maxLargestSumTillNow < newLargestSum) {\n            maxLargestSumTillNow = newLargestSum;\n        }\n\n        // If the largest sum is negative then we will reset the value of largest sum to 0 and start the calculation again of largest sum from next element\n        if (newLargestSum < 0) {\n            newLargestSum = 0;\n        }\n    }\n\n    // After the completion of iteration we will return the max largest sub array value\n    return maxLargestSumTillNow;\n}\n\n// Driver code\nvar arr = [-2, -3, 4, -1, -2, 1, 5, -3];\nconsole.log(largestSumOfSubArray(arr));\n\n// Input: arr = [-2, -3, 4, -1, -2, 1, 5, -3];\n//Output: 7\n"
  },
  {
    "path": "Famous Algorithms/kmp.java",
    "content": "/**\n * Summary:\n * This program implements the Knuth-Morris-Pratt (KMP) algorithm for string pattern matching.\n * Given a text string and a pattern string, the algorithm searches for the pattern in the text and returns\n * the index where the pattern is found in the text. If the pattern is not found, it returns -1.\n * \n * Inputs:\n * The program expects two strings as inputs: text and pattern.\n * \n * Outputs:\n * The output of the program is the index where the pattern is found in the text, or -1 if the pattern is not found.\n * \n * Example Usage:\n * // Input\n * String text = \"ABABDABACDABABCABAB\";\n * String pattern = \"ABABCABAB\";\n * \n * // Execute the KMP algorithm for string pattern matching\n * int index = searchPattern(text, pattern);\n * \n * // Output\n * if (index != -1) {\n *     System.out.println(\"Pattern found at index: \" + index);\n * } else {\n *     System.out.println(\"Pattern not found in the text.\");\n * }\n * \n * Complexity Analysis:\n * The time complexity of the KMP algorithm is O(n + m), where n is the length of the text and m is the length of the pattern.\n * This is because the algorithm avoids unnecessary comparisons by utilizing the computed Longest Proper Prefix-Suffix (LPS) array.\n * The space complexity is O(m) as it requires storing the LPS array of the pattern.\n */\n\npublic class Graph_KMPAlgorithm {\n\n    public static int[] computeLPSArray(String pattern) {\n        int[] lps = new int[pattern.length()];\n        int len = 0;  // Length of the previous longest prefix suffix\n        int i = 1;\n\n        while (i < pattern.length()) {\n            if (pattern.charAt(i) == pattern.charAt(len)) {\n                len++;\n                lps[i] = len;\n                i++;\n            } else {\n                if (len != 0) {\n                    len = lps[len - 1];\n                } else {\n                    lps[i] = 0;\n                    i++;\n                }\n            }\n        }\n\n        return lps;\n    }\n\n    public static int searchPattern(String text, String pattern) {\n        int n = text.length();\n        int m = pattern.length();\n\n        int[] lps = computeLPSArray(pattern);\n\n        int i = 0;  // index for text\n        int j = 0;  // index for pattern\n\n        while (i < n) {\n            if (text.charAt(i) == pattern.charAt(j)) {\n                i++;\n                j++;\n            }\n\n            if (j == m) {\n                return i - j;\n            } else if (i < n && text.charAt(i) != pattern.charAt(j)) {\n                if (j != 0) {\n                    j = lps[j - 1];\n                } else {\n                    i++;\n                }\n            }\n        }\n\n        return -1;  // pattern not found in text\n    }\n\n    public static void main(String[] args) {\n        String text = \"ABABDABACDABABCABAB\";\n        String pattern = \"ABABCABAB\";\n\n        int index = searchPattern(text, pattern);\n\n        if (index != -1) {\n            System.out.println(\"Pattern found at index: \" + index);\n        } else {\n            System.out.println(\"Pattern not found in the text.\");\n        }\n    }\n}\n"
  },
  {
    "path": "Famous Algorithms/kmp.js",
    "content": "/**The Knuth-Morris-Pratt (KMP) algorithm is a string matching algorithm that efficiently finds occurrences of a pattern within a text. It was developed by Donald Knuth and Vaughan Pratt in 1977.\n\nThe key idea behind the KMP algorithm is to take advantage of the information present in the pattern itself to avoid unnecessary character comparisons during the search process. It achieves this by utilizing a preprocessed array called the Longest Proper Prefix which is also Suffix (LPS) array or failure function.\n\nHere's a step-by-step explanation of the KMP algorithm:\n\n1. Preprocessing (Compute LPS Array):\n   - Given a pattern of length m, the first step is to compute the LPS array, which holds information about the longest proper prefix that is also a suffix for each position in the pattern.\n   - The LPS array is initialized with the first element as 0 and then iteratively calculated for each position of the pattern using the following rules:\n     - If the characters at the current position and the previous longest proper prefix suffix match, increment the length of the prefix and store it in the LPS array.\n     - If the characters don't match:\n       - If the length of the prefix is not zero, move to the previous longest proper prefix suffix and continue the comparison.\n       - If the length of the prefix is zero, store 0 in the LPS array for the current position.\n   - This preprocessing step is done in O(m) time complexity.\n\n2. Search (Pattern Matching):\n   - With the LPS array computed, the search process begins by comparing characters of the text and pattern.\n   - Initialize two pointers, i for the text and j for the pattern, both starting from 0.\n   - Iterate over the text from left to right until i reaches the end of the text:\n     - If the characters at the current positions i and j match, increment both i and j.\n     - If j reaches the end of the pattern, a match is found:\n       - Store the index (i - j) as an occurrence of the pattern in the text.\n       - Move j to the previous longest proper prefix suffix using the LPS array.\n     - If the characters at the current positions i and j don't match:\n       - If j is not at the beginning of the pattern, move j to the previous longest proper prefix suffix using the LPS array.\n       - If j is at the beginning of the pattern, increment i and continue the search.\n   - The search process iterates over the text once and performs comparisons using the LPS array, resulting in a time complexity of O(n), where n is the length of the text.\n\nThe KMP algorithm provides an efficient way to search for patterns within a text by avoiding redundant comparisons. It achieves this by utilizing the LPS array, which stores information about the pattern's structure. This makes the KMP algorithm more efficient than naive approaches such as the brute-force method, especially when the pattern has repeated characters or subsequences. */\n\n/**\n * Computes the Longest Proper Prefix which is also Suffix (LPS) array for the given pattern.\n * The LPS array is used to determine the longest prefix of the pattern that is also a suffix.\n *\n * @param {string} pattern - The pattern string.\n * @returns {number[]} - The LPS array.\n */\n function computeLPSArray(pattern) {\n    const lps = [0]; // Initialize LPS array with the first element as 0.\n    let len = 0; // Length of the previous longest prefix suffix.\n    let i = 1; // Current index in the pattern string.\n  \n    while (i < pattern.length) {\n      if (pattern[i] === pattern[len]) {\n        len++;\n        lps[i] = len;\n        i++;\n      } else {\n        if (len !== 0) {\n          // Move len to the previous longest prefix suffix value.\n          len = lps[len - 1];\n        } else {\n          lps[i] = 0;\n          i++;\n        }\n      }\n    }\n  \n    return lps;\n  }\n  \n  /**\n   * Performs the Knuth-Morris-Pratt (KMP) algorithm to find all occurrences of a pattern within a text.\n   *\n   * @param {string} text - The text string.\n   * @param {string} pattern - The pattern string.\n   * @returns {number[]} - An array of indices where the pattern is found within the text.\n   */\n  function KMP(text, pattern) {\n    const m = pattern.length; // Length of the pattern.\n    const n = text.length; // Length of the text.\n    const lps = computeLPSArray(pattern); // Compute the LPS array for the pattern.\n    const indices = []; // Array to store the indices where the pattern is found.\n  \n    let i = 0; // Current index in the text string.\n    let j = 0; // Current index in the pattern string.\n  \n    while (i < n) {\n      if (pattern[j] === text[i]) {\n        i++;\n        j++;\n      }\n  \n      if (j === m) {\n        // Pattern found at index i - j.\n        indices.push(i - j);\n        j = lps[j - 1]; // Move j to the previous longest prefix suffix value.\n      } else if (i < n && pattern[j] !== text[i]) {\n        if (j !== 0) {\n          j = lps[j - 1]; // Move j to the previous longest prefix suffix value.\n        } else {\n          i++;\n        }\n      }\n    }\n  \n    return indices;\n  }\n  \n  // Example usage:\n  const text = \"ABABDABACDABABCABAB\";\n  const pattern = \"ABABCABAB\";\n  \n  const indices = KMP(text, pattern);\n  console.log(\"Pattern found at indices:\", indices);\n  \n  // Pattern found at indices: [10]\n\n  /**\n   \nTime Complexity:\n\nThe KMP algorithm has a time complexity of O(m + n), where m is the length of the pattern and n is the length of the text. It computes the LPS array in O(m) time and performs a single pass over the text in O(n) time.\n\nSpace Complexity:\n\nThe space complexity of the KMP algorithm is O(m), where m is the length of the pattern. It is due to the LPS array, which requires O(m) space to store the longest prefix suffix values for each index in the pattern. The additional space used by the algorithm is minimal and does not depend on the input size */"
  },
  {
    "path": "Famous Algorithms/kmp.py",
    "content": "# Implementation of KMP Algorithm. Program Author : SNEHA CHAUHAN\n''' problem: Given a text txt and a pattern pat, write a function search(char pat[], char txt[]) \n    that prints all occurrences of pat[] in txt[]. \n\n    KMP algorithm is used to find the pattern in the given string. This is naive approach to find \n    the pattern in the given string.\n\n    Time Complexity: O(n*m)\n    Space Complexity: O(1)\n\n    Example: \n    input: txt = “AAAABAAABA” pat = “AAAA”\n    output: Pattern found at index 0\n        \n    Algorithm:\n    1. Start from the leftmost character of txt and one by one compare it with each character of pat.\n    2. If a character matches, then move both txt and pat ahead and compare the next character.\n    3. If a mismatch occurs, then move pat to the index where the mismatch occurs and compare again.\n    4. If pat reaches its end without any mismatch, then pattern found.\n\n    '''\n\ndef search(pat, txt):\n    M = len(pat)\n    N = len(txt)\n\n    # A loop to slide pat[] one by one\n    for i in range(N - M + 1):\n        j = 0\n\n        # For current index i, check for pattern match\n        for j in range(0, M):\n            if (txt[i + j] != pat[j]):\n                break\n\n        if (j == M - 1):\n            print(\"Pattern found at index \", i)\n\n\n# Driver Code\nif __name__ == '__main__':\n    txt = \"AABAACAADAABAAABAA\"\n    pat = \"AABA\"\n    search(pat, txt)"
  },
  {
    "path": "Fast and Slow Pointers/happy_number.go",
    "content": "/*\nWrite an algorithm to determine if a number num is happy.\n\nA happy number is a number defined by the following process:\n\nStarting with any positive integer, replace the number by the sum of the squares of its digits.\nRepeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1\n\nThose numbers for which this process ends in 1 are happy.\nReturn TRUE if num is a happy number, and FALSE if not.\n\nSample Input : 4\nOutput: False\n\nSample Input : 19\nOutput: True\n\n*/\n\npackage main\n\nimport \"fmt\"\n\n// pow calculates the power of the given digit\nfunc pow(digit int, power int) int {\n\tres := 1\n\tfor i := 0; i < power; i++ {\n\t\tres = res * digit\n\t}\n\treturn res\n}\n\n// sumDigits is a helper function that calculates the sum of digits.\nfunc sumDigits(number int) int {\n    totalSum := 0\n    for number > 0 {\n        digit := number % 10\n        number = number / 10\n        totalSum += pow(digit, 2)\n    }\n    return totalSum\n}\n\nfunc happyNumber(num int) bool {\n\tslow := num\n\tfast := sumDigits(num)\n\tfor fast != 1 && fast != slow {\n\t\t\tslow = sumDigits(slow)\n\t\t\tfast = sumDigits(sumDigits(fast))\n\t}\n\treturn fast == 1\n}\n\nfunc main() {\n\tfmt.Println(happyNumber(4)) // false\n\tfmt.Println(happyNumber(19))  // true\n\tfmt.Println(happyNumber(100))  // true\n}"
  },
  {
    "path": "Fast and Slow Pointers/linked_list_compute_midpoint.cpp",
    "content": "// Finding Midpoint of a LinkedList\n// Program Author : Abhisek Kumar Gupta \n// Naive Approach: Find the length of the linked list and return the (length/2)th node.\n// One pass Approach: Use two pointers, the 2nd pointer should traverse twice as fast at the first.\n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nnode* compute_midpoint(node *head){\n    if(head->next == NULL || head == NULL){\n        return head;\n    }\n    node *slow = head;\n    node *fast = head->next;\n    while(fast != NULL && fast->next != NULL){\n        fast = fast->next->next;\n        slow = slow->next;\n    }\n    return slow;\n}\nint main(){\n    node *head = NULL;\n    makeLinkedList(head);\n    print_linked_list(head);\n    node *midpoint = compute_midpoint(head);\n    cout << endl;\n    cout << midpoint->data << endl;\n    return 0;\n}"
  },
  {
    "path": "Fast and Slow Pointers/linked_list_compute_midpoint.java",
    "content": "/*\n * LEETCODE 876\nGiven the head of a singly linked list, return the middle node of the linked list.\nIf there are two middle nodes, return the second middle node.\n*Example 1:\nInput: head = [1,2,3,4,5]\nOutput: [3,4,5]\nExplanation: The middle node of the list is node 3.\n\n*Example 2:\nInput: head = [1,2,3,4,5,6]\nOutput: [4,5,6]\nExplanation: Since the list has two middle nodes with values 3 and 4, we return the second one.\n\n*CODE EXPLAINATION WITH DRY RUN:\nThis Java code finds the midpoint node of a singly-linked list. If the linked list has an even number \nof nodes, it returns the second middle node.\n\nFirst, the Node class is defined with a constructor that takes in an integer value and initializes\nthe next reference to null. The insertAtTail() method takes in a head node and an integer value,\nand inserts a new node with the given value at the end of the linked list. The printLinkedList() method \ntakes in a head node and prints out all the values in the linked list.\n\nThe makeLinkedList() method prompts the user to enter integers until -1 is inputted. Each integer is \ninserted into a new node at the tail of the linked list. The computeMidpoint() method takes in a head \nnode and returns the middle node(s) of the linked list. If the linked list has no nodes or only one node, \nit just returns the head node. Otherwise, it initializes a slow pointer and a fast pointer to the head \nnode. The while loop advances the fast pointer by two nodes and the slow pointer by one node at each \niteration until the fast pointer reaches the end of the linked list. At that point, the slow pointer \nwill be pointing to the midpoint node(s) of the linked list.\n\nFinally, in the main() method, a new linked list is created by calling makeLinkedList(). The linked \nlist is printed using printLinkedList(). The midpoint of the linked list is computed using \ncomputeMidpoint(), and its value is printed out.\n\n*Example Dry Run:\nSuppose we have the following input:\n1 2 3 4 5 -1\nThis creates a linked list with the following structure:\n1 -> 2 -> 3 -> 4 -> 5 -> null\nInitially, the slow pointer and fast pointer both point to the head node, which is 1. In the first iteration of the while loop, the fast pointer moves two nodes ahead to node 3, while the slow pointer moves one node ahead to node 2. In the second iteration, the fast pointer moves another two nodes ahead to null, while the slow pointer moves one more node ahead to node 3. At this point, the slow pointer is pointing to the midpoint node(s) of the linked list.\nTherefore, computeMidpoint() returns node 3, which is printed out as output.\n\n*/\nimport java.util.Scanner;\n\npublic class linked_list_compute_midpoint {\n\n  static class Node {\n\n    int data;\n    Node next;\n\n    public Node(int data) {\n      this.data = data;\n      next = null;\n    }\n  }\n\n  static Node insertAtTail(Node head, int data) {\n    if (head == null) {\n      head = new Node(data);\n      return head;\n    }\n    Node n = new Node(data);\n    Node temp = head;\n    while (temp.next != null) {\n      temp = temp.next;\n    }\n    temp.next = n;\n    return head;\n  }\n\n  static void printLinkedList(Node head) {\n    while (head != null) {\n      System.out.print(head.data + \"->\");\n      head = head.next;\n    }\n  }\n\n  static Node makeLinkedList() {\n    Scanner scanner = new Scanner(System.in);\n    int data = scanner.nextInt();\n    Node head = null;\n    while (data != -1) {\n      head = insertAtTail(head, data);\n      data = scanner.nextInt();\n    }\n    scanner.close();\n    return head;\n  }\n\n  static Node computeMidpoint(Node head) {\n    if (head == null || head.next == null) {\n      return head;\n    }\n    Node slow = head;\n    Node fast = head.next;\n    while (fast != null && fast.next != null) {\n      fast = fast.next.next;\n      slow = slow.next;\n    }\n    return slow;\n  }\n\n  public static void main(String[] args) {\n    Node head = makeLinkedList();\n    printLinkedList(head);\n    System.out.println();\n    Node midpoint = computeMidpoint(head);\n    System.out.println(midpoint.data);\n  }\n}\n"
  },
  {
    "path": "Fast and Slow Pointers/linked_list_find_middle.py",
    "content": "# Finding Midpoint of a LinkedList\n# Node class\nclass Node:\n\n\t# Function to initialise the node object\n\tdef __init__(self, data):\n\t\tself.data = data\n\t\tself.next = None\n\nclass LinkedList:\n\n\tdef __init__(self):\n\t\tself.head = None\n\n\tdef push(self, new_data):\n\t\tnew_node = Node(new_data)\n\t\tnew_node.next = self.head\n\t\tself.head = new_node\n\n    \n\n\t# Function to get the middle of\n\t# the linked list using pointers\n\tdef printMiddle(self):\n\t\tslow_ptr = self.head \n\t\tfast_ptr = self.head\n\n\t\tif self.head is not None:\n\t\t\twhile (fast_ptr is not None and fast_ptr.next is not None):\n\t\t\t\tfast_ptr = fast_ptr.next.next\n\t\t\t\tslow_ptr = slow_ptr.next\n\t\t\tprint(\"The middle element is: \", slow_ptr.data)\n\n    \n\n# Driver code\nlist1 = LinkedList()\nlist1.push(25)\nlist1.push(33)\nlist1.push(14)\nlist1.push(22)\nlist1.push(9)\nlist1.push(11)\nlist1.push(20)\nlist1.printMiddle()\n"
  },
  {
    "path": "Fast and Slow Pointers/linked_list_floyds_cycle_detection.cpp",
    "content": "// Floyds Cycle detection and removal\n// Program Author : Abhisek Kumar Gupta \n// The cycle detection problem is to find the cycle in a sequence, \n// and Floyd’s cycle detection algorithm, aka Tortoise and Hare algorithm, \n// is a two-pointer algorithm to detect the cycle and locate the start of the cycle as well.\n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n    head->next->next->next = head;\n}\nbool detect_cycle(node *head){\n    node *slow = head;\n    node *fast = head;\n    while(fast != NULL && fast->next != NULL){\n        fast = fast->next->next;\n        slow = slow->next;\n        if(fast == slow){\n            //return true;\n            slow = head;\n            if(slow == fast){\n                while(fast->next != slow) fast = fast->next;\n            }\n            else{\n                while(slow->next != fast->next){\n                    slow = slow->next;\n                    fast = fast->next;\n                }\n            }\n            fast->next = NULL;\n            cout << \"Cycle Detected and Removed \\n\";\n        }\n    }\n    return false;\n}\nint main(){\n    node *head = NULL;\n    makeLinkedList(head);\n    //print_linked_list(head);\n    if(detect_cycle(head)){\n        cout << \"Cycle detected \\n\";\n    }\n    else {\n        cout << \"No cycle \\n\";\n    }\n    print_linked_list(head);\n    return 0;\n}"
  },
  {
    "path": "Fast and Slow Pointers/linked_list_floyds_cycle_detection.py",
    "content": "'''\n     Floyds Cycle detection and removal\n     Program Author : Abhisek Kumar Gupta \n     The cycle detection problem is to find the cycle in a sequence, \n     and Floyd’s cycle detection algorithm, aka Tortoise and Hare algorithm, \n     is a two-pointer algorithm to detect the cycle and locate the start of the cycle as well.\n'''\n# Definition for singly-linked list.\n# class ListNode:\n#     def __init__(self, x):\n#         self.val = x\n#         self.next = None\n\nclass Solution:\n    def hasCycle(self, head: Optional[ListNode]) -> bool:\n        #Floyd's cycle detection algorithm uses slow and fast points to find the loop\n        #Reference - https://www.geeksforgeeks.org/floyds-cycle-finding-algorithm/\n        slow,fast= head,head\n        while(slow!=None and fast!=None and fast.next!=None):\n            slow = slow.next\n            fast = fast.next.next\n            if(slow == fast):\n                return True\n        return False"
  },
  {
    "path": "Graphs/Diljstra.go",
    "content": "package main\n\nimport (\n    \"fmt\"\n    \"math\"\n)\n\n// Define a struct to represent a graph.\ntype Graph struct {\n    nodes map[string]map[string]float64\n}\n\n// Add an edge to the graph.\nfunc (g *Graph) AddEdge(node1, node2 string, weight float64) {\n    if g.nodes == nil {\n        g.nodes = make(map[string]map[string]float64)\n    }\n    if g.nodes[node1] == nil {\n        g.nodes[node1] = make(map[string]float64)\n    }\n    if g.nodes[node2] == nil {\n        g.nodes[node2] = make(map[string]float64)\n    }\n    g.nodes[node1][node2] = weight\n    g.nodes[node2][node1] = weight // Assuming an undirected graph\n}\n\n// Dijkstra's algorithm to find the shortest path.\nfunc Dijkstra(graph Graph, startNode string) map[string]float64 {\n    distances := make(map[string]float64)\n    visited := make(map[string]bool)\n\n    for node := range graph.nodes {\n        distances[node] = math.Inf(1)\n    }\n\n    distances[startNode] = 0\n\n    for {\n        var closestNode string\n        var shortestDistance float64 = math.Inf(1)\n\n        for node, distance := range distances {\n            if !visited[node] && distance < shortestDistance {\n                closestNode = node\n                shortestDistance = distance\n            }\n        }\n\n        if closestNode == \"\" {\n            break\n        }\n\n        visited[closestNode] = true\n\n        for neighbor, weight := range graph.nodes[closestNode] {\n            if newDistance := distances[closestNode] + weight; newDistance < distances[neighbor] {\n                distances[neighbor] = newDistance\n            }\n        }\n    }\n\n    return distances\n}\n\nfunc main() {\n    // Create a graph.\n    g := Graph{}\n    g.AddEdge(\"A\", \"B\", 1)\n    g.AddEdge(\"A\", \"C\", 4)\n    g.AddEdge(\"B\", \"C\", 2)\n    g.AddEdge(\"B\", \"D\", 5)\n    g.AddEdge(\"C\", \"D\", 1)\n    g.AddEdge(\"D\", \"E\", 3)\n    g.AddEdge(\"E\", \"F\", 2)\n\n    // Find the shortest distances from node \"A\" to all other nodes.\n    shortestDistances := Dijkstra(g, \"A\")\n\n    // Print the shortest distances.\n    for node, distance := range shortestDistances {\n        fmt.Printf(\"Shortest distance from A to %s: %v\\n\", node, distance)\n    }\n}\n"
  },
  {
    "path": "Graphs/GraphBFS.java",
    "content": "/**\n * The GraphBFS class represents a simple undirected graph using an adjacency list\n * and provides a breadth-first search (BFS) algorithm to traverse the graph.\n */\nimport java.util.*;\nimport java.io.*;\n\nclass GraphBFS {\n    private int V; // Number of vertices in the graph\n    private List<Integer> adjacency[]; // Adjacency list to represent the graph\n\n    // Constructor to initialize the graph with the given number of vertices\n    GraphBFS(int v) {\n        V = v;\n        adjacency = new ArrayList[V];\n        for(int i = 0; i < V; i++) {\n            adjacency[i] = new ArrayList<Integer>();\n        }\n    }\n\n    // Method to add an edge between vertices 'u' and 'v' in the graph\n    void addEdge(int u, int v) {\n        adjacency[u].add(v);\n        adjacency[v].add(u);\n    }\n\n    /**\n     * Performs breadth-first search (BFS) starting from the given source vertex 's'.\n     * Prints the vertices in BFS order.\n     * @param s The source vertex from which BFS starts.\n     */\n    void bfs(int s) {\n        boolean[] visited = new boolean[V]; // Array to track visited vertices\n        visited[s] = true; // Mark the source vertex as visited\n        LinkedList<Integer> Q = new LinkedList<Integer>(); // Queue for BFS traversal\n        Q.add(s); // Enqueue the source vertex\n\n        // BFS traversal\n        while(Q.size() != 0) {\n            int current = Q.poll(); // Dequeue the current vertex\n            System.out.print(current + \" -> \"); // Print the current vertex\n\n            // Visit all neighbors of the current vertex\n            for(int neighbour: adjacency[current]) {\n                if(!visited[neighbour]) {\n                    visited[neighbour] = true; // Mark the neighbour as visited\n                    Q.add(neighbour); // Enqueue the neighbour for further exploration\n                }\n            }\n        }\n    }\n\n    // Main method for testing the GraphBFS class\n    public static void main(String[] args) {\n        GraphBFS g = new GraphBFS(5); // Create a graph with 5 vertices\n        g.addEdge(2, 3); // Add edges to the graph\n        g.addEdge(2, 4);\n        g.addEdge(3, 1);\n        g.addEdge(4, 1);\n\n        g.bfs(2); // Perform BFS starting from vertex 2\n    }\n}\n"
  },
  {
    "path": "Graphs/Graph_Dijstra.java",
    "content": "import java.util.*;\n\nclass Graph {\n    private int V; // Number of vertices\n    private List<List<Node>> adj; // Adjacency list\n\n    public Graph(int V) {\n        this.V = V;\n        adj = new ArrayList<>(V);\n        for (int i = 0; i < V; i++) {\n            adj.add(new ArrayList<>());\n        }\n    }\n\n    // Add an edge to the graph\n    public void addEdge(int source, int destination, int weight) {\n        Node node = new Node(destination, weight);\n        adj.get(source).add(node);\n    }\n\n    public void dijkstra(int source) {\n        int[] distance = new int[V];\n        Arrays.fill(distance, Integer.MAX_VALUE);\n        distance[source] = 0;\n\n        PriorityQueue<Node> pq = new PriorityQueue<>(V, Comparator.comparingInt(node -> node.weight));\n        pq.add(new Node(source, 0));\n\n        while (!pq.isEmpty()) {\n            int u = pq.poll().vertex;\n\n            for (Node neighbor : adj.get(u)) {\n                int v = neighbor.vertex;\n                int w = neighbor.weight;\n\n                if (distance[u] != Integer.MAX_VALUE && distance[u] + w < distance[v]) {\n                    distance[v] = distance[u] + w;\n                    pq.add(new Node(v, distance[v]));\n                }\n            }\n        }\n\n        // Print the shortest distances from the source\n        System.out.println(\"Shortest distances from source vertex \" + source + \":\");\n        for (int i = 0; i < V; i++) {\n            System.out.println(\"Vertex \" + i + \": \" + distance[i]);\n        }\n    }\n\n    private static class Node {\n        int vertex;\n        int weight;\n\n        Node(int vertex, int weight) {\n            this.vertex = vertex;\n            this.weight = weight;\n        }\n    }\n}\n\npublic class DijkstraAlgorithm {\n    public static void main(String[] args) {\n        int V = 6; // Number of vertices\n        Graph graph = new Graph(V);\n\n        // Add edges and their weights\n        graph.addEdge(0, 1, 2);\n        graph.addEdge(0, 2, 4);\n        graph.addEdge(1, 2, 1);\n        graph.addEdge(1, 3, 7);\n        graph.addEdge(2, 4, 3);\n        graph.addEdge(3, 4, 1);\n        graph.addEdge(3, 5, 5);\n        graph.addEdge(4, 5, 2);\n\n        int source = 0; // Source vertex\n        graph.dijkstra(source);\n    }\n}\n"
  },
  {
    "path": "Graphs/Graphs_Dijkstras.py",
    "content": "# Graphs Dijkstras Implementation\n# Program Author : Tyler Le\n\n# Dijkstra's algorithm is a graph search algorithm \n# that solves the single-source shortest path problem \n# for a graph with non-negative edge weights\n\ndef dijkstra(graph, start):\n    # Create a dictionary to store the shortest distances to each node\n    shortest_distances = {node: float('inf') for node in graph}\n    shortest_distances[start] = 0\n    \n    # Create a set to store nodes that have been processed\n    processed_nodes = set()\n    \n    # Create a priority queue to store nodes and their distances\n    queue = [(start, 0)]\n    \n    while queue:\n        # Get the node with the smallest distance from the start node\n        current_node, current_distance = min(queue, key=lambda x: x[1])\n        queue.remove((current_node, current_distance))\n        \n        # If we've already processed this node, skip it   \n        if current_node in processed_nodes:\n            continue\n        \n        # Mark this node as processed\n        processed_nodes.add(current_node)\n        \n        # Update the shortest distances to all neighboring nodes\n        for neighbor, weight in graph[current_node].items():\n            distance = current_distance + weight\n            if distance < shortest_distances[neighbor]:\n                shortest_distances[neighbor] = distance\n                queue.append((neighbor, distance))\n    \n    return shortest_distances\n\n# Example usage\ngraph = {\n    'A': {'B': 5, 'C': 1},\n    'B': {'A': 5, 'C': 2, 'D': 1},\n    'C': {'A': 1, 'B': 2, 'D': 4},\n    'D': {'B': 1, 'C': 4}\n}\n\nstart_node = 'A'\ndistances = dijkstra(graph, start_node)\n\nprint(distances)\n"
  },
  {
    "path": "Graphs/Graphs_Ford_Fulkerson.cpp",
    "content": "The Ford-Fulkerson algorithm is a graph algorithm used to find the maximum flow in a flow network. \nHere is a high-level overview of the algorithm and some resources for further documentation:\n\nFord-Fulkerson Algorithm Overview:\n\nStart with an initial flow of zero.\nWhile there exists an augmenting path from the source to the sink:\nFind the residual capacity of the augmenting path (minimum capacity edge along the path).\nUpdate the flow by increasing the flow along the augmenting path.\nUpdate the residual capacities of the edges.\nThe maximum flow is the sum of the flows along the augmenting paths.\n\nHere's an example of the Ford-Fulkerson algorithm implemented in C++:\n\n#include <iostream>\n#include <vector>\n#include <queue>\n#include <algorithm>\nusing namespace std;\n\n// Number of vertices in the graph\n#define V 6\n\n// A BFS based function to check whether there is an augmenting path\n// from source to sink. Returns true if there is an augmenting path,\n// else returns false\nbool bfs(int rGraph[V][V], int s, int t, int parent[])\n{\n    // Create a visited array and mark all vertices as not visited\n    bool visited[V];\n    memset(visited, 0, sizeof(visited));\n\n    // Create a queue, enqueue source vertex and mark source vertex\n    // as visited\n    queue<int> q;\n    q.push(s);\n    visited[s] = true;\n    parent[s] = -1;\n\n    // Standard BFS Loop\n    while (!q.empty()) {\n        int u = q.front();\n        q.pop();\n\n        for (int v = 0; v < V; v++) {\n            if (visited[v] == false && rGraph[u][v] > 0) {\n                q.push(v);\n                parent[v] = u;\n                visited[v] = true;\n            }\n        }\n    }\n\n    // If we reached the sink in BFS starting from source, then return\n    // true, else false\n    return (visited[t] == true);\n}\n\n// A function to implement the Ford-Fulkerson algorithm\n// This will find the maximum possible flow from the source to the sink\nint fordFulkerson(int graph[V][V], int s, int t)\n{\n    int u, v;\n\n    // Create a residual graph and fill the residual graph with\n    // given capacities in the original graph as residual capacities\n    // in residual graph\n    int rGraph[V][V]; // Residual graph where rGraph[i][j] indicates\n                      // residual capacity of edge from i to j (if there\n                      // is an edge. If rGraph[i][j] is 0, then there is not)\n    for (u = 0; u < V; u++)\n        for (v = 0; v < V; v++)\n            rGraph[u][v] = graph[u][v];\n\n    int parent[V]; // This array is filled by BFS and to store path\n\n    int maxFlow = 0; // There is no flow initially\n\n    // Augument the flow while there is path from source to sink\n    while (bfs(rGraph, s, t, parent)) {\n        // Find minimum residual capacity of the edges along the\n        // path filled by BFS. Or we can say find the maximum flow\n        // through the path found.\n        int pathFlow = INT_MAX;\n        for (v = t; v != s; v = parent[v]) {\n            u = parent[v];\n            pathFlow = min(pathFlow, rGraph[u][v]);\n        }\n\n        // Update residual capacities of the edges and reverse edges\n        // along the path\n        for (v = t; v != s; v = parent[v]) {\n            u = parent[v];\n            rGraph[u][v] -= pathFlow;\n            rGraph[v][u] += pathFlow;\n        }\n\n        // Add path flow to overall flow\n        maxFlow += pathFlow;\n    }\n\n    // Return the overall flow as the maximum flow\n    return maxFlow;\n}\n// Driver program to test above functions\nint main()\n{\n    // Let us create a graph shown in the above example\n    int graph[V][V] = { { 0, 16, 13, 0, 0, 0 },\n                        { 0, 0, 10, 12, 0, 0 },\n                        { 0, 4, 0, 0, 14, 0 },\n                        { 0, 0, 9, 0, 0, 20 },\n                        { 0, 0, 0, 7, 0, 4 },\n                        { 0, 0, 0, 0, 0, 0 } };\n\n    int source = 0;\n    int sink = 5;\n\n    cout << \"The maximum possible flow is: \" << fordFulkerson(graph, source, sink) << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Graphs/Graphs_bfs.cpp",
    "content": "// Graphs Adjacency List implementation for Generic Data\r\n// Program Author : Abhisek Kumar Gupta\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\n\r\ntemplate<typename T>\r\nclass Graph{\r\n    map<T, list<T> > adjList;\r\n    public:\r\n        Graph(){\r\n\r\n        }\r\n        void addEdge(T u, T v, bool bidir = true){\r\n            adjList[u].push_back(v);\r\n            if(bidir){\r\n                adjList[v].push_back(u);\r\n            }\r\n        }\r\n        void printAdjList(){\r\n            for(auto obj : adjList){\r\n                cout << obj.first <<  \"->\";\r\n                for(auto element : obj.second){\r\n                    cout << element << \",\";\r\n                }\r\n                cout << endl;\r\n            }\r\n        }\r\n        void bfs(int n){\r\n            queue<int> q;\r\n            q.push(n);\r\n            map<int, bool> visited;\r\n            visited[n] = true;\r\n            while(!q.empty()){\r\n                int node_element = q.front();\r\n                cout << node_element << \" \";\r\n                q.pop();\r\n                for(int neighbour : adjList[node_element]){\r\n                    if(!visited[neighbour]){\r\n                        q.push(neighbour);\r\n                        visited[neighbour] = true;\r\n                    }\r\n                }\r\n            }\r\n\r\n        }\r\n};\r\nint main(){\r\n    Graph<int> g;\r\n    g.addEdge(0, 1);\r\n    g.addEdge(0, 4);\r\n    g.addEdge(1, 4);\r\n    g.addEdge(1, 3);\r\n    g.addEdge(1, 2);\r\n    g.addEdge(2, 3);\r\n    g.addEdge(4, 3);\r\n    g.printAdjList();\r\n    g.bfs(0);\r\n    return 0;\r\n}"
  },
  {
    "path": "Graphs/Graphs_bfs.js",
    "content": "// Define a function that takes a graph and a starting node as input\nfunction bfs(graph, startNode) {\n    // Initialize an empty object to keep track of visited nodes\n    const visited = {}\n    // Initialize a queue with the starting node\n    const queue = [startNode]\n  \n    // Mark the starting node as visited\n    visited[startNode] = true\n  \n    // While there are nodes in the queue\n    while (queue.length > 0) {\n      // Get the next node from the front of the queue\n      const currentNode = queue.shift()\n      // Log the current node to the console (or do something else with it)\n      console.log(currentNode)\n  \n      // Get the adjacent nodes of the current node from the graph\n      const adjacentNodes = graph[currentNode]\n  \n      // For each adjacent node\n      for (let i = 0; i < adjacentNodes.length; i++) {\n        // Get the adjacent node\n        const adjacentNode = adjacentNodes[i].node\n  \n        // If the adjacent node has not been visited\n        if (!visited[adjacentNode]) {\n          // Mark the adjacent node as visited\n          visited[adjacentNode] = true\n          // Add the adjacent node to the back of the queue\n          queue.push(adjacentNode)\n        }\n      }\n    }\n  }\n\n// SAMPLE USE CASE\n// The graph will be represented in form of an adjacency list.\n/* \n    The graph will be in form of an object where each key represents the nodes and each value will be an array of the neighbors of the node.\n\n    The array in values will be an object array, where each object has the node, which is the neighbor, and weight, which is the distance to that neighbor from the current node.\n*/\nconst graph = {\n    0: [{ node: 1, weight: 10 }],\n    1: [\n        { node: 0, weight: 10 },\n        { node: 2, weight: 10 },\n        { node: 3, weight: 5 },\n    ],\n    2: [{ node: 1, weight: 10 }],\n    3: [\n        { node: 1, weight: 5 },\n        { node: 4, weight: 10 },\n        { node: 5, weight: 10 },\n    ],\n    4: [\n        { node: 3, weight: 10 },\n        { node: 5, weight: 10 },\n    ],\n    5: [\n        { node: 3, weight: 10 },\n        { node: 4, weight: 10 },\n    ],\n}\n\nbfs(graph, 2)"
  },
  {
    "path": "Graphs/Graphs_bfs.py",
    "content": "from collections import defaultdict\n\nclass Graph:\n    def __init__(self):\n        self.graph = defaultdict(list)\n\n    def insertEdge(self,v1,v2):\n        self.graph[v1].append(v2)\n\n    def subBfs(self,visited,queue):\n        while(queue):\n            v=queue.pop(0)\n            visited.add(v)\n            print(v,end=\" \")\n            \n            for neighbour in self.graph[v]:\n                if neighbour not in visited:\n                    queue.append(neighbour)\n                    visited.add(neighbour)\n        \n    def bfs(self,v):\n        visited=set()\n        queue=[v]\n        self.subBfs(visited,queue)\n\ng=Graph()\ng.insertEdge(1,2)\ng.insertEdge(2,1)\ng.insertEdge(2,3)\ng.insertEdge(3,4)\ng.insertEdge(4,5)\ng.insertEdge(5,6)\ng.insertEdge(2,6)\n\ng.bfs(1)\n"
  },
  {
    "path": "Graphs/Graphs_bfs_sssp.cpp",
    "content": "// Graphs Adjacency List implementation for Generic Data\r\n// Program Author : Abhisek Kumar Gupta\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\n\r\ntemplate<typename T>\r\nclass Graph{\r\n    map<T, list<T> > adjList;\r\n    public:\r\n        Graph(){\r\n\r\n        }\r\n        void addEdge(T u, T v, bool bidir = true){\r\n            adjList[u].push_back(v);\r\n            if(bidir){\r\n                adjList[v].push_back(u);\r\n            }\r\n        }\r\n        void printAdjList(){\r\n            for(auto obj : adjList){\r\n                cout << obj.first <<  \"->\";\r\n                for(auto element : obj.second){\r\n                    cout << element << \",\";\r\n                }\r\n                cout << endl;\r\n            }\r\n        }\r\n        void bfs_sssp(int n){\r\n            queue<int> q;\r\n            map<int, int> distance;\r\n            map<int, int> parent;\r\n            for(auto i : adjList){\r\n                distance[i.first] = INT_MAX;\r\n            }\r\n            q.push(n);\r\n            distance[n] = 0;\r\n            parent[n] = n;\r\n            while(!q.empty()){\r\n                int node_element = q.front();\r\n                cout << node_element << \" \";\r\n                q.pop();\r\n                for(int neighbour : adjList[node_element]){\r\n                    if(distance[neighbour] == INT_MAX){\r\n                        q.push(neighbour);\r\n                        distance[neighbour] = distance[node_element] + 1;\r\n                        parent[neighbour] = node_element;\r\n                    }\r\n                }\r\n            }\r\n            cout << endl;\r\n            for(auto i : adjList){\r\n                int node = i.first;\r\n                cout << \"Distance of \" << node << \" from \" << n << \" is \" << distance[node] << endl;\r\n            }\r\n            for(auto x: parent){\r\n                cout << x.first << \" \" << x.second << endl;\r\n            }\r\n\r\n        }\r\n};\r\nint main(){\r\n    Graph<int> g;\r\n    g.addEdge(0, 1);\r\n    g.addEdge(0, 4);\r\n    g.addEdge(1, 4);\r\n    g.addEdge(1, 3);\r\n    g.addEdge(1, 2);\r\n    g.addEdge(2, 3);\r\n    g.addEdge(4, 3);\r\n    g.printAdjList();\r\n    g.bfs_sssp(4);\r\n    return 0;\r\n}"
  },
  {
    "path": "Graphs/Graphs_cycle_detection_bfs.cpp",
    "content": "// Graphs Cycle detection using BFS\r\n// Program Author : Abhisek Kumar Gupta\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\ntemplate<typename T>\r\nclass Graph{\r\n    map<T, list<T> > L;\r\n    public:\r\n        Graph(){\r\n\r\n        }\r\n        void add_edge(T u, T v, bool bidir = true){\r\n            L[u].push_back(v);\r\n            if(bidir){\r\n                L[v].push_back(u);\r\n            }\r\n        }\r\n        void print_edge(){\r\n            for(auto x : L){\r\n                cout << x.first << \"->\";\r\n                for(auto element : x.second){\r\n                    cout << element << \",\";\r\n                }\r\n                cout << endl;\r\n            }\r\n        }\r\n        bool is_cyclic(T source){\r\n            map<T, bool> visited;\r\n            map<T, int> parent;\r\n            queue<T> q;\r\n            q.push(source);\r\n            visited[source] = true;\r\n            parent[source] = source;\r\n            while(!q.empty()){\r\n                T node = q.front();\r\n                q.pop();\r\n                for(T neighbour : L[node]){\r\n                    if(visited[neighbour]==true && parent[node] != neighbour){\r\n                        return true;\r\n                    }\r\n                    else if(!visited[neighbour]){\r\n                        visited[neighbour] = true;\r\n                        q.push(neighbour);\r\n                        parent[neighbour] = node;\r\n                    }\r\n                }\r\n            }\r\n            return false;\r\n        }\r\n  \r\n};\r\n\r\nint main(){\r\n    Graph<int> g;\r\n    g.add_edge(1,2);\r\n    g.add_edge(1,4);\r\n    g.add_edge(4,3);\r\n    g.add_edge(2,3);\r\n    g.print_edge();\r\n    if(g.is_cyclic(1)){\r\n        cout << \"Graph is Cyclic\";\r\n    }\r\n    else{\r\n        cout << \"Graph is not Cyclic\";\r\n    }\r\n    return 0;\r\n}"
  },
  {
    "path": "Graphs/Graphs_cycle_detection_dfs.cpp",
    "content": "// Graphs Cycle detection using DFS\r\n// Program Author : Abhisek Kumar Gupta\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\ntemplate<typename T>\r\nclass Graph{\r\n    map<T, list<T> > L;\r\n    public:\r\n        Graph(){\r\n\r\n        }\r\n        void add_edge(T u, T v, bool bidir = true){\r\n            L[u].push_back(v);\r\n            if(bidir){\r\n                L[v].push_back(u);\r\n            }\r\n        }\r\n        bool is_cyclic_helper(T node, map<T, bool> &visited, map<T, bool> &in_stack){\r\n            visited[node] = true;\r\n            in_stack[node] = true;\r\n            for(T neighbour : L[node]){\r\n                if((!visited[neighbour] && is_cyclic_helper(neighbour, visited, in_stack)) || in_stack[neighbour]){\r\n                    return true;\r\n                }\r\n            }\r\n            in_stack[node] = false;\r\n            return false;\r\n        }\r\n        bool is_cyclic(){\r\n            map<T, bool> visited;\r\n            map<T, bool> in_stack;\r\n            for(auto x: L){\r\n                T node = x.first;\r\n                if(!visited[node]){\r\n                    bool answer = is_cyclic_helper(node, visited, in_stack);\r\n                    if(answer){\r\n                        return true;\r\n                    }\r\n                    else{\r\n                        return false;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n};\r\n\r\nint main(){\r\n    Graph<int> g;\r\n    g.add_edge(0, 2, false);\r\n    g.add_edge(0, 1, false);\r\n    g.add_edge(2, 3, false);\r\n    g.add_edge(2, 4, false);\r\n //   g.add_edge(3, 0, false);\r\n    g.add_edge(4, 5, false);\r\n    g.add_edge(1, 5, false);\r\n    if(g.is_cyclic()){\r\n        cout << \"Cycle present\" << endl;\r\n    }\r\n    else{\r\n        cout << \"Cycle not present\" <<  endl;\r\n    }\r\n    return 0;\r\n}"
  },
  {
    "path": "Graphs/Graphs_dfs.cpp",
    "content": "// Graphs Adjacency List implementation for Generic Data\r\n// Program Author : Abhisek Kumar Gupta\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\n\r\ntemplate<typename T>\r\nclass Graph{\r\n    map<T, list<T> > adjList;\r\n    public:\r\n        Graph(){\r\n\r\n        }\r\n        void addEdge(T u, T v, bool bidir = true){\r\n            adjList[u].push_back(v);\r\n            if(bidir){\r\n                adjList[v].push_back(u);\r\n            }\r\n        }\r\n        void printAdjList(){\r\n            for(auto obj : adjList){\r\n                cout << obj.first <<  \"->\";\r\n                for(auto element : obj.second){\r\n                    cout << element << \",\";\r\n                }\r\n                cout << endl;\r\n            }\r\n        }\r\n        void dfsHelper(int node, map<int, bool> &visited){\r\n            visited[node] = true;\r\n            cout << node << \"->\";\r\n            for(int neighbour : adjList[node]){\r\n                if(!visited[neighbour]){\r\n                    dfsHelper(neighbour, visited);\r\n                }\r\n            }\r\n        }\r\n        void dfs(int src){\r\n            map<int, bool> visited;\r\n            dfsHelper(src, visited);\r\n        }\r\n};\r\nint main(){\r\n    Graph<int> g;\r\n    g.addEdge(0, 1);\r\n    g.addEdge(0, 4);\r\n    g.addEdge(1, 4);\r\n    g.addEdge(1, 3);\r\n    g.addEdge(1, 2);\r\n    g.addEdge(2, 3);\r\n    g.addEdge(4, 3);\r\n    g.printAdjList();\r\n    g.dfs(0);\r\n    return 0;\r\n}"
  },
  {
    "path": "Graphs/Graphs_dfs.java",
    "content": "/*Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem :  Implement Depth First Search in Java\nIssue Number : #733\nProblem statement : \n\nExplanation of the below Java code :\n\nIn this example, we have a Node class representing each node in the graph. Each Node has a value, a list of neighbors, and a boolean flag to track if it has been visited.\n\nThe DepthFirstSearch class contains the dfs method, which performs the depth-first search traversal. It takes a starting node as an argument and recursively visits all unvisited neighbors of that node. When visiting a node, it marks it as visited and prints its value.\n\nIn the main method, we create a small graph with five nodes and test the dfs method by starting the traversal from the first node (node1). The output will display the visited nodes in the order they are traversed:\n\n\n*/\n\n-------------------------------------------------------------------------//Java code begins here------------------------------------------------------------------------\n\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nclass Node {\n    int value;\n    List<Node> neighbors;\n    boolean visited;\n\n    Node(int value) {\n        this.value = value;\n        this.neighbors = new ArrayList<>();\n        this.visited = false;\n    }\n\n    void addNeighbor(Node neighbor) {\n        this.neighbors.add(neighbor);\n    }\n}\n\nclass DepthFirstSearch {\n    void dfs(Node startNode) {\n        // Mark the startNode as visited\n        startNode.visited = true;\n        System.out.println(\"Visited Node: \" + startNode.value);\n\n        // Recursively visit all unvisited neighbors\n        for (Node neighbor : startNode.neighbors) {\n            if (!neighbor.visited) {\n                dfs(neighbor);\n            }\n        }\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        // Create a graph for testing\n        Node node1 = new Node(1);\n        Node node2 = new Node(2);\n        Node node3 = new Node(3);\n        Node node4 = new Node(4);\n        Node node5 = new Node(5);\n\n        node1.addNeighbor(node2);\n        node1.addNeighbor(node3);\n        node2.addNeighbor(node4);\n        node3.addNeighbor(node4);\n        node4.addNeighbor(node5);\n\n        DepthFirstSearch dfs = new DepthFirstSearch();\n        dfs.dfs(node1);\n    }\n}\n"
  },
  {
    "path": "Graphs/Graphs_dfs.js",
    "content": "// Takes in a graph object and a starting node\nfunction dfs(graph, startNode) {\n    // Initialize an empty visited object\n    const visited = {}\n\n    // Call the dfsHelper function with the starting node, the visited object, and the graph object\n    dfsHelper(startNode, visited, graph)\n}\n\n// Recursive helper function for the DFS algorithm\n// Takes in a current node, a visited object, and a graph object\nfunction dfsHelper(node, visited, graph) {\n    // Mark the current node as visited by adding it to the visited object\n    visited[node] = true\n\n    // Print the current node (or perform some other action)\n    console.log(node)\n\n    // Get the adjacent nodes of the current node from the graph object\n    const adjacentNodes = graph[node]\n\n    // Iterate over the adjacent nodes\n    for (let i = 0; i < adjacentNodes.length; i++) {\n        // Get the node of the current adjacent node\n        const adjacentNode = adjacentNodes[i].node\n\n        // If the adjacent node has not been visited yet, recursively call dfsHelper with the adjacent node\n        if (!visited[adjacentNode]) {\n            dfsHelper(adjacentNode, visited, graph)\n        }\n    }\n}\n\n// SAMPLE USE CASE\n// The graph will be represented in form of an adjacency list.\n/* \n    The graph will be in form of an object where each key represents the nodes and each value will be an array of the neighbors of the node.\n\n    The array in values will be an object array, where each object has the node, which is the neighbor, and weight, which is the distance to that neighbor from the current node.\n*/\n\nconst graph = {\n    0: [{ node: 1, weight: 10 }],\n    1: [\n        { node: 0, weight: 10 },\n        { node: 2, weight: 10 },\n        { node: 3, weight: 5 },\n    ],\n    2: [{ node: 1, weight: 10 }],\n    3: [\n        { node: 1, weight: 5 },\n        { node: 4, weight: 10 },\n        { node: 5, weight: 10 },\n    ],\n    4: [\n        { node: 3, weight: 10 },\n        { node: 5, weight: 10 },\n    ],\n    5: [\n        { node: 3, weight: 10 },\n        { node: 4, weight: 10 },\n    ],\n}\n\ndfs(graph, 0)"
  },
  {
    "path": "Graphs/Graphs_dfs.py",
    "content": "from collections import defaultdict\n\nclass Graph:\n    def __init__(self):\n        self.graph = defaultdict(list)\n    \n    def insertEdge(self,v1,v2):\n        self.graph[v1].append(v2)\n    \n    def dfsSub(self,v,visited):\n\n        visited.add(v)\n        print(v,end=\" \")\n\n        for neighbour in self.graph[v]:\n            if neighbour not in visited:\n                self.dfsSub(neighbour,visited)\n\n    def dfs(self,v):\n\n        visited = set()\n        self.dfsSub(v,visited)\n\ng=Graph()\ng.insertEdge(1,2)\ng.insertEdge(2,1)\ng.insertEdge(3,4)\ng.insertEdge(4,5)\ng.insertEdge(5,6)\ng.insertEdge(2,6)\n\ng.dfs(2)\n        \n"
  },
  {
    "path": "Graphs/Graphs_dfs_connected_components.cpp",
    "content": "// Graphs Adjacency List implementation for Generic Data\r\n// Program Author : Abhisek Kumar Gupta\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\n\r\ntemplate<typename T>\r\nclass Graph{\r\n    map<T, list<T> > adjList;\r\n    public:\r\n        Graph(){\r\n\r\n        }\r\n        void addEdge(T u, T v, bool bidir = true){\r\n            adjList[u].push_back(v);\r\n            if(bidir){\r\n                adjList[v].push_back(u);\r\n            }\r\n        }\r\n        void printAdjList(){\r\n            for(auto obj : adjList){\r\n                cout << obj.first <<  \"->\";\r\n                for(auto element : obj.second){\r\n                    cout << element << \",\";\r\n                }\r\n                cout << endl;\r\n            }\r\n        }\r\n        void dfsHelper(T node, map<T, bool> &visited){\r\n            visited[node] = true;\r\n            cout << node << \"->\";\r\n            for(T neighbour : adjList[node]){\r\n                if(!visited[neighbour]){\r\n                    dfsHelper(neighbour, visited);\r\n                }\r\n            }\r\n        }\r\n        void dfs(T src){\r\n            map<T, bool> visited;\r\n            int component = 1;\r\n            dfsHelper(src, visited);\r\n            cout << endl;\r\n            for(auto x : adjList){\r\n                T city =  x.first;\r\n                if(!visited[city]){\r\n                    dfsHelper(city, visited);\r\n                    component++;\r\n                    cout << endl;\r\n                }\r\n            }\r\n            cout << \"Graph has \" << component << \" component.\" << endl;\r\n        }\r\n};\r\nint main(){\r\n    Graph<string> g;\r\n    g.addEdge(\"Amritsar\", \"Jaipur\");\r\n    g.addEdge(\"Amritsar\", \"Delhi\");\r\n    g.addEdge(\"Delhi\", \"Jaipur\");\r\n    g.addEdge(\"Mumbai\", \"Jaipur\");\r\n    g.addEdge(\"Mumbai\", \"Bhopal\");\r\n    g.addEdge(\"Delhi\", \"Bhopal\");\r\n    g.addEdge(\"Mumbai\", \"Bangalore\");\r\n    g.addEdge(\"Agra\", \"Delhi\");\r\n    g.addEdge(\"Andaman\", \"Nicobar\");\r\n    g.addEdge(\"Nagaland\", \"Manipur\");\r\n    g.printAdjList();\r\n    g.dfs(\"Amritsar\");\r\n    return 0;\r\n}"
  },
  {
    "path": "Graphs/Graphs_dijkstras.js",
    "content": "// A class representing a priority queue\nclass PriorityQueue {\n    constructor() {\n        this.items = []\n    }\n\n    // Adds an item to the priority queue with a given priority\n    enqueue(item, priority) {\n        let added = false\n\n        for (let i = 0; i < this.items.length; i++) {\n            if (priority < this.items[i].priority) {\n                this.items.splice(i, 0, { item, priority })\n                added = true\n                break\n            }\n        }\n\n        if (!added) this.items.push({ item, priority })\n    }\n\n    // Removes and returns the item with minimum priority from the priority queue\n    dequeue() {\n        if (this.isEmpty()) return null\n\n        return this.items.shift()\n    }\n\n    // Returns true if the priority queue is empty, false otherwise\n    isEmpty() {\n        return this.items.length === 0\n    }\n\n    // Returns the number of items in the priority queue\n    size() {\n        return this.items.length\n    }\n}\n\n// Performs Dijkstra's shortest path algorithm on a given graph with a specified start node\nfunction dijkstra(graph, n, start) {\n    const visited = new Array(n) // An array to keep track of visited nodes\n    visited.fill(false)\n\n    const distances = new Array(n) // An array to store the distances from the start node to each node in the graph based on indices\n    distances.fill(Number.POSITIVE_INFINITY)\n    distances[start] = 0\n\n    // An array to store the previous node in the shortest path to each node in the graph based on indices\n    const prev = new Array(n)\n    prev.fill(null)\n\n    const pq = new PriorityQueue() //Creating a new priority queue\n    pq.enqueue(start, 0) // Initializing the priority queue\n\n    while (!pq.isEmpty()) {\n        const val = pq.dequeue() // Dequeue the node with the lowest priority\n        const idx = val.item // Get the index of the dequeued node\n        const min = val.priority // Get the distance of the dequeued node\n        visited[idx] = true // Mark the node as visited\n\n        if (distances[idx] < min) continue // If the distance of the dequeued node is less than the minimum distance, continue to the next iteration of the loop\n\n        // Iterate over the neighbors of the dequeued/current node\n        for (let edge of graph[idx]) {\n            if (visited[edge]) continue // If the destination node of the edge has already been visited, continue to the next iteration of the loop\n\n            const newDist = distances[idx] + edge.weight // Calculate the new distance to the destination node\n\n            // If the new distance is less than the current distance to the destination node, update the previous node, distance, and add the destination node to the priority queue\n            if (newDist < distances[edge.node]) {\n                prev[edge.node] = idx\n                distances[edge.node] = newDist\n                pq.enqueue(edge.node, newDist)\n            }\n        }\n    }\n\n    // Return the distances and previous nodes arrays in an object\n    return { distances, prev }\n}\n\n// Finds the shortest path between the start and end nodes in the given graph using Dijkstra's algorithm\nfunction findShortestPath(graph, n, start, end) {\n\n    // check if start node is present in the graph, if not, throw error.\n    if (!graph.hasOwnProperty(start)) {\n        throw new Error(`Start node ${start} not found in graph`)\n    }\n\n    // check if end node is present in the graph, if not, throw error.\n    if (!graph.hasOwnProperty(end)) {\n        throw new Error(`End node ${end} not found in graph`)\n    }\n\n    const res = dijkstra(graph, n, start) // Run Dijkstra's algorithm to get the shortest distances and paths from the start node to all other nodes\n    const distances = res.distances // Extract the distances array from the result of Dijkstra's algorithm\n    const prev = res.prev // Extract the previous nodes array from the result of Dijkstra's algorithm\n    const path = [] // Initialize an empty array to store the shortest path from the start to end node\n\n    // If the end node is not reachable from the start node, return an empty path\n    if (distances[parseInt(end)] == Number.POSITIVE_INFINITY) return path\n\n    // Traverse the previous nodes array backwards from the end node to the start node to construct the shortest path\n    for (let i = end; i !== null; i = prev[i]) path.unshift(i)\n\n    // Return the shortest path\n    return path\n}\n\n// Sample Use Case\n// The graph will be represented in form of an adjacency list.\n/* \n    The graph will be in form of an object where each key represents the nodes and each value will be an array of the neighbors of the node.\n\n    The array in values will be an object array, where each object has the node, which is the neighbor, and weight, which is the distance to that neighbor from the current node.\n*/\nconst graph = {\n    0: [{ node: 1, weight: 10 }],\n    1: [\n        { node: 0, weight: 10 },\n        { node: 2, weight: 10 },\n        { node: 3, weight: 5 },\n    ],\n    2: [{ node: 1, weight: 10 }],\n    3: [\n        { node: 1, weight: 5 },\n        { node: 4, weight: 10 },\n        { node: 5, weight: 10 },\n    ],\n    4: [\n        { node: 3, weight: 10 },\n        { node: 5, weight: 10 },\n    ],\n    5: [\n        { node: 3, weight: 10 },\n        { node: 4, weight: 10 },\n    ],\n}\n\nconsole.log(findShortestPath(graph, 6, 2, 5))"
  },
  {
    "path": "Graphs/Graphs_flood_fill.cpp",
    "content": "/*\r\n    Flood fill, also called seed fill, is a flooding algorithm that determines and alters the area connected \r\n    to a given node in a multi-dimensional array with some matching attribute. It is used in the \"bucket\" fill \r\n    tool of paint programs to fill connected, similarly-colored areas with a different color, and in games such \r\n    as Go and Minesweeper for determining which pieces are cleared.  Source(https://en.wikipedia.org/wiki/Flood_fill)\r\n\r\nSample Input 15 30\r\n..............................\r\n.............#####............\r\n.............#...#............\r\n.....#########...#######......\r\n....###.....######.....###....\r\n...##....................##...\r\n..##......................#...\r\n..##.....................##...\r\n..###...................##....\r\n....###................###....\r\n......###............###......\r\n........###........###........\r\n..........##########..........\r\n..............................\r\n...........A.P.P.L.E..........\r\nOutput : \r\n..............................\r\n.............#####............\r\n.............#...#............\r\n.....#########...#######......\r\n....###.....######.....###....\r\n...##....................##...\r\n..##......................#...\r\n..##.....................##...\r\n..###...................##....\r\n....###................###....\r\n......###............###......\r\n........###........###........\r\n..........##########..........\r\n..............................\r\n...........A.P.P.L.E..........\r\n..............................\r\n.............#####............\r\n.............#...#............\r\n.....#########...#######......\r\n....###rrrrr######rrrrr###....\r\n...##rrrrrrrrrrrrrrrrrrrr##...\r\n..##rrrrrrrrrrrrrrrrrrrrrr#...\r\n..##rrrrrrrrrrrrrrrrrrrrr##...\r\n..###rrrrrrrrrrrrrrrrrrr##....\r\n....###rrrrrrrrrrrrrrrr###....\r\n......###rrrrrrrrrrrr###......\r\n........###rrrrrrrr###........\r\n..........##########..........\r\n..............................\r\n...........A.P.P.L.E..........\r\n..............................\r\n.............#####............\r\n.............#bbb#............\r\n.....#########bbb#######......\r\n....###rrrrr######rrrrr###....\r\n...##rrrrrrrrrrrrrrrrrrrr##...\r\n..##rrrrrrrrrrrrrrrrrrrrrr#...\r\n..##rrrrrrrrrrrrrrrrrrrrr##...\r\n..###rrrrrrrrrrrrrrrrrrr##....\r\n....###rrrrrrrrrrrrrrrr###....\r\n......###rrrrrrrrrrrr###......\r\n........###rrrrrrrr###........\r\n..........##########..........\r\n..............................\r\n...........A.P.P.L.E..........\r\n*/\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\nint R, C;\r\nvoid print_matrix(char input[][50]){\r\n    for(int i = 0; i < R; i++){\r\n        for(int j = 0; j < C; j++){\r\n            cout << input[i][j];\r\n        }\r\n        cout << \"\\n\";\r\n    }\r\n}\r\nint dx[] = {-1, 0, 1, 0};\r\nint dy[] = {0, -1, 0, 1};\r\nvoid flood_fill(char input[][50], int i, int j, char ch, char color){\r\n    // base case :  make sure we do not cross boundries of input matrix\r\n    if(i < 0 || j < 0 || i >= R || j >= C)\r\n        return;\r\n    // if we are coming to a cell that is not equal to ch then we dont do anything\r\n    if(input[i][j] != ch)\r\n        return;\r\n    // fill the color     \r\n    input[i][j] = color;\r\n    \r\n    // dfs flood_fill on all directions\r\n    for(int k = 0; k < 4; k++){\r\n        flood_fill(input, i + dx[k], j + dy[k], ch, color);\r\n    }        \r\n}\r\nint main(){\r\n    cin >> R >> C;\r\n    char input[15][50];\r\n    for(int i = 0; i < R; i++){\r\n        for(int j = 0; j < C; j++){\r\n            cin >> input[i][j];\r\n        }\r\n    }\r\n    print_matrix(input);\r\n    flood_fill(input, 8, 13, '.', 'r');\r\n    print_matrix(input);\r\n    flood_fill(input, 2, 15, '.', 'b');\r\n    print_matrix(input);\r\nreturn 0;\r\n}\r\n\r\n"
  },
  {
    "path": "Graphs/Graphs_kill_process.cpp",
    "content": "/* \r\n    Given a list of process where each process has a unique id and parent id.\r\n    Parent id is the id of the process that initiated that process.\r\n    You have to kill a particular process given by an integer kill. \r\n    Print id of all the processes that will be killed to kill that process\r\n    In order to kill a process, all its child processes should be killed as well \r\n    also only one process have parent id as 0 ie the process that started itself\r\n    Input : process id : [3, 1, 5, 7, 10, 11, 12] \r\n            parent id  : [0, 3, 3, 5, 5, 10, 10]\r\n            kill_id    : 5\r\n    Output:              [5, 7, 10, 11, 12]         \r\n*/\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\n\r\ntemplate<typename T>\r\nclass Graph{\r\n    map<T, list<T> > L;\r\n    public:\r\n        Graph(){\r\n\r\n        }\r\n        void add_list(int u, int v, bool bidir = false){\r\n            L[u].push_back(v);\r\n            if(bidir){\r\n                L[v].push_back(u);\r\n            }    \r\n        }\r\n        void print_graph(){\r\n            for(T node : L){\r\n                cout << node.first << \"->\";\r\n                for(T neighbour: node.second){\r\n                    cout << neighbour << \",\";\r\n                }\r\n                cout << endl;\r\n            }\r\n        }\r\n        void kill_process(int process){\r\n            map<T, bool> visited;\r\n            queue<T> q;\r\n            q.push(process);\r\n            visited[process] = true;\r\n            while(!q.empty()){\r\n                int node = q.front();\r\n                cout << node << \"->\";\r\n                q.pop();\r\n                for(T neighbour : L[node]){\r\n                    if(!visited[neighbour]){\r\n                        q.push(neighbour);\r\n                        visited[neighbour] = true;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n};\r\nint main(){\r\n    Graph<int> g;\r\n    int n;\r\n    cout << \"Enter number of process : \";\r\n    cin >> n;\r\n    vector<int> process_id(n);\r\n    vector<int> parent_id(n);\r\n    for(int i = 0; i < n; i++){\r\n        cin >> process_id[i];\r\n    }\r\n    for(int i = 0; i < n; i++){\r\n        cin >> parent_id[i];\r\n    }\r\n    for(int i = 0; i < n; i++){\r\n        g.add_list(parent_id[i], process_id[i]);\r\n    }\r\n    int kill;\r\n    cout << \"Enter process to be killed : \";\r\n    cin >> kill;\r\n    g.kill_process(kill);\r\n    return 0;\r\n}"
  },
  {
    "path": "Graphs/Graphs_kruskals_algo.cpp",
    "content": "/*\nName : MAnmay Ghosh\nGithub username : ManmayGhosh\nRepository name : data-structures-and-algorithms\nProblem :  Implement Kruskal's algorithm in C++ \nIssue Number : #1301\n\nExplanation of the below C++ code :\n\nIn this implementation, In Kruskal’s algorithm, sort all edges of the given graph in increasing order. \nThen it keeps on adding new edges and nodes in the MST if the newly added edge does not form a cycle. \nIt picks the minimum weighted edge at first at the maximum weighted edge at last.\nThus we can say that it makes a locally optimal choice in each step in order to find the optimal solution\n\npseudosteps\n1. Sort all the edges in non-decreasing order of their weight. \n2. Pick the smallest edge. Check if it forms a cycle with the spanning tree formed so far. \n    If the cycle is not formed, include this edge. Else, discard it. \n3. Repeat step#2 until there are (V-1) edges in the spanning tree.\n-------------------------------------------------------------------------//C++ code begins here------------------------------------------------------------------------\n*/\n\n#include <bits/stdc++.h>\nusing namespace std;\n \n// DS data structure class will help in building graph \nclass D_S {\n    int* parent;                                        // to create a parent relationship b/w two nodes\n    int* child;                                         // to create a child relationship b/w two nodes\npublic:\n\n    //This function will create a user defined data structure which will help to create a graph\n    D_S(int n)                                          \n    {\n        parent = new int[n];\n        child = new int[n];\n        for (int i = 0; i < n; i++) {\n            parent[i] = -1;\n            child[i] = 1;\n        }\n    }\n \n    // Find function to find edges b/w vertices\n    int find(int i)\n    {\n        if (parent[i] == -1)\n            return i;\n        return parent[i] = find(parent[i]);\n    }\n \n    // Union function to joint two nodes via smallest possible weighted edge\n    void unite(int x, int y)\n    {\n        int s1 = find(x);\n        int s2 = find(y);\n \n        if (s1 != s2) {\n            if (child[s1] < child[s2])\n                parent[s1] = s2;\n            else if (child[s1] > child[s2])\n                parent[s2] = s1;\n            else {\n                parent[s2] = s1;\n                child[s1] += 1;\n            }\n        }\n    }\n};\n \nclass Graph {\n    //As we know for kruskal's algorithm we have to maintain a list for edges b/w two vertices \n    //from lowest weight to highest weight in increasing order\n    vector<vector<int>> edgelist;\n    int V;\n \npublic:\n    Graph(int V) { this->V = V; }\n \n    // Function to add edge in a graph\n    void addEdge(int x, int y, int w)\n    {\n        edgelist.push_back({ w, x, y });\n    }\n \n\n    //Kruskal's Algorithm\n    void kruskals_mst()\n    {\n        // Arrange all edges in ascending order to find minimum weight edge\n        sort(edgelist.begin(), edgelist.end());\n \n        // Initialize the DSU\n        D_S gr(V);\n        int ans = 0;\n        cout << \"Following are the edges in the constructed MST\"<< endl;\n        for (auto edge : edgelist) {\n            int w = edge[0];\n            int x = edge[1];\n            int y = edge[2];\n \n            // Take the edge in MST if it does not forms a cycle\n            if (gr.find(x) != gr.find(y)) {\n                gr.unite(x, y);\n                ans += w;\n                cout << x << \" -- \" << y << \" == \" << w<< endl;\n            }\n        }\n        cout << \"Minimum Cost Spanning Tree: \" << ans;\n    }\n};\n \n// Driver code\nint main()\n{\n    Graph g(4);\n    g.addEdge(0, 1, 10);\n    g.addEdge(1, 3, 15);\n    g.addEdge(2, 3, 4);\n    g.addEdge(2, 0, 6);\n    g.addEdge(0, 3, 5);\n \n    // Function call\n    g.kruskals_mst();\n \n    return 0;\n}\n\n\n/*\nTime Complexity: O(E * logE) or O(E * logV) \n\nSorting of edges takes O(E * logE) time. \nAfter sorting, we iterate through all edges and apply the find-union algorithm. The find and union operations can take at most O(logV) time.\nSo overall complexity is O(E * logE + E * logV) time. \nThe value of E can be at most O(V2), so O(logV) and O(logE) are the same. Therefore, the overall time complexity is O(E * logE) or O(E*logV).\n*/"
  },
  {
    "path": "Graphs/Graphs_kruskals_algorithm.js",
    "content": "/**\n * Graphs: Implement Kruskal's Algorithm in JavaScript\n *\n * This code implements Kruskal's Algorithm to find the Minimum Spanning Tree (MST)\n * in a graph. The graph is represented using an adjacency list. The algorithm works\n * by repeatedly adding the minimum weight edges that do not form a cycle in the MST.\n *\n * Time Complexity: O(E log V), where E is the number of edges and V is the number of vertices.\n * Space Complexity: O(V), where V is the number of vertices.\n */\n\n/**\n * Class representing a Disjoint Set data structure.\n * Used to track disjoint sets and perform union-find operations.\n */\nclass DisjointSet {\n  constructor(n) {\n    this.parent = new Array(n).fill(-1); // Array to store parent of each node\n    this.rank = new Array(n).fill(0); // Array to store the rank of each node\n  }\n\n  /**\n   * Find the parent of a node in the disjoint set.\n   * Implements path compression to optimize future finds.\n   * @param {number} x - The node to find the parent for.\n   * @returns {number} The parent of the given node.\n   */\n  find(x) {\n    if (this.parent[x] === -1) {\n      return x;\n    }\n    this.parent[x] = this.find(this.parent[x]); // Path compression\n    return this.parent[x];\n  }\n\n  /**\n   * Union two disjoint sets by rank.\n   * Uses union by rank to optimize the merge operation.\n   * @param {number} x - The first node to union.\n   * @param {number} y - The second node to union.\n   */\n  union(x, y) {\n    let xRoot = this.find(x);\n    let yRoot = this.find(y);\n\n    if (this.rank[xRoot] < this.rank[yRoot]) {\n      this.parent[xRoot] = yRoot;\n    } else if (this.rank[xRoot] > this.rank[yRoot]) {\n      this.parent[yRoot] = xRoot;\n    } else {\n      this.parent[yRoot] = xRoot;\n      this.rank[xRoot]++;\n    }\n  }\n}\n\n/**\n * Function to implement Kruskal's Algorithm for finding the Minimum Spanning Tree (MST).\n * @param {number} n - The number of vertices in the graph.\n * @param {Array} edges - The edges of the graph represented as an adjacency list.\n * @returns {Array} The edges of the Minimum Spanning Tree.\n */\nfunction kruskalsAlgorithm(n, edges) {\n  // Sort edges in non-decreasing order by weight\n  edges.sort((a, b) => a[2] - b[2]);\n\n  const mst = []; // Minimum Spanning Tree\n  const disjointSet = new DisjointSet(n); // Create a disjoint set for tracking sets\n\n  for (let [src, dest, weight] of edges) {\n    let srcRoot = disjointSet.find(src);\n    let destRoot = disjointSet.find(dest);\n\n    // If adding the edge does not create a cycle, add it to the MST\n    if (srcRoot !== destRoot) {\n      mst.push([src, dest, weight]);\n      disjointSet.union(srcRoot, destRoot);\n    }\n  }\n\n  return mst;\n}\n\n// Example usage\nconst numVertices = 5;\nconst graphEdges = [\n  [0, 1, 2],\n  [1, 2, 3],\n  [0, 3, 6],\n  [1, 3, 8],\n  [1, 4, 5],\n  [2, 4, 7],\n  [3, 4, 9],\n];\n\nconst minimumSpanningTree = kruskalsAlgorithm(numVertices, graphEdges);\nconsole.log(\"Minimum Spanning Tree:\", minimumSpanningTree);\n"
  },
  {
    "path": "Graphs/Graphs_topological_sort_bfs.cpp",
    "content": "/*\r\nImplementation of Topological sort using BFS\r\nAccording to Introduction to Algorithms, given a directed acyclic graph (DAG), \r\na topological sort is a linear ordering of all vertices such that for any edge (u, v), u comes before v. Another way to describe \r\nit is that when you put all vertices horizontally on a line, all of the edges are pointing from left to right.\r\n*/\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\ntemplate<typename T>\r\nclass Graph{\r\n    public:\r\n        map<T, list<T> > L;\r\n        Graph(){ \r\n\r\n        }\r\n        void addEdge(int u, int v, bool bidir = false){\r\n            L[u].push_back(v);\r\n            if(bidir){\r\n                L[v].push_back(u);\r\n            }\r\n        }\r\n        void printList(){\r\n            for(auto i : L){\r\n                cout << i.first << \"->\";\r\n                for(auto element : i.second){\r\n                    cout << element << \", \";\r\n                }\r\n                cout << endl;\r\n            }\r\n        }\r\n        void bfsTopologicalSort(){\r\n            queue<T> q;\r\n            map<T, bool> visited;\r\n            map<T, int> indegree;\r\n            for(auto i : L){\r\n                T node = i.first;\r\n                visited[node] = false;\r\n                indegree[node] = 0;\r\n            }\r\n            // Initialize the indegrees of all nodes\r\n            for(auto i: L){\r\n                T u = i.first;\r\n                for(T v : L[u]){\r\n                    indegree[v]++;\r\n                }\r\n            }\r\n            // Finding nodes with 0 indegree\r\n            for(auto i : L){\r\n                T node = i.first;\r\n                if(indegree[node] == 0){\r\n                    q.push(node);\r\n                }\r\n            }\r\n            while(!q.empty()){\r\n                T node = q.front();\r\n                q.pop();\r\n                cout << node << \"->\";\r\n                for(T neighbours : L[node]){\r\n                    indegree[neighbours]--;\r\n                    if(indegree[neighbours] == 0){\r\n                        q.push(neighbours);\r\n                    }\r\n                }\r\n            }\r\n        }\r\n\r\n};\r\n\r\nint main(){\r\n    Graph<int> g;\r\n    /*\r\n    g.addEdge(0, 2);\r\n    g.addEdge(1, 0);\r\n    g.addEdge(0, 7);\r\n    g.addEdge(1, 3);\r\n    g.addEdge(2, 4);\r\n    g.addEdge(3, 4);\r\n    g.addEdge(4, 5);\r\n    g.addEdge(4, 6);\r\n    */\r\n    g.addEdge(1, 2);\r\n    g.addEdge(1, 3);\r\n    g.addEdge(1, 4);\r\n    g.addEdge(2, 4);\r\n    g.addEdge(4, 3);\r\n    g.addEdge(2, 3);\r\n    g.addEdge(3, 5);\r\n    g.addEdge(4, 5);\r\n    g.bfsTopologicalSort();\r\n    return 0;\r\n}"
  },
  {
    "path": "Graphs/Graphs_topological_sort_dfs.cpp",
    "content": "/*\r\nImplementation of Topological sort using DFS\r\nAccording to Introduction to Algorithms, given a directed acyclic graph (DAG), \r\na topological sort is a linear ordering of all vertices such that for any edge (u, v), u comes before v. Another way to describe \r\nit is that when you put all vertices horizontally on a line, all of the edges are pointing from left to right.\r\n*/\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\ntemplate<typename T>\r\nclass Graph{\r\n    map<T, list<T> > L;\r\n    public:\r\n        Graph(){\r\n\r\n        }\r\n        void addEdge(T v, T u, bool bidir = false){\r\n            L[v].push_back(u);\r\n            if(bidir){\r\n                L[u].push_back(v);\r\n            }\r\n        }\r\n        void print_edge(){\r\n            for(auto x : L){\r\n                cout << x.first << \"->\";\r\n                for(auto y : x.second){\r\n                    cout << y << \",\";\r\n                }\r\n                cout << endl;\r\n            }\r\n        }\r\n        void dfsHelper(T node, map<T, bool> &visited, list<T> &ordering){\r\n            visited[node] = true;\r\n            for(T neighbours : L[node]){\r\n                if(!visited[neighbours]){\r\n                    dfsHelper(neighbours, visited, ordering);\r\n                }                \r\n            }\r\n            // add current node to list because all children of curr node have been visited\r\n            ordering.push_front(node);\r\n        }\r\n        void dfs(){\r\n            map<T, bool> visited;\r\n            list<T> ordering;\r\n            for(auto i : L){\r\n                T node  = i.first;\r\n                if(!visited[node]){\r\n                    dfsHelper(node, visited, ordering);\r\n                }\r\n            }\r\n            for(T element : ordering){\r\n                cout << element << \"->\";\r\n            }\r\n        }\r\n};\r\nint main(){\r\n    Graph<int> g;\r\n    g.addEdge(0, 2);\r\n    g.addEdge(1, 0);\r\n    g.addEdge(0, 7);\r\n    g.addEdge(1, 3);\r\n    g.addEdge(2, 4);\r\n    g.addEdge(3, 4);\r\n    g.addEdge(4, 5);\r\n    g.addEdge(4, 6);\r\n    g.print_edge();\r\n    g.dfs();\r\n    return 0;\r\n}"
  },
  {
    "path": "Graphs/a_star_algorithm.py",
    "content": "\"\"\"\nA* Algorithm\n\nMotivation - To approximate the shortest path in real-life situations, like- in maps, games where there can be many hindrances.\n\nUnlike other traversal techniques which focus on the path to be taken, A* algorithm focuses on the distance to be travelled.\nIt is a combination of Uniform Cost Search(UCS) and Best First Search(BFS).\n\nExplanation\nA* algorithm is a best-first search algorithm in which the cost associated with a node is f(n) = g(n) + h(n), where g(n) is the cost of the path from the initial state to node n and h(n) is the heuristic estimate or the cost or a path from node n to a goal.\nheuristic means guess or estimate.\n\nConsider a square grid having many obstacles and we are given a starting cell and a target cell. We want to reach the target cell (if possible) from the starting cell as quickly as possible. \n\nHere g(n) is the distance between the current cell and the start cell. So we can say g(n) is the cost of the path from initial state to n. \nh(n) is a heuristic function that is used to estimate the cost of the cheapest path from n to the goal. So we can say h(n) is the cost from n to goal. \n\nSo we can say f(n) is the cost of the cheapest path from initial state to goal passing through n.\n\npseudocode\n1. Initialize the open list\n2. Initialize the closed list\nput the starting node on the open list (you can leave its f at zero)\n\n3. while the open list is not empty\n    a) find the node with the least f on the open list, call it \"q\"\n    b) pop q off the open list\n    c) generate q's 8 successors and set their parents to q\n    d) for each successor\n        i) if successor is the goal, stop search\n    \n        ii) else, compute both g and h for successor \n        successor.g = q.g + distance between successor and q\n        successor.h = distance from goal to successor\n        successor.f = successor.g + successor.h\n        \n        iii) if a node with the same position as successor is in the OPEN list which has a lower f than successor, skip this successor\n        \n        iv) if a node with the same position as successor is in the CLOSED list which has a lower f than successor, skip this successor\n        otherwise, add the node to the open list\n        \n    e) push q on the closed list\n    \nFor more information, visit: https://www.geeksforgeeks.org/a-search-algorithm/ or https://stackabuse.com/courses/graphs-in-python-theory-and-implementation/lessons/a-star-search-algorithm/\n    \n\"\"\"\n\nfrom collections import deque\n\n\nclass Graph:\n    # example of adjacency list (or rather map)\n    # adjacency_list = {\n    # 'A': [('B', 1), ('C', 3), ('D', 7)],\n    # 'B': [('D', 5)],\n    # 'C': [('D', 12)]\n    # }\n\n    def __init__(self, adjacency_list):\n        self.adjacency_list = adjacency_list\n\n    def get_neighbors(self, v):\n        return self.adjacency_list[v]\n\n    # heuristic function with equal values for all nodes\n    def h(self, n):\n        H = {\"A\": 1, \"B\": 1, \"C\": 1, \"D\": 1}\n\n        return H[n]\n\n    def a_star_algorithm(self, start_node, stop_node):\n        # open_list is a list of nodes which have been visited, but who's neighbors\n        # haven't all been inspected, starts off with the start node\n        # closed_list is a list of nodes which have been visited\n        # and who's neighbors have been inspected\n        open_list = set([start_node])\n        closed_list = set([])\n\n        # g contains current distances from start_node to all other nodes\n        # the default value (if it's not found in the map) is +infinity\n        g = {}\n\n        g[start_node] = 0\n\n        # parents contains an adjacency map of all nodes\n        parents = {}\n        parents[start_node] = start_node\n\n        while len(open_list) > 0:\n            n = None\n\n            # find a node with the lowest value of f() - evaluation function\n            for v in open_list:\n                if n == None or g[v] + self.h(v) < g[n] + self.h(n):\n                    n = v\n\n            if n == None:\n                print(\"Path does not exist!\")\n                return None\n\n            # if the current node is the stop_node\n            # then we begin reconstructin the path from it to the start_node\n            if n == stop_node:\n                reconst_path = []\n\n                while parents[n] != n:\n                    reconst_path.append(n)\n                    n = parents[n]\n\n                reconst_path.append(start_node)\n\n                reconst_path.reverse()\n\n                print(\"Path found: {}\".format(reconst_path))\n                return reconst_path\n\n            # for all neighbors of the current node do\n            for m, weight in self.get_neighbors(n):\n                # if the current node isn't in both open_list and closed_list\n                # add it to open_list and note n as it's parent\n                if m not in open_list and m not in closed_list:\n                    open_list.add(m)\n                    parents[m] = n\n                    g[m] = g[n] + weight\n\n                # otherwise, check if it's quicker to first visit n, then m\n                # and if it is, update parent data and g data\n                # and if the node was in the closed_list, move it to open_list\n                else:\n                    if g[m] > g[n] + weight:\n                        g[m] = g[n] + weight\n                        parents[m] = n\n\n                        if m in closed_list:\n                            closed_list.remove(m)\n                            open_list.add(m)\n\n            # remove n from the open_list, and add it to closed_list\n            # because all of his neighbors were inspected\n            open_list.remove(n)\n            closed_list.add(n)\n\n        print(\"Path does not exist!\")\n        return None\n\n\n# Driver code\n\nadjacency_list = {\n    \"A\": [(\"B\", 1), (\"C\", 3), (\"D\", 7)],\n    \"B\": [(\"D\", 5)],\n    \"C\": [(\"D\", 12)],\n}\n\ngraph1 = Graph(adjacency_list)\ngraph1.a_star_algorithm(\"A\", \"D\")\n\n# Output:\n# Path found: ['A', 'B', 'D']\n# Explanation: The path with the lowest cost is A -> B -> D with a cost of 6.\n"
  },
  {
    "path": "Graphs/adjacency_list.java",
    "content": "/*\n    This code is an implementation of a graph data structure using an adjacency list representation in Java. Let's break down the code and explain it step by step:\n\n    1. `GraphNode` Class:\n    - This class represents a node in the graph.\n    - It has three attributes:\n        - `name`: A string that represents the name or label of the node.\n        - `index`: An integer that serves as a unique identifier/index for the node.\n        - `neighbors`: An ArrayList of `GraphNode` objects that stores the neighboring nodes of the current node.\n\n    2. `AdjacencyList` Class:\n    - This class represents the graph using an adjacency list.\n    - It has the following attributes:\n        - `nodeList`: An ArrayList of `GraphNode` objects that stores all the nodes in the graph.\n    - The constructor takes an ArrayList of `GraphNode` objects and initializes the `nodeList` attribute with it.\n    - The class provides the following methods:\n        - `addUndirectedEdge(int i, int j)`: This method takes two indices (`i` and `j`) representing two nodes in the graph and \n        adds an undirected edge between them. It does so by retrieving the corresponding `GraphNode` objects from the `nodeList` \n        and adding each node to the `neighbors` list of the other.\n        - `printGraph()`: This method returns a human-readable representation of the graph. It iterates through the `nodeList`, \n        prints the name of each node, and lists its neighboring nodes.\n\n    3. `main` Class:\n    - This is the main class to demonstrate the graph creation and printing.\n    - Inside the `main` method:\n        - An ArrayList of `GraphNode` objects (`nodeList`) is created, and five nodes are added to it, each with a name and index.\n        - An `AdjacencyList` object (`al`) is created, passing the `nodeList` to its constructor.\n        - Several undirected edges are added using the `addUndirectedEdge` method to establish connections between nodes.\n        - Finally, the `printGraph` method is called on the `al` object to print the graph's structure.\n\n    The code demonstrates how to create a graph using an adjacency list and provides a readable representation of the graph, including its nodes and edges.\n*/\n\n\nimport java.util.ArrayList;\n\npublic class GraphNode {\n    public String name;\n    public int index;\n    // An ArrayList to store neighboring nodes\n    public ArrayList<GraphNode> neighbors = new ArrayList<GraphNode>();\n\n    public GraphNode(String name, int index) {\n        this.name = name;\n        this.index = index;\n    }\n}\n\npublic class AdjacencyList {\n    // An ArrayList to store all nodes in the graph\n    ArrayList<GraphNode> nodeList = new ArrayList<GraphNode>();\n\n    public AdjacencyList(ArrayList<GraphNode> nodeList) {\n        this.nodeList = nodeList;\n    }\n\n    // Method to add an undirected edge between two nodes\n    public void addUndirectedEdge(int i, int j) {\n        GraphNode first = nodeList.get(i);\n        GraphNode second = nodeList.get(j);\n        first.neighbors.add(second);\n        second.neighbors.add(first);\n    }\n\n    // Method to print a human-readable representation of the graph\n    public String printGraph() {\n        StringBuilder s = new StringBuilder();\n        for (int i = 0; i < nodeList.size(); i++) {\n            s.append(nodeList.get(i).name + \": \");\n            for (int j = 0; j < nodeList.get(i).neighbors.size(); j++) {\n                if (j == nodeList.get(i).neighbors.size() - 1) {\n                    s.append(nodeList.get(i).neighbors.get(j).name);\n                } else {\n                    s.append(nodeList.get(i).neighbors.get(j).name + \" --> \");\n                }\n            }\n            s.append(\"\\n\");\n        }\n        return s.toString();\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<GraphNode> nodeList = new ArrayList<GraphNode>();\n        nodeList.add(new GraphNode(\"A\", 0));\n        nodeList.add(new GraphNode(\"B\", 1));\n        nodeList add(new GraphNode(\"C\", 2));\n        nodeList.add(new GraphNode(\"D\", 3));\n        nodeList.add(new GraphNode(\"E\", 4));\n\n        AdjacencyList al = new AdjacencyList(nodeList);\n        al.addUndirectedEdge(0, 1);\n        al.addUndirectedEdge(0, 2);\n        al.addUndirectedEdge(0, 3);\n        al.addUndirectedEdge(1, 4);\n        al.addUndirectedEdge(2, 3);\n        al.addUndirectedEdge(3, 4);\n        System.out.println(al.printGraph());\n    }\n}\n"
  },
  {
    "path": "Graphs/adjacency_matrix.go",
    "content": "package main\n\nimport \"errors\"\n\ntype AdjacencyMatrix struct {\n\tVertices  int\n\tEdges     int\n\tGraphType GraphType\n\tAdjMatrix [][]int\n}\ntype GraphType string\n\nconst (\n\tDIRECTED   GraphType = \"DIRECTED\"\n\tUNDIRECTED GraphType = \"UNDIRECTED\"\n)\n\ntype Graph interface {\n\tInit()\n\tAddEdge(vertexOne int, vertexTwo int) error\n\tAddEdgeWithWeight(vertexOne int, vertexTwo int, weight int) error\n\tRemoveEdge(vertexOne int, vertexTwo int) error\n\tHasEdge(vertexOne int, vertexTwo int) bool\n\tGetGraphType() GraphType\n\tGetAdjacentNodesForVertex(vertex int) map[int]bool\n\tGetWeightOfEdge(vertexOne int, vertexTwo int) (int, error)\n\tGetNumberOfVertices() int\n\tGetNumberOfEdges() int\n\tGetIndegreeForVertex(vertex int) int\n}\n\nfunc (G *AdjacencyMatrix) Init() {\n\tG.AdjMatrix = make([][]int, G.Vertices)\n\tG.Edges = 0\n\tfor i := 0; i < G.Vertices; i++ {\n\t\tG.AdjMatrix[i] = make([]int, G.Vertices) // default initialization is 0\n\t}\n}\nfunc (G *AdjacencyMatrix) AddEdge(vertexOne int, vertexTwo int) error {\n\tif vertexOne >= G.Vertices || vertexTwo >= G.Vertices || vertexOne < 0 || vertexTwo < 0 {\n\t\treturn errors.New(\"Index out of bounds\")\n\t}\n\tG.AdjMatrix[vertexOne][vertexTwo] = 1\n\tG.Edges++\n\tif G.GraphType == UNDIRECTED {\n\t\tG.AdjMatrix[vertexTwo][vertexOne] = 1\n\t\tG.Edges++\n\t}\n\treturn nil\n}\n\nfunc (G *AdjacencyMatrix) AddEdgeWithWeight(vertexOne int, vertexTwo int, weight int) error {\n\tif vertexOne >= G.Vertices || vertexTwo >= G.Vertices || vertexOne < 0 || vertexTwo < 0 {\n\t\treturn errors.New(\"Index out of bounds\")\n\t}\n\tG.AdjMatrix[vertexOne][vertexTwo] = weight\n\tG.Edges++\n\tif G.GraphType == UNDIRECTED {\n\t\tG.AdjMatrix[vertexTwo][vertexOne] = weight\n\t\tG.Edges++\n\t}\n\treturn nil\n}\n\nfunc (G *AdjacencyMatrix) RemoveEdge(vertexOne int, vertexTwo int) error {\n\tif vertexOne >= G.Vertices || vertexTwo >= G.Vertices || vertexOne < 0 || vertexTwo < 0 {\n\t\treturn errors.New(\"Index out of bounds\")\n\t}\n\tG.AdjMatrix[vertexOne][vertexTwo] = 0\n\tG.Edges--\n\tif G.GraphType == UNDIRECTED {\n\t\tG.AdjMatrix[vertexTwo][vertexOne] = 0\n\t\tG.Edges--\n\t}\n\treturn nil\n}\nfunc (G *AdjacencyMatrix) HasEdge(vertexOne int, vertexTwo int) bool {\n\tif vertexOne >= G.Vertices || vertexTwo >= G.Vertices || vertexOne < 0 || vertexTwo < 0 {\n\t\treturn false\n\t}\n\treturn G.AdjMatrix[vertexOne][vertexTwo] != 0\n}\n\nfunc (G *AdjacencyMatrix) GetIndegreeForVertex(vertex int) int {\n\tindegree := 0\n\tadjacentNodes := G.GetAdjacentNodesForVertex(vertex)\n\tfor key := range adjacentNodes {\n\t\tif adjacentNodes[key] {\n\t\t\tindegree++\n\t\t}\n\t}\n\treturn indegree\n}\n\nfunc (G *AdjacencyMatrix) GetGraphType() GraphType {\n\treturn G.GraphType\n}\nfunc (G *AdjacencyMatrix) GetAdjacentNodesForVertex(vertex int) map[int]bool {\n\tadjacencyMatrixVertices := map[int]bool{}\n\tif vertex >= G.Vertices || vertex < 0 {\n\t\treturn adjacencyMatrixVertices\n\t}\n\tfor i := 0; i < G.Vertices; i++ {\n\t\tif G.AdjMatrix[vertex][i] != 0 {\n\t\t\tadjacencyMatrixVertices[i] = (G.AdjMatrix[vertex][i] != 0)\n\t\t}\n\t}\n\treturn adjacencyMatrixVertices\n}\n\nfunc (G *AdjacencyMatrix) GetWeightOfEdge(vertexOne int, vertexTwo int) (int, error) {\n\tif vertexOne >= G.Vertices || vertexTwo >= G.Vertices || vertexOne < 0 || vertexTwo < 0 {\n\t\treturn 0, errors.New(\"Error getting weight for vertex\")\n\t}\n\treturn G.AdjMatrix[vertexOne][vertexTwo], nil\n}\n\nfunc (G *AdjacencyMatrix) GetNumberOfVertices() int {\n\treturn G.Vertices\n}\n\nfunc (G *AdjacencyMatrix) GetNumberOfEdges() int {\n\treturn G.Edges\n}"
  },
  {
    "path": "Graphs/adjacency_matrix.java",
    "content": "/*\n    This code snippet is a Java implementation of a graph using an adjacency matrix to represent the connections between nodes. Here's an explanation of the code:\n\n    1. `GraphNode` Class:\n    - `GraphNode` represents a node or vertex in the graph.\n    - It has two attributes: `name` to store the name of the node and `index` to store the index of the node.\n    - The constructor initializes these attributes.\n\n    2. `AdjacencyMatrix` Class:\n    - `AdjacencyMatrix` represents the graph using an adjacency matrix.\n    - It has the following attributes:\n        - `nodeList`: An `ArrayList` that stores all the nodes in the graph.\n        - `adjacencyMatrix`: A 2D array that represents the connections between nodes.\n    - The constructor takes an `ArrayList` of `GraphNode` objects and initializes the `nodeList` and `adjacencyMatrix` based on the size of the node list.\n\n    3. `addUndirectedEdge` Method:\n    - This method is used to add an undirected edge between two nodes.\n    - It takes two indices `i` and `j` to represent the nodes between which the edge is added.\n    - It sets the corresponding values in the adjacency matrix to 1, indicating an edge exists between nodes `i` and `j`. Since it's an undirected graph, it sets both `adjacencyMatrix[i][j]` and `adjacencyMatrix[j][i]` to 1.\n\n    4. `printGraph` Method:\n    - This method generates a human-readable string representation of the graph, including the adjacency matrix.\n    - It first prints the node names as column headers and then iterates through the adjacency matrix to display the connections between nodes.\n\n    5. `Main` Class:\n    - In the `Main` class, a list of `GraphNode` objects (`nodeList`) is created, each representing a node with a name and an index.\n    - An `AdjacencyMatrix` object (`am`) is created, passing the `nodeList` to its constructor.\n    - Undirected edges are added between nodes using the `addUndirectedEdge` method.\n    - Finally, the graph is printed using the `printGraph` method.\n\n    The example in the `main` method demonstrates the creation of a simple graph with five nodes and several edges. When you run this program, it will print a representation of the graph showing the connections between the nodes based on the adjacency matrix.\n\n    Output:\n    A B C D E \n    A: 0 1 1 1 0 \n    B: 1 0 0 0 1 \n    C: 1 0 0 1 0 \n    D: 1 0 1 0 1 \n    E: 0 1 0 1 0 \n\n*/\nimport java.util.ArrayList;\n\n// Class to represent a graph node\npublic class GraphNode {\n    public String name;\n    public int index;\n    \n    // Constructor to initialize name and index\n    GraphNode(String name, int index) {\n        this.name = name;\n        this.index = index;\n    }\n}\n\n// Class to represent a graph using an adjacency matrix\npublic class AdjacencyMatrix {\n    ArrayList<GraphNode> nodeList = new ArrayList<GraphNode>();\n    int[][] adjacencyMatrix;\n    \n    // Constructor to initialize nodeList and adjacencyMatrix\n    public AdjacencyMatrix(ArrayList<GraphNode> nodeList) {\n        this.nodeList = nodeList;\n        adjacencyMatrix = new int[nodeList.size()][nodeList.size()];\n    }\n    \n    // Method to add an undirected edge between two nodes\n    public void addUndirectedEdge(int i, int j) {\n        adjacencyMatrix[i][j] = 1;\n        adjacencyMatrix[j][i] = 1;\n    }\n    \n    // Method to print a human-readable representation of the graph\n    public String printGraph() {\n        StringBuilder s = new StringBuilder();\n        \n        // Print column headers (node names)\n        s.append(\"   \");\n        for (int i = 0; i < nodeList.size(); i++) {\n            s.append(nodeList.get(i).name + \" \");\n        }\n        s.append(\"\\n\");\n        \n        // Print node names and adjacency matrix\n        for (int i = 0; i < nodeList.size(); i++) {\n            s.append(nodeList.get(i).name + \": \");\n            for (int j : adjacencyMatrix[i]) {\n                s.append((j) + \" \");\n            }\n            s.append(\"\\n\");\n        }\n        return s.toString();\n    }\n}\n\n// Main class to demonstrate the graph creation\npublic class Main {\n    public static void main(String[] args) {\n        ArrayList<GraphNode> nodeList = new ArrayList<GraphNode>();\n        nodeList.add(new GraphNode(\"A\", 0));\n        nodeList.add(new GraphNode(\"B\", 1));\n        nodeList.add(new GraphNode(\"C\", 2));\n        nodeList.add(new GraphNode(\"D\", 3));\n        nodeList.add(new GraphNode(\"E\", 4));\n        AdjacencyMatrix am = new AdjacencyMatrix(nodeList);\n        \n        // Adding undirected edges\n        am.addUndirectedEdge(0, 1);\n        am.addUndirectedEdge(0, 2);\n        am.addUndirectedEdge(0, 3);\n        am.addUndirectedEdge(1, 4);\n        am.addUndirectedEdge(2, 3);\n        am.addUndirectedEdge(3, 4);\n        \n        // Printing the graph\n        System.out.println(am.printGraph());\n    }\n}\n"
  },
  {
    "path": "Graphs/dijkstras.cpp",
    "content": "/*Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem :  Implement Dijkstra's algorithm in C++ \nIssue Number : #947\nProblem statement : \n\nExplanation of the below C++ code :\n\nIn this implementation, we have a dijkstra function that takes a graph represented as an adjacency list, the starting node, and the total number of nodes. It returns a vector containing the shortest distances from the start node to all other nodes.\n\nThe dijkstra function initializes all distances to infinity except for the start node, which is set to 0. It uses a min heap priority queue to process nodes based on their distances. The algorithm iteratively selects the node with the minimum distance, updates the distances of its neighbors if a shorter path is found, and adds them to the priority queue.\n\nIn the main function, we create a graph using the adjacency list representation. Each element of the graph vector is a vector of pairs, where the first element of the pair represents the neighbor node, and the second element represents the weight of the edge.\n\nWe then call the dijkstra function with the graph, starting node, and the total number of nodes. Finally, we print the shortest distances from the start node to all other nodes.\n\n\n*/\n\n-------------------------------------------------------------------------//C++ code begins here------------------------------------------------------------------------\n\n\n#include <iostream>\n#include <vector>\n#include <queue>\n#include <climits>\n\nusing namespace std;\n\ntypedef pair<int, int> pii;\n\nvector<int> dijkstra(vector<vector<pii>>& graph, int start, int n) {\n    vector<int> dist(n, INT_MAX); // Initialize distances to infinity\n    dist[start] = 0; // Distance from start node to itself is 0\n\n    // Create a min heap priority queue to store vertices based on their distances\n    priority_queue<pii, vector<pii>, greater<pii>> pq;\n    pq.push(make_pair(0, start));\n\n    while (!pq.empty()) {\n        int u = pq.top().second;\n        pq.pop();\n\n        // Traverse all neighboring nodes of u\n        for (auto& neighbor : graph[u]) {\n            int v = neighbor.first;\n            int weight = neighbor.second;\n\n            // Update distance if a shorter path is found\n            if (dist[v] > dist[u] + weight) {\n                dist[v] = dist[u] + weight;\n                pq.push(make_pair(dist[v], v));\n            }\n        }\n    }\n\n    return dist;\n}\n\nint main() {\n    int n, m; // Number of nodes and edges\n    int start; // Starting node\n\n    cout << \"Enter the number of nodes: \";\n    cin >> n;\n\n    cout << \"Enter the number of edges: \";\n    cin >> m;\n\n    cout << \"Enter the starting node: \";\n    cin >> start;\n\n    // Create an adjacency list representation of the graph\n    vector<vector<pii>> graph(n);\n\n    cout << \"Enter the edges and their weights (node1 node2 weight):\" << endl;\n    for (int i = 0; i < m; i++) {\n        int node1, node2, weight;\n        cin >> node1 >> node2 >> weight;\n        graph[node1].push_back(make_pair(node2, weight));\n    }\n\n    // Run Dijkstra's algorithm\n    vector<int> distances = dijkstra(graph, start, n);\n\n    // Print the shortest distances from the start node to all other nodes\n    for (int i = 0; i < n; i++) {\n        cout << \"Shortest distance from node \" << start << \" to node \" << i << \": \" << distances[i] << endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "Graphs/dijkstras.go",
    "content": "/*\n\n   Write a function that computes the lengths of the shortest paths between start and all of the other vertices in the graph using Dijkstra's algorithm and returns them in an array.\n\n   Sample Input:\n   Start: 0\n   Edges :  = [\n        [[1, 7]],\n        [[2, 6], [3, 20], [4, 3]],\n        [[3, 14]],\n        [[4, 2]],\n        [],\n        [],\n    ]\n    Output: [0, 7, 13, 27, 10, -1]\n\n   Dijkstras Algorithm\n\n   Explanation:\n\n   The code snippet is an implementation of Dijkstra's algorithm for finding the shortest path from a given starting vertex to all other vertices in a graph. Here's a breakdown of the code:\n\n   1. The `DijkstrasAlgorithm` function takes the starting vertex (`start`) and the graph represented by the adjacency list (`edges`) as input and returns a list of minimum distances from the starting vertex to all other vertices.\n\n   2. It initializes `numberOfVertices` as the total number of vertices in the graph.\n\n   3. The `minDistances` slice is initialized with maximum integer values to represent infinity distance for all vertices. The length of `minDistances` is set to the number of vertices.\n\n   4. The minimum distance from the starting vertex to itself is set to 0.\n\n   5. The `visited` map is used to keep track of visited vertices. Initially, it is empty.\n\n   6. The algorithm iterates until all vertices have been visited. In each iteration, it selects the vertex with the minimum distance from the `minDistances` slice using the `getVertexWithMinDistance` function.\n\n   7. If the current minimum distance is infinity (i.e., no more vertices to visit), the loop breaks.\n\n   8. The selected vertex is marked as visited by adding it to the `visited` map.\n\n   9. For each neighboring vertex of the selected vertex, it calculates the new path distance and updates the `minDistances` if the new distance is smaller.\n\n   10. After all iterations, the `finalDistances` slice is created to convert the `minDistances` into a format where unreachable vertices are represented as -1.\n\n   11. The `getVertexWithMinDistance` function returns the vertex with the minimum distance from the `distances` slice and the current minimum distance.\n\n   Overall, the code implements Dijkstra's algorithm to find the shortest path from a starting vertex to all other vertices in a graph, using an adjacency list representation. It keeps track of minimum distances, visited vertices, and updates the distances based on the neighboring vertices.\n\n   Time Complexity: O(V^2 + e)\n   Space complexity: O(V)\n*/\npackage main\n\nimport \"math\"\n\n// DijkstrasAlgorithm finds the shortest path from a starting vertex to all other vertices in a graph.\nfunc DijkstrasAlgorithm(start int, edges [][][]int) []int {\n\tnumberOfVertices := len(edges)\n\tminDistances := make([]int, 0, len(edges))\n\n\t// Initialize the minDistances slice with maximum integer values\n\tfor range edges {\n\t\tminDistances = append(minDistances, math.MaxInt32)\n\t}\n\n\t// Set the distance of the starting vertex to 0\n\tminDistances[start] = 0\n\tvisited := map[int]bool{}\n\n\t// Iterate until all vertices have been visited\n\tfor len(visited) != numberOfVertices {\n\t\t// Get the vertex with the minimum distance\n\t\tvertex, currentMinDistance := getVertexWithMinDistance(minDistances, visited)\n\n\t\t// If the current minimum distance is infinity, break the loop\n\t\tif currentMinDistance == math.MaxInt32 {\n\t\t\tbreak\n\t\t}\n\n\t\t// Mark the vertex as visited\n\t\tvisited[vertex] = true\n\n\t\t// Explore neighboring vertices\n\t\tfor _, edge := range edges[vertex] {\n\t\t\tdestination, distanceToDestination := edge[0], edge[1]\n\n\t\t\t// Skip if the destination vertex is already visited\n\t\t\tif visited[destination] {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Calculate the new path distance to the destination\n\t\t\tnewPathDistance := currentMinDistance + distanceToDestination\n\t\t\tcurrentDestinationDistance := minDistances[destination]\n\n\t\t\t// Update the minimum distance if the new distance is smaller\n\t\t\tif newPathDistance < currentDestinationDistance {\n\t\t\t\tminDistances[destination] = newPathDistance\n\t\t\t}\n\t\t}\n\t}\n\n\t// Convert the minDistances slice to finalDistances, representing unreachable vertices as -1\n\tfinalDistances := make([]int, 0, len(minDistances))\n\tfor _, distance := range minDistances {\n\t\tif distance == math.MaxInt32 {\n\t\t\tfinalDistances = append(finalDistances, -1)\n\t\t} else {\n\t\t\tfinalDistances = append(finalDistances, distance)\n\t\t}\n\t}\n\n\treturn finalDistances\n}\n\n// getVertexWithMinDistance returns the vertex with the minimum distance from the distances slice.\nfunc getVertexWithMinDistance(distances []int, visited map[int]bool) (int, int) {\n\tcurrentMinDistance := math.MaxInt32\n\tvertex := -1\n\n\t// Find the vertex with the minimum distance among unvisited vertices\n\tfor vertexIdx, distance := range distances {\n\t\tif visited[vertexIdx] {\n\t\t\tcontinue\n\t\t}\n\n\t\tif distance <= currentMinDistance {\n\t\t\tvertex = vertexIdx\n\t\t\tcurrentMinDistance = distance\n\t\t}\n\t}\n\n\treturn vertex, currentMinDistance\n}\n"
  },
  {
    "path": "Graphs/dijkstras.java",
    "content": "import java.util.*;\n\nclass Main {\n    // Represents a node in the graph\n    static class Node implements Comparable<Node> {\n        String name;\n        int distance;\n\n        Node(String name) {\n            this.name = name;\n            this.distance = Integer.MAX_VALUE; // Initialize distance to infinity\n        }\n\n        @Override\n        public int compareTo(Node other) {\n            return Integer.compare(this.distance, other.distance);\n        }\n    }\n\n    // Represents a weighted edge between two nodes\n    static class Edge {\n        Node source;\n        Node destination;\n        int weight;\n\n        Edge(Node source, Node destination, int weight) {\n            this.source = source;\n            this.destination = destination;\n            this.weight = weight;\n        }\n    }\n\n    // Dijkstra's algorithm implementation\n    static void dijkstra(Map<String, List<Edge>> graph, String start) {\n        Map<String, Node> nodes = new HashMap<>(); // Stores nodes and their distances\n\n        // Initialize nodes with their respective distances\n        for (String nodeName : graph.keySet()) {\n            Node node = new Node(nodeName);\n            if (nodeName.equals(start)) {\n                node.distance = 0; // Set distance of start node to 0\n            }\n            nodes.put(nodeName, node);\n        }\n\n        PriorityQueue<Node> queue = new PriorityQueue<>(); // Priority queue for node selection\n        queue.add(nodes.get(start)); // Add the start node to the queue\n\n        // Dijkstra's algorithm main loop\n        while (!queue.isEmpty()) {\n            Node current = queue.poll(); // Get the node with the smallest distance from the queue\n\n            // Iterate over the edges of the current node\n            for (Edge edge : graph.get(current.name)) {\n                int newDistance = current.distance + edge.weight; // Calculate new distance to the neighbor node\n                Node neighbor = nodes.get(edge.destination.name); // Get the neighbor node\n\n                // If the new distance is shorter, update the neighbor node's distance and re-add it to the queue\n                if (newDistance < neighbor.distance) {\n                    queue.remove(neighbor); // Remove the neighbor node from the queue\n                    neighbor.distance = newDistance; // Update the distance of the neighbor node\n                    queue.add(neighbor); // Re-add the neighbor node to the queue\n                }\n            }\n        }\n    }\n\n    public static void main(String[] args) {\n        Map<String, List<Edge>> graph = new HashMap<>(); // Graph represented as a map of nodes and edges\n\n        // Create edges and add them to the graph\n        List<Edge> edgesA = new ArrayList<>();\n        edgesA.add(new Edge(new Node(\"A\"), new Node(\"B\"), 2));\n        edgesA.add(new Edge(new Node(\"A\"), new Node(\"C\"), 3));\n        graph.put(\"A\", edgesA);\n\n        List<Edge> edgesB = new ArrayList<>();\n        edgesB.add(new Edge(new Node(\"B\"), new Node(\"C\"), 1));\n        edgesB.add(new Edge(new Node(\"B\"), new Node(\"D\"), 1));\n        graph.put(\"B\", edgesB);\n\n        List<Edge> edgesC = new ArrayList<>();\n        edgesC.add(new Edge(new Node(\"C\"), new Node(\"D\"), 4));\n        graph.put(\"C\", edgesC);\n\n        List<Edge> edgesD = new ArrayList<>();\n        edgesD.add(new Edge(new Node(\"D\"), new Node(\"C\"), 2));\n        graph.put(\"D\", edgesD);\n\n        String start = \"A\"; // Starting node\n        dijkstra(graph, start); // Run Dijkstra's algorithm\n\n        // Print the shortest distances from the start node to each node in the graph\n        for (String nodeName : graph.keySet()) {\n            Node node = graph.get(nodeName).get(0).source;\n            System.out.println(\"Shortest distance from \" + start + \" to \" + node.name + \": \" + node.distance);\n        }\n    }\n}\n\n"
  },
  {
    "path": "Graphs/dijkstras.py",
    "content": "\n'''\n\n   Write a function that computes the lengths of the shortest paths between start and all of the other vertices in the graph using Dijkstra's algorithm and returns them in an array.\n\n   Sample Input:\n   Start: 0\n   Edges :  = [\n        [[1, 7]],\n        [[2, 6], [3, 20], [4, 3]],\n        [[3, 14]],\n        [[4, 2]],\n        [],\n        [],\n    ]\n    Output: [0, 7, 13, 27, 10, -1]\n\n   Dijkstras Algorithm\n\n   Explanation:\n\n   The code snippet is an implementation of Dijkstra's algorithm for finding the shortest path from a given starting vertex to all other vertices in a graph. Here's a breakdown of the code:\n\n   1. The `DijkstrasAlgorithm` function takes the starting vertex (`start`) and the graph represented by the adjacency list (`edges`) as input and returns a list of minimum distances from the starting vertex to all other vertices.\n\n   2. It initializes `numberOfVertices` as the total number of vertices in the graph.\n\n   3. The `minDistances` slice is initialized with maximum integer values to represent infinity distance for all vertices. The length of `minDistances` is set to the number of vertices.\n\n   4. The minimum distance from the starting vertex to itself is set to 0.\n\n   5. The `visited` map is used to keep track of visited vertices. Initially, it is empty.\n\n   6. The algorithm iterates until all vertices have been visited. In each iteration, it selects the vertex with the minimum distance from the `minDistances` slice using the `getVertexWithMinDistance` function.\n\n   7. If the current minimum distance is infinity (i.e., no more vertices to visit), the loop breaks.\n\n   8. The selected vertex is marked as visited by adding it to the `visited` map.\n\n   9. For each neighboring vertex of the selected vertex, it calculates the new path distance and updates the `minDistances` if the new distance is smaller.\n\n   10. After all iterations, the `finalDistances` slice is created to convert the `minDistances` into a format where unreachable vertices are represented as -1.\n\n   11. The `getVertexWithMinDistance` function returns the vertex with the minimum distance from the `distances` slice and the current minimum distance.\n\n   Overall, the code implements Dijkstra's algorithm to find the shortest path from a starting vertex to all other vertices in a graph, using an adjacency list representation. It keeps track of minimum distances, visited vertices, and updates the distances based on the neighboring vertices.\n\n   Time Complexity: O(V^2 + e)\n   Space complexity: O(V)\n\n'''\n\nimport \"math\"\n\n# DijkstrasAlgorithm finds the shortest path from a starting vertex to all other vertices in a graph.\nfunc DijkstrasAlgorithm(start int, edges [][][]int) []int {\n\tnumberOfVertices := len(edges)\n\tminDistances := make([]int, 0, len(edges))\n\n\t# Initialize the minDistances slice with maximum integer values\n\tfor range edges {\n\t\tminDistances = append(minDistances, math.MaxInt32)\n\t}\n\n\t# Set the distance of the starting vertex to 0\n\tminDistances[start] = 0\n\tvisited := map[int]bool{}\n\n\t# Iterate until all vertices have been visited\n\tfor len(visited) != numberOfVertices {\n\t\t# Get the vertex with the minimum distance\n\t\tvertex, currentMinDistance := getVertexWithMinDistance(minDistances, visited)\n\n\t\t# If the current minimum distance is infinity, break the loop\n\t\tif currentMinDistance == math.MaxInt32 {\n\t\t\tbreak\n\t\t}\n\n\t\t# Mark the vertex as visited\n\t\tvisited[vertex] = true\n\n\t\t# Explore neighboring vertices\n\t\tfor _, edge := range edges[vertex] {\n\t\t\tdestination, distanceToDestination := edge[0], edge[1]\n\n\t\t\t# Skip if the destination vertex is already visited\n\t\t\tif visited[destination] {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t# Calculate the new path distance to the destination\n\t\t\tnewPathDistance := currentMinDistance + distanceToDestination\n\t\t\tcurrentDestinationDistance := minDistances[destination]\n\n\t\t\t# Update the minimum distance if the new distance is smaller\n\t\t\tif newPathDistance < currentDestinationDistance {\n\t\t\t\tminDistances[destination] = newPathDistance\n\t\t\t}\n\t\t}\n\t}\n\n\t# Convert the minDistances slice to finalDistances, representing unreachable vertices as -1\n\tfinalDistances := make([]int, 0, len(minDistances))\n\tfor _, distance := range minDistances {\n\t\tif distance == math.MaxInt32 {\n\t\t\tfinalDistances = append(finalDistances, -1)\n\t\t} else {\n\t\t\tfinalDistances = append(finalDistances, distance)\n\t\t}\n\t}\n\n\treturn finalDistances\n}\n\n# getVertexWithMinDistance returns the vertex with the minimum distance from the distances slice.\nfunc getVertexWithMinDistance(distances []int, visited map[int]bool) (int, int) {\n\tcurrentMinDistance := math.MaxInt32\n\tvertex := -1\n\n\t# Find the vertex with the minimum distance among unvisited vertices\n\tfor vertexIdx, distance := range distances {\n\t\tif visited[vertexIdx] {\n\t\t\tcontinue\n\t\t}\n\n\t\tif distance <= currentMinDistance {\n\t\t\tvertex = vertexIdx\n\t\t\tcurrentMinDistance = distance\n\t\t}\n\t}\n\n\treturn vertex, currentMinDistance\n}\n"
  },
  {
    "path": "Graphs/dijkstras_heap_based.go",
    "content": "/*\n\tDijkstras heap based\n\n\tExplanation:\n\tThe given code snippet implements Dijkstra's algorithm to find the shortest path from a given start vertex to all other\n\tvertices in a weighted directed graph. Here's how the code works:\n\n\t1. The `DijkstrasAlgorithm` function takes the start vertex and the edges of the graph as input and returns an array of\n\t   shortest distances from the start vertex to all other vertices.\n\n\t2. First, it initializes the `minDistances` array with the maximum integer value except for the start vertex, which is\n\t   set to 0. This array will store the minimum distances from the start vertex to each vertex.\n\n\t3. It creates a min-heap data structure called `minDistancesHeap` to keep track of the minimum distances. Each item in\n\t   the heap represents a vertex and its distance from the start vertex.\n\n\t4. The algorithm starts by removing the vertex with the minimum distance from the `minDistancesHeap` and explores its\n\t   outgoing edges.\n\n\t5. For each edge, it calculates the new path distance from the start vertex to the destination vertex through the\n\t   current vertex. If the new path distance is smaller than the current distance, it updates the `minDistances` array and the `minDistancesHeap` with the new distance.\n\n\t6. The process continues until all vertices have been visited.\n\n\t7. Finally, it constructs the final distances array (`finalDistances`) based on the `minDistances` array. If a vertex's\n\t   distance is still set to the maximum integer value, it means there is no path from the start vertex to that vertex, so -1\n\t   is stored instead.\n\n\t8. The `Item` struct represents a vertex and its distance in the min-heap.\n\n\t9. The `MinHeap` struct represents the min-heap data structure. It contains an array of `Item` structs and a vertex-to-index\n\t   map to efficiently update and access items in the heap.\n\n\t10. The `Remove` method removes the item with the minimum distance from the heap and returns its vertex and distance.\n\n\t11. The `Update` method updates the distance of a vertex in the heap and maintains the heap property by performing sift-up\n\t   or sift-down operations.\n\n\t12. The `siftDown` method performs the sift-down operation to maintain the heap property by comparing the distance of the\n\t   current item with its children and swapping if necessary.\n\n\t13. The `siftUp` method performs the sift-up operation to maintain the heap property by comparing the distance of the\n\t   current item with its parent and swapping if necessary.\n\n\tThe time complexity of Dijkstra's algorithm with a min-heap implementation is typically O((V + E) log V), where V is the\n\tnumber of vertices and E is the number of edges in the graph.\n\tThe space complexity is O(V) for storing the `minDistances` array and the min-heap.\n*/\npackage main\n\nimport \"math\"\n\n// DijkstrasAlgorithm finds the shortest distances from the start vertex to all other vertices using Dijkstra's algorithm.\nfunc DijkstrasAlgorithm(start int, edges [][][]int) []int {\n\t// Get the number of vertices in the graph.\n\tnumberOfVertices := len(edges)\n\n\t// Initialize the minDistances array with maximum integer values except for the start vertex, which is set to 0.\n\tminDistances := make([]int, 0, numberOfVertices)\n\tfor range edges {\n\t\tminDistances = append(minDistances, math.MaxInt32)\n\t}\n\tminDistances[start] = 0\n\n\t// Create a min-heap to store vertices and their distances from the start vertex.\n\tminDistancePairs := make([]Item, 0, len(edges))\n\tfor i := range edges {\n\t\tminDistancePairs = append(minDistancePairs, Item{i, math.MaxInt32})\n\t}\n\tminDistancesHeap := NewMinHeap(minDistancePairs)\n\tminDistancesHeap.Update(start, 0)\n\n\t// Explore vertices in the graph using Dijkstra's algorithm until all vertices have been visited.\n\tfor !minDistancesHeap.IsEmpty() {\n\t\tvertex, currentMinDistance := minDistancesHeap.Remove()\n\n\t\t// If the currentMinDistance is still set to the maximum integer value, there is no path from the start vertex to this vertex.\n\t\tif currentMinDistance == math.MaxInt32 {\n\t\t\tbreak\n\t\t}\n\n\t\t// Explore the outgoing edges of the current vertex.\n\t\tfor _, edge := range edges[vertex] {\n\t\t\tdestination, distanceToDestination := edge[0], edge[1]\n\n\t\t\t// Calculate the new path distance from the start vertex to the destination vertex through the current vertex.\n\t\t\tnewPathDistance := currentMinDistance + distanceToDestination\n\n\t\t\t// Update the minDistances array and the minDistancesHeap with the new distance if it is smaller.\n\t\t\tcurrentDestinationDistance := minDistances[destination]\n\t\t\tif newPathDistance < currentDestinationDistance {\n\t\t\t\tminDistances[destination] = newPathDistance\n\t\t\t\tminDistancesHeap.Update(destination, newPathDistance)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Construct the finalDistances array based on the minDistances array.\n\tfinalDistances := make([]int, 0, len(minDistances))\n\tfor _, distance := range minDistances {\n\t\t// If a vertex's distance is still set to the maximum integer value, there is no path from the start vertex to that vertex.\n\t\t// So, -1 is stored instead.\n\t\tif distance == math.MaxInt32 {\n\t\t\tfinalDistances = append(finalDistances, -1)\n\t\t} else {\n\t\t\tfinalDistances = append(finalDistances, distance)\n\t\t}\n\t}\n\n\treturn finalDistances\n}\n\n// Item represents a vertex and its distance in the min-heap.\ntype Item struct {\n\tVertex   int // Vertex represents the index of the vertex.\n\tDistance int // Distance represents the distance from the start vertex to the current vertex.\n}\n\n// MinHeap represents a min-heap data structure.\ntype MinHeap struct {\n\tarray     []Item   // array is an array of Item structs to represent the heap.\n\tvertexMap map[int]int // vertexMap is a map to efficiently update and access items in the heap.\n}\n\n// NewMinHeap creates a new MinHeap instance with the given array of items.\nfunc NewMinHeap(array []Item) *MinHeap {\n\t// Initialize the vertexMap to store the index of each vertex in the heap.\n\tvertexMap := map[int]int{}\n\tfor _, item := range array {\n\t\tvertexMap[item.Vertex] = item.Vertex\n\t}\n\n\t// Create the MinHeap with the array and vertexMap.\n\theap := &MinHeap{array: array, vertexMap: vertexMap}\n\theap.buildHeap()\n\treturn heap\n}\n\n// IsEmpty checks if the min-heap is empty.\nfunc (h *MinHeap) IsEmpty() bool {\n\treturn h.length() == 0\n}\n\n// Remove removes the item with the minimum distance from the heap and returns its vertex and distance.\nfunc (h *MinHeap) Remove() (int, int) {\n\tl := h.length()\n\th.swap(0, l-1)\n\tpeeked := h.array[l-1]\n\th.array = h.array[0:l-1]\n\tdelete(h.vertexMap, peeked.Vertex)\n\th.siftDown(0, l-2)\n\treturn peeked.Vertex, peeked.Distance\n}\n\n// Update updates the distance of a vertex in the heap and maintains the heap property.\nfunc (h *MinHeap) Update(vertex int, value int) {\n\th.array[h.vertexMap[vertex]] = Item{vertex, value}\n\th.siftUp(h.vertexMap[vertex])\n}\n\n// swap swaps two items in the min-heap.\nfunc (h MinHeap) swap(i, j int) {\n\th.vertexMap[h.array[i].Vertex] = j\n\th.vertexMap[h.array[j].Vertex] = i\n\th.array[i], h.array[j] = h.array[j], h.array[i]\n}\n\n// length returns the length of the min-heap.\nfunc (h MinHeap) length() int {\n\treturn len(h.array)\n}\n\n// buildHeap performs the build-heap operation on the min-heap.\nfunc (h *MinHeap) buildHeap() {\n\tfirst := (len(h.array) - 2) / 2\n\tfor currentIdx := first + 1; currentIdx >= 0; currentIdx-- {\n\t\th.siftDown(currentIdx, len(h.array)-1)\n\t}\n}\n\n// siftDown performs the sift-down operation to maintain the heap property.\nfunc (h *MinHeap) siftDown(currentIdx, endIdx int) {\n\tchildOneIdx := currentIdx*2 + 1\n\tfor childOneIdx <= endIdx {\n\t\tchildTwoIdx := -1\n\t\tif currentIdx*2+2 <= endIdx {\n\t\t\tchildTwoIdx = currentIdx*2 + 2\n\t\t}\n\t\tindexToSwap := childOneIdx\n\t\tif childTwoIdx > -1 && h.array[childTwoIdx].Distance < h.array[childOneIdx].Distance {\n\t\t\tindexToSwap = childTwoIdx\n\t\t}\n\t\tif h.array[indexToSwap].Distance < h.array[currentIdx].Distance {\n\t\t\th.swap(currentIdx, indexToSwap)\n\t\t\tcurrentIdx = indexToSwap\n\t\t\tchildOneIdx = currentIdx*2 + 1\n\t\t} else {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// siftUp performs the sift-up operation to maintain the heap property.\nfunc (h *MinHeap) siftUp(currentIdx int) {\n\tparentIdx := (currentIdx - 1) / 2\n\tfor currentIdx > 0 && h.array[currentIdx].Distance < h.array[parentIdx].Distance {\n\t\th.swap(currentIdx, parentIdx)\n\t\tcurrentIdx = parentIdx\n\t\tparentIdx = (currentIdx - 1) / 2\n\t}\n}\n"
  },
  {
    "path": "Graphs/ford_fulkerson.cpp",
    "content": "/*\n\tName : Shruti Swarupa Dhar\n\tGithub username : Shr-reny\n\tRepository name : data-structures-and-algorithms\n\tProblem :  Implement Ford Fulkerson algorithm in C++ \n\tIssue Number : #1386\n\tProblem statement : \n\n\tGiven a graph which represents a flow network where every edge has a capacity. Also, given two vertices source ‘s’ and sink ‘t’ in the graph, find the maximum possible flow from s to t with the following constraints:\n\tFlow on an edge doesn’t exceed the given capacity of the edge.\n\tIncoming flow is equal to outgoing flow for every vertex except s and t.\n\n\tExplanation of the below C++ code :\n\n\tThe Ford-Fulkerson algorithm is a widely used algorithm to solve the maximum flow problem in a flow network. The maximum flow problem involves determining the maximum amount of flow that can be sent from a source vertex to a sink vertex in a directed weighted graph, subject to capacity constraints on the edges.\n\tThe algorithm works by iteratively finding an augmenting path, which is a path from the source to the sink in the residual graph, i.e., the graph obtained by subtracting the current flow from the capacity of each edge. The algorithm then increases the flow along this path by the maximum possible amount, which is the minimum capacity of the edges along the path.\n\n\tTime Complexity : O(|V| * E^2) ,where E is the number of edges and V is the number of vertices.\n\n\tSpace Complexity :O(V) , as we created queue.\n*/\n\n\n// C++ program for implementation of Ford Fulkerson\n// algorithm\n#include <iostream>\n#include <limits.h>\n#include <queue>\n#include <string.h>\nusing namespace std;\n\n// Number of vertices in given graph\n#define V 6\n\n/* Returns true if there is a path from source 's' to sink\n't' in residual graph. Also fills parent[] to store the\npath */\nbool bfs(int rGraph[V][V], int s, int t, int parent[])\n{\n\t// Create a visited array and mark all vertices as not\n\t// visited\n\tbool visited[V];\n\tmemset(visited, 0, sizeof(visited));\n\n\t// Create a queue, enqueue source vertex and mark source\n\t// vertex as visited\n\tqueue<int> q;\n\tq.push(s);\n\tvisited[s] = true;\n\tparent[s] = -1;\n\n\t// Standard BFS Loop\n\twhile (!q.empty()) {\n\t\tint u = q.front();\n\t\tq.pop();\n\n\t\tfor (int v = 0; v < V; v++) {\n\t\t\tif (visited[v] == false && rGraph[u][v] > 0) {\n\t\t\t\t// If we find a connection to the sink node,\n\t\t\t\t// then there is no point in BFS anymore We\n\t\t\t\t// just have to set its parent and can return\n\t\t\t\t// true\n\t\t\t\tif (v == t) {\n\t\t\t\t\tparent[v] = u;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tq.push(v);\n\t\t\t\tparent[v] = u;\n\t\t\t\tvisited[v] = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// We didn't reach sink in BFS starting from source, so\n\t// return false\n\treturn false;\n}\n\n// Returns the maximum flow from s to t in the given graph\nint fordFulkerson(int graph[V][V], int s, int t)\n{\n\tint u, v;\n\n\t// Create a residual graph and fill the residual graph\n\t// with given capacities in the original graph as\n\t// residual capacities in residual graph\n\tint rGraph[V]\n\t\t\t[V]; // Residual graph where rGraph[i][j]\n\t\t\t\t// indicates residual capacity of edge\n\t\t\t\t// from i to j (if there is an edge. If\n\t\t\t\t// rGraph[i][j] is 0, then there is not)\n\tfor (u = 0; u < V; u++)\n\t\tfor (v = 0; v < V; v++)\n\t\t\trGraph[u][v] = graph[u][v];\n\n\tint parent[V]; // This array is filled by BFS and to\n\t\t\t\t// store path\n\n\tint max_flow = 0; // There is no flow initially\n\n\t// Augment the flow while there is path from source to\n\t// sink\n\twhile (bfs(rGraph, s, t, parent)) {\n\t\t// Find minimum residual capacity of the edges along\n\t\t// the path filled by BFS. Or we can say find the\n\t\t// maximum flow through the path found.\n\t\tint path_flow = INT_MAX;\n\t\tfor (v = t; v != s; v = parent[v]) {\n\t\t\tu = parent[v];\n\t\t\tpath_flow = min(path_flow, rGraph[u][v]);\n\t\t}\n\n\t\t// update residual capacities of the edges and\n\t\t// reverse edges along the path\n\t\tfor (v = t; v != s; v = parent[v]) {\n\t\t\tu = parent[v];\n\t\t\trGraph[u][v] -= path_flow;\n\t\t\trGraph[v][u] += path_flow;\n\t\t}\n\n\t\t// Add path flow to overall flow\n\t\tmax_flow += path_flow;\n\t}\n\n\t// Return the overall flow\n\treturn max_flow;\n}\n\n// Driver program to test above functions\nint main()\n{\n\t// Let us create a graph shown in the above example\n\tint graph[V][V]\n\t\t= { { 0, 16, 13, 0, 0, 0 }, { 0, 0, 10, 12, 0, 0 },\n\t\t\t{ 0, 4, 0, 0, 14, 0 }, { 0, 0, 9, 0, 0, 20 },\n\t\t\t{ 0, 0, 0, 7, 0, 4 }, { 0, 0, 0, 0, 0, 0 } };\n\n\tcout << \"The maximum possible flow is \"\n\t\t<< fordFulkerson(graph, 0, 5);\n\n\treturn 0;\n}\n\n/*Sample Output:\nThe maximum possible flow is 23. */\n"
  },
  {
    "path": "Graphs/graphs_adjacency_list.cpp",
    "content": "// Graphs Adjacency List implementation\n// Program Author : Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\n\nclass Graph{\npublic:\n    int V;\n    list<int> *L; // a pointer to an array of linkedlist\n    Graph(int v){\n        V = v;\n        L = new list<int>[V]; // Array of LL\n        // there is a pointer to an array whose size is v and every object is list of integer\n    }\n    void addEdge(int u, int v, bool bidir = true){\n        L[u].push_back(v);\n        if(bidir){\n            L[v].push_back(u);\n        }\n    }\n    void printAdjacencyList(){\n        for(int i = 0; i < V; i++){\n            cout << i << \"-> \";\n            for(auto vertex : L[i]){\n                cout << vertex << \", \";\n            }\n            cout << endl;\n        }\n    }\n};\nint main(){\n    //graph has 5 vertices numbered from 0-4\n    Graph g(5);\n    g.addEdge(0, 1);\n    g.addEdge(0, 4);\n    g.addEdge(1, 4);\n    g.addEdge(1, 3);\n    g.addEdge(1, 2);\n    g.addEdge(2, 3);\n    g.addEdge(4, 3);\n    g.printAdjacencyList();\n    return 0;\n}"
  },
  {
    "path": "Graphs/graphs_adjacency_list_generic.cpp",
    "content": "// Graphs Adjacency List implementation for Generic Data\n// Program Author : Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\n\ntemplate<typename T>\nclass Graph{\n    map<T, list<T> > adjList;\n    public:\n        Graph(){\n\n        }\n        void addEdge(T u, T v, bool bidir = true){\n            adjList[u].push_back(v);\n            if(bidir){\n                adjList[v].push_back(u);\n            }\n        }\n        void printAdjList(){\n            for(auto obj : adjList){\n                cout << obj.first <<  \"->\";\n                for(auto element : obj.second){\n                    cout << element << \",\";\n                }\n                cout << endl;\n            }\n        }\n};\nint main(){\n    Graph<string> g;\n    g.addEdge(\"Ashish\", \"Asif\", false);\n    g.addEdge(\"Ashish\", \"Abhisek\", false);\n    g.addEdge(\"Ashish\", \"Amir\", false);\n    g.addEdge(\"Abhisek\", \"Asif\", true);\n    g.addEdge(\"Abhisek\", \"Anvesh\", true);\n    g.addEdge(\"Anvesh\", \"Sai\", false);\n    g.addEdge(\"Sai\", \"Abhisek\", false);\n    g.printAdjList();\n    return 0;\n}"
  },
  {
    "path": "Graphs/graphs_bfs.go",
    "content": "// Breadth First Search\n/*\n\tIn this implementation, we define a Graph struct that represents a graph with a given number of vertices,\n\tedges, and a visited array to keep track of visited vertices. We also define two methods - addEdge to\n\tadd an edge to the graph and BFS to perform the BFS algorithm.\n\n\tIn the BFS method, we start by creating a queue to store the vertices to visit. We mark the start node\n\tas visited and enqueue it. Then, while the queue is not empty, we dequeue a vertex from the queue,\n\tprint it out, and get all its adjacent vertices. For each adjacent vertex, if it hasn't been visited,\n\twe mark it as visited and enqueue it. This continues until all reachable vertices have been visited.\n\n\tIn the main function, we create a new Graph with 5 vertices and add edges to it. We then perform\n\tBFS starting from vertex 2, and print out the visited vertices. The output of this program will be:\n\tBFS starting from vertex 2:\n\t2 0 3 1\n\n\tThe time complexity of BFS (Breadth-First Search) algorithm is O(V + E), where V is the number of\n\tvertices and E is the number of edges in the graph. This is because BFS traverses all the vertices\n\tand edges of the graph exactly once, and the time taken to visit each vertex and edge is constant.\n\tTherefore, the time complexity of BFS is proportional to the size of the graph.\n\n\tThe space complexity of BFS is O(|V|), where |V| is the number of vertices in the graph.\n\tThis is because in the worst case scenario, we would need to store all vertices in the queue\n\tbefore we finish traversing the graph.\n*/\npackage main\n\nimport \"fmt\"\n\n// Define a Graph struct to represent a graph\ntype Graph struct {\n\tvertices int        // Number of vertices in the graph\n\tedges    [][]int    // Adjacency list to store edges\n\tvisited  []bool     // Track if a vertex is visited or not\n}\n\n// Function to add an edge to the graph\nfunc (g *Graph) addEdge(u, v int) {\n\t// Add edge from u to v\n\tg.edges[u] = append(g.edges[u], v)\n\t// Add edge from v to u\n\tg.edges[v] = append(g.edges[v], u)\n}\n\n// Function to perform Breadth First Search\nfunc BFS(g *Graph, start int) {\n\t// Create a queue for BFS\n\tqueue := []int{}\n\t// Mark the start node as visited and enqueue it\n\tg.visited[start] = true\n\tqueue = append(queue, start)\n\n\tfor len(queue) != 0 {\n\t\t// Dequeue a vertex from the queue\n\t\tcurrVertex := queue[0]\n\t\tqueue = queue[1:]\n\t\tfmt.Printf(\"%d \", currVertex)\n\n\t\t// Get all adjacent vertices of the dequeued vertex currVertex\n\t\t// If an adjacent vertex has not been visited, mark it as visited and enqueue it\n\t\tfor _, adjVertex := range g.edges[currVertex] {\n\t\t\tif !g.visited[adjVertex] {\n\t\t\t\tg.visited[adjVertex] = true\n\t\t\t\tqueue = append(queue, adjVertex)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc main() {\n\t// Create a new graph with 5 vertices\n\tg := Graph{\n\t\tvertices: 5,\n\t\tedges:    make([][]int, 5),\n\t\t // Initially all vertices are unvisited\n\t\tvisited:  make([]bool, 5),\n\t}\n\n\t// Add edges to the graph\n\tg.addEdge(0, 1)\n\tg.addEdge(0, 2)\n\tg.addEdge(1, 2)\n\tg.addEdge(2, 0)\n\tg.addEdge(2, 3)\n\tg.addEdge(3, 3)\n\n\t// Perform BFS starting from vertex 2\n\tfmt.Println(\"BFS starting from vertex 2:\")\n\tBFS(&g, 2)\n}\n\n"
  },
  {
    "path": "Graphs/graphs_dfs.go",
    "content": "/*\n   This implementation represents a graph as a collection of nodes, where each node has a value and a list of\n   neighboring nodes. The DFS algorithm is implemented recursively by starting from the given node, marking\n   it as visited, and printing its value. Then, the algorithm recursively visits each of the neighboring\n   nodes that have not been visited yet. The time complexity of DFS is O(V + E), where V is the number of\n   vertices (nodes) in the graph and E is the number of edges between the vertices.\n\n   Sample Input : graph = {\n   'A': ['B', 'C'],\n   'B': ['D', 'E'],\n   'C': ['F'],\n   'D': [],\n   'E': ['F'],\n   'F': []\n   }\n   Output : DFS Traversal: A B D E F C\n   Here, we have a graph represented as an adjacency list, with nodes A, B, C, D, E, and F and their respective neighbors.\n   The DFS traversal starts at node A and visits each node in the graph, outputting the final order in which the nodes were visited.\n\n   The time complexity of the DFS algorithm is O(V + E), where V is the number of vertices (nodes) and E is the number of\n   edges in the graph. This is because the algorithm visits every vertex and every edge once.\n\n   The space complexity of DFS depends on the maximum depth of the recursion stack. In the worst case, where the tree or\n   graph is completely unbalanced, the recursion stack can reach a depth of O(n), where n is the number of nodes in the graph.\n   Therefore, the space complexity of DFS is O(n).\n\n*/\npackage main\n\nimport \"fmt\"\n\n// Node represents a single node in the graph\ntype Node struct {\n    value int\n    visited bool\n    neighbors []*Node\n}\n\n// DFS traverses the graph starting from the given node using Depth First Search\nfunc DFS(node *Node) {\n    // Mark the current node as visited\n    node.visited = true\n\n    // Print the value of the current node\n    fmt.Printf(\"%d \", node.value)\n\n    // Visit each of the neighboring nodes\n    for _, neighbor := range node.neighbors {\n        // If the neighbor has not been visited yet, visit it recursively\n        if !neighbor.visited {\n            DFS(neighbor)\n        }\n    }\n}\n\nfunc main() {\n    // Create the nodes of the graph\n    node1 := &Node{value: 1}\n    node2 := &Node{value: 2}\n    node3 := &Node{value: 3}\n    node4 := &Node{value: 4}\n    node5 := &Node{value: 5}\n\n    // Add the neighbors for each node\n    node1.neighbors = []*Node{node2, node3}\n    node2.neighbors = []*Node{node1, node4, node5}\n    node3.neighbors = []*Node{node1, node5}\n    node4.neighbors = []*Node{node2}\n    node5.neighbors = []*Node{node2, node3}\n\n    // Start the DFS traversal from node1\n    DFS(node1)\n}\n"
  },
  {
    "path": "Graphs/kruskals_algorithm.java",
    "content": "/*\nWhat is a minimum spanning tree?\nA minimum spanning tree (MST) or minimum weight spanning tree for a weighted, connected, undirected graph is a spanning tree with a weight less than or equal to the weight of every other spanning tree. \n\nWhat is Kruskal’s algorithm?\nIn Kruskal’s algorithm, sort all edges of the given graph in increasing order. Then it keeps on adding new edges and nodes in the MST if the newly added edge does not form a cycle. It picks the minimum weighted edge at first at the maximum weighted edge at last. Thus we can say that it makes a locally optimal choice in each step in order to find the optimal solution.\n\nHow Kruskal's algorithm works\nIt falls under a class of algorithms called greedy algorithms that find the local optimum in the hopes of finding a global optimum. We start from the edges with the lowest weight and keep adding edges until we reach our goal.\nThe steps for implementing Kruskal's algorithm are as follows:\n1. Sort all the edges from low weight to high\n2. Take the edge with the lowest weight and add it to the spanning tree. If adding the edge created a cycle, then reject this edge.\n3. Keep adding edges until we reach all vertices.\n\nTime Complexity: O(E * logE) or O(E * logV)\nAuxiliary Space: O(V + E), where V is the number of vertices and E is the number of edges in the graph.\n*/\n\n// Java program for Kruskal's algorithm\n\nimport java.util.ArrayList;\nimport java.util.Comparator;\nimport java.util.List;\n\npublic class KruskalsMST {\n\n\t// Defines edge structure\n\tstatic class Edge {\n\t\tint src, dest, weight;\n\n\t\tpublic Edge(int src, int dest, int weight)\n\t\t{\n\t\t\tthis.src = src;\n\t\t\tthis.dest = dest;\n\t\t\tthis.weight = weight;\n\t\t}\n\t}\n\n\t// Defines subset element structure\n\tstatic class Subset {\n\t\tint parent, rank;\n\n\t\tpublic Subset(int parent, int rank)\n\t\t{\n\t\t\tthis.parent = parent;\n\t\t\tthis.rank = rank;\n\t\t}\n\t}\n\n\t// Starting point of program execution\n\tpublic static void main(String[] args)\n\t{\n\t\tint V = 4;\n\t\tList<Edge> graphEdges = new ArrayList<Edge>(\n\t\t\tList.of(new Edge(0, 1, 10), new Edge(0, 2, 6),\n\t\t\t\t\tnew Edge(0, 3, 5), new Edge(1, 3, 15),\n\t\t\t\t\tnew Edge(2, 3, 4)));\n\n\t\t// Sort the edges in non-decreasing order\n\t\t// (increasing with repetition allowed)\n\t\tgraphEdges.sort(new Comparator<Edge>() {\n\t\t\t@Override public int compare(Edge o1, Edge o2)\n\t\t\t{\n\t\t\t\treturn o1.weight - o2.weight;\n\t\t\t}\n\t\t});\n\n\t\tkruskals(V, graphEdges);\n\t}\n\n\t// Function to find the MST\n\tprivate static void kruskals(int V, List<Edge> edges)\n\t{\n\t\tint j = 0;\n\t\tint noOfEdges = 0;\n\n\t\t// Allocate memory for creating V subsets\n\t\tSubset subsets[] = new Subset[V];\n\n\t\t// Allocate memory for results\n\t\tEdge results[] = new Edge[V];\n\n\t\t// Create V subsets with single elements\n\t\tfor (int i = 0; i < V; i++) {\n\t\t\tsubsets[i] = new Subset(i, 0);\n\t\t}\n\n\t\t// Number of edges to be taken is equal to V-1\n\t\twhile (noOfEdges < V - 1) {\n\n\t\t\t// Pick the smallest edge. And increment\n\t\t\t// the index for next iteration\n\t\t\tEdge nextEdge = edges.get(j);\n\t\t\tint x = findRoot(subsets, nextEdge.src);\n\t\t\tint y = findRoot(subsets, nextEdge.dest);\n\n\t\t\t// If including this edge doesn't cause cycle,\n\t\t\t// include it in result and increment the index\n\t\t\t// of result for next edge\n\t\t\tif (x != y) {\n\t\t\t\tresults[noOfEdges] = nextEdge;\n\t\t\t\tunion(subsets, x, y);\n\t\t\t\tnoOfEdges++;\n\t\t\t}\n\n\t\t\tj++;\n\t\t}\n\n\t\t// Print the contents of result[] to display the\n\t\t// built MST\n\t\tSystem.out.println(\n\t\t\t\"Following are the edges of the constructed MST:\");\n\t\tint minCost = 0;\n\t\tfor (int i = 0; i < noOfEdges; i++) {\n\t\t\tSystem.out.println(results[i].src + \" -- \"\n\t\t\t\t\t\t\t+ results[i].dest + \" == \"\n\t\t\t\t\t\t\t+ results[i].weight);\n\t\t\tminCost += results[i].weight;\n\t\t}\n\t\tSystem.out.println(\"Total cost of MST: \" + minCost);\n\t}\n\n\t// Function to unite two disjoint sets\n\tprivate static void union(Subset[] subsets, int x,\n\t\t\t\t\t\t\tint y)\n\t{\n\t\tint rootX = findRoot(subsets, x);\n\t\tint rootY = findRoot(subsets, y);\n\n\t\tif (subsets[rootY].rank < subsets[rootX].rank) {\n\t\t\tsubsets[rootY].parent = rootX;\n\t\t}\n\t\telse if (subsets[rootX].rank\n\t\t\t\t< subsets[rootY].rank) {\n\t\t\tsubsets[rootX].parent = rootY;\n\t\t}\n\t\telse {\n\t\t\tsubsets[rootY].parent = rootX;\n\t\t\tsubsets[rootX].rank++;\n\t\t}\n\t}\n\n\t// Function to find parent of a set\n\tprivate static int findRoot(Subset[] subsets, int i)\n\t{\n\t\tif (subsets[i].parent == i)\n\t\t\treturn subsets[i].parent;\n\n\t\tsubsets[i].parent\n\t\t\t= findRoot(subsets, subsets[i].parent);\n\t\treturn subsets[i].parent;\n\t}\n}\n\n/* Output\nFollowing are the edges in the constructed MST\n2 -- 3 == 4\n0 -- 3 == 5\n0 -- 1 == 10\nMinimum Cost Spanning Tree: 19\n*/\n\n"
  },
  {
    "path": "Graphs/kruskals_algorithm.py",
    "content": "#Question: Implement Kruskal's algorithm in Python to find the minimum spanning tree of a given graph.\n#Intuition:\n# Kruskal's algorithm is a greedy algorithm that aims to find the minimum spanning tree (MST) of a connected, weighted graph.\n# The MST is a subset of the graph's edges that connects all the vertices with the minimum total weight.\n# The algorithm works by iteratively selecting the edges in ascending order of their weights, while ensuring that adding an edge to the growing MST does not create a cycle. \n#It uses a disjoint set data structure, typically implemented with the Union-Find algorithm, to efficiently keep track of the connected components and \n# detect cycles.\n\n#Implementing Kruskal's algorithm with the help of a Union-Find data structure allows for efficient detection of cycles and union operations,\n#resulting in a time complexity of O(E log E), where E is the number of edges in the graph.\n\n# Initialize a Union-Find data structure to keep track of the connected components.\nclass UnionFind:\n    def __init__(self, n):\n        # Initialize the parent and rank lists\n        self.parent = list(range(n))\n        self.rank = [0] * n\n\n    def find(self, x):\n        # Find the root of the set to which x belongs\n        if self.parent[x] != x:\n            self.parent[x] = self.find(self.parent[x])  # Path compression\n        return self.parent[x]\n\n    def union(self, x, y):\n        # Perform the union of two sets\n        root_x = self.find(x)\n        root_y = self.find(y)\n\n        if root_x != root_y:\n            if self.rank[root_x] < self.rank[root_y]:\n                self.parent[root_x] = root_y\n            elif self.rank[root_x] > self.rank[root_y]:\n                self.parent[root_y] = root_x\n            else:\n                self.parent[root_y] = root_x\n                self.rank[root_x] += 1\n\n# Define the Kruskal function\ndef kruskal(graph):\n    edges = []\n    for u in range(len(graph)):\n        for v, weight in graph[u]:\n            edges.append((weight, u, v))\n\n    edges.sort()\n   # Create an empty list to store the MST\n    mst = []\n    uf = UnionFind(len(graph))\n\n    for weight, u, v in edges:\n        if uf.find(u) != uf.find(v):\n            uf.union(u, v)\n            mst.append((u, v, weight))\n\n    return mst\n\n# Example usage: Create a list of all the edges in the graph, along with their weights.\ngraph = [\n    [(1, 1), (2, 2)],           # Node 0\n    [(0, 1), (2, 3), (3, 4)],   # Node 1\n    [(0, 2), (1, 3), (3, 5)],   # Node 2\n    [(1, 4), (2, 5)]            # Node 3\n]\n#Sort the edges in ascending order based on their weights.\nmst = kruskal(graph)\nfor u, v, weight in mst:\n    print(f\"Edge ({u}, {v}) with weight {weight}\")\n"
  },
  {
    "path": "Graphs/remove_island.go",
    "content": "/*\n\tRemoev island that are not connected to Border\n\n\tSample Input:\n\n\t1 0 0 0 0 0\n\t0 1 0 1 0 1\n\t0 0 1 0 1 1\n\t1 1 0 0 1 0\n\t1 0 1 1 0 0\n\n\tOutput:\n\t1 0 0 0 0 0\n\t0 0 0 0 0 1\n\t0 0 0 0 1 1\n\t1 1 0 0 1 0\n\t1 0 1 1 0 0\n\n\tExplanation:\n\tThe provided code snippet is an implementation of the \"Remove Islands\" algorithm. This algorithm aims to identify and remove\n\tislands in a binary matrix. An island is a connected region of 1s surrounded by 0s. The algorithm marks islands connected\n\tto the border of the matrix as non-islands and returns the modified matrix.\n\n\t\tLet's break down the code snippet and explain each part:\n\n\t\t1. Initialization:\n\n\t\tonesConnectedToBorder := make([][]bool, len(matrix))\n\t\tfor i := range matrix {\n\t\t\tonesConnectedToBorder[i] = make([]bool, len(matrix[0]))\n\t\t}\n\n\t\tThis part initializes a 2D boolean array `onesConnectedToBorder`, which has the same dimensions as the input matrix. It is used to mark cells that are connected to the border.\n\n\t\t2. Marking Ones Connected to Border:\n\n\t\tfor row := 0; row < len(matrix); row++ {\n\t\t\tfor col := 0; col < len(matrix[row]); col++ {\n\t\t\t\trowIsBorder := row == 0 || row == len(matrix)-1\n\t\t\t\tcolIsBorder := col == 0 || col == len(matrix[row])-1\n\t\t\t\tisBorder := rowIsBorder || colIsBorder\n\t\t\t\tif !isBorder {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif matrix[row][col] != 1 {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tfindOnesConnectedToBorder(matrix, row, col, onesConnectedToBorder)\n\t\t\t}\n\t\t}\n\n\t\tThis part iterates through the matrix and checks if each cell is on the border. If a cell is on the border and contains a 1, it calls the `findOnesConnectedToBorder` function to mark the connected 1s using a depth-first search approach. The connected 1s are marked in the `onesConnectedToBorder` array.\n\n\t\t3. Removing Non-Border Islands:\n\n\t\tfor row := 0; row < len(matrix)-1; row++ {\n\t\t\tfor col := 0; col < len(matrix[row])-1; col++ {\n\t\t\t\tif onesConnectedToBorder[row][col] {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tmatrix[row][col] = 0\n\t\t\t}\n\t\t}\n\n\t\tThis part iterates through the matrix again, excluding the border cells. If a cell is not marked as connected to the border (an island cell), it is set to 0, effectively removing the island.\n\n\t\t4. Utility Functions:\n\t\tThe code also includes two utility functions:\n\t\t- `findOnesConnectedToBorder`: This function performs a depth-first search (DFS) to mark all the 1s connected to a border cell. It uses a stack to keep track of the cells to visit next.\n\t\t- `getNeighbors`: This function returns the valid neighboring cells (up, down, left, right) for a given cell in the matrix.\n\n\t\tFinally, the modified matrix is returned as the result.\n\n\t\tO(wh) time | O(wh) space - where w and h are the width and height of the input matrix\t\n\n\t\tNote: The code snippet provided assumes that the matrix is a 2D integer slice (`[][]int`) and uses Go syntax..\n*/\npackage main\n\nimport \"fmt\"\n\n// Function to remove islands in a binary matrix\nfunc RemoveIslands(matrix [][]int) [][]int {\n\t// Create a boolean matrix to track if each cell is connected to the border\n\tonesConnectedToBorder := make([][]bool, len(matrix))\n\tfor i := range matrix {\n\t\tonesConnectedToBorder[i] = make([]bool, len(matrix[0]))\n\t}\n\n\t// Mark 1s connected to the border\n\tfor row := 0; row < len(matrix); row++ {\n\t\tfor col := 0; col < len(matrix[row]); col++ {\n\t\t\trowIsBorder := row == 0 || row == len(matrix)-1\n\t\t\tcolIsBorder := col == 0 || col == len(matrix[row])-1\n\t\t\tisBorder := rowIsBorder || colIsBorder\n\n\t\t\tif !isBorder {\n\t\t\t\tcontinue // Skip if not a border cell\n\t\t\t}\n\n\t\t\tif matrix[row][col] != 1 {\n\t\t\t\tcontinue // Skip if not a 1\n\t\t\t}\n\n\t\t\tfindOnesConnectedToBorder(matrix, row, col, onesConnectedToBorder)\n\t\t}\n\t}\n\n\t// Remove non-border islands\n\tfor row := 0; row < len(matrix)-1; row++ {\n\t\tfor col := 0; col < len(matrix[row])-1; col++ {\n\t\t\tif onesConnectedToBorder[row][col] {\n\t\t\t\tcontinue // Skip if connected to the border\n\t\t\t}\n\n\t\t\tmatrix[row][col] = 0 // Set non-border island to 0\n\t\t}\n\t}\n\n\treturn matrix\n}\n\n// Function to perform DFS and mark 1s connected to the border\nfunc findOnesConnectedToBorder(matrix [][]int, startRow, startCol int, onesConnectedToBorder [][]bool) {\n\tstack := [][]int{{startRow, startCol}}\n\tvar currentPosition []int\n\n\tfor len(stack) > 0 {\n\t\tcurrentPosition, stack = stack[len(stack)-1], stack[:len(stack)-1]\n\t\tcurrentRow, currentCol := currentPosition[0], currentPosition[1]\n\t\talreadyVisited := onesConnectedToBorder[currentRow][currentCol]\n\n\t\tif alreadyVisited {\n\t\t\tcontinue // Skip if already visited\n\t\t}\n\n\t\tonesConnectedToBorder[currentRow][currentCol] = true // Mark cell as connected to the border\n\n\t\tneighbors := getNeighbors(matrix, currentRow, currentCol)\n\t\tfor _, neighbor := range neighbors {\n\t\t\trow, col := neighbor[0], neighbor[1]\n\t\t\tif matrix[row][col] != 1 {\n\t\t\t\tcontinue // Skip if not a 1\n\t\t\t}\n\t\t\tstack = append(stack, neighbor) // Add neighbor to the stack\n\t\t}\n\t}\n}\n\n// Function to get valid neighboring cells\nfunc getNeighbors(matrix [][]int, row, col int) [][]int {\n\tneighbors := make([][]int, 0)\n\tnumRows := len(matrix)\n\tnumCols := len(matrix[row])\n\n\tif row-1 >= 0 {\n\t\tneighbors = append(neighbors, []int{row - 1, col}) // Top neighbor\n\t}\n\tif row+1 < numRows {\n\t\tneighbors = append(neighbors, []int{row + 1, col}) // Bottom neighbor\n\t}\n\tif col-1 >= 0 {\n\t\tneighbors = append(neighbors, []int{row, col - 1}) // Left neighbor\n\t}\n\tif col+1 < numCols {\n\t\tneighbors = append(neighbors, []int{row, col + 1}) // Right neighbor\n\t}\n\n\treturn neighbors\n}\n\nfunc main() {\n\t// Example usage\n\tmatrix := [][]int{\n\t\t{1, 0, 0, 0, 0, 0},\n\t\t{0, 1, 0, 1, 0, 1},\n\t\t{0, 0, 1, 0, 1, 1},\n\t\t{1, 1, 0, 0, 1, 0},\n\t\t{1, 0, 1, 1, 0, 0},\n\t}\n\n\tfmt.Println(\"Original Matrix:\")\n\tprintMatrix(matrix)\n\n\tupdatedMatrix := RemoveIslands(matrix)\n\n\tfmt.Println(\"Updated Matrix:\")\n\tprintMatrix(updatedMatrix)\n}\n\n// Helper function to print the matrix\nfunc printMatrix(matrix [][]int) {\n\tfor _, row := range matrix {\n\t\tfor _, val := range row {\n\t\t\tfmt.Printf(\"%d \", val)\n\t\t}\n\t\tfmt.Println()\n\t}\n}\n\n\n\n\n\n"
  },
  {
    "path": "Graphs/river_sizes.cpp",
    "content": "/*\n  \tYou're given a two-dimensional array (a matrix) of potentially unequal height and width containing only\n\t0's and 1's. Each 0 represent land and each 1 represent part of river. A river consists of any number of 1's\n\tthat are either horizontally or vertically adjacent (but not diagonally adjacent).\n\tThe number of adjacent 1's forming a river determine its size.\n\n  \tNote that a river can twist. In other words, it doesn't have to be a straight vertical line or a straight\n\thorizontal line; it can be L-shaped, for example.\n\n  \tWrite a function that returns an array of the sizes of all rivers represented in the input matrix.\n\tThe sizes don't need to be in any particular order.\n\n\tSample Input:[\n\t\t\t\t\t[1, 0, 0, 1, 0],\n\t\t\t\t\t[1, 0, 1, 0, 0],\n\t\t\t\t\t[0, 0, 1, 0, 1],\n\t\t\t\t\t[1, 0, 1, 0, 1],\n\t\t\t\t\t[1, 0, 1, 1, 0],\n\t\t\t\t]\n\tOutput: [1, 2, 2, 2, 5]\n\n\tExplanation:\n\n\t1. The function `RiverSizes` initializes an empty slice `sizes` to store the sizes of rivers found in the matrix. It also creates a 2D `visited` matrix of the same size as the input matrix to keep track of visited nodes.\n\n\t2. The function then iterates over each cell in the matrix using nested loops.\n\n\t3. If a cell has already been visited (marked as `true` in the `visited` matrix), the code continues to the next iteration to avoid processing it again.\n\n\t4. If a cell has not been visited, the code calls the `traverseNode` function to explore the river connected to that cell and updates the `sizes` slice with the size of the river.\n\n\t5. The `traverseNode` function takes the starting position (i, j) of a river, the matrix, the `visited` matrix, and the `sizes` slice as input.\n\n\t6. It initializes a variable `currentRiverSize` to 0 to keep track of the size of the river being explored.\n\n\t7. It maintains a queue (`nodesToExplore`) to store the nodes that need to be visited. It starts with the initial node (i, j).\n\n\t8. The function enters a loop that continues until there are no more nodes to explore in the queue.\n\n\t9. In each iteration, it dequeues the first node from the `nodesToExplore` queue and updates the current position (i, j) accordingly.\n\n\t10. If the current node has already been visited, the code continues to the next iteration.\n\n\t11. If the current node contains a value of 0 (indicating land), the code continues to the next iteration, as it's not part of the river.\n\n\t12. If the current node contains a value of 1 (indicating a river), it increments the `currentRiverSize` by 1.\n\n\t13. It then retrieves the unvisited neighboring nodes of the current node using the `getUnvisitedNeighbors` function and adds them to the `nodesToExplore` queue.\n\n\t14. Once the loop finishes, if the `currentRiverSize` is greater than 0, it appends it to the `sizes` slice.\n\n\t15. Finally, the `sizes` slice containing the sizes of all rivers is returned.\n\n\t16. The `getUnvisitedNeighbors` function takes the current position (i, j), the matrix, and the `visited` matrix as input.\n\n\t17. It checks the four neighboring cells (up, down, left, right) of the current cell and adds the unvisited neighbors to the `unvisitedNeighbors` slice.\n\n\t18. The function returns the `unvisitedNeighbors` slice.\n\n\tThe code essentially performs a depth-first search (DFS) traversal on the matrix to find connected regions of 1s (rivers) and keeps track of their sizes. The `visited` matrix helps avoid revisiting nodes that have already been processed, ensuring each river is counted only once.\n*/\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nvector<int> riverSizes(vector<vector<int>>& matrix) {\n    // Vector to store the sizes of rivers\n    vector<int> sizes;\n\n    // Create a visited matrix to keep track of visited nodes\n    vector<vector<bool>> visited(matrix.size(), vector<bool>(matrix[0].size(), false));\n\n    // Iterate over each cell in the matrix\n    for (int i = 0; i < matrix.size(); i++) {\n        for (int j = 0; j < matrix[i].size(); j++) {\n            // If the cell has already been visited, continue to the next iteration\n            if (visited[i][j]) {\n                continue;\n            }\n\n            // Explore the river connected to the current cell and update sizes\n            sizes = traverseNode(i, j, matrix, visited, sizes);\n        }\n    }\n\n    return sizes;\n}\n\nvector<int> traverseNode(int i, int j, vector<vector<int>>& matrix, vector<vector<bool>>& visited, vector<int>& sizes) {\n    // Variable to track the size of the current river\n    int currentRiverSize = 0;\n\n    // Queue to store nodes that need to be visited\n    vector<vector<int>> nodesToExplore{{i, j}};\n\n    // Loop until there are no more nodes to explore\n    while (!nodesToExplore.empty()) {\n        // Dequeue the first node from the queue and update the current position (i, j)\n        vector<int> currentNode = nodesToExplore[0];\n        nodesToExplore.erase(nodesToExplore.begin());\n        i = currentNode[0];\n        j = currentNode[1];\n\n        // If the current node has already been visited, continue to the next iteration\n        if (visited[i][j]) {\n            continue;\n        }\n\n        // Mark the current node as visited\n        visited[i][j] = true;\n\n        // If the current node is land (0), continue to the next iteration\n        if (matrix[i][j] == 0) {\n            continue;\n        }\n\n        // Increment the size of the current river\n        currentRiverSize++;\n\n        // Get the unvisited neighboring nodes of the current node\n        vector<vector<int>> unvisitedNeighbors = getUnvisitedNeighbors(i, j, matrix, visited);\n\n        // Add the unvisited neighbors to the nodesToExplore queue\n        for (const auto& neighbor : unvisitedNeighbors) {\n            nodesToExplore.push_back(neighbor);\n        }\n    }\n\n    // If the current river size is greater than 0, append it to the sizes vector\n    if (currentRiverSize > 0) {\n        sizes.push_back(currentRiverSize);\n    }\n\n    return sizes;\n}\n\nvector<vector<int>> getUnvisitedNeighbors(int i, int j, vector<vector<int>>& matrix, vector<vector<bool>>& visited) {\n    // Vector to store unvisited neighboring nodes\n    vector<vector<int>> unvisitedNeighbors;\n\n    // Check the four neighboring cells (up, down, left, right) of the current cell\n    // and add unvisited neighbors to the unvisitedNeighbors vector\n\n    // Up neighbor\n    if (i > 0 && !visited[i - 1][j]) {\n        unvisitedNeighbors.push_back({i - 1, j});\n    }\n\n    // Down neighbor\n    if (i < matrix.size() - 1 && !visited[i + 1][j]) {\n        unvisitedNeighbors.push_back({i + 1, j});\n    }\n\n    // Left neighbor\n    if (j > 0 && !visited[i][j - 1]) {\n        unvisitedNeighbors.push_back({i, j - 1});\n    }\n\n    // Right neighbor\n    if (j < matrix[0].size() - 1 && !visited[i][j + 1]) {\n        unvisitedNeighbors.push_back({i, j + 1});\n    }\n\n    return unvisitedNeighbors;\n}\n\nint main() {\n    // Test the riverSizes function\n    vector<vector<int>> matrix = {\n        {1, 0, 0, 1, 0},\n        {1, 0, 1, 0, 0},\n        {0, 0, 1, 0, 1},\n        {1, 0, 1, 0, 1},\n        {1, 0, 1, 1, 0}\n    };\n\n    vector<int> sizes = riverSizes(matrix);\n\n    // Print the sizes of the rivers\n    for (const auto& size : sizes) {\n        cout << size << \" \";\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "Graphs/river_sizes.go",
    "content": "/*\n\n  \tYou're given a two-dimensional array (a matrix) of potentially unequal height and width containing only\n\t0's and 1's. Each 0 represent land and each 1 represent part of river. A river consists of any number of 1's\n\tthat are either horizontally or vertically adjacent (but not diagonally adjacent).\n\tThe number of adjacent 1's forming a river determine its size.\n\n  \tNote that a river can twist. In other words, it doesn't have to be a straight vertical line or a straight\n\thorizontal line; it can be L-shaped, for example.\n\n  \tWrite a function that returns an array of the sizes of all rivers represented in the input matrix.\n\tThe sizes don't need to be in any particular order.\n\n\tSample Input:[\n\t\t\t\t\t[1, 0, 0, 1, 0],\n\t\t\t\t\t[1, 0, 1, 0, 0],\n\t\t\t\t\t[0, 0, 1, 0, 1],\n\t\t\t\t\t[1, 0, 1, 0, 1],\n\t\t\t\t\t[1, 0, 1, 1, 0],\n\t\t\t\t]\n\tOutput: [1, 2, 2, 2, 5]\n\n\tExplanation:\n\n\t1. The function `RiverSizes` initializes an empty slice `sizes` to store the sizes of rivers found in the matrix. It also creates a 2D `visited` matrix of the same size as the input matrix to keep track of visited nodes.\n\n\t2. The function then iterates over each cell in the matrix using nested loops.\n\n\t3. If a cell has already been visited (marked as `true` in the `visited` matrix), the code continues to the next iteration to avoid processing it again.\n\n\t4. If a cell has not been visited, the code calls the `traverseNode` function to explore the river connected to that cell and updates the `sizes` slice with the size of the river.\n\n\t5. The `traverseNode` function takes the starting position (i, j) of a river, the matrix, the `visited` matrix, and the `sizes` slice as input.\n\n\t6. It initializes a variable `currentRiverSize` to 0 to keep track of the size of the river being explored.\n\n\t7. It maintains a queue (`nodesToExplore`) to store the nodes that need to be visited. It starts with the initial node (i, j).\n\n\t8. The function enters a loop that continues until there are no more nodes to explore in the queue.\n\n\t9. In each iteration, it dequeues the first node from the `nodesToExplore` queue and updates the current position (i, j) accordingly.\n\n\t10. If the current node has already been visited, the code continues to the next iteration.\n\n\t11. If the current node contains a value of 0 (indicating land), the code continues to the next iteration, as it's not part of the river.\n\n\t12. If the current node contains a value of 1 (indicating a river), it increments the `currentRiverSize` by 1.\n\n\t13. It then retrieves the unvisited neighboring nodes of the current node using the `getUnvisitedNeighbors` function and adds them to the `nodesToExplore` queue.\n\n\t14. Once the loop finishes, if the `currentRiverSize` is greater than 0, it appends it to the `sizes` slice.\n\n\t15. Finally, the `sizes` slice containing the sizes of all rivers is returned.\n\n\t16. The `getUnvisitedNeighbors` function takes the current position (i, j), the matrix, and the `visited` matrix as input.\n\n\t17. It checks the four neighboring cells (up, down, left, right) of the current cell and adds the unvisited neighbors to the `unvisitedNeighbors` slice.\n\n\t18. The function returns the `unvisitedNeighbors` slice.\n\n\tThe code essentially performs a depth-first search (DFS) traversal on the matrix to find connected regions of 1s (rivers) and keeps track of their sizes. The `visited` matrix helps avoid revisiting nodes that have already been processed, ensuring each river is counted only once.\n*/\npackage main\n\nfunc RiverSizes(matrix [][]int) []int {\n\t// Slice to store the sizes of rivers\n\tsizes := []int{}\n\n\t// Create a visited matrix to keep track of visited nodes\n\tvisited := make([][]bool, len(matrix))\n\tfor i := range visited {\n\t\tvisited[i] = make([]bool, len(matrix[i]))\n\t}\n\n\t// Iterate over each cell in the matrix\n\tfor i := range matrix {\n\t\tfor j := range matrix[i] {\n\t\t\t// If the cell has already been visited, continue to the next iteration\n\t\t\tif visited[i][j] {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Explore the river connected to the current cell and update sizes\n\t\t\tsizes = traverseNode(i, j, matrix, visited, sizes)\n\t\t}\n\t}\n\n\treturn sizes\n}\n\nfunc traverseNode(i, j int, matrix [][]int, visited [][]bool, sizes []int) []int {\n\t// Variable to track the size of the current river\n\tcurrentRiverSize := 0\n\n\t// Queue to store nodes that need to be visited\n\tnodesToExplore := [][]int{{i, j}}\n\n\t// Loop until there are no more nodes to explore\n\tfor len(nodesToExplore) > 0 {\n\t\t// Dequeue the first node from the queue and update the current position (i, j)\n\t\tcurrentNode := nodesToExplore[0]\n\t\tnodesToExplore = nodesToExplore[1:]\n\t\ti, j := currentNode[0], currentNode[1]\n\n\t\t// If the current node has already been visited, continue to the next iteration\n\t\tif visited[i][j] {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Mark the current node as visited\n\t\tvisited[i][j] = true\n\n\t\t// If the current node is land (0), continue to the next iteration\n\t\tif matrix[i][j] == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Increment the size of the current river\n\t\tcurrentRiverSize++\n\n\t\t// Get the unvisited neighboring nodes of the current node\n\t\tunvisitedNeighbors := getUnvisitedNeighbors(i, j, matrix, visited)\n\n\t\t// Add the unvisited neighbors to the nodesToExplore queue\n\t\tfor _, neighbor := range unvisitedNeighbors {\n\t\t\tnodesToExplore = append(nodesToExplore, neighbor)\n\t\t}\n\t}\n\n\t// If the current river size is greater than 0, append it to the sizes slice\n\tif currentRiverSize > 0 {\n\t\tsizes = append(sizes, currentRiverSize)\n\t}\n\n\treturn sizes\n}\n\nfunc getUnvisitedNeighbors(i, j int, matrix [][]int, visited [][]bool) [][]int {\n\t// Slice to store unvisited neighboring nodes\n\tunvisitedNeighbors := [][]int{}\n\n\t// Check the four neighboring cells (up, down, left, right) of the current cell\n\t// and add unvisited neighbors to the unvisitedNeighbors slice\n\n\t// Up neighbor\n\tif i > 0 && !visited[i-1][j] {\n\t\tunvisitedNeighbors = append(unvisitedNeighbors, []int{i - 1, j})\n\t}\n\n\t// Down neighbor\n\tif i < len(matrix)-1 && !visited[i+1][j] {\n\t\tunvisitedNeighbors = append(unvisitedNeighbors, []int{i + 1, j})\n\t}\n\n\t// Left neighbor\n\tif j > 0 && !visited[i][j-1] {\n\t\tunvisitedNeighbors = append(unvisitedNeighbors, []int{i, j - 1})\n\t}\n\n\t// Right neighbor\n\tif j < len(matrix[0])-1 && !visited[i][j+1] {\n\t\tunvisitedNeighbors = append(unvisitedNeighbors, []int{i, j + 1})\n\t}\n\n\treturn unvisitedNeighbors\n}\n"
  },
  {
    "path": "Graphs/river_sizes.java",
    "content": "/*\n\n  \tYou're given a two-dimensional array (a matrix) of potentially unequal height and width containing only\n\t0's and 1's. Each 0 represent land and each 1 represent part of river. A river consists of any number of 1's\n\tthat are either horizontally or vertically adjacent (but not diagonally adjacent).\n\tThe number of adjacent 1's forming a river determine its size.\n\n  \tNote that a river can twist. In other words, it doesn't have to be a straight vertical line or a straight\n\thorizontal line; it can be L-shaped, for example.\n\n  \tWrite a function that returns an array of the sizes of all rivers represented in the input matrix.\n\tThe sizes don't need to be in any particular order.\n\n\tSample Input:[\n\t\t\t\t\t[1, 0, 0, 1, 0],\n\t\t\t\t\t[1, 0, 1, 0, 0],\n\t\t\t\t\t[0, 0, 1, 0, 1],\n\t\t\t\t\t[1, 0, 1, 0, 1],\n\t\t\t\t\t[1, 0, 1, 1, 0],\n\t\t\t\t]\n\tOutput: [1, 2, 2, 2, 5]\n\n\tExplanation:\n\n\t1. The function `RiverSizes` initializes an empty slice `sizes` to store the sizes of rivers found in the matrix. It also creates a 2D `visited` matrix of the same size as the input matrix to keep track of visited nodes.\n\n\t2. The function then iterates over each cell in the matrix using nested loops.\n\n\t3. If a cell has already been visited (marked as `true` in the `visited` matrix), the code continues to the next iteration to avoid processing it again.\n\n\t4. If a cell has not been visited, the code calls the `traverseNode` function to explore the river connected to that cell and updates the `sizes` slice with the size of the river.\n\n\t5. The `traverseNode` function takes the starting position (i, j) of a river, the matrix, the `visited` matrix, and the `sizes` slice as input.\n\n\t6. It initializes a variable `currentRiverSize` to 0 to keep track of the size of the river being explored.\n\n\t7. It maintains a queue (`nodesToExplore`) to store the nodes that need to be visited. It starts with the initial node (i, j).\n\n\t8. The function enters a loop that continues until there are no more nodes to explore in the queue.\n\n\t9. In each iteration, it dequeues the first node from the `nodesToExplore` queue and updates the current position (i, j) accordingly.\n\n\t10. If the current node has already been visited, the code continues to the next iteration.\n\n\t11. If the current node contains a value of 0 (indicating land), the code continues to the next iteration, as it's not part of the river.\n\n\t12. If the current node contains a value of 1 (indicating a river), it increments the `currentRiverSize` by 1.\n\n\t13. It then retrieves the unvisited neighboring nodes of the current node using the `getUnvisitedNeighbors` function and adds them to the `nodesToExplore` queue.\n\n\t14. Once the loop finishes, if the `currentRiverSize` is greater than 0, it appends it to the `sizes` slice.\n\n\t15. Finally, the `sizes` slice containing the sizes of all rivers is returned.\n\n\t16. The `getUnvisitedNeighbors` function takes the current position (i, j), the matrix, and the `visited` matrix as input.\n\n\t17. It checks the four neighboring cells (up, down, left, right) of the current cell and adds the unvisited neighbors to the `unvisitedNeighbors` slice.\n\n\t18. The function returns the `unvisitedNeighbors` slice.\n\n\tThe code essentially performs a depth-first search (DFS) traversal on the matrix to find connected regions of 1s (rivers) and keeps track of their sizes. The `visited` matrix helps avoid revisiting nodes that have already been processed, ensuring each river is counted only once.\n*/\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class RiverSizes {\n\n    public static List<Integer> riverSizes(int[][] matrix) {\n        List<Integer> sizes = new ArrayList<>();\n        int numRows = matrix.length;\n        int numCols = matrix[0].length;\n        boolean[][] visited = new boolean[numRows][numCols];\n\n        // Iterate over each cell in the matrix\n        for (int i = 0; i < numRows; i++) {\n            for (int j = 0; j < numCols; j++) {\n                // If the cell has already been visited, continue to the next iteration\n                if (visited[i][j]) {\n                    continue;\n                }\n\n                // Explore the river connected to the current cell and update sizes\n                sizes = traverseNode(i, j, matrix, visited, sizes);\n            }\n        }\n\n        return sizes;\n    }\n\n    private static List<Integer> traverseNode(int i, int j, int[][] matrix, boolean[][] visited, List<Integer> sizes) {\n        int currentRiverSize = 0;\n        List<int[]> nodesToExplore = new ArrayList<>();\n        nodesToExplore.add(new int[]{i, j});\n\n        while (!nodesToExplore.isEmpty()) {\n            int[] currentNode = nodesToExplore.remove(0);\n            i = currentNode[0];\n            j = currentNode[1];\n\n            // If the current node has already been visited, continue to the next iteration\n            if (visited[i][j]) {\n                continue;\n            }\n\n            // Mark the current node as visited\n            visited[i][j] = true;\n\n            // If the current node is land (0), continue to the next iteration\n            if (matrix[i][j] == 0) {\n                continue;\n            }\n\n            // Increment the size of the current river\n            currentRiverSize++;\n\n            // Get the unvisited neighboring nodes of the current node\n            List<int[]> unvisitedNeighbors = getUnvisitedNeighbors(i, j, matrix, visited);\n\n            // Add the unvisited neighbors to the nodesToExplore list\n            nodesToExplore.addAll(unvisitedNeighbors);\n        }\n\n        // If the current river size is greater than 0, add it to the sizes list\n        if (currentRiverSize > 0) {\n            sizes.add(currentRiverSize);\n        }\n\n        return sizes;\n    }\n\n    private static List<int[]> getUnvisitedNeighbors(int i, int j, int[][] matrix, boolean[][] visited) {\n        List<int[]> unvisitedNeighbors = new ArrayList<>();\n\n        // Check the four neighboring cells (up, down, left, right) of the current cell\n        // and add unvisited neighbors to the unvisitedNeighbors list\n\n        // Up neighbor\n        if (i > 0 && !visited[i - 1][j]) {\n            unvisitedNeighbors.add(new int[]{i - 1, j});\n        }\n\n        // Down neighbor\n        if (i < matrix.length - 1 && !visited[i + 1][j]) {\n            unvisitedNeighbors.add(new int[]{i + 1, j});\n        }\n\n        // Left neighbor\n        if (j > 0 && !visited[i][j - 1]) {\n            unvisitedNeighbors.add(new int[]{i, j - 1});\n        }\n\n        // Right neighbor\n        if (j < matrix[0].length - 1 && !visited[i][j + 1]) {\n            unvisitedNeighbors.add(new int[]{i, j + 1});\n        }\n\n        return unvisitedNeighbors;\n    }\n\n    public static void main(String[] args) {\n        int[][] matrix = {\n            {1, 0, 0, 1, 0},\n            {1, 0, 1, 0, 0},\n            {0, 0, 1, 0, 1},\n            {1, 0, 1, 0, 1},\n            {1, 0, 1, 1, 0}\n        };\n\n        List<Integer> sizes = riverSizes(matrix);\n\n        // Printing the sizes of rivers\n        for (int size : sizes) {\n            System.out.print(size + \" \");\n        }\n    }\n}\n"
  },
  {
    "path": "Graphs/river_sizes.js",
    "content": "/*\n  \tYou're given a two-dimensional array (a matrix) of potentially unequal height and width containing only\n\t0's and 1's. Each 0 represent land and each 1 represent part of river. A river consists of any number of 1's\n\tthat are either horizontally or vertically adjacent (but not diagonally adjacent).\n\tThe number of adjacent 1's forming a river determine its size.\n\n  \tNote that a river can twist. In other words, it doesn't have to be a straight vertical line or a straight\n\thorizontal line; it can be L-shaped, for example.\n\n  \tWrite a function that returns an array of the sizes of all rivers represented in the input matrix.\n\tThe sizes don't need to be in any particular order.\n\n\tSample Input:[\n\t\t\t\t\t[1, 0, 0, 1, 0],\n\t\t\t\t\t[1, 0, 1, 0, 0],\n\t\t\t\t\t[0, 0, 1, 0, 1],\n\t\t\t\t\t[1, 0, 1, 0, 1],\n\t\t\t\t\t[1, 0, 1, 1, 0],\n\t\t\t\t]\n\tOutput: [1, 2, 2, 2, 5]\n\n\tExplanation:\n\n\t1. The function `RiverSizes` initializes an empty slice `sizes` to store the sizes of rivers found in the matrix. It also creates a 2D `visited` matrix of the same size as the input matrix to keep track of visited nodes.\n\n\t2. The function then iterates over each cell in the matrix using nested loops.\n\n\t3. If a cell has already been visited (marked as `true` in the `visited` matrix), the code continues to the next iteration to avoid processing it again.\n\n\t4. If a cell has not been visited, the code calls the `traverseNode` function to explore the river connected to that cell and updates the `sizes` slice with the size of the river.\n\n\t5. The `traverseNode` function takes the starting position (i, j) of a river, the matrix, the `visited` matrix, and the `sizes` slice as input.\n\n\t6. It initializes a variable `currentRiverSize` to 0 to keep track of the size of the river being explored.\n\n\t7. It maintains a queue (`nodesToExplore`) to store the nodes that need to be visited. It starts with the initial node (i, j).\n\n\t8. The function enters a loop that continues until there are no more nodes to explore in the queue.\n\n\t9. In each iteration, it dequeues the first node from the `nodesToExplore` queue and updates the current position (i, j) accordingly.\n\n\t10. If the current node has already been visited, the code continues to the next iteration.\n\n\t11. If the current node contains a value of 0 (indicating land), the code continues to the next iteration, as it's not part of the river.\n\n\t12. If the current node contains a value of 1 (indicating a river), it increments the `currentRiverSize` by 1.\n\n\t13. It then retrieves the unvisited neighboring nodes of the current node using the `getUnvisitedNeighbors` function and adds them to the `nodesToExplore` queue.\n\n\t14. Once the loop finishes, if the `currentRiverSize` is greater than 0, it appends it to the `sizes` slice.\n\n\t15. Finally, the `sizes` slice containing the sizes of all rivers is returned.\n\n\t16. The `getUnvisitedNeighbors` function takes the current position (i, j), the matrix, and the `visited` matrix as input.\n\n\t17. It checks the four neighboring cells (up, down, left, right) of the current cell and adds the unvisited neighbors to the `unvisitedNeighbors` slice.\n\n\t18. The function returns the `unvisitedNeighbors` slice.\n\n\tThe code essentially performs a depth-first search (DFS) traversal on the matrix to find connected regions of 1s (rivers) and keeps track of their sizes. The `visited` matrix helps avoid revisiting nodes that have already been processed, ensuring each river is counted only once.\n*/\nfunction riverSizes(matrix) {\n  // Array to store the sizes of rivers\n  const sizes = [];\n\n  // Create a visited matrix to keep track of visited nodes\n  const visited = Array.from({ length: matrix.length }, () =>\n    new Array(matrix[0].length).fill(false)\n  );\n\n  // Iterate over each cell in the matrix\n  for (let i = 0; i < matrix.length; i++) {\n    for (let j = 0; j < matrix[i].length; j++) {\n      // If the cell has already been visited, continue to the next iteration\n      if (visited[i][j]) {\n        continue;\n      }\n\n      // Explore the river connected to the current cell and update sizes\n      sizes.push(traverseNode(i, j, matrix, visited));\n    }\n  }\n\n  return sizes;\n}\n\nfunction traverseNode(i, j, matrix, visited) {\n  // Variable to track the size of the current river\n  let currentRiverSize = 0;\n\n  // Queue to store nodes that need to be visited\n  const nodesToExplore = [[i, j]];\n\n  // Loop until there are no more nodes to explore\n  while (nodesToExplore.length) {\n    // Dequeue the first node from the queue and update the current position (i, j)\n    const [currentI, currentJ] = nodesToExplore.shift();\n\n    // If the current node has already been visited, continue to the next iteration\n    if (visited[currentI][currentJ]) {\n      continue;\n    }\n\n    // Mark the current node as visited\n    visited[currentI][currentJ] = true;\n\n    // If the current node is land (0), continue to the next iteration\n    if (matrix[currentI][currentJ] === 0) {\n      continue;\n    }\n\n    // Increment the size of the current river\n    currentRiverSize++;\n\n    // Get the unvisited neighboring nodes of the current node\n    const unvisitedNeighbors = getUnvisitedNeighbors(\n      currentI,\n      currentJ,\n      matrix,\n      visited\n    );\n\n    // Add the unvisited neighbors to the nodesToExplore queue\n    nodesToExplore.push(...unvisitedNeighbors);\n  }\n\n  return currentRiverSize;\n}\n\nfunction getUnvisitedNeighbors(i, j, matrix, visited) {\n  // Array to store unvisited neighboring nodes\n  const unvisitedNeighbors = [];\n\n  // Check the four neighboring cells (up, down, left, right) of the current cell\n  // and add unvisited neighbors to the unvisitedNeighbors array\n\n  // Up neighbor\n  if (i > 0 && !visited[i - 1][j]) {\n    unvisitedNeighbors.push([i - 1, j]);\n  }\n\n  // Down neighbor\n  if (i < matrix.length - 1 && !visited[i + 1][j]) {\n    unvisitedNeighbors.push([i + 1, j]);\n  }\n\n  // Left neighbor\n  if (j > 0 && !visited[i][j - 1]) {\n    unvisitedNeighbors.push([i, j - 1]);\n  }\n\n  // Right neighbor\n  if (j < matrix[0].length - 1 && !visited[i][j + 1]) {\n    unvisitedNeighbors.push([i, j + 1]);\n  }\n\n  return unvisitedNeighbors;\n}\n\n// Test the riverSizes function\nconst matrix = [\n  [1, 0, 0, 1, 0],\n  [1, 0, 1, 0, 0],\n  [0, 0, 1, 0, 1],\n  [1, 0, 1, 0, 1],\n  [1, 0, 1, 1, 0],\n];\n\nconst sizes = riverSizes(matrix);\n\n// Print the sizes of the rivers\nconsole.log(sizes);\n"
  },
  {
    "path": "Graphs/river_sizes.py",
    "content": "'''\n\n  \tYou're given a two-dimensional array (a matrix) of potentially unequal height and width containing only\n\t0's and 1's. Each 0 represent land and each 1 represent part of river. A river consists of any number of 1's\n\tthat are either horizontally or vertically adjacent (but not diagonally adjacent).\n\tThe number of adjacent 1's forming a river determine its size.\n\n  \tNote that a river can twist. In other words, it doesn't have to be a straight vertical line or a straight\n\thorizontal line; it can be L-shaped, for example.\n\n  \tWrite a function that returns an array of the sizes of all rivers represented in the input matrix.\n\tThe sizes don't need to be in any particular order.\n\n\tSample Input:[\n\t\t\t\t\t[1, 0, 0, 1, 0],\n\t\t\t\t\t[1, 0, 1, 0, 0],\n\t\t\t\t\t[0, 0, 1, 0, 1],\n\t\t\t\t\t[1, 0, 1, 0, 1],\n\t\t\t\t\t[1, 0, 1, 1, 0],\n\t\t\t\t]\n\tOutput: [1, 2, 2, 2, 5]\n\n\tExplanation:\n\n\t1. The function `RiverSizes` initializes an empty slice `sizes` to store the sizes of rivers found in the matrix. It also creates a 2D `visited` matrix of the same size as the input matrix to keep track of visited nodes.\n\n\t2. The function then iterates over each cell in the matrix using nested loops.\n\n\t3. If a cell has already been visited (marked as `true` in the `visited` matrix), the code continues to the next iteration to avoid processing it again.\n\n\t4. If a cell has not been visited, the code calls the `traverseNode` function to explore the river connected to that cell and updates the `sizes` slice with the size of the river.\n\n\t5. The `traverseNode` function takes the starting position (i, j) of a river, the matrix, the `visited` matrix, and the `sizes` slice as input.\n\n\t6. It initializes a variable `currentRiverSize` to 0 to keep track of the size of the river being explored.\n\n\t7. It maintains a queue (`nodesToExplore`) to store the nodes that need to be visited. It starts with the initial node (i, j).\n\n\t8. The function enters a loop that continues until there are no more nodes to explore in the queue.\n\n\t9. In each iteration, it dequeues the first node from the `nodesToExplore` queue and updates the current position (i, j) accordingly.\n\n\t10. If the current node has already been visited, the code continues to the next iteration.\n\n\t11. If the current node contains a value of 0 (indicating land), the code continues to the next iteration, as it's not part of the river.\n\n\t12. If the current node contains a value of 1 (indicating a river), it increments the `currentRiverSize` by 1.\n\n\t13. It then retrieves the unvisited neighboring nodes of the current node using the `getUnvisitedNeighbors` function and adds them to the `nodesToExplore` queue.\n\n\t14. Once the loop finishes, if the `currentRiverSize` is greater than 0, it appends it to the `sizes` slice.\n\n\t15. Finally, the `sizes` slice containing the sizes of all rivers is returned.\n\n\t16. The `getUnvisitedNeighbors` function takes the current position (i, j), the matrix, and the `visited` matrix as input.\n\n\t17. It checks the four neighboring cells (up, down, left, right) of the current cell and adds the unvisited neighbors to the `unvisitedNeighbors` slice.\n\n\t18. The function returns the `unvisitedNeighbors` slice.\n\n\tThe code essentially performs a depth-first search (DFS) traversal on the matrix to find connected regions of 1s (rivers) and keeps track of their sizes. The `visited` matrix helps avoid revisiting nodes that have already been processed, ensuring each river is counted only once.\n\n'''\ndef riverSizes(matrix):\n    # List to store the sizes of rivers\n    sizes = []\n\n    # Create a visited matrix to keep track of visited nodes\n    visited = [[False for _ in range(len(matrix[0]))] for _ in range(len(matrix))]\n\n    # Iterate over each cell in the matrix\n    for i in range(len(matrix)):\n        for j in range(len(matrix[i])):\n            # If the cell has already been visited, continue to the next iteration\n            if visited[i][j]:\n                continue\n\n            # Explore the river connected to the current cell and update sizes\n            sizes = traverseNode(i, j, matrix, visited, sizes)\n\n    return sizes\n\n\ndef traverseNode(i, j, matrix, visited, sizes):\n    # Variable to track the size of the current river\n    currentRiverSize = 0\n\n    # Queue to store nodes that need to be visited\n    nodesToExplore = [[i, j]]\n\n    # Loop until there are no more nodes to explore\n    while nodesToExplore:\n        # Dequeue the first node from the queue and update the current position (i, j)\n        currentNode = nodesToExplore.pop(0)\n        i, j = currentNode[0], currentNode[1]\n\n        # If the current node has already been visited, continue to the next iteration\n        if visited[i][j]:\n            continue\n\n        # Mark the current node as visited\n        visited[i][j] = True\n\n        # If the current node is land (0), continue to the next iteration\n        if matrix[i][j] == 0:\n            continue\n\n        # Increment the size of the current river\n        currentRiverSize += 1\n\n        # Get the unvisited neighboring nodes of the current node\n        unvisitedNeighbors = getUnvisitedNeighbors(i, j, matrix, visited)\n\n        # Add the unvisited neighbors to the nodesToExplore queue\n        nodesToExplore.extend(unvisitedNeighbors)\n\n    # If the current river size is greater than 0, append it to the sizes list\n    if currentRiverSize > 0:\n        sizes.append(currentRiverSize)\n\n    return sizes\n\n\ndef getUnvisitedNeighbors(i, j, matrix, visited):\n    # List to store unvisited neighboring nodes\n    unvisitedNeighbors = []\n\n    # Check the four neighboring cells (up, down, left, right) of the current cell\n    # and add unvisited neighbors to the unvisitedNeighbors list\n\n    # Up neighbor\n    if i > 0 and not visited[i - 1][j]:\n        unvisitedNeighbors.append([i - 1, j])\n\n    # Down neighbor\n    if i < len(matrix) - 1 and not visited[i + 1][j]:\n        unvisitedNeighbors.append([i + 1, j])\n\n    # Left neighbor\n    if j > 0 and not visited[i][j - 1]:\n        unvisitedNeighbors.append([i, j - 1])\n\n    # Right neighbor\n    if j < len(matrix[0]) - 1 and not visited[i][j + 1]:\n        unvisitedNeighbors.append([i, j + 1])\n\n    return unvisitedNeighbors\n"
  },
  {
    "path": "Graphs/single_cycle_check.cpp",
    "content": "/*\n  \tYou're given an array of integers where each integer represents a jump of its value in the array. For instance, the integer\n\t2  represents a jump of two indices forward in the array; the integer -3  represents a jump of three indices backward in the array.\n\tIf a jump spills past the array's bounds, it wraps over to the other side. For instance, a jump of -1  at index 0 brings us to the\n\tlast index in the array. Similarly, a jump of 1  at the last index in the array brings us to index  0\n\n  \tWrite a function that returns a boolean representing whether the jumps in the array form a single\n\tcycle. A single cycle occurs if, starting at any index in the array and following the jumps, every\n\telement in the array is visited exactly once before landing back on the starting index.\n\n\tSample Input: [2, 3, 1, -4, -4, 2]\n\tOutput:  True\n\n\tExplanation:\n\n\tThe HasSingleCycle function takes an integer array as input and returns a boolean value indicating whether the array\n\thas a single cycle. It initializes two variables: nextElementVisited to keep track of the number of elements visited, and\n\tcurrIdx to track the current index in the array.\n\n\tThe function enters a loop that continues until all elements in the array are visited. It checks if nextElementVisited is\n\tgreater than 0 (indicating that at least one element has been visited) and currIdx is 0. If this condition is true, it means\n\tthe loop has returned to the starting index prematurely, indicating multiple cycles. In such a case, the function returns\n\tfalse.\n\n\tInside the loop, nextElementVisited is incremented by 1, and the currIdx is updated using the getNextIdx function, which we\n\twill examine next.\n\n\tThe getNextIdx function takes an integer array and the current index as input and returns the index of the next element in\n\tthe cycle.\n\n\tIt first retrieves the jump value from the current index in the array. The jump value represents the number of steps to take\n\tfrom the current element.\n\n\tThe nextIdx is calculated by adding the jump value to the current index and taking the modulo % operator with the length of\n\tthe array. This ensures that the index stays within the valid range of the array.\n\n\tFinally, there is a check to ensure that nextIdx is non-negative. If it is negative, it means the index has wrapped around to\n\tthe beginning of the array. In such a case, the function adds the length of the array to nextIdx to correctly calculate the next index.\n\n\tOnce the loop in the HasSingleCycle function completes, the final check is made to ensure that the currIdx is back at the\n\tstarting index (0). If it is, it means all elements have been visited in a single cycle, and the function returns true.\n\tOtherwise, it returns false.\n\n\tOverall, this code snippet implements the logic to determine whether an array has a single cycle by tracking the indices\n\tand jumps between elements.\n\n\tTime Complexity : O(n) where n is the length of the input array\n\tSpace Complexity : O(1)\n*/\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\n// Function to check if the given array has a single cycle\nbool hasSingleCycle(vector<int>& array) {\n    int nextElementVisited = 0;\n    int currIdx = 0;\n\n    while (nextElementVisited < array.size()) {\n        // Check if more than one element has been visited and current index is back to the starting index (0)\n        if (nextElementVisited > 0 && currIdx == 0) {\n            return false; // Multiple cycles detected, return false\n        }\n\n        nextElementVisited++; // Increment the count of visited elements\n        currIdx = getNextIdx(array, currIdx); // Get the index of the next element\n    }\n\n    return currIdx == 0; // Return true if all elements have been visited in a single cycle\n}\n\n// Function to get the index of the next element in the cycle\nint getNextIdx(vector<int>& array, int currIdx) {\n    int jump = array[currIdx]; // Get the jump value from the current index\n    int nextIdx = (currIdx + jump) % array.size(); // Calculate the index of the next element\n\n    if (nextIdx >= 0) {\n        return nextIdx; // Return the next index if it is non-negative\n    }\n\n    return nextIdx + array.size(); // Adjust the next index if it is negative (wrapped around to the beginning)\n}\n\nint main() {\n    // Test cases\n    vector<int> array1 = {2, 3, 1, -4, -4, 2};\n    cout << \"Array 1: \" << (hasSingleCycle(array1) ? \"true\" : \"false\") << endl;\n\n    vector<int> array2 = {2, 2, -1};\n    cout << \"Array 2: \" << (hasSingleCycle(array2) ? \"true\" : \"false\") << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Graphs/single_cycle_check.go",
    "content": "/*\n  \tYou're given an array of integers where each integer represents a jump of its value in the array. For instance, the integer\n\t2  represents a jump of two indices forward in the array; the integer -3  represents a jump of three indices backward in the array.\n\tIf a jump spills past the array's bounds, it wraps over to the other side. For instance, a jump of -1  at index 0 brings us to the\n\tlast index in the array. Similarly, a jump of 1  at the last index in the array brings us to index  0\n\n  \tWrite a function that returns a boolean representing whether the jumps in the array form a single\n\tcycle. A single cycle occurs if, starting at any index in the array and following the jumps, every\n\telement in the array is visited exactly once before landing back on the starting index.\n\n\tSample Input: [2, 3, 1, -4, -4, 2]\n\tOutput:  True\n\n\tExplanation:\n\n\tThe HasSingleCycle function takes an integer array as input and returns a boolean value indicating whether the array\n\thas a single cycle. It initializes two variables: nextElementVisited to keep track of the number of elements visited, and\n\tcurrIdx to track the current index in the array.\n\n\tThe function enters a loop that continues until all elements in the array are visited. It checks if nextElementVisited is\n\tgreater than 0 (indicating that at least one element has been visited) and currIdx is 0. If this condition is true, it means\n\tthe loop has returned to the starting index prematurely, indicating multiple cycles. In such a case, the function returns\n\tfalse.\n\n\tInside the loop, nextElementVisited is incremented by 1, and the currIdx is updated using the getNextIdx function, which we\n\twill examine next.\n\n\tThe getNextIdx function takes an integer array and the current index as input and returns the index of the next element in\n\tthe cycle.\n\n\tIt first retrieves the jump value from the current index in the array. The jump value represents the number of steps to take\n\tfrom the current element.\n\n\tThe nextIdx is calculated by adding the jump value to the current index and taking the modulo % operator with the length of\n\tthe array. This ensures that the index stays within the valid range of the array.\n\n\tFinally, there is a check to ensure that nextIdx is non-negative. If it is negative, it means the index has wrapped around to\n\tthe beginning of the array. In such a case, the function adds the length of the array to nextIdx to correctly calculate the next index.\n\n\tOnce the loop in the HasSingleCycle function completes, the final check is made to ensure that the currIdx is back at the\n\tstarting index (0). If it is, it means all elements have been visited in a single cycle, and the function returns true.\n\tOtherwise, it returns false.\n\n\tOverall, this code snippet implements the logic to determine whether an array has a single cycle by tracking the indices\n\tand jumps between elements.\n\n\tTime Complexity : O(n) where n is the length of the input array\n\tSpace Complexity : O(1)\n*/\npackage main\n\nimport \"fmt\"\n\n\nfunc HasSingleCycle(array []int) bool {\n\tnextElementVisited := 0\n\tcurrIdx := 0\n\n\tfor nextElementVisited < len(array) {\n\t\t// Check if more than one element has been visited and current index is back to the starting index (0)\n\t\tif nextElementVisited > 0 && currIdx == 0 {\n\t\t\treturn false // Multiple cycles detected, return false\n\t\t}\n\n\t\tnextElementVisited += 1 // Increment the count of visited elements\n\t\tcurrIdx = getNextIdx(array, currIdx) // Get the index of the next element\n\t}\n\n\treturn currIdx == 0 // Return true if all elements have been visited in a single cycle\n}\n\nfunc getNextIdx(array []int, currIdx int) int {\n\tjump := array[currIdx]                   // Get the jump value from the current index\n\tnextIdx := (currIdx + jump) % len(array) // Calculate the index of the next element\n\n\tif nextIdx >= 0 {\n\t\treturn nextIdx // Return the next index if it is non-negative\n\t}\n\n\treturn nextIdx + len(array) // Adjust the next index if it is negative (wrapped around to the beginning)\n}\n\n\nfunc main() {\n\t// Test cases\n\tarray1 := []int{2, 3, 1, -4, -4, 2} // has a single cycle\n\tfmt.Println(\"Array 1:\", HasSingleCycle(array1)) // Output: true\n\n\tarray2 := []int{2, 2, -1} // does  have a single cycle\n\tfmt.Println(\"Array 2:\", HasSingleCycle(array2)) // Output: true\n}"
  },
  {
    "path": "Graphs/single_cycle_check.java",
    "content": "/*\n  \tYou're given an array of integers where each integer represents a jump of its value in the array. For instance, the integer\n\t2  represents a jump of two indices forward in the array; the integer -3  represents a jump of three indices backward in the array.\n\tIf a jump spills past the array's bounds, it wraps over to the other side. For instance, a jump of -1  at index 0 brings us to the\n\tlast index in the array. Similarly, a jump of 1  at the last index in the array brings us to index  0\n\n  \tWrite a function that returns a boolean representing whether the jumps in the array form a single\n\tcycle. A single cycle occurs if, starting at any index in the array and following the jumps, every\n\telement in the array is visited exactly once before landing back on the starting index.\n\n\tSample Input: [2, 3, 1, -4, -4, 2]\n\tOutput:  True\n\n\tExplanation:\n\n\tThe HasSingleCycle function takes an integer array as input and returns a boolean value indicating whether the array\n\thas a single cycle. It initializes two variables: nextElementVisited to keep track of the number of elements visited, and\n\tcurrIdx to track the current index in the array.\n\n\tThe function enters a loop that continues until all elements in the array are visited. It checks if nextElementVisited is\n\tgreater than 0 (indicating that at least one element has been visited) and currIdx is 0. If this condition is true, it means\n\tthe loop has returned to the starting index prematurely, indicating multiple cycles. In such a case, the function returns\n\tfalse.\n\n\tInside the loop, nextElementVisited is incremented by 1, and the currIdx is updated using the getNextIdx function, which we\n\twill examine next.\n\n\tThe getNextIdx function takes an integer array and the current index as input and returns the index of the next element in\n\tthe cycle.\n\n\tIt first retrieves the jump value from the current index in the array. The jump value represents the number of steps to take\n\tfrom the current element.\n\n\tThe nextIdx is calculated by adding the jump value to the current index and taking the modulo % operator with the length of\n\tthe array. This ensures that the index stays within the valid range of the array.\n\n\tFinally, there is a check to ensure that nextIdx is non-negative. If it is negative, it means the index has wrapped around to\n\tthe beginning of the array. In such a case, the function adds the length of the array to nextIdx to correctly calculate the next index.\n\n\tOnce the loop in the HasSingleCycle function completes, the final check is made to ensure that the currIdx is back at the\n\tstarting index (0). If it is, it means all elements have been visited in a single cycle, and the function returns true.\n\tOtherwise, it returns false.\n\n\tOverall, this code snippet implements the logic to determine whether an array has a single cycle by tracking the indices\n\tand jumps between elements.\n\n\tTime Complexity : O(n) where n is the length of the input array\n\tSpace Complexity : O(1)\n*/\nimport java.util.*;\n\npublic class Main {\n    // Function to check if the given array has a single cycle\n    public static boolean hasSingleCycle(int[] array) {\n        int nextElementVisited = 0;\n        int currIdx = 0;\n\n        while (nextElementVisited < array.length) {\n            // Check if more than one element has been visited and current index is back to the starting index (0)\n            if (nextElementVisited > 0 && currIdx == 0) {\n                return false; // Multiple cycles detected, return false\n            }\n\n            nextElementVisited++; // Increment the count of visited elements\n            currIdx = getNextIdx(array, currIdx); // Get the index of the next element\n        }\n\n        return currIdx == 0; // Return true if all elements have been visited in a single cycle\n    }\n\n    // Function to get the index of the next element in the cycle\n    public static int getNextIdx(int[] array, int currIdx) {\n        int jump = array[currIdx]; // Get the jump value from the current index\n        int nextIdx = (currIdx + jump) % array.length; // Calculate the index of the next element\n\n        if (nextIdx >= 0) {\n            return nextIdx; // Return the next index if it is non-negative\n        }\n\n        return nextIdx + array.length; // Adjust the next index if it is negative (wrapped around to the beginning)\n    }\n\n    public static void main(String[] args) {\n        // Test cases\n        int[] array1 = {2, 3, 1, -4, -4, 2};\n        System.out.println(\"Array 1: \" + (hasSingleCycle(array1) ? \"true\" : \"false\"));\n\n        int[] array2 = {2, 2, -1};\n        System.out.println(\"Array 2: \" + (hasSingleCycle(array2) ? \"true\" : \"false\"));\n    }\n}\n"
  },
  {
    "path": "Graphs/single_cycle_check.js",
    "content": "/*\n  \tYou're given an array of integers where each integer represents a jump of its value in the array. For instance, the integer\n\t2  represents a jump of two indices forward in the array; the integer -3  represents a jump of three indices backward in the array.\n\tIf a jump spills past the array's bounds, it wraps over to the other side. For instance, a jump of -1  at index 0 brings us to the\n\tlast index in the array. Similarly, a jump of 1  at the last index in the array brings us to index  0\n\n  \tWrite a function that returns a boolean representing whether the jumps in the array form a single\n\tcycle. A single cycle occurs if, starting at any index in the array and following the jumps, every\n\telement in the array is visited exactly once before landing back on the starting index.\n\n\tSample Input: [2, 3, 1, -4, -4, 2]\n\tOutput:  True\n\n\tExplanation:\n\n\tThe HasSingleCycle function takes an integer array as input and returns a boolean value indicating whether the array\n\thas a single cycle. It initializes two variables: nextElementVisited to keep track of the number of elements visited, and\n\tcurrIdx to track the current index in the array.\n\n\tThe function enters a loop that continues until all elements in the array are visited. It checks if nextElementVisited is\n\tgreater than 0 (indicating that at least one element has been visited) and currIdx is 0. If this condition is true, it means\n\tthe loop has returned to the starting index prematurely, indicating multiple cycles. In such a case, the function returns\n\tfalse.\n\n\tInside the loop, nextElementVisited is incremented by 1, and the currIdx is updated using the getNextIdx function, which we\n\twill examine next.\n\n\tThe getNextIdx function takes an integer array and the current index as input and returns the index of the next element in\n\tthe cycle.\n\n\tIt first retrieves the jump value from the current index in the array. The jump value represents the number of steps to take\n\tfrom the current element.\n\n\tThe nextIdx is calculated by adding the jump value to the current index and taking the modulo % operator with the length of\n\tthe array. This ensures that the index stays within the valid range of the array.\n\n\tFinally, there is a check to ensure that nextIdx is non-negative. If it is negative, it means the index has wrapped around to\n\tthe beginning of the array. In such a case, the function adds the length of the array to nextIdx to correctly calculate the next index.\n\n\tOnce the loop in the HasSingleCycle function completes, the final check is made to ensure that the currIdx is back at the\n\tstarting index (0). If it is, it means all elements have been visited in a single cycle, and the function returns true.\n\tOtherwise, it returns false.\n\n\tOverall, this code snippet implements the logic to determine whether an array has a single cycle by tracking the indices\n\tand jumps between elements.\n\n\tTime Complexity : O(n) where n is the length of the input array\n\tSpace Complexity : O(1)\n*/\nfunction hasSingleCycle(array) {\n  let nextElementVisited = 0;\n  let currIdx = 0;\n\n  while (nextElementVisited < array.length) {\n    // Check if more than one element has been visited and current index is back to the starting index (0)\n    if (nextElementVisited > 0 && currIdx === 0) {\n      return false; // Multiple cycles detected, return false\n    }\n\n    nextElementVisited += 1; // Increment the count of visited elements\n    currIdx = getNextIdx(array, currIdx); // Get the index of the next element\n  }\n\n  return currIdx === 0; // Return true if all elements have been visited in a single cycle\n}\n\nfunction getNextIdx(array, currIdx) {\n  const jump = array[currIdx]; // Get the jump value from the current index\n  const nextIdx = (currIdx + jump) % array.length; // Calculate the index of the next element\n\n  if (nextIdx >= 0) {\n    return nextIdx; // Return the next index if it is non-negative\n  }\n\n  return nextIdx + array.length; // Adjust the next index if it is negative (wrapped around to the beginning)\n}\n\n// Test cases\nconst array1 = [2, 3, 1, -4, -4, 2];\nconsole.log(\"Array 1:\", hasSingleCycle(array1));\n\nconst array2 = [2, 2, -1];\nconsole.log(\"Array 2:\", hasSingleCycle(array2));\n"
  },
  {
    "path": "Graphs/single_cycle_check.py",
    "content": "'''\n  \tYou're given an array of integers where each integer represents a jump of its value in the array. For instance, the integer\n\t2  represents a jump of two indices forward in the array; the integer -3  represents a jump of three indices backward in the array.\n\tIf a jump spills past the array's bounds, it wraps over to the other side. For instance, a jump of -1  at index 0 brings us to the\n\tlast index in the array. Similarly, a jump of 1  at the last index in the array brings us to index  0\n\n  \tWrite a function that returns a boolean representing whether the jumps in the array form a single\n\tcycle. A single cycle occurs if, starting at any index in the array and following the jumps, every\n\telement in the array is visited exactly once before landing back on the starting index.\n\n\tSample Input: [2, 3, 1, -4, -4, 2]\n\tOutput:  True\n\n\tExplanation:\n\n\tThe HasSingleCycle function takes an integer array as input and returns a boolean value indicating whether the array\n\thas a single cycle. It initializes two variables: nextElementVisited to keep track of the number of elements visited, and\n\tcurrIdx to track the current index in the array.\n\n\tThe function enters a loop that continues until all elements in the array are visited. It checks if nextElementVisited is\n\tgreater than 0 (indicating that at least one element has been visited) and currIdx is 0. If this condition is true, it means\n\tthe loop has returned to the starting index prematurely, indicating multiple cycles. In such a case, the function returns\n\tfalse.\n\n\tInside the loop, nextElementVisited is incremented by 1, and the currIdx is updated using the getNextIdx function, which we\n\twill examine next.\n\n\tThe getNextIdx function takes an integer array and the current index as input and returns the index of the next element in\n\tthe cycle.\n\n\tIt first retrieves the jump value from the current index in the array. The jump value represents the number of steps to take\n\tfrom the current element.\n\n\tThe nextIdx is calculated by adding the jump value to the current index and taking the modulo % operator with the length of\n\tthe array. This ensures that the index stays within the valid range of the array.\n\n\tFinally, there is a check to ensure that nextIdx is non-negative. If it is negative, it means the index has wrapped around to\n\tthe beginning of the array. In such a case, the function adds the length of the array to nextIdx to correctly calculate the next index.\n\n\tOnce the loop in the HasSingleCycle function completes, the final check is made to ensure that the currIdx is back at the\n\tstarting index (0). If it is, it means all elements have been visited in a single cycle, and the function returns true.\n\tOtherwise, it returns false.\n\n\tOverall, this code snippet implements the logic to determine whether an array has a single cycle by tracking the indices\n\tand jumps between elements.\n\n\tTime Complexity : O(n) where n is the length of the input array\n\tSpace Complexity : O(1)\n'''\n\ndef has_single_cycle(array):\n    next_element_visited = 0\n    curr_idx = 0\n\n    while next_element_visited < len(array):\n        # Check if more than one element has been visited and current index is back to the starting index (0)\n        if next_element_visited > 0 and curr_idx == 0:\n            return False  # Multiple cycles detected, return False\n\n        next_element_visited += 1  # Increment the count of visited elements\n        curr_idx = get_next_idx(array, curr_idx)  # Get the index of the next element\n\n    return curr_idx == 0  # Return True if all elements have been visited in a single cycle\n\n\ndef get_next_idx(array, curr_idx):\n    jump = array[curr_idx]  # Get the jump value from the current index\n    next_idx = (curr_idx + jump) % len(array)  # Calculate the index of the next element\n\n    if next_idx >= 0:\n        return next_idx  # Return the next index if it is non-negative\n\n    return next_idx + len(array)  # Adjust the next index if it is negative (wrapped around to the beginning)\n\n\n# Test cases\narray1 = [2, 3, 1, -4, -4, 2]\nprint(\"Array 1:\", has_single_cycle(array1))\n\narray2 = [2, 2, -1]\nprint(\"Array 2:\", has_single_cycle(array2))\n"
  },
  {
    "path": "Graphs/snack_ladders.cpp",
    "content": "/*\nYou are given an n x n integer matrix board where the cells are labeled from 1 to n2 in a Boustrophedon style starting from the bottom left of the board (i.e. board[n - 1][0]) and alternating direction each row.\n\nYou start on square 1 of the board. In each move, starting from square curr, do the following:\n\nChoose a destination square next with a label in the range [curr + 1, min(curr + 6, n2)].\nThis choice simulates the result of a standard 6-sided die roll: i.e., there are always at most 6 destinations, regardless of the size of the board.\nIf next has a snake or ladder, you must move to the destination of that snake or ladder. Otherwise, you move to next.\nThe game ends when you reach the square n2.\nA board square on row r and column c has a snake or ladder if board[r][c] != -1. The destination of that snake or ladder is board[r][c]. Squares 1 and n2 do not have a snake or ladder.\n\nNote that you only take a snake or ladder at most once per move. If the destination to a snake or ladder is the start of another snake or ladder, you do not follow the subsequent snake or ladder.\n\nFor example, suppose the board is [[-1,4],[-1,3]], and on the first move, your destination square is 2. You follow the ladder to square 3, but do not follow the subsequent ladder to 4.\nReturn the least number of moves required to reach the square n2. If it is not possible to reach the square, return -1.\n\n \n\nExample 1:\n\n\nInput: board = [[-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1],[-1,35,-1,-1,13,-1],[-1,-1,-1,-1,-1,-1],[-1,15,-1,-1,-1,-1]]\nOutput: 4\nExplanation: \nIn the beginning, you start at square 1 (at row 5, column 0).\nYou decide to move to square 2 and must take the ladder to square 15.\nYou then decide to move to square 17 and must take the snake to square 13.\nYou then decide to move to square 14 and must take the ladder to square 35.\nYou then decide to move to square 36, ending the game.\nThis is the lowest possible number of moves to reach the last square, so return 4.\nExample 2:\n\nInput: board = [[-1,-1],[-1,3]]\nOutput: 1\n \n\nConstraints:\n\nn == board.length == board[i].length\n2 <= n <= 20\nboard[i][j] is either -1 or in the range [1, n2].\nThe squares labeled 1 and n2 do not have any ladders or snakes.\n*/\n\n#include<bits/stdc++.h>\nusing namespace std;\n\ntemplate<typename T>\nclass Graph{\n    map<T, list<T> > adjList;\n    public:\n        Graph(){\n\n        }\n        void addEdge(T u, T v, bool bidir = true){\n            adjList[u].push_back(v);\n            if(bidir){\n                adjList[v].push_back(u);\n            }\n        }\n        void printAdjList(){\n            for(auto obj : adjList){\n                cout << obj.first <<  \"->\";\n                for(auto element : obj.second){\n                    cout << element << \",\";\n                }\n                cout << endl;\n            }\n        }\n        int bfs_sssp(int n, int m){\n            queue<int> q;\n            map<int, int> dist;\n            map<int, int> parent;\n            for(auto i : adjList){\n                dist[i.first] = INT_MAX;\n            }\n            q.push(n);\n            dist[n] = 0;\n            parent[n] = n;\n            while(!q.empty()){\n                int node_element = q.front();\n                q.pop();\n                for(int neighbour : adjList[node_element]){\n                    if(dist[neighbour] == INT_MAX){\n                        q.push(neighbour);\n                        dist[neighbour] = dist[node_element] + 1;\n                        parent[neighbour] = node_element;\n                    }\n                }\n            }\n            cout << endl;\n            int temp = m;\n            while(temp != n){\n                cout << temp << \"-->\";\n                temp = parent[temp];\n            }\n            cout << n << endl;\n            /*\n            for(auto i : adjList){\n                int node = i.first;\n                cout << \"Distance of \" << node << \" is \" << dist[node] << endl;\n            }\n            */\n            return dist[m];\n\n        }\n};\nint main(){\n    Graph<int> g;\n    int board[50] = {0};\n    board[2] = 13;\n    board[5] = 2;\n    board[9] = 18;\n    board[18] = 11;\n    board[17] = -13;\n    board[20] = -14;\n    board[24] = -8;\n    board[25] = -10;\n    board[32] = -2;\n    board[34] = -22;\n    for(int u = 0; u <= 36; u++){\n        for(int dice  = 1; dice <= 6; dice++){\n            int v = u + dice + board[u + dice];\n            g.addEdge(u, v, false);\n        }\n    }\n    cout <<  \"The shortest distance is \" << g.bfs_sssp(1, 36) << endl;\n    return 0;\n}"
  },
  {
    "path": "Graphs/snack_ladders.js",
    "content": "// Define the number of squares on the board\n\nconst BOARD_SIZE = 100;\n\n// Define the start and end points of the snakes and ladders\n\nconst snakesAndLadders = {\n\n  14: 4, 19: 8, 22: 20, 41: 38, 50: 39, 54: 34, 66: 53, 68: 63, 79: 67, 83: 72,\n\n  92: 88, 97: 76, 8: 15, 13: 23, 37: 43, 40: 48, 57: 63, 61: 69, 65: 72, 75: 83,\n\n  78: 87, 80: 92, 88: 94\n\n};\n\n// Define a function to build the game graph\n\nfunction buildGraph() {\n\n  const graph = {};\n\n  for (let i = 1; i <= BOARD_SIZE; i++) {\n\n    graph[i] = [];\n\n    for (let j = i + 1; j <= i + 6 && j <= BOARD_SIZE; j++) {\n\n      if (snakesAndLadders[j]) {\n\n        graph[i].push(snakesAndLadders[j]);\n\n      } else {\n\n        graph[i].push(j);\n\n      }\n\n    }\n\n  }\n\n  return graph;\n\n}\n\n// Define the main function of the game\n\nfunction playGame() {\n\n  // Build the game graph\n\n  const graph = buildGraph();\n\n  // Define the starting node and the goal node\n\n  const startNode = 1;\n\n  const goalNode = BOARD_SIZE;\n\n  // Define a queue for BFS\n\n  const queue = [startNode];\n\n  // Define a visited set for BFS\n\n  const visited = new Set();\n\n  visited.add(startNode);\n\n  // Define a map for BFS to keep track of the parent node\n\n  const parentMap = new Map();\n\n  parentMap.set(startNode, null);\n\n  // Loop until the goal node is found or the queue is empty\n\n  while (queue.length > 0) {\n\n    // Dequeue the next node from the queue\n\n    const currentNode = queue.shift();\n\n    // If the goal node is found, reconstruct the path and return it\n\n    if (currentNode === goalNode) {\n\n      const path = [];\n\n      let node = currentNode;\n\n      while (node !== null) {\n\n        path.unshift(node);\n\n        node = parentMap.get(node);\n\n      }\n\n      return path;\n\n    }\n\n    // Loop through the neighbors of the current node\n\n    for (const neighbor of graph[currentNode]) {\n\n      // If the neighbor has not been visited, add it to the queue\n\n      if (!visited.has(neighbor)) {\n\n        queue.push(neighbor);\n\n        visited.add(neighbor);\n\n        parentMap.set(neighbor, currentNode);\n\n      }\n\n    }\n\n  }\n\n  // If the goal node is not found, return null\n\n  return null;\n\n}\n\n// Play the game and print the result\n\nconsole.log(playGame());\n"
  },
  {
    "path": "Graphs/snack_ladders.py",
    "content": "'''\n    You are given an n x n integer matrix board where the cells are labeled from 1 to n2 in a Boustrophedon style starting from the bottom left of the board (i.e. board[n - 1][0]) and alternating direction each row.\n\n    You start on square 1 of the board. In each move, starting from square curr, do the following:\n\n    Choose a destination square next with a label in the range [curr + 1, min(curr + 6, n2)].\n    This choice simulates the result of a standard 6-sided die roll: i.e., there are always at most 6 destinations, regardless of the size of the board.\n    If next has a snake or ladder, you must move to the destination of that snake or ladder. Otherwise, you move to next.\n    The game ends when you reach the square n2.\n    A board square on row r and column c has a snake or ladder if board[r][c] != -1. The destination of that snake or ladder is board[r][c]. Squares 1 and n2 do not have a snake or ladder.\n\n    Note that you only take a snake or ladder at most once per move. If the destination to a snake or ladder is the start of another snake or ladder, you do not follow the subsequent snake or ladder.\n\n    For example, suppose the board is [[-1,4],[-1,3]], and on the first move, your destination square is 2. You follow the ladder to square 3, but do not follow the subsequent ladder to 4.\n    Return the least number of moves required to reach the square n2. If it is not possible to reach the square, return -1.\n\n    Example 1:\n    Input: board = [[-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1,-1],[-1,35,-1,-1,13,-1],[-1,-1,-1,-1,-1,-1],[-1,15,-1,-1,-1,-1]]\n    Output: 4\n    \n    Explanation: \n    In the beginning, you start at square 1 (at row 5, column 0).\n    You decide to move to square 2 and must take the ladder to square 15.\n    You then decide to move to square 17 and must take the snake to square 13.\n    You then decide to move to square 14 and must take the ladder to square 35.\n    You then decide to move to square 36, ending the game.\n    This is the lowest possible number of moves to reach the last square, so return 4.\n    \n    Example 2:\n    Input: board = [[-1,-1],[-1,3]]\n    Output: 1\n\n    Constraints:\n    n == board.length == board[i].length\n    2 <= n <= 20\n    board[i][j] is either -1 or in the range [1, n2].\n    The squares labeled 1 and n2 do not have any ladders or snakes.\n'''\nfrom collections import deque\n\ndef snakesAndLadders(board):\n    n = len(board)\n    target = n*n\n    moves = {1: 0}\n    queue = deque([1])\n\n    while queue:\n        curr = queue.popleft()\n        if curr == target:\n            return moves[curr]\n        for i in range(1, 7):\n            next = curr + i\n            if next > target:\n                break\n            row, col = getRowCol(next, n)\n            if board[row][col] != -1:\n                next = board[row][col]\n            if next not in moves:\n                moves[next] = moves[curr] + 1\n                queue.append(next)\n    \n    return -1\n\ndef getRowCol(idx, n):\n    row = (idx - 1) // n\n    col = (idx - 1) % n\n    if row % 2 == 1:\n        col = n - col - 1\n    row = n - row - 1\n    return row, col\n"
  },
  {
    "path": "Graphs/snakes_ladders.java",
    "content": "/*You are given an n x n integer matrix board where the cells are labeled from 1 to n2 in a Boustrophedon style starting from the bottom left of the board (i.e. board[n - 1][0]) and alternating direction each row.\n\nYou start on square 1 of the board. In each move, starting from square curr, do the following:\n\nChoose a destination square next with a label in the range [curr + 1, min(curr + 6, n2)].\nThis choice simulates the result of a standard 6-sided die roll: i.e., there are always at most 6 destinations, regardless of the size of the board.\nIf next has a snake or ladder, you must move to the destination of that snake or ladder. Otherwise, you move to next.\nThe game ends when you reach the square n2.\nA board square on row r and column c has a snake or ladder if board[r][c] != -1. The destination of that snake or ladder is board[r][c]. Squares 1 and n2 do not have a snake or ladder.\n\nNote that you only take a snake or ladder at most once per move. If the destination to a snake or ladder is the start of another snake or ladder, you do not follow the subsequent snake or ladder.\n\nFor example, suppose the board is [[-1,4],[-1,3]], and on the first move, your destination square is 2. You follow the ladder to square 3, but do not follow the subsequent ladder to 4.\nReturn the least number of moves required to reach the square n2. If it is not possible to reach the square, return -1.\n\nExplanation:\n\nWe start by importing the necessary classes and defining the class SnakesAndLadders.\nWe declare the constant BOARD_SIZE to represent the number of cells on the board.\nWe declare two maps: snakes to store the snake positions, and ladders to store the ladder positions.\nThe SnakesAndLadders class has a constructor that initializes the snakes and ladders maps.\nThe addSnake method is used to add a snake to the game by providing the start and end positions.\nThe addLadder method is used to add a ladder to the game by providing the start and end positions.\nThe playGame method simulates the game. It starts with the player's position at 0 and the number of dice rolls at 0.\nInside the while loop, a dice is rolled using the rollDice method, and the player's position is updated.\nAfter each move, we check if the player has landed on a ladder or a snake. If so, we update the player's position accordingly.\nThe rollDice method generates a random number between 1 and 6, simulating a dice roll.\nIn the main method, we create an instance of SnakesAndLadders and add snakes and ladders to the game.\nFinally, we call the playGame method to start the game and print the number of dice rolls required to reach or exceed the BOARD_SIZE.\nBelow is an implementation of the Snakes and Ladders game in Java, along with comments:*/\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class SnakesAndLadders {\n    private static final int BOARD_SIZE = 100;  // Number of cells in the board\n    private Map<Integer, Integer> snakes;        // Map to store snake positions\n    private Map<Integer, Integer> ladders;       // Map to store ladder positions\n\n    public SnakesAndLadders() {\n        // Initialize the snake and ladder positions\n        snakes = new HashMap<>();\n        ladders = new HashMap<>();\n    }\n\n    public void addSnake(int start, int end) {\n        snakes.put(start, end);\n    }\n\n    public void addLadder(int start, int end) {\n        ladders.put(start, end);\n    }\n\n    public int playGame() {\n        int currentPlayerPosition = 0;  // Player's current position\n        int diceRolls = 0;              // Number of dice rolls\n\n        while (currentPlayerPosition < BOARD_SIZE) {\n            // Roll a dice\n            int dice = rollDice();\n\n            // Move the player\n            currentPlayerPosition += dice;\n\n            // Check if the player has landed on a ladder\n            if (ladders.containsKey(currentPlayerPosition)) {\n                // Climb the ladder\n                currentPlayerPosition = ladders.get(currentPlayerPosition);\n            }\n\n            // Check if the player has landed on a snake\n            if (snakes.containsKey(currentPlayerPosition)) {\n                // Go down the snake\n                currentPlayerPosition = snakes.get(currentPlayerPosition);\n            }\n\n            diceRolls++;  // Increment the number of dice rolls\n        }\n\n        return diceRolls;\n    }\n\n    private int rollDice() {\n        // Generates a random number between 1 and 6 (inclusive)\n        return (int) (Math.random() * 6) + 1;\n    }\n\n    public static void main(String[] args) {\n        SnakesAndLadders game = new SnakesAndLadders();\n\n        // Add snakes to the game\n        game.addSnake(16, 6);\n        game.addSnake(47, 26);\n        game.addSnake(49, 11);\n        game.addSnake(56, 53);\n        game.addSnake(62, 19);\n        game.addSnake(64, 60);\n        game.addSnake(87, 24);\n        game.addSnake(93, 73);\n        game.addSnake(95, 75);\n        game.addSnake(98, 78);\n\n        // Add ladders to the game\n        game.addLadder(1, 38);\n        game.addLadder(4, 14);\n        game.addLadder(9, 31);\n        game.addLadder(21, 42);\n        game.addLadder(28, 84);\n        game.addLadder(36, 44);\n        game.addLadder(51, 67);\n        game.addLadder(71, 91);\n        game.addLadder(80, 100);\n\n        // Play the game\n        int diceRolls = game.playGame();\n        System.out.println(\"Number of dice rolls: \" + diceRolls);\n    }\n}\n\nTime Complexity:  the average generalized time complexity of the code can be expressed as O(N), where N represents the average number of dice rolls required to\n                  complete the game over a large number of instances.\nSpace Complexity: The average generalized space complexity of the code can be expressed as O(M), where M represents the average number of snakes and ladders add-\n                  -ed to the game.\n"
  },
  {
    "path": "Graphs/topological_sort.cpp",
    "content": "/*\n\tYou're given a list of arbitrary jobs that need to be completed; these jobs\n\tare represented by distinct integers. You're also given a list of dependencies. A\n\tdependency is represented as a pair of jobs where the first job is a\n\tprerequisite of the second one. In other words, the second job depends on the\n\tfirst one; it can only be completed once the first job is completed.\n\n\tWrite a function that takes in a list of jobs and a list of dependencies and\n\treturns a list containing a valid order in which the given jobs can be\n\tcompleted. If no such order exists, the function should return an empty array.\n\n\tSample INput:\n\tjobs: [1, 2, 3, 4]\n\tdeps:  = [[1, 2], [1, 3], [3, 2], [4, 2], [4, 3]]\n\tOutput: [1, 4, 3, 2] or [4, 1, 3, 2]\n\n\tExplanation:\n\tThe provided code implements a topological sorting algorithm to find the order in which jobs can be executed given their dependencies. It uses a directed acyclic graph (DAG) representation to represent the jobs and their dependencies.\n\n\tLet's go through each part of the code in detail:\n\n\t1. `Dep` struct:\n\t- This is a simple struct that represents a dependency between two jobs.\n\t- `Prereq` field indicates the prerequisite job.\n\t- `Job` field indicates the job that depends on the prerequisite.\n\n\t2. `TopologicalSort` function:\n\t- This is the main function that performs the topological sorting of jobs.\n\t- It takes two input parameters: `jobs`, a list of job IDs, and `deps`, a list of dependencies.\n\t- It first creates a job graph using the `createJobGraph` function and then gets the ordered jobs using the `getOrderedJobs` function.\n\n\t3. `createJobGraph` function:\n\t- This function creates a job graph from the list of jobs and dependencies.\n\t- It creates a new instance of the `JobGraph` struct and iterates through the dependencies.\n\t- For each dependency, it adds the prerequisite job to the dependent job's list of prerequisites in the job graph.\n\n\t4. `getOrderedJobs` function:\n\t- This function performs a depth-first traversal of the job graph to get the ordered jobs.\n\t- It iterates through the nodes of the graph until all nodes have been visited.\n\t- For each node, it calls the `depthFirstTraverse` function to perform the depth-first traversal and get the ordered jobs.\n\t- If a cycle is detected in the graph during the traversal, it means that there is a circular dependency, and the function returns an empty list.\n\n\t5. `depthFirstTraverse` function:\n\t- This function performs the depth-first traversal of the graph starting from a given node.\n\t- It checks if the current node has been visited (i.e., it is not part of any cycle).\n\t- If the node is currently being visited (marked as `Visiting`), it means that there is a cycle, and the function returns `true`.\n\t- Otherwise, it marks the node as `Visiting`, recursively traverses through its prerequisites, and marks it as `Visited` after the traversal.\n\t- It appends the job to the `orderedJobs` list in the correct order.\n\n\t6. `JobGraph` struct:\n\t- This struct represents the job graph.\n\t- `Nodes` is a list of all the job nodes in the graph.\n\t- `Graph` is a map where the key is the job ID, and the value is a pointer to the corresponding `JobNode` in the graph.\n\n\t7. `NewJobGraph` function:\n\t- This function creates a new instance of the `JobGraph` struct and initializes its `Graph` field with an empty map.\n\t- It also adds individual job nodes to the `Nodes` list.\n\n\t8. `Addprereq`, `AddNode`, and `GetNode` functions:\n\t- These are helper functions to add prerequisites to a job, add a new job node to the graph, and get an existing job node, respectively.\n\n\t9. `JobNode` struct:\n\t- This struct represents a node in the job graph.\n\t- `Job` is the job ID.\n\t- `Prereqs` is a list of pointers to other job nodes that are prerequisites for the current job.\n\t- `Visited` and `Visiting` are boolean flags used during the depth-first traversal to track the traversal status of each node.\n\n\tOverall, the code implements the topological sorting algorithm using depth-first traversal to find the order in which jobs can be executed without violating their dependencies. It efficiently handles circular dependencies and returns the ordered jobs or an empty list if a circular dependency is detected.\n\n\tO(j + d) time | O(j + d) space - where j is the number of jobs and d is the number of dependencies\n*/\n#include <vector>\n#include <unordered_map>\n\nusing namespace std;\n\nstruct Dep {\n    int Prereq;\n    int Job;\n};\n\nclass JobGraph;\n\n// Function prototypes\nJobGraph createJobGraph(vector<int>& jobs, vector<Dep>& deps);\nvector<int> getOrderedJobs(JobGraph& graph);\nbool depthFirstTraverse(JobGraph& graph, int jobId, vector<int>& orderedJobs);\n\nclass JobGraph {\npublic:\n    // Constructor to create a job graph from a list of jobs\n    JobGraph(vector<int>& jobs) {\n        for (int job : jobs) {\n            // Add each job as a node to the graph\n            addNode(job);\n        }\n    }\n\n    // Function to add a prerequisite to a job node\n    void addPrereq(int job, int prereq) {\n        JobNode* jobNode = getNode(job);\n        JobNode* prereqNode = getNode(prereq);\n        // Add the prerequisite node to the list of prerequisites for the job node\n        jobNode->prereqs.push_back(prereqNode);\n    }\n\n    // Function to add a new job node to the graph\n    void addNode(int job) {\n        // Create a new job node and add it to the graph and nodes list\n        graph[job] = new JobNode(job);\n        nodes.push_back(graph[job]);\n    }\n\n    // Function to get a job node from the graph by its ID\n    JobNode* getNode(int job) {\n        // If the node does not exist in the graph, create a new node and add it to the graph\n        if (graph.find(job) == graph.end()) {\n            addNode(job);\n        }\n        return graph[job];\n    }\n\n    // Data members\n    vector<JobNode*> nodes; // List of all job nodes in the graph\n    unordered_map<int, JobNode*> graph; // Map to store the job nodes by their IDs\n};\n\n// Function to perform topological sorting and return the ordered jobs\nvector<int> TopologicalSort(vector<int>& jobs, vector<Dep>& deps) {\n    // Create a job graph from the list of jobs and dependencies\n    JobGraph graph = createJobGraph(jobs, deps);\n    // Get the ordered jobs using depth-first traversal\n    return getOrderedJobs(graph);\n}\n\n// Function to create a job graph from a list of jobs and dependencies\nJobGraph createJobGraph(vector<int>& jobs, vector<Dep>& deps) {\n    // Initialize an empty graph\n    JobGraph graph(jobs);\n    // Add each dependency as a prerequisite to the corresponding job node in the graph\n    for (Dep dep : deps) {\n        graph.addPrereq(dep.Job, dep.Prereq);\n    }\n    return graph;\n}\n\n// Function to perform depth-first traversal and get the ordered jobs\nvector<int> getOrderedJobs(JobGraph& graph) {\n    vector<int> orderedJobs;\n    vector<JobNode*>& nodes = graph.nodes;\n\n    // Continue the traversal until all nodes have been visited\n    while (!nodes.empty()) {\n        // Get the last node from the list of nodes and remove it from the list\n        JobNode* node = nodes.back();\n        nodes.pop_back();\n\n        // Perform depth-first traversal starting from the current node\n        if (!depthFirstTraverse(graph, node->job, orderedJobs)) {\n            return {}; // If a cycle is detected during traversal, return an empty list\n        }\n    }\n    return orderedJobs;\n}\n\n// Function to perform depth-first traversal starting from a specific job node\nbool depthFirstTraverse(JobGraph& graph, int jobId, vector<int>& orderedJobs) {\n    // Get the job node from the graph\n    JobNode* node = graph.getNode(jobId);\n\n    // If the node has been visited, it means it is not part of any cycle, so return false\n    if (node->visited) {\n        return false;\n    }\n\n    // If the node is currently being visited, it means there is a cycle, so return true\n    if (node->visiting) {\n        return true;\n    }\n\n    // Mark the node as currently being visited\n    node->visiting = true;\n\n    // Recursively traverse through each prerequisite of the current node\n    for (JobNode* prereqNode : node->prereqs) {\n        // If a cycle is detected during the traversal, return true\n        if (depthFirstTraverse(graph, prereqNode->job, orderedJobs)) {\n            return true;\n        }\n    }\n\n    // Mark the node as visited and no longer being visited\n    node->visited = true;\n    node->visiting = false;\n\n    // Append the job to the orderedJobs list in the correct order\n    orderedJobs.push_back(node->job);\n\n    // Return false, as no cycle was detected during the traversal\n    return false;\n}\n\n// Definition of the JobNode class\nclass JobNode {\npublic:\n    int job; // Job ID\n    vector<JobNode*> prereqs; // List of prerequisite job nodes\n    bool visited; // Flag to mark if the node has been visited\n    bool visiting; // Flag to mark if the node is currently being visited\n\n    // Constructor to initialize a job node\n    JobNode(int jobId) : job(jobId), visited(false), visiting(false) {}\n};\n"
  },
  {
    "path": "Graphs/topological_sort.go",
    "content": "/*\n\tYou're given a list of arbitrary jobs that need to be completed; these jobs\n\tare represented by distinct integers. You're also given a list of dependencies. A\n\tdependency is represented as a pair of jobs where the first job is a\n\tprerequisite of the second one. In other words, the second job depends on the\n\tfirst one; it can only be completed once the first job is completed.\n\n\tWrite a function that takes in a list of jobs and a list of dependencies and\n\treturns a list containing a valid order in which the given jobs can be\n\tcompleted. If no such order exists, the function should return an empty array.\n\n\tSample INput:\n\tjobs: [1, 2, 3, 4]\n\tdeps:  = [[1, 2], [1, 3], [3, 2], [4, 2], [4, 3]]\n\tOutput: [1, 4, 3, 2] or [4, 1, 3, 2]\n\n\tExplanation:\n\tThe provided code implements a topological sorting algorithm to find the order in which jobs can be executed given their dependencies. It uses a directed acyclic graph (DAG) representation to represent the jobs and their dependencies.\n\n\tLet's go through each part of the code in detail:\n\n\t1. `Dep` struct:\n\t- This is a simple struct that represents a dependency between two jobs.\n\t- `Prereq` field indicates the prerequisite job.\n\t- `Job` field indicates the job that depends on the prerequisite.\n\n\t2. `TopologicalSort` function:\n\t- This is the main function that performs the topological sorting of jobs.\n\t- It takes two input parameters: `jobs`, a list of job IDs, and `deps`, a list of dependencies.\n\t- It first creates a job graph using the `createJobGraph` function and then gets the ordered jobs using the `getOrderedJobs` function.\n\n\t3. `createJobGraph` function:\n\t- This function creates a job graph from the list of jobs and dependencies.\n\t- It creates a new instance of the `JobGraph` struct and iterates through the dependencies.\n\t- For each dependency, it adds the prerequisite job to the dependent job's list of prerequisites in the job graph.\n\n\t4. `getOrderedJobs` function:\n\t- This function performs a depth-first traversal of the job graph to get the ordered jobs.\n\t- It iterates through the nodes of the graph until all nodes have been visited.\n\t- For each node, it calls the `depthFirstTraverse` function to perform the depth-first traversal and get the ordered jobs.\n\t- If a cycle is detected in the graph during the traversal, it means that there is a circular dependency, and the function returns an empty list.\n\n\t5. `depthFirstTraverse` function:\n\t- This function performs the depth-first traversal of the graph starting from a given node.\n\t- It checks if the current node has been visited (i.e., it is not part of any cycle).\n\t- If the node is currently being visited (marked as `Visiting`), it means that there is a cycle, and the function returns `true`.\n\t- Otherwise, it marks the node as `Visiting`, recursively traverses through its prerequisites, and marks it as `Visited` after the traversal.\n\t- It appends the job to the `orderedJobs` list in the correct order.\n\n\t6. `JobGraph` struct:\n\t- This struct represents the job graph.\n\t- `Nodes` is a list of all the job nodes in the graph.\n\t- `Graph` is a map where the key is the job ID, and the value is a pointer to the corresponding `JobNode` in the graph.\n\n\t7. `NewJobGraph` function:\n\t- This function creates a new instance of the `JobGraph` struct and initializes its `Graph` field with an empty map.\n\t- It also adds individual job nodes to the `Nodes` list.\n\n\t8. `Addprereq`, `AddNode`, and `GetNode` functions:\n\t- These are helper functions to add prerequisites to a job, add a new job node to the graph, and get an existing job node, respectively.\n\n\t9. `JobNode` struct:\n\t- This struct represents a node in the job graph.\n\t- `Job` is the job ID.\n\t- `Prereqs` is a list of pointers to other job nodes that are prerequisites for the current job.\n\t- `Visited` and `Visiting` are boolean flags used during the depth-first traversal to track the traversal status of each node.\n\n\tOverall, the code implements the topological sorting algorithm using depth-first traversal to find the order in which jobs can be executed without violating their dependencies. It efficiently handles circular dependencies and returns the ordered jobs or an empty list if a circular dependency is detected.\n\n\tO(j + d) time | O(j + d) space - where j is the number of jobs and d is the number of dependencies\n*/\npackage main\n\ntype Dep struct {\n\tPrereq int\n\tJob    int\n}\n\n// TopologicalSort performs topological sorting of jobs given their dependencies.\nfunc TopologicalSort(jobs []int, deps []Dep) []int {\n\t// Create a job graph from the list of jobs and dependencies.\n\tjobGraph := createJobGraph(jobs, deps)\n\n\t// Get the ordered jobs using depth-first traversal.\n\treturn getOrderedJobs(jobGraph)\n}\n\n// createJobGraph creates a job graph from the list of jobs and dependencies.\nfunc createJobGraph(jobs []int, deps []Dep) *JobGraph {\n\tgraph := NewJobGraph(jobs)\n\tfor _, dep := range deps {\n\t\t// Add each dependency as a prerequisite to the corresponding job node in the graph.\n\t\tgraph.Addprereq(dep.Job, dep.Prereq)\n\t}\n\treturn graph\n}\n\n// getOrderedJobs performs a depth-first traversal of the job graph to get the ordered jobs.\nfunc getOrderedJobs(graph *JobGraph) []int {\n\torderedJobs := []int{}\n\tnodes := graph.Nodes\n\n\t// Continue the traversal until all nodes have been visited.\n\tfor len(nodes) != 0 {\n\t\t// Get the last node from the list of nodes and remove it from the list.\n\t\tnode := nodes[len(nodes)-1]\n\t\tnodes = nodes[:len(nodes)-1]\n\n\t\t// Perform depth-first traversal starting from the current node.\n\t\t// If a cycle is detected, return an empty list.\n\t\tcontainsCycle := depthFirstTraverse(node, &orderedJobs)\n\t\tif containsCycle {\n\t\t\treturn []int{}\n\t\t}\n\t}\n\treturn orderedJobs\n}\n\n// depthFirstTraverse performs depth-first traversal starting from the given node.\n// It returns true if a cycle is detected, otherwise, it returns false.\nfunc depthFirstTraverse(node *JobNode, orderedJobs *[]int) bool {\n\t// If the node has been visited, it means it is not part of any cycle, so return false.\n\tif node.Visited {\n\t\treturn false\n\t}\n\t// If the node is currently being visited it means there is a cycle, so return true.\n\tif node.Visiting {\n\t\treturn true\n\t}\n\n\t// Mark the node as currently being visited.\n\tnode.Visiting = true\n\n\t// Recursively traverse through each prerequisite of the current node.\n\tfor _, prereqNode := range node.Prereqs {\n\t\t// If a cycle is detected during the traversal, return true.\n\t\tcontainsCycle := depthFirstTraverse(prereqNode, orderedJobs)\n\t\tif containsCycle {\n\t\t\treturn true\n\t\t}\n\t}\n\n\t// Mark the node as visited and no longer being visited.\n\tnode.Visited = true\n\tnode.Visiting = false\n\n\t// Append the job to the orderedJobs list in the correct order.\n\t*orderedJobs = append(*orderedJobs, node.Job)\n\n\t// Return false, as no cycle was detected during the traversal.\n\treturn false\n}\n\n// JobGraph represents the job graph.\ntype JobGraph struct {\n\tNodes []*JobNode\n\tGraph map[int]*JobNode\n}\n\n// NewJobGraph creates a new instance of the JobGraph and initializes its Graph field.\nfunc NewJobGraph(jobs []int) *JobGraph {\n\tg := &JobGraph{\n\t\tGraph: map[int]*JobNode{},\n\t}\n\tfor _, job := range jobs {\n\t\t// Add individual job nodes to the Nodes list.\n\t\tg.AddNode(job)\n\t}\n\treturn g\n}\n\n// Addprereq adds a prerequisite to a job in the job graph.\nfunc (g *JobGraph) Addprereq(job, prereq int) {\n\tjobNode := g.GetNode(job)\n\tprereqNode := g.GetNode(prereq)\n\t// Add the prerequisite node to the list of prerequisites for the job node.\n\tjobNode.Prereqs = append(jobNode.Prereqs, prereqNode)\n}\n\n// AddNode adds a new job node to the job graph.\nfunc (g *JobGraph) AddNode(job int) {\n\t// Create a new job node and add it to the graph and nodes list.\n\tg.Graph[job] = &JobNode{Job: job}\n\tg.Nodes = append(g.Nodes, g.Graph[job])\n}\n\n// GetNode gets an existing job node from the job graph.\nfunc (g *JobGraph) GetNode(job int) *JobNode {\n\t// If the node does not exist in the graph, create a new node and add it to the graph.\n\tif _, found := g.Graph[job]; !found {\n\t\tg.AddNode(job)\n\t}\n\treturn g.Graph[job]\n}\n\n// JobNode represents a node in the job graph.\ntype JobNode struct {\n\tJob      int\n\tPrereqs  []*JobNode\n\tVisited  bool\n\tVisiting bool\n}\n"
  },
  {
    "path": "Graphs/topological_sort.java",
    "content": "/*\n\tYou're given a list of arbitrary jobs that need to be completed; these jobs\n\tare represented by distinct integers. You're also given a list of dependencies. A\n\tdependency is represented as a pair of jobs where the first job is a\n\tprerequisite of the second one. In other words, the second job depends on the\n\tfirst one; it can only be completed once the first job is completed.\n\n\tWrite a function that takes in a list of jobs and a list of dependencies and\n\treturns a list containing a valid order in which the given jobs can be\n\tcompleted. If no such order exists, the function should return an empty array.\n\n\tSample INput:\n\tjobs: [1, 2, 3, 4]\n\tdeps:  = [[1, 2], [1, 3], [3, 2], [4, 2], [4, 3]]\n\tOutput: [1, 4, 3, 2] or [4, 1, 3, 2]\n\n\tExplanation:\n\tThe provided code implements a topological sorting algorithm to find the order in which jobs can be executed given their dependencies. It uses a directed acyclic graph (DAG) representation to represent the jobs and their dependencies.\n\n\tLet's go through each part of the code in detail:\n\n\t1. `Dep` struct:\n\t- This is a simple struct that represents a dependency between two jobs.\n\t- `Prereq` field indicates the prerequisite job.\n\t- `Job` field indicates the job that depends on the prerequisite.\n\n\t2. `TopologicalSort` function:\n\t- This is the main function that performs the topological sorting of jobs.\n\t- It takes two input parameters: `jobs`, a list of job IDs, and `deps`, a list of dependencies.\n\t- It first creates a job graph using the `createJobGraph` function and then gets the ordered jobs using the `getOrderedJobs` function.\n\n\t3. `createJobGraph` function:\n\t- This function creates a job graph from the list of jobs and dependencies.\n\t- It creates a new instance of the `JobGraph` struct and iterates through the dependencies.\n\t- For each dependency, it adds the prerequisite job to the dependent job's list of prerequisites in the job graph.\n\n\t4. `getOrderedJobs` function:\n\t- This function performs a depth-first traversal of the job graph to get the ordered jobs.\n\t- It iterates through the nodes of the graph until all nodes have been visited.\n\t- For each node, it calls the `depthFirstTraverse` function to perform the depth-first traversal and get the ordered jobs.\n\t- If a cycle is detected in the graph during the traversal, it means that there is a circular dependency, and the function returns an empty list.\n\n\t5. `depthFirstTraverse` function:\n\t- This function performs the depth-first traversal of the graph starting from a given node.\n\t- It checks if the current node has been visited (i.e., it is not part of any cycle).\n\t- If the node is currently being visited (marked as `Visiting`), it means that there is a cycle, and the function returns `true`.\n\t- Otherwise, it marks the node as `Visiting`, recursively traverses through its prerequisites, and marks it as `Visited` after the traversal.\n\t- It appends the job to the `orderedJobs` list in the correct order.\n\n\t6. `JobGraph` struct:\n\t- This struct represents the job graph.\n\t- `Nodes` is a list of all the job nodes in the graph.\n\t- `Graph` is a map where the key is the job ID, and the value is a pointer to the corresponding `JobNode` in the graph.\n\n\t7. `NewJobGraph` function:\n\t- This function creates a new instance of the `JobGraph` struct and initializes its `Graph` field with an empty map.\n\t- It also adds individual job nodes to the `Nodes` list.\n\n\t8. `Addprereq`, `AddNode`, and `GetNode` functions:\n\t- These are helper functions to add prerequisites to a job, add a new job node to the graph, and get an existing job node, respectively.\n\n\t9. `JobNode` struct:\n\t- This struct represents a node in the job graph.\n\t- `Job` is the job ID.\n\t- `Prereqs` is a list of pointers to other job nodes that are prerequisites for the current job.\n\t- `Visited` and `Visiting` are boolean flags used during the depth-first traversal to track the traversal status of each node.\n\n\tOverall, the code implements the topological sorting algorithm using depth-first traversal to find the order in which jobs can be executed without violating their dependencies. It efficiently handles circular dependencies and returns the ordered jobs or an empty list if a circular dependency is detected.\n\n\tO(j + d) time | O(j + d) space - where j is the number of jobs and d is the number of dependencies\n*/\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nclass Dep {\n    int Prereq;\n    int Job;\n\n    public Dep(int Prereq, int Job) {\n        this.Prereq = Prereq;\n        this.Job = Job;\n    }\n}\n\nclass JobGraph {\n\n    // Inner class representing a job node\n    static class JobNode {\n        int job; // Job ID\n        List<JobNode> prereqs; // List of prerequisite job nodes\n        boolean visited; // Flag to mark if the node has been visited\n        boolean visiting; // Flag to mark if the node is currently being visited\n\n        // Constructor to initialize a job node\n        public JobNode(int job) {\n            this.job = job;\n            this.prereqs = new ArrayList<>();\n            this.visited = false;\n            this.visiting = false;\n        }\n    }\n\n    List<JobNode> nodes; // List of all job nodes in the graph\n    Map<Integer, JobNode> graph; // Map to store the job nodes by their IDs\n\n    // Constructor to create a job graph from a list of jobs\n    public JobGraph(List<Integer> jobs) {\n        this.nodes = new ArrayList<>();\n        this.graph = new HashMap<>();\n        for (int job : jobs) {\n            // Add each job as a node to the graph\n            addNode(job);\n        }\n    }\n\n    // Function to add a prerequisite to a job node\n    public void addPrereq(int job, int prereq) {\n        JobNode jobNode = getNode(job);\n        JobNode prereqNode = getNode(prereq);\n        // Add the prerequisite node to the list of prerequisites for the job node\n        jobNode.prereqs.add(prereqNode);\n    }\n\n    // Function to add a new job node to the graph\n    public void addNode(int job) {\n        // Create a new job node and add it to the graph and nodes list\n        JobNode node = new JobNode(job);\n        graph.put(job, node);\n        nodes.add(node);\n    }\n\n    // Function to get a job node from the graph by its ID\n    public JobNode getNode(int job) {\n        // If the node does not exist in the graph, create a new node and add it to the graph\n        if (!graph.containsKey(job)) {\n            addNode(job);\n        }\n        return graph.get(job);\n    }\n}\n\npublic class Main {\n\n    // Function to perform topological sorting and return the ordered jobs\n    public static List<Integer> TopologicalSort(List<Integer> jobs, List<Dep> deps) {\n        // Create a job graph from the list of jobs and dependencies\n        JobGraph graph = createJobGraph(jobs, deps);\n        // Get the ordered jobs using depth-first traversal\n        return getOrderedJobs(graph);\n    }\n\n    // Function to create a job graph from a list of jobs and dependencies\n    public static JobGraph createJobGraph(List<Integer> jobs, List<Dep> deps) {\n        // Initialize an empty graph\n        JobGraph graph = new JobGraph(jobs);\n        // Add each dependency as a prerequisite to the corresponding job node in the graph\n        for (Dep dep : deps) {\n            graph.addPrereq(dep.Job, dep.Prereq);\n        }\n        return graph;\n    }\n\n    // Function to perform depth-first traversal and get the ordered jobs\n    public static List<Integer> getOrderedJobs(JobGraph graph) {\n        List<Integer> orderedJobs = new ArrayList<>();\n        List<JobGraph.JobNode> nodes = graph.nodes;\n\n        // Continue the traversal until all nodes have been visited\n        while (!nodes.isEmpty()) {\n            // Get the last node from the list of nodes and remove it from the list\n            JobGraph.JobNode node = nodes.remove(nodes.size() - 1);\n\n            // Perform depth-first traversal starting from the current node\n            if (!depthFirstTraverse(graph, node.job, orderedJobs)) {\n                return new ArrayList<>(); // If a cycle is detected during traversal, return an empty list\n            }\n        }\n        return orderedJobs;\n    }\n\n    // Function to perform depth-first traversal starting from a specific job node\n    public static boolean depthFirstTraverse(JobGraph graph, int jobId, List<Integer> orderedJobs) {\n        // Get the job node from the graph\n        JobGraph.JobNode node = graph.getNode(jobId);\n\n        // If the node has been visited, it means it is not part of any cycle, so return false\n        if (node.visited) {\n            return false;\n        }\n\n        // If the node is currently being visited, it means there is a cycle, so return true\n        if (node.visiting) {\n            return true;\n        }\n\n        // Mark the node as currently being visited\n        node.visiting = true;\n\n        // Recursively traverse through each prerequisite of the current node\n        for (JobGraph.JobNode prereqNode : node.prereqs) {\n            // If a cycle is detected during the traversal, return true\n            if (depth\n"
  },
  {
    "path": "Graphs/topological_sort.js",
    "content": "/*\n\tYou're given a list of arbitrary jobs that need to be completed; these jobs\n\tare represented by distinct integers. You're also given a list of dependencies. A\n\tdependency is represented as a pair of jobs where the first job is a\n\tprerequisite of the second one. In other words, the second job depends on the\n\tfirst one; it can only be completed once the first job is completed.\n\n\tWrite a function that takes in a list of jobs and a list of dependencies and\n\treturns a list containing a valid order in which the given jobs can be\n\tcompleted. If no such order exists, the function should return an empty array.\n\n\tSample INput:\n\tjobs: [1, 2, 3, 4]\n\tdeps:  = [[1, 2], [1, 3], [3, 2], [4, 2], [4, 3]]\n\tOutput: [1, 4, 3, 2] or [4, 1, 3, 2]\n\n\tExplanation:\n\tThe provided code implements a topological sorting algorithm to find the order in which jobs can be executed given their dependencies. It uses a directed acyclic graph (DAG) representation to represent the jobs and their dependencies.\n\n\tLet's go through each part of the code in detail:\n\n\t1. `Dep` struct:\n\t- This is a simple struct that represents a dependency between two jobs.\n\t- `Prereq` field indicates the prerequisite job.\n\t- `Job` field indicates the job that depends on the prerequisite.\n\n\t2. `TopologicalSort` function:\n\t- This is the main function that performs the topological sorting of jobs.\n\t- It takes two input parameters: `jobs`, a list of job IDs, and `deps`, a list of dependencies.\n\t- It first creates a job graph using the `createJobGraph` function and then gets the ordered jobs using the `getOrderedJobs` function.\n\n\t3. `createJobGraph` function:\n\t- This function creates a job graph from the list of jobs and dependencies.\n\t- It creates a new instance of the `JobGraph` struct and iterates through the dependencies.\n\t- For each dependency, it adds the prerequisite job to the dependent job's list of prerequisites in the job graph.\n\n\t4. `getOrderedJobs` function:\n\t- This function performs a depth-first traversal of the job graph to get the ordered jobs.\n\t- It iterates through the nodes of the graph until all nodes have been visited.\n\t- For each node, it calls the `depthFirstTraverse` function to perform the depth-first traversal and get the ordered jobs.\n\t- If a cycle is detected in the graph during the traversal, it means that there is a circular dependency, and the function returns an empty list.\n\n\t5. `depthFirstTraverse` function:\n\t- This function performs the depth-first traversal of the graph starting from a given node.\n\t- It checks if the current node has been visited (i.e., it is not part of any cycle).\n\t- If the node is currently being visited (marked as `Visiting`), it means that there is a cycle, and the function returns `true`.\n\t- Otherwise, it marks the node as `Visiting`, recursively traverses through its prerequisites, and marks it as `Visited` after the traversal.\n\t- It appends the job to the `orderedJobs` list in the correct order.\n\n\t6. `JobGraph` struct:\n\t- This struct represents the job graph.\n\t- `Nodes` is a list of all the job nodes in the graph.\n\t- `Graph` is a map where the key is the job ID, and the value is a pointer to the corresponding `JobNode` in the graph.\n\n\t7. `NewJobGraph` function:\n\t- This function creates a new instance of the `JobGraph` struct and initializes its `Graph` field with an empty map.\n\t- It also adds individual job nodes to the `Nodes` list.\n\n\t8. `Addprereq`, `AddNode`, and `GetNode` functions:\n\t- These are helper functions to add prerequisites to a job, add a new job node to the graph, and get an existing job node, respectively.\n\n\t9. `JobNode` struct:\n\t- This struct represents a node in the job graph.\n\t- `Job` is the job ID.\n\t- `Prereqs` is a list of pointers to other job nodes that are prerequisites for the current job.\n\t- `Visited` and `Visiting` are boolean flags used during the depth-first traversal to track the traversal status of each node.\n\n\tOverall, the code implements the topological sorting algorithm using depth-first traversal to find the order in which jobs can be executed without violating their dependencies. It efficiently handles circular dependencies and returns the ordered jobs or an empty list if a circular dependency is detected.\n\n\tO(j + d) time | O(j + d) space - where j is the number of jobs and d is the number of dependencies\n*/\nclass Dep {\n  constructor(Prereq, Job) {\n    this.Prereq = Prereq;\n    this.Job = Job;\n  }\n}\n\nclass JobGraph {\n  constructor(jobs) {\n    this.nodes = [];\n    this.graph = new Map();\n    for (const job of jobs) {\n      // Add each job as a node to the graph\n      this.addNode(job);\n    }\n  }\n\n  addPrereq(job, prereq) {\n    const jobNode = this.getNode(job);\n    const prereqNode = this.getNode(prereq);\n    // Add the prerequisite node to the list of prerequisites for the job node\n    jobNode.prereqs.push(prereqNode);\n  }\n\n  addNode(job) {\n    // Create a new job node and add it to the graph and nodes list\n    const node = { job, prereqs: [], visited: false, visiting: false };\n    this.graph.set(job, node);\n    this.nodes.push(node);\n  }\n\n  getNode(job) {\n    // If the node does not exist in the graph, create a new node and add it to the graph\n    if (!this.graph.has(job)) {\n      this.addNode(job);\n    }\n    return this.graph.get(job);\n  }\n}\n\nfunction TopologicalSort(jobs, deps) {\n  // Create a job graph from the list of jobs and dependencies\n  const graph = createJobGraph(jobs, deps);\n  // Get the ordered jobs using depth-first traversal\n  return getOrderedJobs(graph);\n}\n\nfunction createJobGraph(jobs, deps) {\n  // Initialize an empty graph\n  const graph = new JobGraph(jobs);\n  // Add each dependency as a prerequisite to the corresponding job node in the graph\n  for (const dep of deps) {\n    graph.addPrereq(dep.Job, dep.Prereq);\n  }\n  return graph;\n}\n\nfunction getOrderedJobs(graph) {\n  const orderedJobs = [];\n  const nodes = graph.nodes;\n\n  // Continue the traversal until all nodes have been visited\n  while (nodes.length > 0) {\n    // Get the last node from the list of nodes and remove it from the list\n    const node = nodes.pop();\n\n    // Perform depth-first traversal starting from the current node\n    if (!depthFirstTraverse(graph, node.job, orderedJobs)) {\n      return []; // If a cycle is detected during traversal, return an empty list\n    }\n  }\n  return orderedJobs;\n}\n\nfunction depthFirstTraverse(graph, jobId, orderedJobs) {\n  // Get the job node from the graph\n  const node = graph.getNode(jobId);\n\n  // If the node has been visited, it means it is not part of any cycle, so return false\n  if (node.visited) {\n    return false;\n  }\n\n  // If the node is currently being visited, it means there is a cycle, so return true\n  if (node.visiting) {\n    return true;\n  }\n\n  // Mark the node as currently being visited\n  node.visiting = true;\n\n  // Recursively traverse through each prerequisite of the current node\n  for (const prereqNode of node.prereqs) {\n    // If a cycle is detected during the traversal, return true\n    if (depthFirstTraverse(graph, prereqNode.job, orderedJobs)) {\n      return true;\n    }\n  }\n\n  // Mark the node as visited and not currently being visited\n  node.visited = true;\n  node.visiting = false;\n\n  // Add the job to the ordered jobs list\n  orderedJobs.push(jobId);\n\n  // Return false to indicate that no cycle was detected\n  return false;\n}\n"
  },
  {
    "path": "Graphs/topological_sort.py",
    "content": "\"\"\"\nImplementation of Topological sort using DFS\nAccording to Introduction to Algorithms, given a directed acyclic graph (DAG), \na topological sort is a linear ordering of all vertices such that for any edge\n(u, v), u comes before v. Another way to describe it is that when you put all\nvertices horizontally on a line, all of the edges are pointing from left to right.\n\nTime complexity O(Vertices + Edges)\n\"\"\"\n\ndef main():\n    adj_list = {\n        5: [2, 0],\n        4: [0, 1],\n        3: [1],\n        2: [3],\n        1: [],\n        0: []\n    }\n\n    dfs(adj_list, set(), [])\n\n\n\ndef dfs(adj_list, visited, stack):\n    for vertex in range(6):\n        if vertex in visited:\n            continue\n        dfs_visit(adj_list, visited, vertex, stack)\n\n    print(stack[::-1])\n\n\ndef dfs_visit(adj_list, visited, node, stack):\n    visited.add(node)\n\n    for neighbor in adj_list[node]:\n        if neighbor in visited:\n            continue\n        dfs_visit(adj_list, visited, neighbor, stack)\n\n    stack.append(node)\n\n\n\nif __name__ == \"__main__\":\n    main()"
  },
  {
    "path": "Graphs/two_colorable.cpp",
    "content": "/*\n\tYou're given a list of edges  representing a connected, unweighted, undirected graph with at least one node.\n\tWrite a function that returns a boolean representing whether the given graph is two-colorable.\n\n\tExplanation:\n\tThe code snippet implements an algorithm to determine if a given graph is two-colorable or bipartite. A graph is two-colorable if its vertices can be divided into two groups such that no two adjacent vertices have the same color.\n\n\tThe function `TwoColorable(edges [][]int) bool` takes a 2D array of integers `edges`, representing the edges of the graph. Each row `edges[i]` contains the list of vertices that are connected to vertex `i`.\n\n\tThe algorithm uses a stack and a map to keep track of the colors assigned to the vertices. It starts by assigning the first vertex (vertex 0) to color true and pushing it onto the stack.\n\n\tThen, it performs a depth-first traversal of the graph using the stack. For each vertex popped from the stack, it explores its adjacent vertices. If an adjacent vertex has not been colored yet (not present in the colors map), it assigns the opposite color to it (i.e., `!colors[node]`) and pushes it onto the stack. If the adjacent vertex has already been colored and its color is the same as the current vertex's color, then the graph cannot be two-colorable, and the function returns false.\n\n\tIf the traversal completes without any conflicts (i.e., no adjacent vertices have the same color), the function returns true, indicating that the graph is two-colorable.\n\n\tThe algorithm relies on the fact that a graph is two-colorable if and only if it is bipartite, and the two colors represent the two disjoint sets of vertices in the bipartite graph.\n\n\tHere's a step-by-step explanation of the algorithm:\n\n\t1. Initialize the `colors` map with the first vertex (0) assigned the color true (representing one group of vertices).\n\t2. Initialize an empty stack and push the first vertex (0) onto it.\n\t3. While the stack is not empty, repeat the following steps:\n\ta. Pop the top vertex from the stack (denoted by `node`).\n\tb. For each vertex `connection` connected to `node` (i.e., `edges[node]`), do the following:\n\t\ti. If `connection` has not been colored yet (not present in the `colors` map), assign it the opposite color of\n\t\t`node` (i.e., `!colors[node]`) and push it onto the stack.\n\t\tii. If `connection` has already been colored and its color is the same as `node`'s color, return false since the\n\t\tgraph is not two-colorable.\n\t4. If the traversal completes without conflicts, return true, indicating that the graph is two-colorable.\n\n\tNote: The algorithm assumes that the graph is connected, meaning there is a path from any vertex to any other vertex.\n\tIf the graph is not connected, the algorithm will only determine whether the connected component containing vertex 0 is two-colorable.\n\n\tO(v + e) time | O(v) space - where v is the number of vertices and e is the number of edges in the graph\n\n*/\n#include <iostream>\n#include <vector>\n#include <unordered_map>\n#include <stack>\n\nbool isTwoColorable(std::vector<std::vector<int>>& edges) {\n    // colors keeps track of the colors assigned to each vertex.\n    // We start by assigning the first vertex (0) the color true (denoted by 0: true).\n    std::unordered_map<int, bool> colors;\n    colors[0] = true;\n\n    // stack is used for depth-first traversal of the graph.\n    std::stack<int> stack;\n    stack.push(0);\n\n    while (!stack.empty()) {\n        // Pop the top vertex from the stack (denoted by 'node').\n        int node = stack.top();\n        stack.pop();\n\n        // Explore adjacent vertices (connections) of the current vertex 'node'.\n        for (int connection : edges[node]) {\n            // If the adjacent vertex has not been colored yet (not present in the 'colors' map),\n            // assign it the opposite color of the current vertex (denoted by !colors[node]),\n            // and push it onto the stack.\n            if (colors.find(connection) == colors.end()) {\n                colors[connection] = !colors[node];\n                stack.push(connection);\n            } else {\n                // If the adjacent vertex has already been colored and its color is the same as the current vertex's color,\n                // then the graph cannot be two-colorable, return false.\n                if (colors[connection] == colors[node]) {\n                    return false;\n                }\n            }\n        }\n    }\n\n    // If the traversal completes without any conflicts (no adjacent vertices have the same color),\n    // return true, indicating that the graph is two-colorable.\n    return true;\n}\n\nint main() {\n    std::vector<std::vector<int>> edges = {{1, 2}, {0, 3}, {0, 4}, {1}, {2}};\n    bool isTwoColorableResult = isTwoColorable(edges);\n    std::cout << \"Is Two-Colorable: \" << std::boolalpha << isTwoColorableResult << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "Graphs/two_colorable.go",
    "content": "/*\n\tYou're given a list of edges  representing a connected, unweighted, undirected graph with at least one node.\n\tWrite a function that returns a boolean representing whether the given graph is two-colorable.\n\n\tExplanation:\n\tThe code snippet implements an algorithm to determine if a given graph is two-colorable or bipartite. A graph is two-colorable if its vertices can be divided into two groups such that no two adjacent vertices have the same color.\n\n\tThe function `TwoColorable(edges [][]int) bool` takes a 2D array of integers `edges`, representing the edges of the graph. Each row `edges[i]` contains the list of vertices that are connected to vertex `i`.\n\n\tThe algorithm uses a stack and a map to keep track of the colors assigned to the vertices. It starts by assigning the first vertex (vertex 0) to color true and pushing it onto the stack.\n\n\tThen, it performs a depth-first traversal of the graph using the stack. For each vertex popped from the stack, it explores its adjacent vertices. If an adjacent vertex has not been colored yet (not present in the colors map), it assigns the opposite color to it (i.e., `!colors[node]`) and pushes it onto the stack. If the adjacent vertex has already been colored and its color is the same as the current vertex's color, then the graph cannot be two-colorable, and the function returns false.\n\n\tIf the traversal completes without any conflicts (i.e., no adjacent vertices have the same color), the function returns true, indicating that the graph is two-colorable.\n\n\tThe algorithm relies on the fact that a graph is two-colorable if and only if it is bipartite, and the two colors represent the two disjoint sets of vertices in the bipartite graph.\n\n\tHere's a step-by-step explanation of the algorithm:\n\n\t1. Initialize the `colors` map with the first vertex (0) assigned the color true (representing one group of vertices).\n\t2. Initialize an empty stack and push the first vertex (0) onto it.\n\t3. While the stack is not empty, repeat the following steps:\n\ta. Pop the top vertex from the stack (denoted by `node`).\n\tb. For each vertex `connection` connected to `node` (i.e., `edges[node]`), do the following:\n\t\ti. If `connection` has not been colored yet (not present in the `colors` map), assign it the opposite color of\n\t\t`node` (i.e., `!colors[node]`) and push it onto the stack.\n\t\tii. If `connection` has already been colored and its color is the same as `node`'s color, return false since the\n\t\tgraph is not two-colorable.\n\t4. If the traversal completes without conflicts, return true, indicating that the graph is two-colorable.\n\n\tNote: The algorithm assumes that the graph is connected, meaning there is a path from any vertex to any other vertex.\n\tIf the graph is not connected, the algorithm will only determine whether the connected component containing vertex 0 is two-colorable.\n\n\tO(v + e) time | O(v) space - where v is the number of vertices and e is the number of edges in the graph\n\n*/\npackage main\n\nfunc TwoColorable(edges [][]int) bool {\n\t// colors keeps track of the colors assigned to each vertex.\n\t// We start by assigning the first vertex (0) the color true (denoted by 0: true).\n\tcolors := map[int]bool{\n\t\t0: true,\n\t}\n\n\t// stack is used for depth-first traversal of the graph.\n\tstack := []int{0}\n\n\tfor len(stack) > 0 {\n\t\t// Pop the top vertex from the stack (denoted by 'node').\n\t\tnode := stack[len(stack)-1]\n\t\tstack = stack[:len(stack)-1]\n\n\t\t// Explore adjacent vertices (connections) of the current vertex 'node'.\n\t\tfor _, connection := range edges[node] {\n\t\t\t// If the adjacent vertex has not been colored yet (not present in the 'colors' map),\n\t\t\t// assign it the opposite color of the current vertex (denoted by '!colors[node]'),\n\t\t\t// and push it onto the stack.\n\t\t\tif _, colorFound := colors[connection]; !colorFound {\n\t\t\t\tcolors[connection] = !colors[node]\n\t\t\t\tstack = append(stack, connection)\n\t\t\t} else {\n\t\t\t\t// If the adjacent vertex has already been colored and its color is the same as the current vertex's color,\n\t\t\t\t// then the graph cannot be two-colorable, return false.\n\t\t\t\tif colors[connection] == colors[node] {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// If the traversal completes without any conflicts (no adjacent vertices have the same color),\n\t// return true, indicating that the graph is two-colorable.\n\treturn true\n}\n"
  },
  {
    "path": "Graphs/two_colorable.java",
    "content": "/*\n\tYou're given a list of edges  representing a connected, unweighted, undirected graph with at least one node.\n\tWrite a function that returns a boolean representing whether the given graph is two-colorable.\n\n\tExplanation:\n\tThe code snippet implements an algorithm to determine if a given graph is two-colorable or bipartite. A graph is two-colorable if its vertices can be divided into two groups such that no two adjacent vertices have the same color.\n\n\tThe function `TwoColorable(edges [][]int) bool` takes a 2D array of integers `edges`, representing the edges of the graph. Each row `edges[i]` contains the list of vertices that are connected to vertex `i`.\n\n\tThe algorithm uses a stack and a map to keep track of the colors assigned to the vertices. It starts by assigning the first vertex (vertex 0) to color true and pushing it onto the stack.\n\n\tThen, it performs a depth-first traversal of the graph using the stack. For each vertex popped from the stack, it explores its adjacent vertices. If an adjacent vertex has not been colored yet (not present in the colors map), it assigns the opposite color to it (i.e., `!colors[node]`) and pushes it onto the stack. If the adjacent vertex has already been colored and its color is the same as the current vertex's color, then the graph cannot be two-colorable, and the function returns false.\n\n\tIf the traversal completes without any conflicts (i.e., no adjacent vertices have the same color), the function returns true, indicating that the graph is two-colorable.\n\n\tThe algorithm relies on the fact that a graph is two-colorable if and only if it is bipartite, and the two colors represent the two disjoint sets of vertices in the bipartite graph.\n\n\tHere's a step-by-step explanation of the algorithm:\n\n\t1. Initialize the `colors` map with the first vertex (0) assigned the color true (representing one group of vertices).\n\t2. Initialize an empty stack and push the first vertex (0) onto it.\n\t3. While the stack is not empty, repeat the following steps:\n\ta. Pop the top vertex from the stack (denoted by `node`).\n\tb. For each vertex `connection` connected to `node` (i.e., `edges[node]`), do the following:\n\t\ti. If `connection` has not been colored yet (not present in the `colors` map), assign it the opposite color of\n\t\t`node` (i.e., `!colors[node]`) and push it onto the stack.\n\t\tii. If `connection` has already been colored and its color is the same as `node`'s color, return false since the\n\t\tgraph is not two-colorable.\n\t4. If the traversal completes without conflicts, return true, indicating that the graph is two-colorable.\n\n\tNote: The algorithm assumes that the graph is connected, meaning there is a path from any vertex to any other vertex.\n\tIf the graph is not connected, the algorithm will only determine whether the connected component containing vertex 0 is two-colorable.\n\n\tO(v + e) time | O(v) space - where v is the number of vertices and e is the number of edges in the graph\n\n*/\nimport java.util.*;\n\npublic class TwoColorable {\n\n    public static boolean isTwoColorable(List<List<Integer>> edges) {\n        // colors keeps track of the colors assigned to each vertex.\n        // We start by assigning the first vertex (0) the color true (denoted by 0: true).\n        Map<Integer, Boolean> colors = new HashMap<>();\n        colors.put(0, true);\n\n        // stack is used for depth-first traversal of the graph.\n        Stack<Integer> stack = new Stack<>();\n        stack.push(0);\n\n        while (!stack.isEmpty()) {\n            // Pop the top vertex from the stack (denoted by 'node').\n            int node = stack.pop();\n\n            // Explore adjacent vertices (connections) of the current vertex 'node'.\n            for (int connection : edges.get(node)) {\n                // If the adjacent vertex has not been colored yet (not present in the 'colors' map),\n                // assign it the opposite color of the current vertex (denoted by '!colors.get(node)'),\n                // and push it onto the stack.\n                if (!colors.containsKey(connection)) {\n                    colors.put(connection, !colors.get(node));\n                    stack.push(connection);\n                } else {\n                    // If the adjacent vertex has already been colored and its color is the same as the current vertex's color,\n                    // then the graph cannot be two-colorable, return false.\n                    if (colors.get(connection) == colors.get(node)) {\n                        return false;\n                    }\n                }\n            }\n        }\n\n        // If the traversal completes without any conflicts (no adjacent vertices have the same color),\n        // return true, indicating that the graph is two-colorable.\n        return true;\n    }\n\n    public static void main(String[] args) {\n        List<List<Integer>> edges = new ArrayList<>();\n        edges.add(Arrays.asList(1, 2));\n        edges.add(Arrays.asList(0, 3));\n        edges.add(Arrays.asList(0, 4));\n        edges.add(Arrays.asList(1));\n        edges.add(Arrays.asList(2));\n\n        boolean isTwoColorable = isTwoColorable(edges);\n        System.out.println(\"Is Two-Colorable: \" + isTwoColorable);\n    }\n}\n"
  },
  {
    "path": "Graphs/two_colorable.js",
    "content": "/*\n\tYou're given a list of edges  representing a connected, unweighted, undirected graph with at least one node.\n\tWrite a function that returns a boolean representing whether the given graph is two-colorable.\n\n\tExplanation:\n\tThe code snippet implements an algorithm to determine if a given graph is two-colorable or bipartite. A graph is two-colorable if its vertices can be divided into two groups such that no two adjacent vertices have the same color.\n\n\tThe function `TwoColorable(edges [][]int) bool` takes a 2D array of integers `edges`, representing the edges of the graph. Each row `edges[i]` contains the list of vertices that are connected to vertex `i`.\n\n\tThe algorithm uses a stack and a map to keep track of the colors assigned to the vertices. It starts by assigning the first vertex (vertex 0) to color true and pushing it onto the stack.\n\n\tThen, it performs a depth-first traversal of the graph using the stack. For each vertex popped from the stack, it explores its adjacent vertices. If an adjacent vertex has not been colored yet (not present in the colors map), it assigns the opposite color to it (i.e., `!colors[node]`) and pushes it onto the stack. If the adjacent vertex has already been colored and its color is the same as the current vertex's color, then the graph cannot be two-colorable, and the function returns false.\n\n\tIf the traversal completes without any conflicts (i.e., no adjacent vertices have the same color), the function returns true, indicating that the graph is two-colorable.\n\n\tThe algorithm relies on the fact that a graph is two-colorable if and only if it is bipartite, and the two colors represent the two disjoint sets of vertices in the bipartite graph.\n\n\tHere's a step-by-step explanation of the algorithm:\n\n\t1. Initialize the `colors` map with the first vertex (0) assigned the color true (representing one group of vertices).\n\t2. Initialize an empty stack and push the first vertex (0) onto it.\n\t3. While the stack is not empty, repeat the following steps:\n\ta. Pop the top vertex from the stack (denoted by `node`).\n\tb. For each vertex `connection` connected to `node` (i.e., `edges[node]`), do the following:\n\t\ti. If `connection` has not been colored yet (not present in the `colors` map), assign it the opposite color of\n\t\t`node` (i.e., `!colors[node]`) and push it onto the stack.\n\t\tii. If `connection` has already been colored and its color is the same as `node`'s color, return false since the\n\t\tgraph is not two-colorable.\n\t4. If the traversal completes without conflicts, return true, indicating that the graph is two-colorable.\n\n\tNote: The algorithm assumes that the graph is connected, meaning there is a path from any vertex to any other vertex.\n\tIf the graph is not connected, the algorithm will only determine whether the connected component containing vertex 0 is two-colorable.\n\n\tO(v + e) time | O(v) space - where v is the number of vertices and e is the number of edges in the graph\n\n*/\nfunction isTwoColorable(edges) {\n  // colors keeps track of the colors assigned to each vertex.\n  // We start by assigning the first vertex (0) the color true (denoted by 0: true).\n  const colors = new Map();\n  colors.set(0, true);\n\n  // stack is used for depth-first traversal of the graph.\n  const stack = [0];\n\n  while (stack.length > 0) {\n    // Pop the top vertex from the stack (denoted by 'node').\n    const node = stack.pop();\n\n    // Explore adjacent vertices (connections) of the current vertex 'node'.\n    for (const connection of edges[node]) {\n      // If the adjacent vertex has not been colored yet (not present in the 'colors' map),\n      // assign it the opposite color of the current vertex (denoted by !colors.get(node)),\n      // and push it onto the stack.\n      if (!colors.has(connection)) {\n        colors.set(connection, !colors.get(node));\n        stack.push(connection);\n      } else {\n        // If the adjacent vertex has already been colored and its color is the same as the current vertex's color,\n        // then the graph cannot be two-colorable, return false.\n        if (colors.get(connection) === colors.get(node)) {\n          return false;\n        }\n      }\n    }\n  }\n\n  // If the traversal completes without any conflicts (no adjacent vertices have the same color),\n  // return true, indicating that the graph is two-colorable.\n  return true;\n}\n\n// Example usage\nconst edges = [[1, 2], [0, 3], [0, 4], [1], [2]];\nconst isTwoColorableResult = isTwoColorable(edges);\nconsole.log(\"Is Two-Colorable:\", isTwoColorableResult);\n"
  },
  {
    "path": "Graphs/two_colorable.py",
    "content": "'''\n\tYou're given a list of edges  representing a connected, unweighted, undirected graph with at least one node.\n\tWrite a function that returns a boolean representing whether the given graph is two-colorable.\n\n\tExplanation:\n\tThe code snippet implements an algorithm to determine if a given graph is two-colorable or bipartite. A graph is two-colorable if its vertices can be divided into two groups such that no two adjacent vertices have the same color.\n\n\tThe function `TwoColorable(edges [][]int) bool` takes a 2D array of integers `edges`, representing the edges of the graph. Each row `edges[i]` contains the list of vertices that are connected to vertex `i`.\n\n\tThe algorithm uses a stack and a map to keep track of the colors assigned to the vertices. It starts by assigning the first vertex (vertex 0) to color true and pushing it onto the stack.\n\n\tThen, it performs a depth-first traversal of the graph using the stack. For each vertex popped from the stack, it explores its adjacent vertices. If an adjacent vertex has not been colored yet (not present in the colors map), it assigns the opposite color to it (i.e., `!colors[node]`) and pushes it onto the stack. If the adjacent vertex has already been colored and its color is the same as the current vertex's color, then the graph cannot be two-colorable, and the function returns false.\n\n\tIf the traversal completes without any conflicts (i.e., no adjacent vertices have the same color), the function returns true, indicating that the graph is two-colorable.\n\n\tThe algorithm relies on the fact that a graph is two-colorable if and only if it is bipartite, and the two colors represent the two disjoint sets of vertices in the bipartite graph.\n\n\tHere's a step-by-step explanation of the algorithm:\n\n\t1. Initialize the `colors` map with the first vertex (0) assigned the color true (representing one group of vertices).\n\t2. Initialize an empty stack and push the first vertex (0) onto it.\n\t3. While the stack is not empty, repeat the following steps:\n\ta. Pop the top vertex from the stack (denoted by `node`).\n\tb. For each vertex `connection` connected to `node` (i.e., `edges[node]`), do the following:\n\t\ti. If `connection` has not been colored yet (not present in the `colors` map), assign it the opposite color of\n\t\t`node` (i.e., `!colors[node]`) and push it onto the stack.\n\t\tii. If `connection` has already been colored and its color is the same as `node`'s color, return false since the\n\t\tgraph is not two-colorable.\n\t4. If the traversal completes without conflicts, return true, indicating that the graph is two-colorable.\n\n\tNote: The algorithm assumes that the graph is connected, meaning there is a path from any vertex to any other vertex.\n\tIf the graph is not connected, the algorithm will only determine whether the connected component containing vertex 0 is two-colorable.\n\n\tO(v + e) time | O(v) space - where v is the number of vertices and e is the number of edges in the graph\n\n'''\ndef is_two_colorable(edges):\n    # colors keeps track of the colors assigned to each vertex.\n    # We start by assigning the first vertex (0) the color True (denoted by 0: True).\n    colors = {0: True}\n\n    # stack is used for depth-first traversal of the graph.\n    stack = [0]\n\n    while stack:\n        # Pop the top vertex from the stack (denoted by 'node').\n        node = stack.pop()\n\n        # Explore adjacent vertices (connections) of the current vertex 'node'.\n        for connection in edges[node]:\n            # If the adjacent vertex has not been colored yet (not present in the 'colors' dictionary),\n            # assign it the opposite color of the current vertex (denoted by not colors[node]),\n            # and push it onto the stack.\n            if connection not in colors:\n                colors[connection] = not colors[node]\n                stack.append(connection)\n            else:\n                # If the adjacent vertex has already been colored and its color is the same as the current vertex's color,\n                # then the graph cannot be two-colorable, return False.\n                if colors[connection] == colors[node]:\n                    return False\n\n    # If the traversal completes without any conflicts (no adjacent vertices have the same color),\n    # return True, indicating that the graph is two-colorable.\n    return True\n\n# Example usage\nedges = [[1, 2], [0, 3], [0, 4], [1], [2]]\nis_two_colorable_result = is_two_colorable(edges)\nprint(\"Is Two-Colorable:\", is_two_colorable_result)\n"
  },
  {
    "path": "Graphs/union_find.cpp",
    "content": "/*\n\tWrite a UnionFind class that implements the union-find (also called a disjoint set) data structure.\n\tThis class should support three methods:\n\n\n\tThe union-find data structure is similar to a traditional set data structure in that it contains a collection\n\tof unique values. However, these values are spread out amongst a variety of distinct disjoint sets, meaning that no set\n\tcan have duplicate values, and no two sets can contain the same value.\n\n\tcreateSet(value) : : Adds a given value in a new set containing only that value.\n\n\tunion(valueOne, valueTwo) : : Takes in two values and determines which sets they are in. If they are in different sets, the sets are combined\n    into a single set. If either value is not in a set or they are in the same set, the function should have no effect.\n\n\tfind(value): : Returns the \"representative\" value of the set for which a value belongs to. This can be any value in the set, but it should\n    always be the same value, regardless of which value in the set find  is passed. If the value is not in a set, the function\n    should return null / none\n\n\tExplanation:\n\tThe provided code snippet is an optimized version of the Union-Find data structure. Here's a detailed explanation:\n\n\t- `UnionFind` struct: It contains two fields, `parents` and `ranks`. The `parents` map stores the parent of\n\teach element, and the `ranks` map stores the rank of each element. The rank is used to optimize the Union operation.\n\n\t- `NewUnionFind` function: It initializes a new instance of the UnionFind struct by creating empty maps for\n\t`parents` and `ranks`.\n\n\t- `CreateSet` method: It creates a new set with the given value. It sets the parent of the value to itself and\n\tinitializes its rank to 0.\n\n\t- `Find` method: It finds the root/representative of the set to which the given value belongs. It starts from the\n\tgiven value and traverses the parent pointers until it reaches the root. It uses path compression optimization to\n\tupdate the parent pointers along the path to the root. Finally, it returns a pointer to the root.\n\n\t`Union` method: It performs the union of two sets represented by the given values. It first checks if both values exist\n\tin the data structure. If either value is missing, it returns without performing any union operation. Otherwise, it finds\n\tthe roots of the two sets using the `Find` method. It compares the ranks of the two roots and performs the union accordingly:\n\n\tIf the rank of the root of `valueOne` is less than the rank of the root of `valueTwo`, it sets the parent of `valueOne`'s\n\troot to `valueTwo`'s root.\n\n\tIf the rank of the root of `valueOne` is greater than the rank of the root of `valueTwo`, it sets the parent of `valueTwo`'s\n\troot to `valueOne`'s root.\n\n\tIf the ranks are equal, it chooses one root as the parent and increments its rank by 1.\n\n\tBy considering the ranks of the roots during the union, the height of the resulting union-find tree can be minimized.\n\n\tThe time and space complexity of the operations in the `UnionFind` data structure are as follows:\n\n\tCreateSet : O(n) time O(1) space\n\tFind : O(log(n)) time O(1) space where n is total number of values\n\tUnion : O(log(n)) time O(1) space where n is total number of values\n\n*/\n#include <iostream>\n#include <unordered_map>\n\nclass UnionFind {\npublic:\n  std::unordered_map<int, int> parents; // Map to store the parent of each element\n  std::unordered_map<int, int> ranks;   // Map to store the rank of each element\n\n  void createSet(int value) {\n    parents[value] = value; // Set the parent of the value to itself\n    ranks[value] = 0;       // Initialize the rank of the value to 0\n  }\n\n  int find(int value) {\n    if (parents.find(value) == parents.end()) {\n      return -1; // Return -1 if the value is not found (not part of any set)\n    }\n\n    int currentParent = value;\n    while (currentParent != parents[currentParent]) {\n      currentParent = parents[currentParent]; // Traverse the parent pointers until reaching the root\n    }\n\n    // Perform path compression by updating parent pointers along the path to the root\n    // This optimization flattens the tree structure, reducing future lookup time\n    while (value != currentParent) {\n      int nextParent = parents[value];\n      parents[value] = currentParent;\n      value = nextParent;\n    }\n\n    return currentParent; // Return the root/representative\n  }\n\n  void unionSets(int valueOne, int valueTwo) {\n    if (parents.find(valueOne) == parents.end() || parents.find(valueTwo) == parents.end()) {\n      return; // Return if either value is not found (not part of any set)\n    }\n\n    int valueOneRoot = find(valueOne); // Find the root of the set containing valueOne\n    int valueTwoRoot = find(valueTwo); // Find the root of the set containing valueTwo\n\n    if (ranks[valueOneRoot] < ranks[valueTwoRoot]) {\n      parents[valueOneRoot] = valueTwoRoot; // Set the parent of valueOne's root to valueTwo's root\n    } else if (ranks[valueOneRoot] > ranks[valueTwoRoot]) {\n      parents[valueTwoRoot] = valueOneRoot; // Set the parent of valueTwo's root to valueOne's root\n    } else {\n      parents[valueOneRoot] = valueTwoRoot; // Set the parent of valueOne's root to valueTwo's root\n      ranks[valueTwoRoot] += 1;             // Increment the rank of valueTwo's root\n    }\n  }\n};\n\nint main() {\n  UnionFind unionFind;\n\n  // Create individual sets\n  unionFind.createSet(1);\n  unionFind.createSet(2);\n  unionFind.createSet(3);\n\n  // Perform union operations\n  unionFind.unionSets(1, 2);\n  unionFind.unionSets(2, 3);\n\n  // Find representatives of values\n  int representative = unionFind.find(3);\n\n  // Check if the representative is found\n  if (representative != -1) {\n    std::cout << \"The representative of 3 is: \" << representative << std::endl;\n  } else {\n    std::cout << \"Value 3 is not found.\" << std::endl;\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "Graphs/union_find.go",
    "content": "/*\n\tWrite a UnionFind class that implements the union-find (also called a disjoint set) data structure.\n\tThis class should support three methods:\n\n\n\tThe union-find data structure is similar to a traditional set data structure in that it contains a collection\n\tof unique values. However, these values are spread out amongst a variety of distinct disjoint sets, meaning that no set\n\tcan have duplicate values, and no two sets can contain the same value.\n\n\tcreateSet(value) : : Adds a given value in a new set containing only that value.\n\n\tunion(valueOne, valueTwo) : : Takes in two values and determines which sets they are in. If they are in different sets, the sets are combined\n    into a single set. If either value is not in a set or they are in the same set, the function should have no effect.\n\n\tfind(value): : Returns the \"representative\" value of the set for which a value belongs to. This can be any value in the set, but it should\n    always be the same value, regardless of which value in the set find  is passed. If the value is not in a set, the function\n    should return null / none\n\n\tExplanation:\n\tThe provided code snippet is an optimized version of the Union-Find data structure. Here's a detailed explanation:\n\n\t- `UnionFind` struct: It contains two fields, `parents` and `ranks`. The `parents` map stores the parent of\n\teach element, and the `ranks` map stores the rank of each element. The rank is used to optimize the Union operation.\n\n\t- `NewUnionFind` function: It initializes a new instance of the UnionFind struct by creating empty maps for\n\t`parents` and `ranks`.\n\n\t- `CreateSet` method: It creates a new set with the given value. It sets the parent of the value to itself and\n\tinitializes its rank to 0.\n\n\t- `Find` method: It finds the root/representative of the set to which the given value belongs. It starts from the\n\tgiven value and traverses the parent pointers until it reaches the root. It uses path compression optimization to\n\tupdate the parent pointers along the path to the root. Finally, it returns a pointer to the root.\n\n\t`Union` method: It performs the union of two sets represented by the given values. It first checks if both values exist\n\tin the data structure. If either value is missing, it returns without performing any union operation. Otherwise, it finds\n\tthe roots of the two sets using the `Find` method. It compares the ranks of the two roots and performs the union accordingly:\n\n\tIf the rank of the root of `valueOne` is less than the rank of the root of `valueTwo`, it sets the parent of `valueOne`'s\n\troot to `valueTwo`'s root.\n\n\tIf the rank of the root of `valueOne` is greater than the rank of the root of `valueTwo`, it sets the parent of `valueTwo`'s\n\troot to `valueOne`'s root.\n\n\tIf the ranks are equal, it chooses one root as the parent and increments its rank by 1.\n\n\tBy considering the ranks of the roots during the union, the height of the resulting union-find tree can be minimized.\n\n\tThe time and space complexity of the operations in the `UnionFind` data structure are as follows:\n\n\tCreateSet : O(n) time O(1) space\n\tFind : O(log(n)) time O(1) space where n is total number of values\n\tUnion : O(log(n)) time O(1) space where n is total number of values\n\n*/\npackage main\n\nimport \"fmt\"\n\ntype UnionFind struct {\n\tparents map[int]int // Map to store the parent of each element\n\tranks   map[int]int // Map to store the rank of each element\n}\n\n// NewUnionFind creates a new instance of the UnionFind struct.\nfunc NewUnionFind() *UnionFind {\n\treturn &UnionFind{\n\t\tparents: map[int]int{},\n\t\tranks:   map[int]int{},\n\t}\n}\n\n// CreateSet creates a new set with the given value.\nfunc (union *UnionFind) CreateSet(value int) {\n\tunion.parents[value] = value  // Set the parent of the value to itself\n\tunion.ranks[value] = 0       // Initialize the rank of the value to 0\n}\n\n// Find finds the root/representative of the set to which the given value belongs.\nfunc (union *UnionFind) Find(value int) *int {\n\tif _, found := union.parents[value]; !found {\n\t\treturn nil // Return nil if the value is not found (not part of any set)\n\t}\n\tcurrentParent := value\n\tfor currentParent != union.parents[currentParent] {\n\t\tcurrentParent = union.parents[currentParent] // Traverse the parent pointers until reaching the root\n\t}\n\n\t// Perform path compression by updating parent pointers along the path to the root\n\t// This optimization flattens the tree structure, reducing future lookup time\n\tfor value != currentParent {\n\t\tnextParent := union.parents[value]\n\t\tunion.parents[value] = currentParent\n\t\tvalue = nextParent\n\t}\n\n\treturn &currentParent // Return a pointer to the root/representative\n}\n\n// Union performs the union of two sets represented by the given values.\nfunc (union *UnionFind) Union(valueOne, valueTwo int) {\n\t_, parentFoundOne := union.parents[valueOne]\n\t_, parentFoundTwo := union.parents[valueTwo]\n\tif !parentFoundOne || !parentFoundTwo {\n\t\treturn // Return if either value is not found (not part of any set)\n\t}\n\n\tvalueOneRoot := *union.Find(valueOne) // Find the root of the set containing valueOne\n\tvalueTwoRoot := *union.Find(valueTwo) // Find the root of the set containing valueTwo\n\n\tif union.ranks[valueOneRoot] < union.ranks[valueTwoRoot] {\n\t\tunion.parents[valueOneRoot] = valueTwoRoot // Set the parent of valueOne's root to valueTwo's root\n\t} else if union.ranks[valueOneRoot] > union.ranks[valueTwoRoot] {\n\t\tunion.parents[valueTwoRoot] = valueOneRoot // Set the parent of valueTwo's root to valueOne's root\n\t} else {\n\t\tunion.parents[valueOneRoot] = valueTwoRoot       // Set the parent of valueOne's root to valueTwo's root\n\t\tunion.ranks[valueTwoRoot] += 1 // Increment the rank of valueTwo's root\n\t}\n}\n\n\nfunc main() {\n\t// Create a new instance of UnionFind\n\tunion := NewUnionFind()\n\n\t// Create individual sets\n\tunion.CreateSet(1)\n\tunion.CreateSet(2)\n\tunion.CreateSet(3)\n\n\t// Perform union operations\n\tunion.Union(1, 2)\n\tunion.Union(2, 3)\n\n\t// Find representatives of values\n\trepresentative := union.Find(3)\n\n\t// Check if the representative is found\n\tif representative != nil {\n\t\tfmt.Println(\"The representative of 3 is:\", *representative)\n\t} else {\n\t\tfmt.Println(\"Value 3 is not found.\")\n\t}\n}"
  },
  {
    "path": "Graphs/union_find.java",
    "content": "/*\n\tWrite a UnionFind class that implements the union-find (also called a disjoint set) data structure.\n\tThis class should support three methods:\n\n\n\tThe union-find data structure is similar to a traditional set data structure in that it contains a collection\n\tof unique values. However, these values are spread out amongst a variety of distinct disjoint sets, meaning that no set\n\tcan have duplicate values, and no two sets can contain the same value.\n\n\tcreateSet(value) : : Adds a given value in a new set containing only that value.\n\n\tunion(valueOne, valueTwo) : : Takes in two values and determines which sets they are in. If they are in different sets, the sets are combined\n    into a single set. If either value is not in a set or they are in the same set, the function should have no effect.\n\n\tfind(value): : Returns the \"representative\" value of the set for which a value belongs to. This can be any value in the set, but it should\n    always be the same value, regardless of which value in the set find  is passed. If the value is not in a set, the function\n    should return null / none\n\n\tExplanation:\n\tThe provided code snippet is an optimized version of the Union-Find data structure. Here's a detailed explanation:\n\n\t- `UnionFind` struct: It contains two fields, `parents` and `ranks`. The `parents` map stores the parent of\n\teach element, and the `ranks` map stores the rank of each element. The rank is used to optimize the Union operation.\n\n\t- `NewUnionFind` function: It initializes a new instance of the UnionFind struct by creating empty maps for\n\t`parents` and `ranks`.\n\n\t- `CreateSet` method: It creates a new set with the given value. It sets the parent of the value to itself and\n\tinitializes its rank to 0.\n\n\t- `Find` method: It finds the root/representative of the set to which the given value belongs. It starts from the\n\tgiven value and traverses the parent pointers until it reaches the root. It uses path compression optimization to\n\tupdate the parent pointers along the path to the root. Finally, it returns a pointer to the root.\n\n\t`Union` method: It performs the union of two sets represented by the given values. It first checks if both values exist\n\tin the data structure. If either value is missing, it returns without performing any union operation. Otherwise, it finds\n\tthe roots of the two sets using the `Find` method. It compares the ranks of the two roots and performs the union accordingly:\n\n\tIf the rank of the root of `valueOne` is less than the rank of the root of `valueTwo`, it sets the parent of `valueOne`'s\n\troot to `valueTwo`'s root.\n\n\tIf the rank of the root of `valueOne` is greater than the rank of the root of `valueTwo`, it sets the parent of `valueTwo`'s\n\troot to `valueOne`'s root.\n\n\tIf the ranks are equal, it chooses one root as the parent and increments its rank by 1.\n\n\tBy considering the ranks of the roots during the union, the height of the resulting union-find tree can be minimized.\n\n\tThe time and space complexity of the operations in the `UnionFind` data structure are as follows:\n\n\tCreateSet : O(n) time O(1) space\n\tFind : O(log(n)) time O(1) space where n is total number of values\n\tUnion : O(log(n)) time O(1) space where n is total number of values\n\n*/\nimport java.util.HashMap;\nimport java.util.Map;\n\nclass UnionFind {\n    private Map<Integer, Integer> parents; // Map to store the parent of each element\n    private Map<Integer, Integer> ranks;   // Map to store the rank of each element\n\n    public UnionFind() {\n        parents = new HashMap<>();\n        ranks = new HashMap<>();\n    }\n\n    public void createSet(int value) {\n        parents.put(value, value); // Set the parent of the value to itself\n        ranks.put(value, 0);       // Initialize the rank of the value to 0\n    }\n\n    public int find(int value) {\n        if (!parents.containsKey(value)) {\n            return -1; // Return -1 if the value is not found (not part of any set)\n        }\n\n        int currentParent = value;\n        while (currentParent != parents.get(currentParent)) {\n            currentParent = parents.get(currentParent); // Traverse the parent pointers until reaching the root\n        }\n\n        // Perform path compression by updating parent pointers along the path to the root\n        // This optimization flattens the tree structure, reducing future lookup time\n        while (value != currentParent) {\n            int nextParent = parents.get(value);\n            parents.put(value, currentParent);\n            value = nextParent;\n        }\n\n        return currentParent; // Return the root/representative\n    }\n\n    public void unionSets(int valueOne, int valueTwo) {\n        if (!parents.containsKey(valueOne) || !parents.containsKey(valueTwo)) {\n            return; // Return if either value is not found (not part of any set)\n        }\n\n        int valueOneRoot = find(valueOne); // Find the root of the set containing valueOne\n        int valueTwoRoot = find(valueTwo); // Find the root of the set containing valueTwo\n\n        if (ranks.get(valueOneRoot) < ranks.get(valueTwoRoot)) {\n            parents.put(valueOneRoot, valueTwoRoot); // Set the parent of valueOne's root to valueTwo's root\n        } else if (ranks.get(valueOneRoot) > ranks.get(valueTwoRoot)) {\n            parents.put(valueTwoRoot, valueOneRoot); // Set the parent of valueTwo's root to valueOne's root\n        } else {\n            parents.put(valueOneRoot, valueTwoRoot); // Set the parent of valueOne's root to valueTwo's root\n            ranks.put(valueTwoRoot, ranks.get(valueTwoRoot) + 1); // Increment the rank of valueTwo's root\n        }\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        UnionFind unionFind = new UnionFind();\n\n        // Create individual sets\n        unionFind.createSet(1);\n        unionFind.createSet(2);\n        unionFind.createSet(3);\n\n        // Perform union operations\n        unionFind.unionSets(1, 2);\n        unionFind.unionSets(2, 3);\n\n        // Find representatives of values\n        int representative = unionFind.find(3);\n\n        // Check if the representative is found\n        if (representative != -1) {\n            System.out.println(\"The representative of 3 is: \" + representative);\n        } else {\n            System.out.println(\"Value 3 is not found.\");\n        }\n    }\n}\n"
  },
  {
    "path": "Graphs/union_find.js",
    "content": "/*\n\tWrite a UnionFind class that implements the union-find (also called a disjoint set) data structure.\n\tThis class should support three methods:\n\n\n\tThe union-find data structure is similar to a traditional set data structure in that it contains a collection\n\tof unique values. However, these values are spread out amongst a variety of distinct disjoint sets, meaning that no set\n\tcan have duplicate values, and no two sets can contain the same value.\n\n\tcreateSet(value) : : Adds a given value in a new set containing only that value.\n\n\tunion(valueOne, valueTwo) : : Takes in two values and determines which sets they are in. If they are in different sets, the sets are combined\n    into a single set. If either value is not in a set or they are in the same set, the function should have no effect.\n\n\tfind(value): : Returns the \"representative\" value of the set for which a value belongs to. This can be any value in the set, but it should\n    always be the same value, regardless of which value in the set find  is passed. If the value is not in a set, the function\n    should return null / none\n\n\tExplanation:\n\tThe provided code snippet is an optimized version of the Union-Find data structure. Here's a detailed explanation:\n\n\t- `UnionFind` struct: It contains two fields, `parents` and `ranks`. The `parents` map stores the parent of\n\teach element, and the `ranks` map stores the rank of each element. The rank is used to optimize the Union operation.\n\n\t- `NewUnionFind` function: It initializes a new instance of the UnionFind struct by creating empty maps for\n\t`parents` and `ranks`.\n\n\t- `CreateSet` method: It creates a new set with the given value. It sets the parent of the value to itself and\n\tinitializes its rank to 0.\n\n\t- `Find` method: It finds the root/representative of the set to which the given value belongs. It starts from the\n\tgiven value and traverses the parent pointers until it reaches the root. It uses path compression optimization to\n\tupdate the parent pointers along the path to the root. Finally, it returns a pointer to the root.\n\n\t`Union` method: It performs the union of two sets represented by the given values. It first checks if both values exist\n\tin the data structure. If either value is missing, it returns without performing any union operation. Otherwise, it finds\n\tthe roots of the two sets using the `Find` method. It compares the ranks of the two roots and performs the union accordingly:\n\n\tIf the rank of the root of `valueOne` is less than the rank of the root of `valueTwo`, it sets the parent of `valueOne`'s\n\troot to `valueTwo`'s root.\n\n\tIf the rank of the root of `valueOne` is greater than the rank of the root of `valueTwo`, it sets the parent of `valueTwo`'s\n\troot to `valueOne`'s root.\n\n\tIf the ranks are equal, it chooses one root as the parent and increments its rank by 1.\n\n\tBy considering the ranks of the roots during the union, the height of the resulting union-find tree can be minimized.\n\n\tThe time and space complexity of the operations in the `UnionFind` data structure are as follows:\n\n\tCreateSet : O(n) time O(1) space\n\tFind : O(log(n)) time O(1) space where n is total number of values\n\tUnion : O(log(n)) time O(1) space where n is total number of values\n\n*/\nclass UnionFind {\n  constructor() {\n    this.parents = {}; // Map to store the parent of each element\n    this.ranks = {}; // Map to store the rank of each element\n  }\n\n  createSet(value) {\n    this.parents[value] = value; // Set the parent of the value to itself\n    this.ranks[value] = 0; // Initialize the rank of the value to 0\n  }\n\n  find(value) {\n    if (!(value in this.parents)) {\n      return null; // Return null if the value is not found (not part of any set)\n    }\n\n    let currentParent = value;\n    while (currentParent !== this.parents[currentParent]) {\n      currentParent = this.parents[currentParent]; // Traverse the parent pointers until reaching the root\n    }\n\n    // Perform path compression by updating parent pointers along the path to the root\n    // This optimization flattens the tree structure, reducing future lookup time\n    while (value !== currentParent) {\n      const nextParent = this.parents[value];\n      this.parents[value] = currentParent;\n      value = nextParent;\n    }\n\n    return currentParent; // Return the root/representative\n  }\n\n  union(valueOne, valueTwo) {\n    if (!(valueOne in this.parents) || !(valueTwo in this.parents)) {\n      return; // Return if either value is not found (not part of any set)\n    }\n\n    const valueOneRoot = this.find(valueOne); // Find the root of the set containing valueOne\n    const valueTwoRoot = this.find(valueTwo); // Find the root of the set containing valueTwo\n\n    if (this.ranks[valueOneRoot] < this.ranks[valueTwoRoot]) {\n      this.parents[valueOneRoot] = valueTwoRoot; // Set the parent of valueOne's root to valueTwo's root\n    } else if (this.ranks[valueOneRoot] > this.ranks[valueTwoRoot]) {\n      this.parents[valueTwoRoot] = valueOneRoot; // Set the parent of valueTwo's root to valueOne's root\n    } else {\n      this.parents[valueOneRoot] = valueTwoRoot; // Set the parent of valueOne's root to valueTwo's root\n      this.ranks[valueTwoRoot] += 1; // Increment the rank of valueTwo's root\n    }\n  }\n}\n\n// Create a new instance of UnionFind\nconst union = new UnionFind();\n\n// Create individual sets\nunion.createSet(1);\nunion.createSet(2);\nunion.createSet(3);\n\n// Perform union operations\nunion.union(1, 2);\nunion.union(2, 3);\n\n// Find representatives of values\nconst representative = union.find(3);\n\n// Check if the representative is found\nif (representative !== null) {\n  console.log(\"The representative of 3 is:\", representative);\n} else {\n  console.log(\"Value 3 is not found.\");\n}\n"
  },
  {
    "path": "Graphs/union_find.py",
    "content": "'''\n\tWrite a UnionFind class that implements the union-find (also called a disjoint set) data structure.\n\tThis class should support three methods:\n\n\n\tThe union-find data structure is similar to a traditional set data structure in that it contains a collection\n\tof unique values. However, these values are spread out amongst a variety of distinct disjoint sets, meaning that no set\n\tcan have duplicate values, and no two sets can contain the same value.\n\n\tcreateSet(value) : : Adds a given value in a new set containing only that value.\n\n\tunion(valueOne, valueTwo) : : Takes in two values and determines which sets they are in. If they are in different sets, the sets are combined\n    into a single set. If either value is not in a set or they are in the same set, the function should have no effect.\n\n\tfind(value): : Returns the \"representative\" value of the set for which a value belongs to. This can be any value in the set, but it should\n    always be the same value, regardless of which value in the set find  is passed. If the value is not in a set, the function\n    should return null / none\n\n\tExplanation:\n\tThe provided code snippet is an optimized version of the Union-Find data structure. Here's a detailed explanation:\n\n\t- `UnionFind` struct: It contains two fields, `parents` and `ranks`. The `parents` map stores the parent of\n\teach element, and the `ranks` map stores the rank of each element. The rank is used to optimize the Union operation.\n\n\t- `NewUnionFind` function: It initializes a new instance of the UnionFind struct by creating empty maps for\n\t`parents` and `ranks`.\n\n\t- `CreateSet` method: It creates a new set with the given value. It sets the parent of the value to itself and\n\tinitializes its rank to 0.\n\n\t- `Find` method: It finds the root/representative of the set to which the given value belongs. It starts from the\n\tgiven value and traverses the parent pointers until it reaches the root. It uses path compression optimization to\n\tupdate the parent pointers along the path to the root. Finally, it returns a pointer to the root.\n\n\t`Union` method: It performs the union of two sets represented by the given values. It first checks if both values exist\n\tin the data structure. If either value is missing, it returns without performing any union operation. Otherwise, it finds\n\tthe roots of the two sets using the `Find` method. It compares the ranks of the two roots and performs the union accordingly:\n\n\tIf the rank of the root of `valueOne` is less than the rank of the root of `valueTwo`, it sets the parent of `valueOne`'s\n\troot to `valueTwo`'s root.\n\n\tIf the rank of the root of `valueOne` is greater than the rank of the root of `valueTwo`, it sets the parent of `valueTwo`'s\n\troot to `valueOne`'s root.\n\n\tIf the ranks are equal, it chooses one root as the parent and increments its rank by 1.\n\n\tBy considering the ranks of the roots during the union, the height of the resulting union-find tree can be minimized.\n\n\tThe time and space complexity of the operations in the `UnionFind` data structure are as follows:\n\n\tCreateSet : O(n) time O(1) space\n\tFind : O(log(n)) time O(1) space where n is total number of values\n\tUnion : O(log(n)) time O(1) space where n is total number of values\n\n'''\nclass UnionFind:\n    def __init__(self):\n        self.parents = {}  # Map to store the parent of each element\n        self.ranks = {}  # Map to store the rank of each element\n\n    def create_set(self, value):\n        self.parents[value] = value  # Set the parent of the value to itself\n        self.ranks[value] = 0  # Initialize the rank of the value to 0\n\n    def find(self, value):\n        if value not in self.parents:\n            return None  # Return None if the value is not found (not part of any set)\n        \n        current_parent = value\n        while current_parent != self.parents[current_parent]:\n            current_parent = self.parents[current_parent]  # Traverse the parent pointers until reaching the root\n\n        # Perform path compression by updating parent pointers along the path to the root\n        # This optimization flattens the tree structure, reducing future lookup time\n        while value != current_parent:\n            next_parent = self.parents[value]\n            self.parents[value] = current_parent\n            value = next_parent\n\n        return current_parent  # Return the root/representative\n\n    def union(self, value_one, value_two):\n        if value_one not in self.parents or value_two not in self.parents:\n            return  # Return if either value is not found (not part of any set)\n\n        value_one_root = self.find(value_one)  # Find the root of the set containing value_one\n        value_two_root = self.find(value_two)  # Find the root of the set containing value_two\n\n        if self.ranks[value_one_root] < self.ranks[value_two_root]:\n            self.parents[value_one_root] = value_two_root  # Set the parent of value_one's root to value_two's root\n        elif self.ranks[value_one_root] > self.ranks[value_two_root]:\n            self.parents[value_two_root] = value_one_root  # Set the parent of value_two's root to value_one's root\n        else:\n            self.parents[value_one_root] = value_two_root  # Set the parent of value_one's root to value_two's root\n            self.ranks[value_two_root] += 1  # Increment the rank of value_two's root\n\n\n# Create a new instance of UnionFind\nunion = UnionFind()\n\n# Create individual sets\nunion.create_set(1)\nunion.create_set(2)\nunion.create_set(3)\n\n# Perform union operations\nunion.union(1, 2)\nunion.union(2, 3)\n\n# Find representatives of values\nrepresentative = union.find(3)\n\n# Check if the representative is found\nif representative is not None:\n    print(\"The representative of 3 is:\", representative)\nelse:\n    print(\"Value 3 is not found.\")\n"
  },
  {
    "path": "Graphs/validate_bst.cpp",
    "content": "/*\n\tWrite a function that takes in a potentially invalid Binary Search Tree (BST) and returns a boolean representing\n\twhether the BST is valid.\n\n\tExplanation:\n\n\tThis code defines a Binary Search Tree (BST) struct with an integer value and left and right nodes that can point to other\n\tBST nodes. The struct also has a method called ValidateBst() that returns a boolean indicating whether the tree is a valid\n\tBST or not.\n\n\tThe BST struct has another method called validateBST() that is used by ValidateBst() to check whether the tree is a valid\n\tBST or not. The validateBST() method takes in two arguments, min and max, which represent the minimum and maximum values\n\tthat the current node's value can take in order to be a valid BST.\n\n\tThe validateBST() method first checks whether the current node's value is within the valid range determined by the min and\n\tmax arguments. If not, the method returns false, indicating that the tree is not a valid BST.\n\n\tIf the current node's value is within the valid range, the method then recursively calls itself on the left and right\n\tchild nodes to check whether their values are within their valid ranges. The valid range for the left child node is defined by the minimum value and the parent node's value, while the valid range for the right child node is defined by the parent node's value and the maximum value.\n\n\tIf all of the nodes in the tree satisfy the BST property, the method returns true, indicating that the tree is a valid BST.\n\n\tO(n) time | O(d) space - where n is the number of nodes in the BST and d is the depth (height) of the BST\n*/\n#include <iostream>\n#include <limits>\n\nstruct TreeNode {\n    int value;\n    TreeNode* left;\n    TreeNode* right;\n\n    TreeNode(int x) : value(x), left(nullptr), right(nullptr) {}\n};\n\n// Function to check if the BST is valid\nbool isValidBST(TreeNode* root) {\n    return isValidBSTHelper(root, std::numeric_limits<long long>::min(), std::numeric_limits<long long>::max());\n}\n\n// Recursive helper function to check if the BST is valid\nbool isValidBSTHelper(TreeNode* node, long long minVal, long long maxVal) {\n    // Base case: if the current node's value is outside the allowed range, then the tree is invalid\n    if (!node || node->value <= minVal || node->value >= maxVal) {\n        return false;\n    }\n\n    // Recursively check the left subtree, making sure all values are less than the current node's value\n    if (!isValidBSTHelper(node->left, minVal, node->value)) {\n        return false;\n    }\n\n    // Recursively check the right subtree, making sure all values are greater than or equal to the current node's value\n    if (!isValidBSTHelper(node->right, node->value, maxVal)) {\n        return false;\n    }\n\n    // If we reach this point, then the tree is valid\n    return true;\n}\n\nint main() {\n    TreeNode* root = new TreeNode(10);\n    root->left = new TreeNode(5);\n    root->right = new TreeNode(15);\n    root->left->left = new TreeNode(2);\n    root->left->right = new TreeNode(7);\n\n    if (isValidBST(root)) {\n        std::cout << \"The BST is valid.\" << std::endl;\n    } else {\n        std::cout << \"The BST is not valid.\" << std::endl;\n    }\n\n    // Clean up memory\n    delete root->left->left;\n    delete root->left->right;\n    delete root->left;\n    delete root->right;\n    delete root;\n\n    return 0;\n}\n"
  },
  {
    "path": "Graphs/validate_bst.go",
    "content": "/*\n\tWrite a function that takes in a potentially invalid Binary Search Tree (BST) and returns a boolean representing\n\twhether the BST is valid.\n\n\tExplanation:\n\n\tThis code defines a Binary Search Tree (BST) struct with an integer value and left and right nodes that can point to other\n\tBST nodes. The struct also has a method called ValidateBst() that returns a boolean indicating whether the tree is a valid\n\tBST or not.\n\n\tThe BST struct has another method called validateBST() that is used by ValidateBst() to check whether the tree is a valid\n\tBST or not. The validateBST() method takes in two arguments, min and max, which represent the minimum and maximum values\n\tthat the current node's value can take in order to be a valid BST.\n\n\tThe validateBST() method first checks whether the current node's value is within the valid range determined by the min and\n\tmax arguments. If not, the method returns false, indicating that the tree is not a valid BST.\n\n\tIf the current node's value is within the valid range, the method then recursively calls itself on the left and right\n\tchild nodes to check whether their values are within their valid ranges. The valid range for the left child node is defined by the minimum value and the parent node's value, while the valid range for the right child node is defined by the parent node's value and the maximum value.\n\n\tIf all of the nodes in the tree satisfy the BST property, the method returns true, indicating that the tree is a valid BST.\n\n\tO(n) time | O(d) space - where n is the number of nodes in the BST and d is the depth (height) of the BST\n*/\npackage main\n\nimport \"math\"\n\ntype BST struct {\n\tValue int\n\n\tLeft  *BST\n\tRight *BST\n}\n\n// ValidateBst is a method of BST that checks if the binary search tree is valid\nfunc (tree *BST) ValidateBst() bool {\n\treturn tree.validateBST(math.MinInt32, math.MaxInt32)\n}\n\n// validateBST is a recursive helper function that checks if the binary search tree is valid\n// min is the minimum value that a node in the subtree rooted at this node can have\n// max is the maximum value that a node in the subtree rooted at this node can have\nfunc (tree *BST) validateBST(min, max int) bool {\n\t// if the current node's value is outside the allowed range, then the tree is invalid\n\tif tree.Value < min || tree.Value >= max {\n\t\treturn false\n\t}\n\t// recursively check the left subtree, making sure all values are less than the current node's value\n\tif tree.Left != nil && !tree.Left.validateBST(min, tree.Value) {\n\t\treturn false\n\t}\n\t// recursively check the right subtree, making sure all values are greater than or equal to the current node's value\n\tif tree.Right != nil && !tree.Right.validateBST(tree.Value, max) {\n\t\treturn false\n\t}\n\t// if we reach this point, then the tree is valid\n\treturn true\n}\n"
  },
  {
    "path": "Graphs/validate_bst.java",
    "content": "/*\n\tWrite a function that takes in a potentially invalid Binary Search Tree (BST) and returns a boolean representing\n\twhether the BST is valid.\n\n\tExplanation:\n\n\tThis code defines a Binary Search Tree (BST) struct with an integer value and left and right nodes that can point to other\n\tBST nodes. The struct also has a method called ValidateBst() that returns a boolean indicating whether the tree is a valid\n\tBST or not.\n\n\tThe BST struct has another method called validateBST() that is used by ValidateBst() to check whether the tree is a valid\n\tBST or not. The validateBST() method takes in two arguments, min and max, which represent the minimum and maximum values\n\tthat the current node's value can take in order to be a valid BST.\n\n\tThe validateBST() method first checks whether the current node's value is within the valid range determined by the min and\n\tmax arguments. If not, the method returns false, indicating that the tree is not a valid BST.\n\n\tIf the current node's value is within the valid range, the method then recursively calls itself on the left and right\n\tchild nodes to check whether their values are within their valid ranges. The valid range for the left child node is defined by the minimum value and the parent node's value, while the valid range for the right child node is defined by the parent node's value and the maximum value.\n\n\tIf all of the nodes in the tree satisfy the BST property, the method returns true, indicating that the tree is a valid BST.\n\n\tO(n) time | O(d) space - where n is the number of nodes in the BST and d is the depth (height) of the BST\n*/\nimport java.util.*;\n\nclass TreeNode {\n    int value;\n    TreeNode left;\n    TreeNode right;\n\n    TreeNode(int x) {\n        value = x;\n        left = null;\n        right = null;\n    }\n}\n\npublic class ValidateBST {\n\n    // Public method to check if the BST is valid\n    public static boolean isValidBST(TreeNode root) {\n        return isValidBSTHelper(root, Long.MIN_VALUE, Long.MAX_VALUE);\n    }\n\n    // Private recursive helper function to check if the BST is valid\n    private static boolean isValidBSTHelper(TreeNode node, long minVal, long maxVal) {\n        // Base case: if the current node's value is outside the allowed range, then the tree is invalid\n        if (node == null || node.value < minVal || node.value >= maxVal) {\n            return false;\n        }\n\n        // Recursively check the left subtree, making sure all values are less than the current node's value\n        if (!isValidBSTHelper(node.left, minVal, node.value)) {\n            return false;\n        }\n\n        // Recursively check the right subtree, making sure all values are greater than or equal to the current node's value\n        if (!isValidBSTHelper(node.right, node.value, maxVal)) {\n            return false;\n        }\n\n        // If we reach this point, then the tree is valid\n        return true;\n    }\n\n    public static void main(String[] args) {\n        TreeNode root = new TreeNode(10);\n        root.left = new TreeNode(5);\n        root.right = new TreeNode(15);\n        root.left.left = new TreeNode(2);\n        root.left.right = new TreeNode(7);\n\n        if (isValidBST(root)) {\n            System.out.println(\"The BST is valid.\");\n        } else {\n            System.out.println(\"The BST is not valid.\");\n        }\n    }\n}\n"
  },
  {
    "path": "Graphs/validate_bst.js",
    "content": "/*\n\tWrite a function that takes in a potentially invalid Binary Search Tree (BST) and returns a boolean representing\n\twhether the BST is valid.\n\n\tExplanation:\n\n\tThis code defines a Binary Search Tree (BST) struct with an integer value and left and right nodes that can point to other\n\tBST nodes. The struct also has a method called ValidateBst() that returns a boolean indicating whether the tree is a valid\n\tBST or not.\n\n\tThe BST struct has another method called validateBST() that is used by ValidateBst() to check whether the tree is a valid\n\tBST or not. The validateBST() method takes in two arguments, min and max, which represent the minimum and maximum values\n\tthat the current node's value can take in order to be a valid BST.\n\n\tThe validateBST() method first checks whether the current node's value is within the valid range determined by the min and\n\tmax arguments. If not, the method returns false, indicating that the tree is not a valid BST.\n\n\tIf the current node's value is within the valid range, the method then recursively calls itself on the left and right\n\tchild nodes to check whether their values are within their valid ranges. The valid range for the left child node is defined by the minimum value and the parent node's value, while the valid range for the right child node is defined by the parent node's value and the maximum value.\n\n\tIf all of the nodes in the tree satisfy the BST property, the method returns true, indicating that the tree is a valid BST.\n\n\tO(n) time | O(d) space - where n is the number of nodes in the BST and d is the depth (height) of the BST\n*/\nclass TreeNode {\n  constructor(value) {\n    this.value = value;\n    this.left = null;\n    this.right = null;\n  }\n}\n\n// Function to check if the BST is valid\nfunction isValidBST(root) {\n  return isValidBSTHelper(root, -Infinity, Infinity);\n}\n\n// Recursive helper function to check if the BST is valid\nfunction isValidBSTHelper(node, minVal, maxVal) {\n  // Base case: if the current node's value is outside the allowed range, then the tree is invalid\n  if (!node || node.value <= minVal || node.value >= maxVal) {\n    return false;\n  }\n\n  // Recursively check the left subtree, making sure all values are less than the current node's value\n  if (!isValidBSTHelper(node.left, minVal, node.value)) {\n    return false;\n  }\n\n  // Recursively check the right subtree, making sure all values are greater than or equal to the current node's value\n  if (!isValidBSTHelper(node.right, node.value, maxVal)) {\n    return false;\n  }\n\n  // If we reach this point, then the tree is valid\n  return true;\n}\n\n// Example usage:\nconst root = new TreeNode(10);\nroot.left = new TreeNode(5);\nroot.right = new TreeNode(15);\nroot.left.left = new TreeNode(2);\nroot.left.right = new TreeNode(7);\n\nif (isValidBST(root)) {\n  console.log(\"The BST is valid.\");\n} else {\n  console.log(\"The BST is not valid.\");\n}\n"
  },
  {
    "path": "Graphs/validate_bst.py",
    "content": "'''\n\tWrite a function that takes in a potentially invalid Binary Search Tree (BST) and returns a boolean representing\n\twhether the BST is valid.\n\n\tExplanation:\n\n\tThis code defines a Binary Search Tree (BST) struct with an integer value and left and right nodes that can point to other\n\tBST nodes. The struct also has a method called ValidateBst() that returns a boolean indicating whether the tree is a valid\n\tBST or not.\n\n\tThe BST struct has another method called validateBST() that is used by ValidateBst() to check whether the tree is a valid\n\tBST or not. The validateBST() method takes in two arguments, min and max, which represent the minimum and maximum values\n\tthat the current node's value can take in order to be a valid BST.\n\n\tThe validateBST() method first checks whether the current node's value is within the valid range determined by the min and\n\tmax arguments. If not, the method returns false, indicating that the tree is not a valid BST.\n\n\tIf the current node's value is within the valid range, the method then recursively calls itself on the left and right\n\tchild nodes to check whether their values are within their valid ranges. The valid range for the left child node is defined by the minimum value and the parent node's value, while the valid range for the right child node is defined by the parent node's value and the maximum value.\n\n\tIf all of the nodes in the tree satisfy the BST property, the method returns true, indicating that the tree is a valid BST.\n\n\tO(n) time | O(d) space - where n is the number of nodes in the BST and d is the depth (height) of the BST\n'''\nimport math\n\nclass BST:\n    def __init__(self, value):\n        self.value = value\n        self.left = None\n        self.right = None\n\n    # Public method to check if the BST is valid\n    def validate_bst(self):\n        return self._validate_bst(-math.inf, math.inf)\n\n    # Private recursive helper function to check if the BST is valid\n    def _validate_bst(self, min_val, max_val):\n        # Base case: if the current node's value is outside the allowed range, then the tree is invalid\n        if self.value < min_val or self.value >= max_val:\n            return False\n        \n        # Recursively check the left subtree, making sure all values are less than the current node's value\n        if self.left and not self.left._validate_bst(min_val, self.value):\n            return False\n        \n        # Recursively check the right subtree, making sure all values are greater than or equal to the current node's value\n        if self.right and not self.right._validate_bst(self.value, max_val):\n            return False\n        \n        # If we reach this point, then the tree is valid\n        return True\n\n# Example usage:\nroot = BST(10)\nroot.left = BST(5)\nroot.right = BST(15)\nroot.left.left = BST(2)\nroot.left.right = BST(7)\n\nif root.validate_bst():\n    print(\"The BST is valid.\")\nelse:\n    print(\"The BST is not valid.\")\n"
  },
  {
    "path": "Graphs/youngest_common_ancestor.cpp",
    "content": "/*\n\n  \tWrite a function that returns the youngest common ancestor to the two descendants.\n\n\tSample Input:\n\tTop ancestor: node A\n\tdescendantOne: node e\n\tdescandantTwo: node I\n\n\tOutput: node B\n          A\n       /     \\\n      B       C\n    /   \\   /   \\\n   D     E F     G\n /   \\\nH     I\n\tExplanation:\n\n\tThis code snippet implements a solution for finding the youngest common ancestor of two descendants in an ancestral tree.\n\n\t- `type AncestralTree struct` defines the structure of a node in the ancestral tree, which contains a name and a\n\treference to its ancestor node.\n\n\t- `func GetYoungestCommonAncestor` is the main function that takes three parameters: `topAncestor` (the topmost ancestor\n\t\tin the tree), `descendantOne` (the first descendant), and `descendantTwo` (the second descendant). It calculates the depths of the two descendants from the top ancestor and then calls the `backTrackAncestralTree` function with the appropriate parameters.\n\n\t- `func getDescendantDepth` calculates the depth of a descendant node from the top ancestor. It iteratively increments the\n\tdepth and traverses through the ancestors until reaching the top ancestor.\n\n\t- `func backTrackAncestralTree` is a helper function that backtracks the ancestral tree starting from the lowest descendant\n\tuntil the depths of both descendants are equal. It first adjusts the position of the lowest descendant based on the depth difference between the two descendants. Then, it moves both descendants up the tree in tandem until they reach the same ancestor node, which is the youngest common ancestor.\n\n\tThe code assumes that the `topAncestor` provided is a valid ancestor of both `descendantOne` and `descendantTwo`.\n\tThe `GetYoungestCommonAncestor` function returns the youngest common ancestor found in the ancestral tree.\n\n\tTo use this code, you need to create instances of the `AncestralTree` struct representing the ancestral tree and its nodes.\n\tYou can then call the `GetYoungestCommonAncestor` function with the appropriate parameters to find the youngest common\n\tancestor of two descendants.\n\n\tO(d) time | O(1) space - where d is the depth (height) of the ancestral tree\n*/\n#include <iostream>\n#include <unordered_set>\n#include <vector>\n\nusing namespace std;\n\nclass AncestralTree {\npublic:\n    string name;\n    AncestralTree* ancestor;\n\n    AncestralTree(string name) {\n        this->name = name;\n        this->ancestor = NULL;\n    }\n};\n\n// Function to calculate the depth of a descendant from the top ancestor\nint getDescendantDepth(AncestralTree* descendant, AncestralTree* topAncestor) {\n    int depth = 0;\n    while (descendant != topAncestor) {\n        depth++;\n        descendant = descendant->ancestor;\n    }\n    return depth;\n}\n\n// Function to backtrack and find the youngest common ancestor\nAncestralTree* backTrackAncestralTree(AncestralTree* lowestDescendant, AncestralTree* higherDescendant, int diff) {\n    while (diff > 0) {\n        lowestDescendant = lowestDescendant->ancestor;\n        diff--;\n    }\n    while (lowestDescendant != higherDescendant) {\n        lowestDescendant = lowestDescendant->ancestor;\n        higherDescendant = higherDescendant->ancestor;\n    }\n    return lowestDescendant;\n}\n\n// Function to find the youngest common ancestor of two descendants\nAncestralTree* getYoungestCommonAncestor(AncestralTree* topAncestor, AncestralTree* descendantOne, AncestralTree* descendantTwo) {\n    int depthOne = getDescendantDepth(descendantOne, topAncestor);\n    int depthTwo = getDescendantDepth(descendantTwo, topAncestor);\n\n    if (depthOne > depthTwo) {\n        return backTrackAncestralTree(descendantOne, descendantTwo, depthOne - depthTwo);\n    }\n    return backTrackAncestralTree(descendantTwo, descendantOne, depthTwo - depthOne);\n}\n\nint main() {\n    // Create the ancestral tree\n    AncestralTree* topAncestor = new AncestralTree(\"A\");\n    AncestralTree* B = new AncestralTree(\"B\");\n    AncestralTree* C = new AncestralTree(\"C\");\n    AncestralTree* D = new AncestralTree(\"D\");\n    AncestralTree* E = new AncestralTree(\"E\");\n    AncestralTree* F = new AncestralTree(\"F\");\n    AncestralTree* G = new AncestralTree(\"G\");\n    AncestralTree* H = new AncestralTree(\"H\");\n    AncestralTree* I = new AncestralTree(\"I\");\n\n    // Set up the ancestral relationships\n\n    //          A\n    //        /   \\\n    //       B     C\n    //      / \\   / \\\n    //     D   E F   G\n    //    /\n    //   H\n    //  /\n    // I\n\n    topAncestor->ancestor = NULL;\n    B->ancestor = topAncestor;\n    C->ancestor = topAncestor;\n    D->ancestor = B;\n    E->ancestor = B;\n    F->ancestor = C;\n    G->ancestor = C;\n    H->ancestor = D;\n    I->ancestor = H;\n\n    // Find the youngest common ancestor of two descendants\n    AncestralTree* descendantOne = F;\n    AncestralTree* descendantTwo = I;\n    AncestralTree* yca = getYoungestCommonAncestor(topAncestor, descendantOne, descendantTwo);\n\n    cout << \"The youngest common ancestor of \" << descendantOne->name << \" and \" << descendantTwo->name << \" is \" << yca->name << \".\" << endl;\n\n    // Clean up memory\n    delete topAncestor;\n    delete B;\n    delete C;\n    delete D;\n    delete E;\n    delete F;\n    delete G;\n    delete H;\n    delete I;\n\n    return 0;\n}\n"
  },
  {
    "path": "Graphs/youngest_common_ancestor.go",
    "content": "/*\n\n  \tWrite a function that returns the youngest common ancestor to the two descendants.\n\n\tSample Input:\n\tTop ancestor: node A\n\tdescendantOne: node e\n\tdescandantTwo: node I\n\n\tOutput: node B\n          A\n       /     \\\n      B       C\n    /   \\   /   \\\n   D     E F     G\n /   \\\nH     I\n\tExplanation:\n\n\tThis code snippet implements a solution for finding the youngest common ancestor of two descendants in an ancestral tree.\n\n\t- `type AncestralTree struct` defines the structure of a node in the ancestral tree, which contains a name and a\n\treference to its ancestor node.\n\n\t- `func GetYoungestCommonAncestor` is the main function that takes three parameters: `topAncestor` (the topmost ancestor\n\t\tin the tree), `descendantOne` (the first descendant), and `descendantTwo` (the second descendant). It calculates the depths of the two descendants from the top ancestor and then calls the `backTrackAncestralTree` function with the appropriate parameters.\n\n\t- `func getDescendantDepth` calculates the depth of a descendant node from the top ancestor. It iteratively increments the\n\tdepth and traverses through the ancestors until reaching the top ancestor.\n\n\t- `func backTrackAncestralTree` is a helper function that backtracks the ancestral tree starting from the lowest descendant\n\tuntil the depths of both descendants are equal. It first adjusts the position of the lowest descendant based on the depth difference between the two descendants. Then, it moves both descendants up the tree in tandem until they reach the same ancestor node, which is the youngest common ancestor.\n\n\tThe code assumes that the `topAncestor` provided is a valid ancestor of both `descendantOne` and `descendantTwo`.\n\tThe `GetYoungestCommonAncestor` function returns the youngest common ancestor found in the ancestral tree.\n\n\tTo use this code, you need to create instances of the `AncestralTree` struct representing the ancestral tree and its nodes.\n\tYou can then call the `GetYoungestCommonAncestor` function with the appropriate parameters to find the youngest common\n\tancestor of two descendants.\n\n\tO(d) time | O(1) space - where d is the depth (height) of the ancestral tree\n*/\npackage main\n\nimport \"fmt\"\n\ntype AncestralTree struct {\n\tName     string\n\tAncestor *AncestralTree\n}\n\n// GetYoungestCommonAncestor finds the youngest common ancestor of two descendants in an ancestral tree.\nfunc GetYoungestCommonAncestor(topAncestor, descendantOne, descendantTwo *AncestralTree) *AncestralTree {\n\t// Calculate the depths of the two descendants from the top ancestor\n\tdepthOne := getDescendantDepth(descendantOne, topAncestor)\n\tdepthTwo := getDescendantDepth(descendantTwo, topAncestor)\n\n\tif depthOne > depthTwo {\n\t\t// If depthOne is greater, backtrack the ancestral tree from descendantOne to align the depths\n\t\treturn backTrackAncestralTree(descendantOne, descendantTwo, depthOne-depthTwo)\n\t}\n\n\t// If depthTwo is greater or both depths are equal, backtrack the ancestral tree from descendantTwo\n\t// to align the depths\n\treturn backTrackAncestralTree(descendantTwo, descendantOne, depthTwo-depthOne)\n}\n\n// getDescendantDepth calculates the depth of a descendant node from the top ancestor.\nfunc getDescendantDepth(descendant, topAncestor *AncestralTree) int {\n\tdepth := 0\n\tfor descendant != topAncestor {\n\t\tdepth++\n\t\tdescendant = descendant.Ancestor\n\t}\n\treturn depth\n}\n\n// backTrackAncestralTree backtracks the ancestral tree to find the youngest common ancestor.\nfunc backTrackAncestralTree(lowestDescendant, higherDescendant *AncestralTree, diff int) *AncestralTree {\n\t// Adjust the position of the lowest descendant based on the depth difference\n\tfor diff > 0 {\n\t\tlowestDescendant = lowestDescendant.Ancestor\n\t\tdiff--\n\t}\n\n\t// Move both descendants up the tree until they reach the same ancestor node\n\tfor lowestDescendant != higherDescendant {\n\t\tlowestDescendant = lowestDescendant.Ancestor\n\t\thigherDescendant = higherDescendant.Ancestor\n\t}\n\n\treturn lowestDescendant\n}\n\n\nfunc main() {\n\t// Create the ancestral tree\n\ttopAncestor := &AncestralTree{Name: \"A\"}\n\tB := &AncestralTree{Name: \"B\", Ancestor: topAncestor}\n\tC := &AncestralTree{Name: \"C\", Ancestor: topAncestor}\n\tD := &AncestralTree{Name: \"D\", Ancestor: B}\n\tF := &AncestralTree{Name: \"F\", Ancestor: C}\n\tI := &AncestralTree{Name: \"I\", Ancestor: D}\n\n\tdescendantOne := F\n\tdescendantTwo := I\n\tyca := GetYoungestCommonAncestor(topAncestor, descendantOne, descendantTwo)\n\n\tfmt.Printf(\"The youngest common ancestor of %s and %s is %s.\\n\", descendantOne.Name, descendantTwo.Name, yca.Name)\n}"
  },
  {
    "path": "Graphs/youngest_common_ancestor.java",
    "content": "/*\n\n  \tWrite a function that returns the youngest common ancestor to the two descendants.\n\n\tSample Input:\n\tTop ancestor: node A\n\tdescendantOne: node e\n\tdescandantTwo: node I\n\n\tOutput: node B\n          A\n       /     \\\n      B       C\n    /   \\   /   \\\n   D     E F     G\n /   \\\nH     I\n\tExplanation:\n\n\tThis code snippet implements a solution for finding the youngest common ancestor of two descendants in an ancestral tree.\n\n\t- `type AncestralTree struct` defines the structure of a node in the ancestral tree, which contains a name and a\n\treference to its ancestor node.\n\n\t- `func GetYoungestCommonAncestor` is the main function that takes three parameters: `topAncestor` (the topmost ancestor\n\t\tin the tree), `descendantOne` (the first descendant), and `descendantTwo` (the second descendant). It calculates the depths of the two descendants from the top ancestor and then calls the `backTrackAncestralTree` function with the appropriate parameters.\n\n\t- `func getDescendantDepth` calculates the depth of a descendant node from the top ancestor. It iteratively increments the\n\tdepth and traverses through the ancestors until reaching the top ancestor.\n\n\t- `func backTrackAncestralTree` is a helper function that backtracks the ancestral tree starting from the lowest descendant\n\tuntil the depths of both descendants are equal. It first adjusts the position of the lowest descendant based on the depth difference between the two descendants. Then, it moves both descendants up the tree in tandem until they reach the same ancestor node, which is the youngest common ancestor.\n\n\tThe code assumes that the `topAncestor` provided is a valid ancestor of both `descendantOne` and `descendantTwo`.\n\tThe `GetYoungestCommonAncestor` function returns the youngest common ancestor found in the ancestral tree.\n\n\tTo use this code, you need to create instances of the `AncestralTree` struct representing the ancestral tree and its nodes.\n\tYou can then call the `GetYoungestCommonAncestor` function with the appropriate parameters to find the youngest common\n\tancestor of two descendants.\n\n\tO(d) time | O(1) space - where d is the depth (height) of the ancestral tree\n*/\nclass AncestralTree {\n    String name;\n    AncestralTree ancestor;\n\n    public AncestralTree(String name) {\n        this.name = name;\n        this.ancestor = null;\n    }\n}\n\npublic class Main {\n    // Function to calculate the depth of a descendant from the top ancestor\n    public static int getDescendantDepth(AncestralTree descendant, AncestralTree topAncestor) {\n        int depth = 0;\n        while (descendant != topAncestor) {\n            depth++;\n            descendant = descendant.ancestor;\n        }\n        return depth;\n    }\n\n    // Function to backtrack and find the youngest common ancestor\n    public static AncestralTree backTrackAncestralTree(AncestralTree lowestDescendant, AncestralTree higherDescendant, int diff) {\n        while (diff > 0) {\n            lowestDescendant = lowestDescendant.ancestor;\n            diff--;\n        }\n        while (lowestDescendant != higherDescendant) {\n            lowestDescendant = lowestDescendant.ancestor;\n            higherDescendant = higherDescendant.ancestor;\n        }\n        return lowestDescendant;\n    }\n\n    // Function to find the youngest common ancestor of two descendants\n    public static AncestralTree getYoungestCommonAncestor(AncestralTree topAncestor, AncestralTree descendantOne, AncestralTree descendantTwo) {\n        int depthOne = getDescendantDepth(descendantOne, topAncestor);\n        int depthTwo = getDescendantDepth(descendantTwo, topAncestor);\n\n        if (depthOne > depthTwo) {\n            return backTrackAncestralTree(descendantOne, descendantTwo, depthOne - depthTwo);\n        }\n        return backTrackAncestralTree(descendantTwo, descendantOne, depthTwo - depthOne);\n    }\n\n    public static void main(String[] args) {\n        // Create the ancestral tree\n        AncestralTree topAncestor = new AncestralTree(\"A\");\n        AncestralTree B = new AncestralTree(\"B\");\n        AncestralTree C = new AncestralTree(\"C\");\n        AncestralTree D = new AncestralTree(\"D\");\n        AncestralTree E = new AncestralTree(\"E\");\n        AncestralTree F = new AncestralTree(\"F\");\n        AncestralTree G = new AncestralTree(\"G\");\n        AncestralTree H = new AncestralTree(\"H\");\n        AncestralTree I = new AncestralTree(\"I\");\n\n        // Set up the ancestral relationships\n\n        //          A\n        //        /   \\\n        //       B     C\n        //      / \\   / \\\n        //     D   E F   G\n        //    /\n        //   H\n        //  /\n        // I\n\n        topAncestor.ancestor = null;\n        B.ancestor = topAncestor;\n        C.ancestor = topAncestor;\n        D.ancestor = B;\n        E.ancestor = B;\n        F.ancestor = C;\n        G.ancestor = C;\n        H.ancestor = D;\n        I.ancestor = H;\n\n        // Find the youngest common ancestor of two descendants\n        AncestralTree descendantOne = F;\n        AncestralTree descendantTwo = I;\n        AncestralTree yca = getYoungestCommonAncestor(topAncestor, descendantOne, descendantTwo);\n\n        System.out.println(\"The youngest common ancestor of \" + descendantOne.name + \" and \" + descendantTwo.name + \" is \" + yca.name);\n    }\n}\n"
  },
  {
    "path": "Graphs/youngest_common_ancestor.js",
    "content": "/*\n\n  \tWrite a function that returns the youngest common ancestor to the two descendants.\n\n\tSample Input:\n\tTop ancestor: node A\n\tdescendantOne: node e\n\tdescandantTwo: node I\n\n\tOutput: node B\n          A\n       /     \\\n      B       C\n    /   \\   /   \\\n   D     E F     G\n /   \\\nH     I\n\tExplanation:\n\n\tThis code snippet implements a solution for finding the youngest common ancestor of two descendants in an ancestral tree.\n\n\t- `type AncestralTree struct` defines the structure of a node in the ancestral tree, which contains a name and a\n\treference to its ancestor node.\n\n\t- `func GetYoungestCommonAncestor` is the main function that takes three parameters: `topAncestor` (the topmost ancestor\n\t\tin the tree), `descendantOne` (the first descendant), and `descendantTwo` (the second descendant). It calculates the depths of the two descendants from the top ancestor and then calls the `backTrackAncestralTree` function with the appropriate parameters.\n\n\t- `func getDescendantDepth` calculates the depth of a descendant node from the top ancestor. It iteratively increments the\n\tdepth and traverses through the ancestors until reaching the top ancestor.\n\n\t- `func backTrackAncestralTree` is a helper function that backtracks the ancestral tree starting from the lowest descendant\n\tuntil the depths of both descendants are equal. It first adjusts the position of the lowest descendant based on the depth difference between the two descendants. Then, it moves both descendants up the tree in tandem until they reach the same ancestor node, which is the youngest common ancestor.\n\n\tThe code assumes that the `topAncestor` provided is a valid ancestor of both `descendantOne` and `descendantTwo`.\n\tThe `GetYoungestCommonAncestor` function returns the youngest common ancestor found in the ancestral tree.\n\n\tTo use this code, you need to create instances of the `AncestralTree` struct representing the ancestral tree and its nodes.\n\tYou can then call the `GetYoungestCommonAncestor` function with the appropriate parameters to find the youngest common\n\tancestor of two descendants.\n\n\tO(d) time | O(1) space - where d is the depth (height) of the ancestral tree\n*/\nclass AncestralTree {\n  constructor(name) {\n    this.name = name;\n    this.ancestor = null;\n  }\n}\n\n// Function to calculate the depth of a descendant from the top ancestor\nfunction getDescendantDepth(descendant, topAncestor) {\n  let depth = 0;\n  while (descendant !== topAncestor) {\n    depth += 1;\n    descendant = descendant.ancestor;\n  }\n  return depth;\n}\n\n// Function to backtrack and find the youngest common ancestor\nfunction backTrackAncestralTree(lowestDescendant, higherDescendant, diff) {\n  while (diff > 0) {\n    lowestDescendant = lowestDescendant.ancestor;\n    diff -= 1;\n  }\n  while (lowestDescendant !== higherDescendant) {\n    lowestDescendant = lowestDescendant.ancestor;\n    higherDescendant = higherDescendant.ancestor;\n  }\n  return lowestDescendant;\n}\n\n// Function to find the youngest common ancestor of two descendants\nfunction getYoungestCommonAncestor(topAncestor, descendantOne, descendantTwo) {\n  const depthOne = getDescendantDepth(descendantOne, topAncestor);\n  const depthTwo = getDescendantDepth(descendantTwo, topAncestor);\n\n  if (depthOne > depthTwo) {\n    return backTrackAncestralTree(\n      descendantOne,\n      descendantTwo,\n      depthOne - depthTwo\n    );\n  }\n  return backTrackAncestralTree(\n    descendantTwo,\n    descendantOne,\n    depthTwo - depthOne\n  );\n}\n\n// Create the ancestral tree\nconst topAncestor = new AncestralTree(\"A\");\nconst B = new AncestralTree(\"B\");\nconst C = new AncestralTree(\"C\");\nconst D = new AncestralTree(\"D\");\nconst E = new AncestralTree(\"E\");\nconst F = new AncestralTree(\"F\");\nconst G = new AncestralTree(\"G\");\nconst H = new AncestralTree(\"H\");\nconst I = new AncestralTree(\"I\");\n\n// Set up the ancestral relationships\n\n//          A\n//        /   \\\n//       B     C\n//      / \\   / \\\n//     D   E F   G\n//    /\n//   H\n//  /\n// I\n\ntopAncestor.ancestor = null;\nB.ancestor = topAncestor;\nC.ancestor = topAncestor;\nD.ancestor = B;\nE.ancestor = B;\nF.ancestor = C;\nG.ancestor = C;\nH.ancestor = D;\nI.ancestor = H;\n\n// Find the youngest common ancestor of two descendants\nconst descendantOne = F;\nconst descendantTwo = I;\nconst yca = getYoungestCommonAncestor(\n  topAncestor,\n  descendantOne,\n  descendantTwo\n);\n\nconsole.log(\n  \"The youngest common ancestor of\",\n  descendantOne.name,\n  \"and\",\n  descendantTwo.name,\n  \"is\",\n  yca.name\n);\n"
  },
  {
    "path": "Graphs/youngest_common_ancestor.py",
    "content": "'''\n    Write a function that returns the youngest common ancestor to the two descendants.\n\n        Sample Input:\n        Top ancestor: node A\n        descendantOne: node e\n        descandantTwo: node I\n\n        Output: node B\n            A\n        /     \\\n        B       C\n        /   \\   /   \\\n    D     E F     G\n    /   \\\n    H     I\n        Explanation:\n\n        This code snippet implements a solution for finding the youngest common ancestor of two descendants in an ancestral tree.\n\n        - `type AncestralTree struct` defines the structure of a node in the ancestral tree, which contains a name and a\n        reference to its ancestor node.\n\n        - `func GetYoungestCommonAncestor` is the main function that takes three parameters: `topAncestor` (the topmost ancestor\n            in the tree), `descendantOne` (the first descendant), and `descendantTwo` (the second descendant). It calculates the depths of the two descendants from the top ancestor and then calls the `backTrackAncestralTree` function with the appropriate parameters.\n\n        - `func getDescendantDepth` calculates the depth of a descendant node from the top ancestor. It iteratively increments the\n        depth and traverses through the ancestors until reaching the top ancestor.\n\n        - `func backTrackAncestralTree` is a helper function that backtracks the ancestral tree starting from the lowest descendant\n        until the depths of both descendants are equal. It first adjusts the position of the lowest descendant based on the depth difference between the two descendants. Then, it moves both descendants up the tree in tandem until they reach the same ancestor node, which is the youngest common ancestor.\n\n        The code assumes that the `topAncestor` provided is a valid ancestor of both `descendantOne` and `descendantTwo`.\n        The `GetYoungestCommonAncestor` function returns the youngest common ancestor found in the ancestral tree.\n\n        To use this code, you need to create instances of the `AncestralTree` struct representing the ancestral tree and its nodes.\n        You can then call the `GetYoungestCommonAncestor` function with the appropriate parameters to find the youngest common\n        ancestor of two descendants.\n\n        O(d) time | O(1) space - where d is the depth (height) of the ancestral tree\n'''\nclass AncestralTree:\n    def __init__(self, name):\n        self.name = name\n        self.ancestor = None\n\n# Function to calculate the depth of a descendant from the top ancestor\ndef get_descendant_depth(descendant, top_ancestor):\n    depth = 0\n    while descendant != top_ancestor:\n        depth += 1\n        descendant = descendant.ancestor\n    return depth\n\n# Function to backtrack and find the youngest common ancestor\ndef back_track_ancestral_tree(lowest_descendant, higher_descendant, diff):\n    while diff > 0:\n        lowest_descendant = lowest_descendant.ancestor\n        diff -= 1\n    while lowest_descendant != higher_descendant:\n        lowest_descendant = lowest_descendant.ancestor\n        higher_descendant = higher_descendant.ancestor\n    return lowest_descendant\n\n# Function to find the youngest common ancestor of two descendants\ndef get_youngest_common_ancestor(top_ancestor, descendant_one, descendant_two):\n    depth_one = get_descendant_depth(descendant_one, top_ancestor)\n    depth_two = get_descendant_depth(descendant_two, top_ancestor)\n\n    if depth_one > depth_two:\n        return back_track_ancestral_tree(descendant_one, descendant_two, depth_one - depth_two)\n    return back_track_ancestral_tree(descendant_two, descendant_one, depth_two - depth_one)\n\n# Create the ancestral tree\ntop_ancestor = AncestralTree(\"A\")\nB = AncestralTree(\"B\")\nC = AncestralTree(\"C\")\nD = AncestralTree(\"D\")\nE = AncestralTree(\"E\")\nF = AncestralTree(\"F\")\nG = AncestralTree(\"G\")\nH = AncestralTree(\"H\")\nI = AncestralTree(\"I\")\n\n# Set up the ancestral relationships\n\n#          A\n#        /   \\\n#       B     C\n#      / \\   / \\\n#     D   E F   G\n#    /\n#   H\n#  /\n# I\n\ntop_ancestor.ancestor = None\nB.ancestor = top_ancestor\nC.ancestor = top_ancestor\nD.ancestor = B\nE.ancestor = B\nF.ancestor = C\nG.ancestor = C\nH.ancestor = D\nI.ancestor = H\n\n# Find the youngest common ancestor of two descendants\ndescendant_one = F\ndescendant_two = I\nyca = get_youngest_common_ancestor(top_ancestor, descendant_one, descendant_two)\n\nprint(\"The youngest common ancestor of\", descendant_one.name, \"and\", descendant_two.name, \"is\", yca.name)\n"
  },
  {
    "path": "Greedy/coin_change.go",
    "content": "/*\n\tThe coin change problem is a classic algorithmic problem, where given a target amount and a set of coin\n\tdenominations, we need to find the minimum number of coins required to make up that amount.\n\n\tIn this implementation, we start by sorting the array of coin denominations in descending order.\n\tWe then iterate through the array from largest to smallest denomination, and for each denomination,\n\twe repeatedly subtract the largest possible multiple of that denomination from the target amount\n\tuntil we reach 0.\n\n\tThe time complexity of this algorithm is O(n log n) due to the sorting step, where n is the number\n\tof coin denominations. However, the space complexity is O(1) since we are only using a constant\n\tamount of extra space.\n\n\tFor the sample input coins := []int{1, 5, 10, 25} and target := 36, the output should be Minimum\n\tnumber of coins required to make 36 cents: 3.\n*/\npackage main\n\nimport \"fmt\"\n\nfunc coinChangeGreedy(coins []int, target int) int {\n    count := 0\n    for i := len(coins) - 1; i >= 0; i-- {\n        for target >= coins[i] {\n            target -= coins[i]\n            count++\n        }\n    }\n    return count\n}\n\nfunc main() {\n    coins := []int{1, 5, 10, 25}\n    target := 36\n    result := coinChangeGreedy(coins, target)\n    fmt.Printf(\"Minimum number of coins required to make %d cents: %d\\n\", target, result)\n}\n"
  },
  {
    "path": "Greedy/coin_change.java",
    "content": "package Greedy;\n\n /*\n * write a code in java with comments foor As a first example, \n * we consider a problem where we are given a set of coins and our task is to \n * form a sum of money n using the coins. The values of the coins are coins = {c1, c2,..., ck}, \n * and each coin can be used as many times we want. What is the minimum number of coins needed? \n * For example, if the coins are the euro coins (in cents) {1,2,5,10,20,50,100,200} and n = 520,\n *  we need at least four coins. The optimal solution is to select coins 200 + 200 + 100 + 20 whose sum is 520\n */\nimport java.util.Arrays;\n\npublic class CoinChange {\n\n    /**\n     * This method finds the minimum number of coins required to make change for a given amount of money using a given set of coins.\n     *\n     *  coins The set of coins that can be used to make change.\n     *  n The amount of money to make change for.\n     * @return The minimum number of coins required to make change for n.\n     */\n    public static int minCoins(int[] coins, int n) {\n        // Create an array to store the minimum number of coins required to make change for each amount of money.\n        int[] dp = new int[n + 1];\n\n        // Initialize the array to Integer.MAX_VALUE. This means that we do not know the minimum number of coins required to make change for any amount of money yet.\n        Arrays.fill(dp, Integer.MAX_VALUE);\n\n        // Set the minimum number of coins required to make change for 0 to 0.\n        dp[0] = 0;\n\n        // Iterate over the coins array.\n        for (int i = 0; i < coins.length; i++) {\n            // Iterate over the dp array.\n            for (int j = coins[i]; j <= n; j++) {\n                // Update the dp[j] element to be the minimum of dp[j] and dp[j - coins[i]] + 1.\n                dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);\n            }\n        }\n\n        // Return the minimum number of coins required to make change for n.\n        return dp[n];\n    }\n\n    public static void main(String[] args) {\n        // Create a set of coins.\n        int[] coins = {1, 2, 5, 10, 20, 50, 100, 200};\n\n        // The amount of money to make change for.\n        int n = 520;\n\n        // Find the minimum number of coins required to make change for n.\n        int minCoins = minCoins(coins, n);\n\n        // Print the minimum number of coins.\n        System.out.println(\"The minimum number of coins required to make change for \" + n + \" cents is \" + minCoins);\n    }\n}\n\n// The minimum number of coins required to make change for 520 cents is 4\n"
  },
  {
    "path": "Greedy/coin_change.js",
    "content": "\nfunction coinChangeGreedy(s, l) {\n    // First step: sort l in descending order\n    l.sort((a, b) => b - a);\n  \n    let r = []; // Result list\n    let sumr = 0; // Keep track of the current sum of r to avoid iterating over r to calculate the sum\n  \n    for (let coin of l) {\n      if (sumr === s) { // The sum of r is the target sum s\n        break;\n      }\n  \n      let n = Math.floor((s - sumr) / coin); // Calculate the max n with sum(r) + l[i] * n <= s\n  \n      for (let i = 0; i < n; i++) { // Append n elements of this coin to r\n        r.push(coin);\n      }\n  \n      sumr += coin * n; // Update the sum of r\n    }\n  \n    if (sumr !== s) { // The target sum s was not reached\n      return false;\n    }\n  \n    return r;\n  }\n  \n  // SAMPLE 1 (optimal)\n  console.log(coinChangeGreedy(60, [5, 10, 25]));\n  \n  // SAMPLE 2 (not optimal)\n  console.log(coinChangeGreedy(50, [25, 10, 30, 5]));\n  \n  // SAMPLE 3 (fails)\n  console.log(coinChangeGreedy(50, [25, 30]));\n  "
  },
  {
    "path": "Greedy/coin_change.py",
    "content": "\"\"\"TASK\n Greedy: provide a greedy solution for the coin change problem\n A greedy algorithm is trying to make the best local decisions, without caring about future decisions.\n That means that a greedy algorithm is faster than better approaches but it has not always the best solution\n In some case a greedy approach does not find a solution at all.\n\n The coin change problem:\n    -> given sum s\n    -> given list of possible coin types l\n\n    The output has to be a list r, which's elements represent coins from coin types from l.\n    r[i] is in l for every i with [0 <= i < length r];\n    The sum of r has to be s;\n    Furthermore the length of r has to be minimal;\n\n    In other words we need to calculate a way to reach the sum s with minimal coins from coin types l\n\n\nSAMPLE DATA\n Take a look on the following Samples\n Sample A (good for greedy):\n    s = 60\n    l = [25, 10, 5];\n    Best output r = [25,25,10] (take 2 coins from type 25 and one 10, we get 60 with only three coins)\n\n Sample B (bad for greedy):\n    s = 50;\n    l = [30, 25, 10, 5]\n    Best output r = [25,25] (take 2 coins from type 25, we get 50 with only two coins)\n\n Sample C (greedy fails)\n    s = 50\n    l = [30, 25]\n    Best output r = [25,25] (take 2 coins from type 25, we get 50 with only two coins)decisions\n\nAPPROACH\n The greedy approach is very simple\n 1. We have to sort l in descendig order\n 2. Iterate over the sorted list, in each step:\n    1. if the sum of r is equal to s, break\n    2. add n coins of type l[i] to r where n is maximal and sum(r) + l[i]*n <= s (add as many as we can from this coins type)\n 3. if the sum of r is equal to s, return r; otherwise the greedy algorithm has failed\n    \nSAMPLE A\n    1. l in descending order l = [25,10,5]\n    2. loop over l (element 25, r=[])\n    3. take 2 25 coins because 0+25*2 <= 60 but not 0+25*3 <= 60 (sum(r)+l[i]*n <= s)\n    4. next iteration (elment 10, r=[25,25])\n    5. take 1 10 coin because 50+10*1 <= 60 (r=[25,25,10])\n    6. sumr == s => break\n    7. return r\n\nSAMPLE B\n    the greedy takes one 30 coin, a 25 coin cannot be taken (30+25 > 25), but 2 10 coins\n    r = [30, 10, 10]\n    the number of coins is 3, but the optimal solution is 2 [25,25].\n    A greedy algorithm does not provide the optimnal solution\n\nSAMPLE C\n    the greedy takes the 30 coin. But this is a bad decision for the future, because the 25 coin cannot be taken (30+25 > 50)\n    that means that the greedy does not provide any solution because a bad decision was made.\n    To get this solution you have to do a dynamic programmic approach\n\nCOMPLEXITY\n    With sorting (random list l):\n        sorting takes log(l)*l time.\n        looping over l takes O(l) time\n        looping over n takes O(n) time\n        thats a time complexity of O(l*logl + l*n)\n        n is dependend on s and l (for a big s and small l values n gets big, for heavily skewed l values too [1000000,1] for s = 1999999)\n        that means that time complexity class will be O(n ^ 2) in worst case (because n is linear to s)\n        If it is assumed that n is always in a certain range (i.e below 10), the time complexity class will be O(n*logn)\n\n        sorting has O(l) space complexity\n        the space complexity for the whole algorithm is O(l+r) with r being the length of r.\n        Best case space complexity class is O(n) where r is assumed very small (linear or better)\n        Otherwise the space complexity is O(r). r is dependend on s (linear):\n            s = 9\n            l = [10, 1]\n            r = [1,1,1,1,1,1,1,1,1] which is O(s)\n\n        that means that space complexity class is O(n)\n    \n    Without sorting (sorted list l):\n        looping over l takes O(l) time\n        looping over n takes O(n) time\n        thats a time complexity of O(l*n)\n        n is dependend on s and l (linear)\n        that means that time complexity class will be O(n ^ 2) in worst case\n        If it is assumed that n is always in a certain range (i.e below 10), the time complexity class will be O(n)\n\n        the space complexity for the whole algorithm is O(r) with r being the length of r.\n        Best case space complexity class is O(1) where r is assumed very small (linear or better)\n        Otherwise the space complexity is O(n) r is dependend on s (linear)\n\n        that means that space complexity class is O(n) (or O(1) in best case)\n\"\"\"\n\ndef coinChangeGreedy(s:int, l:list[int]):\n    #first step: sort l descending\n    l.sort(reverse=True)    #uses some log(n)*n algorithm\n    r = []                  #return list\n    sumr:int = 0            #keep track of the current sum of r to avoid iterating over r to calculate the sum\n    for coin in l:\n        if(sumr == s):      #the sum of r is the target sum s\n            break\n        n = int((s - sumr)/coin)    #calculate the max n with sum(r) + l[i]*n <= s\n        for i in range(n):          #append n elements of this coin to r\n            r.append(coin)\n        sumr += coin*n              #update the r sum\n    if(sumr != s):      #the target sum s was not reached\n        return False\n    return r\n\n#without sorting\ndef coinChangeGreedySorted(s:int, l:list[int]):\n    r = []                  #return list\n    sumr:int = 0            #keep track of the current sum of r to avoid iterating over r to calculate the sum\n    for coin in l:\n        if(sumr == s):      #the sum of r is the target sum s\n            break\n        n = int((s - sumr)/coin)    #calculate the max n with sum(r) + l[i]*n <= s\n        for i in range(n):          #append n elements of this coin to r\n            r.append(coin)\n        sumr += coin*n              #update the r sum\n    if(sumr != s):      #the target sum s was not reached\n        return False\n    return r\n\n\n#SAMPLE 1 (optimal)\nprint(coinChangeGreedy(60, [5, 10, 25]))\n\n#SAMPLE 2 (not optimal)\nprint(coinChangeGreedy(50, [25, 10, 30, 5]))\n\n#SAMPLE 3 (fails)\nprint(coinChangeGreedy(50, [25, 30]))\n\nprint()\n\n#SAMPLE 1 (optimal)\nprint(coinChangeGreedySorted(60, [25, 10, 5]))\n\n#SAMPLE 2 (not optimal)\nprint(coinChangeGreedySorted(50, [30, 25, 10, 5]))\n\n#SAMPLE 3 (fails)\nprint(coinChangeGreedySorted(50, [30, 25]))"
  },
  {
    "path": "Greedy/task_assignment.cpp",
    "content": "/*\n\t\n  \tYou're given an integer k  representing a number of workers and an array of positive integers representing durations of \n\ttasks that must be completed by the workers. Specifically, each worker must complete two unique tasks and can only work \n\ton one task at a time. The number of tasks will always be equal to 2k  such that each worker always has exactly two tasks\n\tto complete. All tasks are independent of one another and can be completed in any order. Workers will complete their \n\tassigned tasks in parallel, and the time taken to complete all tasks will be equal to the time taken to complete\n\tthe longest pair of tasks (see the sample output for an explanation).\n\n  \n\tWrite a function that returns the optimal assignment of tasks to each worker such that the tasks are completed as fast \n\tas possible. Your function should return a list of pairs, where each pair stores the indices of the tasks that should \n\tbe completed by one worker. The pairs should be in the following format: [task1, task2] , where the order of task1 and \n\ttask2  doesn't matter. Your function can return the pairs in any order. If multiple optimal assignments exist, any \n\tcorrect answer will be accepted.\n\n\tSample Input: K = 3\n\ttasks : [1, 3, 5, 3, 1, 4]\n\n\tOutput: [\n\t\t[0, 2],\n\t\t[4, 5],\n\t\t[1, 3]\n\t]\n\n\tExplanation:\n\tThe code snippet is an implementation of the \"Task Assignment\" algorithm. It pairs tasks from a list based on their durations. The goal is to assign tasks to workers in a way that minimizes the total execution time.\n\n\t- The function `TaskAssignment` takes two parameters: `k` (the number of workers) and `tasks` (a list of task durations).\n\t- It initializes variables for `pairedTasks`, which will store the paired tasks, and `taskDurationToIndices`, which is \n\t  a map that will store the indices of each task duration.\n\t- The `getTaskDurationToIndices` function is called to create the map `taskDurationToIndices`, which maps each task \n\t  duration to a list of indices.\n\t- The task durations are sorted in ascending order using `sort.Ints(tasks)`. This allows us to pair the shortest and \n\t  longest durations together efficiently.\n\t- The loop runs `k` times to pair tasks. In each iteration:\n\t- The shortest duration task is selected and its index is retrieved from `taskDurationToIndices`.\n\t- The index of the selected task is removed from the list of indices to ensure it is not paired again.\n\t- The longest duration task is selected in a similar manner, but from the opposite end of the sorted task durations.\n\t- The paired task indices are added to `pairedTasks`.\n\t- Finally, `pairedTasks` is returned as the result.\n\n\n\tThe `getTaskDurationToIndices` function is a helper function that creates a map `taskDurationToIndices`, which maps each \n    task duration to a list of indices where tasks with that duration occur in the `tasks` list.\n\n\tOverall, the algorithm pairs tasks based on their durations while considering the shortest and longest durations together. \n\tThe result is a list of paired task indices.\n\n\tO(nlog(n)) time | O(n) space - where n is the number of tasks\n*/\n#include <vector>\n#include <algorithm>\n#include <unordered_map>\n\nusing namespace std;\n\n// Function to create a map that maps each task duration to a list of indices\n// where tasks with that duration occur in the given tasks list.\nunordered_map<int, vector<int>> getTaskDurationToIndices(vector<int>& tasks) {\n    unordered_map<int, vector<int>> taskDurationToIndices;\n\n    for (int idx = 0; idx < tasks.size(); idx++) {\n        int taskDuration = tasks[idx];\n        taskDurationToIndices[taskDuration].push_back(idx);\n    }\n\n    return taskDurationToIndices;\n}\n\n// Function to pair tasks from the given list based on their durations.\n// It returns a vector of paired task indices.\nvector<vector<int>> TaskAssignment(int k, vector<int>& tasks) {\n    // Initialize variables\n    vector<vector<int>> pairedTasks;\n    unordered_map<int, vector<int>> taskDurationToIndices = getTaskDurationToIndices(tasks);\n    sort(tasks.begin(), tasks.end());\n    int task1Idx, task2Idx;\n\n    // Pair tasks\n    for (int idx = 0; idx < k; idx++) {\n        // Get the shortest duration task\n        int task1Duration = tasks[idx];\n        vector<int>& indicesWithTask1Duration = taskDurationToIndices[task1Duration];\n        task1Idx = indicesWithTask1Duration.back();\n        indicesWithTask1Duration.pop_back();\n\n        // Get the longest duration task\n        int task2SortedIndex = tasks.size() - 1 - idx;\n        int task2Duration = tasks[task2SortedIndex];\n        vector<int>& indicesWithTask2Duration = taskDurationToIndices[task2Duration];\n        task2Idx = indicesWithTask2Duration.back();\n        indicesWithTask2Duration.pop_back();\n\n        // Add the paired tasks to the result\n        pairedTasks.push_back({task1Idx, task2Idx});\n    }\n\n    return pairedTasks;\n}\n"
  },
  {
    "path": "Greedy/task_assignment.go",
    "content": "/*\n\t\n  \tYou're given an integer k  representing a number of workers and an array of positive integers representing durations of \n\ttasks that must be completed by the workers. Specifically, each worker must complete two unique tasks and can only work \n\ton one task at a time. The number of tasks will always be equal to 2k  such that each worker always has exactly two tasks\n\tto complete. All tasks are independent of one another and can be completed in any order. Workers will complete their \n\tassigned tasks in parallel, and the time taken to complete all tasks will be equal to the time taken to complete\n\tthe longest pair of tasks (see the sample output for an explanation).\n\n  \n\tWrite a function that returns the optimal assignment of tasks to each worker such that the tasks are completed as fast \n\tas possible. Your function should return a list of pairs, where each pair stores the indices of the tasks that should \n\tbe completed by one worker. The pairs should be in the following format: [task1, task2] , where the order of task1 and \n\ttask2  doesn't matter. Your function can return the pairs in any order. If multiple optimal assignments exist, any \n\tcorrect answer will be accepted.\n\n\tSample Input: K = 3\n\ttasks : [1, 3, 5, 3, 1, 4]\n\n\tOutput: [\n\t\t[0, 2],\n\t\t[4, 5],\n\t\t[1, 3]\n\t]\n\n\tExplanation:\n\tThe code snippet is an implementation of the \"Task Assignment\" algorithm. It pairs tasks from a list based on their durations. The goal is to assign tasks to workers in a way that minimizes the total execution time.\n\n\t- The function `TaskAssignment` takes two parameters: `k` (the number of workers) and `tasks` (a list of task durations).\n\t- It initializes variables for `pairedTasks`, which will store the paired tasks, and `taskDurationToIndices`, which is \n\t  a map that will store the indices of each task duration.\n\t- The `getTaskDurationToIndices` function is called to create the map `taskDurationToIndices`, which maps each task \n\t  duration to a list of indices.\n\t- The task durations are sorted in ascending order using `sort.Ints(tasks)`. This allows us to pair the shortest and \n\t  longest durations together efficiently.\n\t- The loop runs `k` times to pair tasks. In each iteration:\n\t- The shortest duration task is selected and its index is retrieved from `taskDurationToIndices`.\n\t- The index of the selected task is removed from the list of indices to ensure it is not paired again.\n\t- The longest duration task is selected in a similar manner, but from the opposite end of the sorted task durations.\n\t- The paired task indices are added to `pairedTasks`.\n\t- Finally, `pairedTasks` is returned as the result.\n\n\n\tThe `getTaskDurationToIndices` function is a helper function that creates a map `taskDurationToIndices`, which maps each \n    task duration to a list of indices where tasks with that duration occur in the `tasks` list.\n\n\tOverall, the algorithm pairs tasks based on their durations while considering the shortest and longest durations together. \n\tThe result is a list of paired task indices.\n\n\tO(nlog(n)) time | O(n) space - where n is the number of tasks\n*/\nimport \"sort\"\n\n// TaskAssignment pairs tasks from the given list based on their durations.\n// It returns a list of paired task indices.\nfunc TaskAssignment(k int, tasks []int) [][]int {\n\t// Initialize variables\n\tpairedTasks := make([][]int, 0)\n\ttaskDurationToIndices := getTaskDurationToIndices(tasks)\n\tsort.Ints(tasks)\n\tvar task1Idx, task2Idx int\n\n\t// Pair tasks\n\tfor idx := 0; idx < k; idx++ {\n\t\t// Get the shortest duration task\n\t\ttask1Duration := tasks[idx]\n\t\tindicesWithTask1Duration := taskDurationToIndices[task1Duration]\n\t\ttask1Idx, taskDurationToIndices[task1Duration] = indicesWithTask1Duration[len(indicesWithTask1Duration)-1], indicesWithTask1Duration[:len(indicesWithTask1Duration)-1]\n\n\t\t// Get the longest duration task\n\t\ttask2SortedIndex := len(tasks) - 1 - idx\n\t\ttask2Duration := tasks[task2SortedIndex]\n\t\tindicesWithTask2Duration := taskDurationToIndices[task2Duration]\n\t\ttask2Idx, taskDurationToIndices[task2Duration] = indicesWithTask2Duration[len(indicesWithTask2Duration)-1], indicesWithTask2Duration[:len(indicesWithTask2Duration)-1]\n\n\t\t// Add the paired tasks to the result\n\t\tpairedTasks = append(pairedTasks, []int{task1Idx, task2Idx})\n\t}\n\n\treturn pairedTasks\n}\n\n// getTaskDurationToIndices creates a map that maps each task duration to a list of indices\n// where tasks with that duration occur in the given tasks list.\nfunc getTaskDurationToIndices(tasks []int) map[int][]int {\n\ttaskDurationToIndices := map[int][]int{}\n\n\tfor idx := range tasks {\n\t\ttaskDuration := tasks[idx]\n\t\ttaskDurationToIndices[taskDuration] = append(taskDurationToIndices[taskDuration], idx)\n\t}\n\n\treturn taskDurationToIndices\n}\n"
  },
  {
    "path": "Greedy/task_assignment.java",
    "content": "/*\n\t\n  \tYou're given an integer k  representing a number of workers and an array of positive integers representing durations of \n\ttasks that must be completed by the workers. Specifically, each worker must complete two unique tasks and can only work \n\ton one task at a time. The number of tasks will always be equal to 2k  such that each worker always has exactly two tasks\n\tto complete. All tasks are independent of one another and can be completed in any order. Workers will complete their \n\tassigned tasks in parallel, and the time taken to complete all tasks will be equal to the time taken to complete\n\tthe longest pair of tasks (see the sample output for an explanation).\n\n  \n\tWrite a function that returns the optimal assignment of tasks to each worker such that the tasks are completed as fast \n\tas possible. Your function should return a list of pairs, where each pair stores the indices of the tasks that should \n\tbe completed by one worker. The pairs should be in the following format: [task1, task2] , where the order of task1 and \n\ttask2  doesn't matter. Your function can return the pairs in any order. If multiple optimal assignments exist, any \n\tcorrect answer will be accepted.\n\n\tSample Input: K = 3\n\ttasks : [1, 3, 5, 3, 1, 4]\n\n\tOutput: [\n\t\t[0, 2],\n\t\t[4, 5],\n\t\t[1, 3]\n\t]\n\n\tExplanation:\n\tThe code snippet is an implementation of the \"Task Assignment\" algorithm. It pairs tasks from a list based on their durations. The goal is to assign tasks to workers in a way that minimizes the total execution time.\n\n\t- The function `TaskAssignment` takes two parameters: `k` (the number of workers) and `tasks` (a list of task durations).\n\t- It initializes variables for `pairedTasks`, which will store the paired tasks, and `taskDurationToIndices`, which is \n\t  a map that will store the indices of each task duration.\n\t- The `getTaskDurationToIndices` function is called to create the map `taskDurationToIndices`, which maps each task \n\t  duration to a list of indices.\n\t- The task durations are sorted in ascending order using `sort.Ints(tasks)`. This allows us to pair the shortest and \n\t  longest durations together efficiently.\n\t- The loop runs `k` times to pair tasks. In each iteration:\n\t- The shortest duration task is selected and its index is retrieved from `taskDurationToIndices`.\n\t- The index of the selected task is removed from the list of indices to ensure it is not paired again.\n\t- The longest duration task is selected in a similar manner, but from the opposite end of the sorted task durations.\n\t- The paired task indices are added to `pairedTasks`.\n\t- Finally, `pairedTasks` is returned as the result.\n\n\n\tThe `getTaskDurationToIndices` function is a helper function that creates a map `taskDurationToIndices`, which maps each \n    task duration to a list of indices where tasks with that duration occur in the `tasks` list.\n\n\tOverall, the algorithm pairs tasks based on their durations while considering the shortest and longest durations together. \n\tThe result is a list of paired task indices.\n\n\tO(nlog(n)) time | O(n) space - where n is the number of tasks\n*/\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class TaskAssignment {\n\n    public static int[][] taskAssignment(int k, int[] tasks) {\n        // Initialize variables\n        List<int[]> pairedTasks = new ArrayList<>();\n        Map<Integer, List<Integer>> taskDurationToIndices = getTaskDurationToIndices(tasks);\n        Arrays.sort(tasks);\n        int task1Idx, task2Idx;\n\n        // Pair tasks\n        for (int idx = 0; idx < k; idx++) {\n            // Get the shortest duration task\n            int task1Duration = tasks[idx];\n            List<Integer> indicesWithTask1Duration = taskDurationToIndices.get(task1Duration);\n            task1Idx = indicesWithTask1Duration.remove(indicesWithTask1Duration.size() - 1);\n\n            // Get the longest duration task\n            int task2SortedIndex = tasks.length - 1 - idx;\n            int task2Duration = tasks[task2SortedIndex];\n            List<Integer> indicesWithTask2Duration = taskDurationToIndices.get(task2Duration);\n            task2Idx = indicesWithTask2Duration.remove(indicesWithTask2Duration.size() - 1);\n\n            // Add the paired tasks to the result\n            pairedTasks.add(new int[]{task1Idx, task2Idx});\n        }\n\n        return pairedTasks.toArray(new int[0][2]);\n    }\n\n    private static Map<Integer, List<Integer>> getTaskDurationToIndices(int[] tasks) {\n        Map<Integer, List<Integer>> taskDurationToIndices = new HashMap<>();\n\n        for (int idx = 0; idx < tasks.length; idx++) {\n            int taskDuration = tasks[idx];\n            List<Integer> indices = taskDurationToIndices.getOrDefault(taskDuration, new ArrayList<>());\n            indices.add(idx);\n            taskDurationToIndices.put(taskDuration, indices);\n        }\n\n        return taskDurationToIndices;\n    }\n\n    public static void main(String[] args) {\n        int k = 3;\n        int[] tasks = {1, 3, 5, 3, 1, 4};\n        int[][] pairedTasks = taskAssignment(k, tasks);\n\n        // Print the paired tasks\n        for (int[] pair : pairedTasks) {\n            System.out.println(Arrays.toString(pair));\n        }\n    }\n}\n"
  },
  {
    "path": "Greedy/task_assignment.js",
    "content": "/*\n\t\n  \tYou're given an integer k  representing a number of workers and an array of positive integers representing durations of \n\ttasks that must be completed by the workers. Specifically, each worker must complete two unique tasks and can only work \n\ton one task at a time. The number of tasks will always be equal to 2k  such that each worker always has exactly two tasks\n\tto complete. All tasks are independent of one another and can be completed in any order. Workers will complete their \n\tassigned tasks in parallel, and the time taken to complete all tasks will be equal to the time taken to complete\n\tthe longest pair of tasks (see the sample output for an explanation).\n\n  \n\tWrite a function that returns the optimal assignment of tasks to each worker such that the tasks are completed as fast \n\tas possible. Your function should return a list of pairs, where each pair stores the indices of the tasks that should \n\tbe completed by one worker. The pairs should be in the following format: [task1, task2] , where the order of task1 and \n\ttask2  doesn't matter. Your function can return the pairs in any order. If multiple optimal assignments exist, any \n\tcorrect answer will be accepted.\n\n\tSample Input: K = 3\n\ttasks : [1, 3, 5, 3, 1, 4]\n\n\tOutput: [\n\t\t[0, 2],\n\t\t[4, 5],\n\t\t[1, 3]\n\t]\n\n\tExplanation:\n\tThe code snippet is an implementation of the \"Task Assignment\" algorithm. It pairs tasks from a list based on their durations. The goal is to assign tasks to workers in a way that minimizes the total execution time.\n\n\t- The function `TaskAssignment` takes two parameters: `k` (the number of workers) and `tasks` (a list of task durations).\n\t- It initializes variables for `pairedTasks`, which will store the paired tasks, and `taskDurationToIndices`, which is \n\t  a map that will store the indices of each task duration.\n\t- The `getTaskDurationToIndices` function is called to create the map `taskDurationToIndices`, which maps each task \n\t  duration to a list of indices.\n\t- The task durations are sorted in ascending order using `sort.Ints(tasks)`. This allows us to pair the shortest and \n\t  longest durations together efficiently.\n\t- The loop runs `k` times to pair tasks. In each iteration:\n\t- The shortest duration task is selected and its index is retrieved from `taskDurationToIndices`.\n\t- The index of the selected task is removed from the list of indices to ensure it is not paired again.\n\t- The longest duration task is selected in a similar manner, but from the opposite end of the sorted task durations.\n\t- The paired task indices are added to `pairedTasks`.\n\t- Finally, `pairedTasks` is returned as the result.\n\n\n\tThe `getTaskDurationToIndices` function is a helper function that creates a map `taskDurationToIndices`, which maps each \n    task duration to a list of indices where tasks with that duration occur in the `tasks` list.\n\n\tOverall, the algorithm pairs tasks based on their durations while considering the shortest and longest durations together. \n\tThe result is a list of paired task indices.\n\n\tO(nlog(n)) time | O(n) space - where n is the number of tasks\n*/\nfunction taskAssignment(k, tasks) {\n  // Initialize variables\n  const pairedTasks = [];\n  const taskDurationToIndices = getTaskDurationToIndices(tasks);\n  tasks.sort((a, b) => a - b);\n  let task1Idx, task2Idx;\n\n  // Pair tasks\n  for (let idx = 0; idx < k; idx++) {\n    // Get the shortest duration task\n    const task1Duration = tasks[idx];\n    const indicesWithTask1Duration = taskDurationToIndices[task1Duration];\n    task1Idx = indicesWithTask1Duration.pop();\n\n    // Get the longest duration task\n    const task2SortedIndex = tasks.length - 1 - idx;\n    const task2Duration = tasks[task2SortedIndex];\n    const indicesWithTask2Duration = taskDurationToIndices[task2Duration];\n    task2Idx = indicesWithTask2Duration.pop();\n\n    // Add the paired tasks to the result\n    pairedTasks.push([task1Idx, task2Idx]);\n  }\n\n  return pairedTasks;\n}\n\nfunction getTaskDurationToIndices(tasks) {\n  const taskDurationToIndices = {};\n\n  for (let idx = 0; idx < tasks.length; idx++) {\n    const taskDuration = tasks[idx];\n    if (!taskDurationToIndices[taskDuration]) {\n      taskDurationToIndices[taskDuration] = [];\n    }\n    taskDurationToIndices[taskDuration].push(idx);\n  }\n\n  return taskDurationToIndices;\n}\n\nconst k = 3;\nconst tasks = [1, 3, 5, 3, 1, 4];\nconst pairedTasks = taskAssignment(k, tasks);\n\n// Print the paired tasks\npairedTasks.forEach((pair) => {\n  console.log(pair);\n});\n"
  },
  {
    "path": "Greedy/task_assignment.py",
    "content": "'''\n\n  \tYou're given an integer k  representing a number of workers and an array of positive integers representing durations of \n\ttasks that must be completed by the workers. Specifically, each worker must complete two unique tasks and can only work \n\ton one task at a time. The number of tasks will always be equal to 2k  such that each worker always has exactly two tasks\n\tto complete. All tasks are independent of one another and can be completed in any order. Workers will complete their \n\tassigned tasks in parallel, and the time taken to complete all tasks will be equal to the time taken to complete\n\tthe longest pair of tasks (see the sample output for an explanation).\n\n  \n\tWrite a function that returns the optimal assignment of tasks to each worker such that the tasks are completed as fast \n\tas possible. Your function should return a list of pairs, where each pair stores the indices of the tasks that should \n\tbe completed by one worker. The pairs should be in the following format: [task1, task2] , where the order of task1 and \n\ttask2  doesn't matter. Your function can return the pairs in any order. If multiple optimal assignments exist, any \n\tcorrect answer will be accepted.\n\n\tSample Input: K = 3\n\ttasks : [1, 3, 5, 3, 1, 4]\n\n\tOutput: [\n\t\t[0, 2],\n\t\t[4, 5],\n\t\t[1, 3]\n\t]\n\n\tExplanation:\n\tThe code snippet is an implementation of the \"Task Assignment\" algorithm. It pairs tasks from a list based on their durations. The goal is to assign tasks to workers in a way that minimizes the total execution time.\n\n\t- The function `TaskAssignment` takes two parameters: `k` (the number of workers) and `tasks` (a list of task durations).\n\t- It initializes variables for `pairedTasks`, which will store the paired tasks, and `taskDurationToIndices`, which is \n\t  a map that will store the indices of each task duration.\n\t- The `getTaskDurationToIndices` function is called to create the map `taskDurationToIndices`, which maps each task \n\t  duration to a list of indices.\n\t- The task durations are sorted in ascending order using `sort.Ints(tasks)`. This allows us to pair the shortest and \n\t  longest durations together efficiently.\n\t- The loop runs `k` times to pair tasks. In each iteration:\n\t- The shortest duration task is selected and its index is retrieved from `taskDurationToIndices`.\n\t- The index of the selected task is removed from the list of indices to ensure it is not paired again.\n\t- The longest duration task is selected in a similar manner, but from the opposite end of the sorted task durations.\n\t- The paired task indices are added to `pairedTasks`.\n\t- Finally, `pairedTasks` is returned as the result.\n\n\n\tThe `getTaskDurationToIndices` function is a helper function that creates a map `taskDurationToIndices`, which maps each \n    task duration to a list of indices where tasks with that duration occur in the `tasks` list.\n\n\tOverall, the algorithm pairs tasks based on their durations while considering the shortest and longest durations together. \n\tThe result is a list of paired task indices.\n\n\tO(nlog(n)) time | O(n) space - where n is the number of tasks\n'''\n\ndef task_assignment(k, tasks):\n    # Initialize variables\n    paired_tasks = []\n    task_duration_to_indices = get_task_duration_to_indices(tasks)\n    tasks.sort()\n    \n    for idx in range(k):\n        # Get the shortest duration task\n        task1_duration = tasks[idx]\n        indices_with_task1_duration = task_duration_to_indices[task1_duration]\n        task1_idx = indices_with_task1_duration.pop()\n        \n        # Get the longest duration task\n        task2_sorted_index = len(tasks) - 1 - idx\n        task2_duration = tasks[task2_sorted_index]\n        indices_with_task2_duration = task_duration_to_indices[task2_duration]\n        task2_idx = indices_with_task2_duration.pop()\n        \n        # Add the paired tasks to the result\n        paired_tasks.append([task1_idx, task2_idx])\n    \n    return paired_tasks\n\ndef get_task_duration_to_indices(tasks):\n    task_duration_to_indices = {}\n    \n    for idx in range(len(tasks)):\n        task_duration = tasks[idx]\n        if task_duration not in task_duration_to_indices:\n            task_duration_to_indices[task_duration] = []\n        task_duration_to_indices[task_duration].append(idx)\n    \n    return task_duration_to_indices\n\n# Example usage\nk = 3\ntasks = [1, 3, 5, 3, 1, 4]\npaired_tasks = task_assignment(k, tasks)\n\n# Print the paired tasks\nfor pair in paired_tasks:\n    print(pair)\n"
  },
  {
    "path": "Hash Table/Bloomfilter.cpp",
    "content": "#include <iostream>\n#include <vector>\n#include <bitset>\n#include <functional>\n\nclass BloomFilter {\nprivate:\n    int size;                    // Size of the Bloom Filter bitset\n    std::vector<std::function<size_t(const std::string&)>> hash_functions;\n    std::bitset<1000000> bitset; // Bitset to represent the Bloom Filter\n\npublic:\n    // Constructor to initialize the Bloom Filter with a given size and hash functions\n    BloomFilter(int size, std::vector<std::function<size_t(const std::string&)>> hash_functions)\n        : size(size), hash_functions(hash_functions) {}\n\n    // Function to add an element to the Bloom Filter\n    void add(const std::string& element) {\n        for (const auto& hash_function : hash_functions) {\n            size_t index = hash_function(element) % size;\n            bitset.set(index);\n        }\n    }\n\n    // Function to check if an element may exist in the Bloom Filter\n    bool contains(const std::string& element) {\n        for (const auto& hash_function : hash_functions) {\n            size_t index = hash_function(element) % size;\n            if (!bitset.test(index)) {\n                return false;  // If any bit is not set, the element is definitely not in the filter\n            }\n        }\n        return true; // If all bits are set, the element may exist in the filter (false positives are possible)\n    }\n};\n\n// Example hash function using std::hash\nsize_t hash1(const std::string& str) {\n    return std::hash<std::string>{}(str);\n}\n\n// Example hash function using a custom hash function\nsize_t hash2(const std::string& str) {\n    size_t hash = 0;\n    for (char c : str) {\n        hash = (hash * 31) + c;\n    }\n    return hash;\n}\n\nint main() {\n    // Create a Bloom Filter with a size of 1000000 and two hash functions\n    BloomFilter bloomFilter(1000000, {hash1, hash2});\n\n    // Add elements to the Bloom Filter\n    bloomFilter.add(\"apple\");\n    bloomFilter.add(\"banana\");\n    bloomFilter.add(\"cherry\");\n\n    // Check if elements may exist in the Bloom Filter\n    std::cout << \"Contains 'apple': \" << bloomFilter.contains(\"apple\") << std::endl;     // Should return 1 (true)\n    std::cout << \"Contains 'grape': \" << bloomFilter.contains(\"grape\") << std::endl;     // Should return 0 (false)\n    std::cout << \"Contains 'cherry': \" << bloomFilter.contains(\"cherry\") << std::endl;   // Should return 1 (true)\n    \n    return 0;\n}\n"
  },
  {
    "path": "Hash Table/Convert an array to reduced form using hashing.cpp",
    "content": "/*Declare an array of name ar[ ] with n elements\nCreate a temp[ ] array of size n\nCreate a hashmap for the same datatype of the array\nCopy the elements of array ar [ ] to temp[ ] array\nSort the temp[ ] array in ascending order\nAfter sorting, mapping the values from 0 to n-1 with the temp array.\nReplace the ar[ ] element with the hashtable values.\nPrint the ar[ ] */\n\n\n\n\n\n\n\n\n#include<bits/stdc++.h>\nusing namespace std;\nint main()\n{\n    int ar[] = {12,34,5,6,8};\n\n    /* calculating the size of the given array */\n    int size = sizeof(ar)/sizeof(ar[0]);\n\n     /* creating temp array to sort and manipulate the array*/\n    int temp[size],val=0;\n\n     /* creating an unordered_map*/\n    unordered_map<int,int> mapped;\n\n\n     /* copying the elements from ar to temp array*/\n    for(int i=0;i<size;i++)\n    {\n        temp[i] = ar[i];\n    }\n\n     /*sorting the temp array using the sort method*/\n    sort(temp,temp+size);\n\n\n     /*mapping the values*/\n    for(int i=0;i<size;i++)\n    {\n        mapped[temp[i]] = val++;\n    }\n\n\n     /* reducing the elements of original array and printing them*/\n    cout<<\"Reduced array:\"<<endl;\n    for(int i=0;i<size;i++)\n    {\n        ar[i] = mapped[ar[i]];\n        cout<<ar[i]<<\" \";\n    }\n}\n \n\nPython\n\nif __name__ == '__main__':\n     ar =[12,34,5,6,8]\n     print(\"Given array: \",ar)\n     size = len(ar)\n     val = 0\n     #copying the elements in tmp array using the copy method\n     tmp = ar.copy()\n     #sorting the tmp array\n     tmp.sort()\n     #creating the map\n     mapvalues = {}\n     \n     #mapping the reduced values\n     for i in range(size):\n         mapvalues[tmp[i]] = val\n         val+=1\n         \n    #reducing the original array and printing it\n     for j in range(size):\n         ar[j] = mapvalues[ar[j]]\n         \n     print(\"Reduced array:\",ar)\n"
  },
  {
    "path": "Hash Table/Count_Pairs_of_Points_With_Distance_k.py",
    "content": "#Given a 2D integer array coordinates and an integer k, where coordinates[i] = [xi, yi] are the coordinates of the ith point in a 2D plane.\n\n#We define the distance between two points (x1, y1) and (x2, y2) as (x1 XOR x2) + (y1 XOR y2) where XOR is the bitwise XOR operation.\n\n#Return the number of pairs (i, j) such that i < j and the distance between points i and j is equal to k.\n\ndef count_pairs(coordinates, k):\n    result = 0\n    seen = {}\n    \n    for x, y in coordinates:\n        for split in range(k + 1):\n            x_complement = x ^ split\n            y_complement = y ^ (k - split)\n            result += seen.get((x_complement, y_complement), 0)\n        seen[x, y] = seen.get((x, y), 0) + 1\n    \n    return result\n\n# Take user input for coordinates\ncoordinates = []\nnum_coordinates = int(input(\"Enter the number of coordinates: \"))\n\nfor i in range(num_coordinates):\n    x = int(input(f\"Enter x-coordinate for point {i + 1}: \"))\n    y = int(input(f\"Enter y-coordinate for point {i + 1}: \"))\n    coordinates.append((x, y))\n\n# Take user input for k\nk = int(input(\"Enter the value of k: \"))\n\npair_count = count_pairs(coordinates, k)\nprint(f\"Number of pairs that satisfy the condition: {pair_count}\")\n"
  },
  {
    "path": "Hash Table/HashTable.java",
    "content": "/*\n\n    1. **Class Structure:**\n    - The `HashTable` class represents a hash table for storing key-value pairs.\n    - It uses a nested `Node` class to encapsulate key-value pairs and handle collisions using a linked list.\n    - The hash table is initialized with a default size of 7, but this size can be modified as needed.\n\n    2. **Node Class:**\n    - The `Node` class is a private nested class within the `HashTable`.\n    - Each `Node` contains a key, an associated integer value, and a reference to the next `Node` in case of collisions.\n\n    3. **Constructor:**\n    - The `HashTable` constructor initializes the data map, an array of `Node` objects, with the default size.\n\n    4. **`printTable` Method:**\n    - `printTable` is used to display the contents of the hash table.\n    - It iterates through the data map and prints the key-value pairs for each index.\n    - If there are collisions, it prints all elements using the linked list structure.\n\n    5. **`hash` Method:**\n    - `hash` is a helper method to map a given key to an index in the data map.\n    - It computes a hash code for the key by summing the ASCII values of its characters and applying a modulo operation based on the data map size.\n\n    6. **`set` Method:**\n    - The `set` method adds a new key-value pair to the hash table.\n    - It computes the index for the given key using the `hash` method and creates a new `Node` for the key-value pair.\n    - If there's no collision at the computed index, it directly assigns the new `Node`. If a collision occurs, it appends the new `Node` to the linked list.\n\n    7. **`get` Method:**\n    - The `get` method retrieves the value associated with a given key.\n    - It computes the index for the key using the `hash` method and searches for the key in the linked list at that index.\n    - If found, it returns the associated value; otherwise, it returns 0.\n\n    8. **`keys` Method:**\n    - The `keys` method returns a list of all keys stored in the hash table.\n    - It iterates through the data map, collecting all keys, even in the presence of collisions.\n\n    In summary, the `HashTable` class provides a basic implementation of a hash table for key-value storage. \n    It handles collisions through linked lists, allowing multiple key-value pairs to exist at the same index. \n    The class offers methods to set key-value pairs, retrieve values by keys, list all keys, and print the \n    contents of the hash table.\n * \n*/\nimport java.util.ArrayList;\n\npublic class HashTable {\n    private int size = 7;\n    private Node[] dataMap;\n\n    // Nested Node class to represent key-value pairs\n    class Node {\n        String key;\n        int value;\n        Node next;\n\n        // Constructor to create a new Node\n        Node(String key, int value) {\n            this.key = key;\n            this.value = value;\n        }\n    }\n\n    // Constructor to create the HashTable with an initial size\n    public HashTable() {\n        dataMap = new Node[size];\n    }\n\n    // Method to print the contents of the HashTable\n    public void printTable() {\n        for (int i = 0; i < dataMap.length; i++) {\n            System.out.println(i + \":\");\n            Node temp = dataMap[i];\n            while (temp != null) {\n                System.out.println(\"{\" + temp.key + \"=\" + temp.value + \"}\");\n                temp = temp.next;\n            }\n        }\n    }\n\n    // A hash function to map a key to an index in the dataMap array\n    public int hash(String key) {\n        int hash = 0;\n        char[] keyChars = key.toCharArray();\n        for (int i = 0; i < keyChars.length; i++) {\n            int asciiValue = keyChars[i];\n            hash = (hash + asciiValue * 23) % dataMap.length;\n        }\n        return hash;\n    }\n\n    // Add a key-value pair to the hash table\n    public void set(String key, int value) {\n        int index = hash(key);\n        Node newNode = new Node(key, value);\n        if (dataMap[index] == null) {\n            dataMap[index] = newNode;\n        } else {\n            Node temp = dataMap[index];\n            while (temp.next != null) {\n                temp = temp.next;\n            }\n            temp.next = newNode;\n        }\n    }\n\n    // Get the value associated with a key\n    public int get(String key) {\n        int index = hash(key);\n        Node temp = dataMap[index];\n        while (temp != null) {\n            if (temp.key.equals(key)) { // Use .equals() to compare strings\n                return temp.value;\n            }\n            temp = temp.next;\n        }\n        return 0; // Return 0 if the key is not found\n    }\n\n    // Get a list of all keys in the hash table\n    public ArrayList<String> keys() {\n        ArrayList<String> allKeys = new ArrayList<>();\n        for (int i = 0; i < dataMap.length; i++) {\n            Node temp = dataMap[i];\n            while (temp != null) {\n                allKeys.add(temp.key);\n                temp = temp.next;\n            }\n        }\n        return allKeys;\n    }\n}\n"
  },
  {
    "path": "Hash Table/Longest_substring_without_repeating_characters.py",
    "content": "'''\n    Given a string s, find the length of the longest \n    substring\n    without repeating characters.\n\n    Example 1:\n    Input: s = \"abcabcbb\"\n    Output: 3\n    Explanation: The answer is \"abc\", with the length of 3.\n    \n    Example 2:\n    Input: s = \"bbbbb\"\n    Output: 1\n    Explanation: The answer is \"b\", with the length of 1.\n    \n    Example 3:\n    Input: s = \"pwwkew\"\n    Output: 3\n    Explanation: The answer is \"wke\", with the length of 3.\n    Notice that the answer must be a substring, \"pwke\" is a subsequence and not a substring.\n\n    Constraints:\n    0 <= s.length <= 5 * 104\n    s consists of English letters, digits, symbols and spaces.\n'''\nclass Solution:\n    #Approach-1\n    #Time Complexity - O(N^2), Space complexity - O(N)\n    #Adding brute-force values into hash_map and calculating the max_length\n    def lengthOfLongestSubstring(self, s: str) -> int:\n        if(len(s)==0 or len(s)==1):\n            return len(s)\n        max_length = 0\n        for i in range(len(s)):\n            temp_length,temp = 0,set()\n            for j in range(i,len(s)):\n                if(temp_length<j-i+1 and s[j] not in temp):\n                    temp_length = j-i+1\n                    max_length = max(max_length,temp_length)\n                    temp.add(s[j])\n                else: \n                    break\n        return max_length\n    \n    #Approach - 2\n    #Time Complexity - O(N), WorstCase-O(N^2), Space Complexity - O(N)\n    def lengthOfLongestSubstring(self, s: str) -> int:\n        if(len(s)==0):\n            return 0\n        hash_set = set()\n        start_ind,end_ind = 0,0\n        max_length = -1\n        while(end_ind<len(s)):\n            if(s[end_ind] not in hash_set):\n                hash_set.add(s[end_ind])\n                end_ind+=1\n                max_length = max(max_length,len(hash_set))\n            else:\n                hash_set.remove(s[start_ind])\n                start_ind+=1\n        return max_length\n"
  },
  {
    "path": "Hash Table/Partition.java",
    "content": "import java.util.ArrayList;\nimport java.util.List;\n\npublic class PalindromePartitioning {\n    public static List<List<String>> partition(String s) {\n        List<List<String>> result = new ArrayList<>();\n        List<String> current = new ArrayList<>();\n        backtrack(result, current, s, 0);\n        return result;\n    }\n    \n    private static void backtrack(List<List<String>> result, List<String> current, String s, int start) {\n        if (start == s.length()) {\n            result.add(new ArrayList<>(current));\n            return;\n        }\n        \n        for (int end = start; end < s.length(); end++) {\n            if (isPalindrome(s, start, end)) {\n                current.add(s.substring(start, end + 1));\n                backtrack(result, current, s, end + 1);\n                current.remove(current.size() - 1);\n            }\n        }\n    }\n    \n    private static boolean isPalindrome(String s, int start, int end) {\n        while (start < end) {\n            if (s.charAt(start) != s.charAt(end)) {\n                return false;\n            }\n            start++;\n            end--;\n        }\n        return true;\n    }\n    \n    public static void main(String[] args) {\n        String input = \"aab\";\n        List<List<String>> partitions = partition(input);\n        \n        for (List<String> partition : partitions) {\n            System.out.println(partition);\n        }\n    }\n}\n"
  },
  {
    "path": "Hash Table/Partition_string.py",
    "content": "def is_palindrome(s):\n    return s == s[::-1]\n\ndef min_partition(s):\n    n = len(s)\n    \n    # Create a hash table to store the results of subproblems\n    # dp[i] represents the minimum number of partitions in s[0:i]\n    dp = [float('inf')] * (n + 1)\n    dp[0] = 0\n    \n    # Iterate through the string\n    for i in range(1, n + 1):\n        # Check all possible substrings s[j:i]\n        for j in range(i):\n            # If s[j:i] is a palindrome, update the minimum number of partitions\n            if is_palindrome(s[j:i]):\n                dp[i] = min(dp[i], dp[j] + 1)\n    \n    # Return the minimum number of partitions for the entire string\n    return dp[n] - 1\n\n# Example usage\nstring = \"aabba\"\noptimal_partitions = min_partition(string)\nprint(\"Optimal number of partitions:\", optimal_partitions)\n\n\n'''\nThe min_partition function utilizes dynamic programming to find the minimum number of partitions in the given string s. It iterates through each character in the string and checks all possible substrings. If a substring is a palindrome, it updates the minimum number of partitions accordingly.\n\nNote that the dp list is initialized with float('inf') values, except for the first element dp[0], which is set to 0. The final result subtracts 1 from dp[n] to account for the fact that the last character does not require a partition.\n\n\n\nThe time complexity of the given solution is O(n^3), where n is the length of the input string s. This is because there are two nested loops, and for each combination of i and j, the is_palindrome function is called, which has a time complexity of O(n). Hence, the overall time complexity is O(n^3).\n\nThe space complexity of the solution is O(n), where n is the length of the input string s. This is because the dp list, used to store the minimum number of partitions for each substring, has a length of n + 1. Therefore, the space required is linearly proportional to the length of the input string.\n'''\n"
  },
  {
    "path": "Hash Table/add_first_missing_positive.cpp",
    "content": "/*\n    Given an unsorted integer array nums, return the smallest missing positive integer.\n    You must implement an algorithm that runs in O(n) time and uses O(1) auxiliary space.\n    Sample Input: [3, 4, -1, 1]\n    Sample Output: 2\n    Explanation:\n    This code implements a solution to find the first missing positive integer from an unsorted array. The function first separates positive and negative numbers.\n    It then considers the array with only positive numbers, and marks the index corresponding to every positive number in this array.\n    The first index which is unmarked corresponds to the first missing positive number.\n    This solution uses the array itself as a pseudo-hash table where the keys are the array indices, and the values are whether or not a positive integer is present in the array.\n    By using the array in this way, we are able to find the solution in O(1) auxiliary space.\n    Time complexity: O(n)\n    Space complexity: O(1)\n*/\n\n#include <iostream>\n#include <vector>\n#include <cmath>\n\nint firstMissingPositive(std::vector<int>& nums) {\n    int n = nums.size();\n\n    // Mark numbers that are out of range as 0\n    for (int i = 0; i < n; i++) {\n        if (nums[i] <= 0 || nums[i] > n) {\n            nums[i] = 0;\n        }\n    }\n\n    // Mark the index corresponding to the value of each number\n    for (int i = 0; i < n; i++) {\n        int num = std::abs(nums[i]);\n\n        if (num > 0) {\n            num--; // subtract 1 because of 0-based indexing\n\n            // Mark as negative\n            if (nums[num] > 0) {\n                nums[num] = -nums[num];\n            }\n        }\n    }\n\n    // Find the first number greater than 0\n    for (int i = 0; i < n; i++) {\n        if (nums[i] >= 0) {\n            return i + 1; // add 1 because of 0-based indexing\n        }\n    }\n\n    // If no number is missing\n    return n + 1;\n}\n\nint main() {\n    std::vector<int> nums = {3, 4, -1, 1};\n    int result = firstMissingPositive(nums);\n    std::cout << \"Smallest missing positive integer: \" << result << std::endl;\n    return 0;\n}\n"
  },
  {
    "path": "Hash Table/add_first_missing_positive.java",
    "content": "/*\n    Given an unsorted integer array nums, return the smallest missing positive integer.\n    You must implement an algorithm that runs in O(n) time and uses O(1) auxiliary space.\n\n    Sample Input: [3, 4, -1, 1]\n    Sample Output: 2\n\n    Explanation:\n    This code implements a solution to find the first missing positive integer from an unsorted array. The function first separates positive and negative numbers.\n    It then considers the array with only positive numbers, and marks the index corresponding to every positive number in this array.\n    The first index which is unmarked corresponds to the first missing positive number.\n\n    This solution uses the array itself as a pseudo-hash table where the keys are the array indices, and the values are whether or not a positive integer is present in the array.\n    By using the array in this way, we are able to find the solution in O(1) auxiliary space.\n\n    Time complexity: O(n)\n    Space complexity: O(1)\n*/\n\npublic class AddFirstMissingPositive{\n    public int firstMissingPositive(int[] nums) {\n        int n = nums.length;\n\n        // Mark numbers that are out of range as 0\n        for(int i = 0; i < n; i++) {\n            if(nums[i] <= 0 || nums[i] > n) {\n                nums[i] = 0;\n            }\n        }\n\n        // Mark the index corresponding to the value of each number\n        for(int i = 0; i < n; i++) {\n            int num = Math.abs(nums[i]);\n\n            if(num > 0) {\n                num--; // subtract 1 because of 0-based indexing\n\n                // Mark as negative\n                if(nums[num] > 0) {\n                    nums[num] = -nums[num];\n                }\n            }\n        }\n\n        // Find the first number greater than 0\n        for(int i = 0; i < n; i++) {\n            if(nums[i] >= 0) {\n                return i + 1; // add 1 because of 0-based indexing\n            }\n        }\n\n        // If no number is missing\n        return n + 1;\n    }\n}\n"
  },
  {
    "path": "Hash Table/find_optimal_partition_of_string.cpp",
    "content": "/* OPTIMAL PARTITION OF STRING */\n/* PROGRAM AUTHOR : VARUN GARG */\n\n/*\n\n      Our task is to partition the string into one or more substrings such that the characters in each substring are unique.\n\n      Approach:\n      Intuitively, we can consider adding characters to a substring as long as we don't see a character \n      that has already been added to the current substring. When we see a character that is already\n      present in the substring, we start a new substring and repeat this process until we iterate over the entire string s.\n      we are declaring a set in which if the character is not present in the set then the character will be inserted in it \n      else it will break from the loop then the count of the strings will be increased .\n\n\n      sample input : abacaba\n      sample output : a b \n                      a c\n                      a b\n                      a\n                      The minimum number of substrings required for partition\n                      4\n\n      Time Complexity: O(n)\n      Space Complexity: O(n)\n*/\n#include<bits/stdc++.h>\nusing namespace std;\n\nint main(){\n      string s;\n      cin>>s; // taking input of the string \n\n      int cnt=0;\n      int n=s.size();\n      for(int i=0;i<n;i){\n            // declaring the set in which characters will be inserted by checking if they were present or not\n            set<char> sub; \n            // taking the unique substrings in a set by checking the character is present in the set or not \n            while(i<n && sub.find(s[i]) == sub.end()){\n                  sub.insert(s[i]); \n                  i++;\n            }\n            for(auto x: sub){\n                  cout<<x<<\" \";\n            }\n            cout<<endl;\n            cnt++; // counting the unique substrings \n      }\n\n      cout<<\"The minimum number of substrings required for partition\"<<endl;\n      cout<<cnt;\n}"
  },
  {
    "path": "Hash Table/find_optimal_partition_of_string.go",
    "content": "/*The function isPalindrome checks if a given substring of s is a palindrome. The minCut function utilizes dynamic programming to find the minimum cuts needed for each substring. It initializes a table cuts to store the minimum cuts for each position in the string. It also creates a palindrome table to check if a substring is a palindrome or not.\n\nThe algorithm iterates through the string s from left to right and checks all possible substrings to find palindromes. If a palindrome is found, it updates the cuts table based on the previous cuts. Finally, it returns the minimum cuts needed for the entire string.\n\nIn the main function, we provide an example string \"aabba\" and print the minimum cuts required. You can replace \"aabba\" with your own string to find its optimal partition.\n\nTime Complexity:\nThe outer loop iterates through the string s once, and for each character, it checks all possible substrings. Therefore, the time complexity of the solution is O(n^2), where n is the length of the string.\n\nSpace Complexity:\nThe space complexity is determined by the two tables used: cuts and palindrome. Both tables have a size of n, where n is the length of the string s. Therefore, the space complexity is O(n).\n\nOverall, the solution has a time complexity of O(n^2) and a space complexity of O(n).\n*/\n\n\n\n\nfunc min(x, y int) int {\n\tif x < y {\n\t\treturn x\n\t}\n\treturn y\n}\n\nfunc isPalindrome(s string, i, j int) bool {\n\tfor i < j {\n\t\tif s[i] != s[j] {\n\t\t\treturn false\n\t\t}\n\t\ti++\n\t\tj--\n\t}\n\treturn true\n}\n\nfunc minCut(s string) int {\n\tn := len(s)\n\tif n <= 1 {\n\t\treturn 0\n\t}\n\n\t// Create a table to store the minimum cuts for each substring\n\tcuts := make([]int, n)\n\tpalindrome := make([][]bool, n)\n\n\tfor i := 0; i < n; i++ {\n\t\tpalindrome[i] = make([]bool, n)\n\t\tcuts[i] = i\n\t}\n\n\tfor j := 0; j < n; j++ {\n\t\tfor i := 0; i <= j; i++ {\n\t\t\tif s[i] == s[j] && (j-i <= 1 || palindrome[i+1][j-1]) {\n\t\t\t\tpalindrome[i][j] = true\n\t\t\t\tif i > 0 {\n\t\t\t\t\tcuts[j] = min(cuts[j], cuts[i-1]+1)\n\t\t\t\t} else {\n\t\t\t\t\tcuts[j] = 0\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn cuts[n-1]\n}\n\nfunc main() {\n\ts := \"aabba\"\n\tminimumCuts := minCut(s)\n\tfmt.Println(\"Minimum cuts:\", minimumCuts)\n}\n"
  },
  {
    "path": "Hash Table/first_duplicate_value.go",
    "content": "/*\n\n  \tGiven an array of integers between  1 and n, inclusive, where n is the length of the array, write a function\n\tthat returns the first integer that appears more than once (when the array is read from left to right).\n\n\tSample Input = [2, 1, 5, 2, 3, 3, 4]\n\tOutput : 2\n\n\tThe time complexity of the `FirstDuplicateValue` function is O(n), where n is the length of the\n\tinput `array`. This is because the function iterates through the array once, performing constant\n\ttime operations (checking if a value exists in a hash map and inserting values into the hash map).\n\tThe worst case scenario is that the function iterates through the entire array without finding a\n\tduplicate, resulting in O(n) time complexity.\n\n\tThe space complexity of the given implementation is O(n), where n is the length of the input array.\n\tThis is because we are using a hash table (implemented as a map in Go) to store the elements we have\n\tseen so far. In the worst case, where there are no duplicates in the array, we will end up storing\n\tall n elements in the hash table, which would require O(n) space.\n*/\npackage main\n\nimport \"fmt\"\n\n/*\n\tThis function takes an array of integers as input and returns the first duplicate value found in\n\tthe array. It uses a hash table, implemented as a Go map, to keep track of the numbers seen so far.\n\tFor each number in the input array, the function checks if it has already been seen before by\n\tchecking if it exists as a key in the map. If it has been seen before, the function returns\n\tthe number as it is the first duplicate value found. Otherwise, the function adds the number\n\tto the map with a value of true to indicate that it has been seen.\n*/\nfunc FirstDuplicateValue(array []int) int {\n\tseenSoFar := make(map[int]bool)\n\tfor _, num := range array {\n\t\tif _, valueExists := seenSoFar[num]; valueExists {\n\t\t\treturn num\n\t\t}\n\t\tseenSoFar[num] = true\n\t}\n\treturn -1\n}\n\nfunc main() {\n\tarray := []int{2, 1, 5, 2, 3, 3, 4}\n\tfirstDuplicate := FirstDuplicateValue(array)\n\tfmt.Println(firstDuplicate)\n}\n"
  },
  {
    "path": "Hash Table/first_missing_positve.go",
    "content": "/*\r\n\t-> The firstMissingPositive function takes a slice of integers called nums as input.\r\n\r\n    -> The function determines the length of the slice nums and assigns it to the variable n.\r\n\r\n    -> Step 1: Move positive numbers to their correct positions\r\n        - The algorithm iterates through each element of the slice using a for loop.\r\n        - Inside the loop, it checks if the current number (nums[i]) is positive and within the range of 1 to n.\r\n        - If the number is valid, it checks whether the number at its correct position (nums[nums[i]-1]) is different \r\n\t\tfrom the current number itself. This ensures that the number is not already in its correct place.\r\n        - If the numbers are different, it swaps the current number with the number at its correct position using the \r\n\t\tGo idiomatic way of swapping values (nums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1]).\r\n        - The swapping process continues until the number at index i is either non-positive or already in its correct \r\n\t\tplace. This step ensures that all positive numbers are placed in their respective positions.\r\n\r\n    -> Step 2: Find the first missing positive\r\n        After completing the first pass through the slice, the algorithm performs a second pass using another for loop.\r\n        Inside the loop, it checks if the number at index i is equal to i + 1. If not, it means that i + 1 is missing from the slice.\r\n        In this case, the algorithm returns i + 1 as the smallest missing positive integer.\r\n\r\n    -> If all positive integers from 1 to n are present in the slice, the function reaches the end without finding a \r\n\tmissing positive. In this case, it returns n + 1 as the smallest missing positive integer.\r\n\r\nThe Go implementation of the algorithm ensures that it modifies the input slice nums in-place without using any \r\nadditional data structures, meeting the O(1) auxiliary space requirement. The time complexity of the algorithm \r\nremains O(n) as it performs two passes through the slice, visiting each element once.\r\n*/\r\n\r\n/*\r\nExample->\r\n\r\nExample 1:\r\nInput: nums := []int{1, 2, 0}\r\nOutput: 3\r\nExplanation: The smallest missing positive integer in the slice is 3.\r\n\r\nExample 2:\r\nInput: nums := []int{3, 4, -1, 1}\r\nOutput: 2\r\nExplanation: The smallest missing positive integer in the slice is 2.\r\n\r\nExample 3:\r\nInput: nums := []int{7, 8, 9, 11, 12}\r\nOutput: 1\r\nExplanation: The smallest missing positive integer in the slice is 1.\r\n\r\n*/\r\n\r\nfunc firstMissingPositive(nums []int) int {\r\n\tn := len(nums)\r\n\r\n\t// Step 1: Move positive numbers to their correct positions\r\n\tfor i := 0; i < n; i++ {\r\n\t\tfor nums[i] > 0 && nums[i] <= n && nums[nums[i]-1] != nums[i] {\r\n\t\t\tnums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1]\r\n\t\t}\r\n\t}\r\n\r\n\t// Step 2: Find the first missing positive\r\n\tfor i := 0; i < n; i++ {\r\n\t\tif nums[i] != i+1 {\r\n\t\t\treturn i + 1\r\n\t\t}\r\n\t}\r\n\r\n\t// If all positive integers are present, return n + 1\r\n\treturn n + 1\r\n}\r\n"
  },
  {
    "path": "Hash Table/first_missing_positve.js",
    "content": "// First Missing Positve\r\n/*\r\n    -> The firstMissingPositive function takes an array of integers called nums as input.\r\n\r\n    -> The function first determines the length of the array nums and assigns it to the variable n.\r\n\r\n    -> Step 1: Move positive numbers to their correct positions\r\n          - The algorithm iterates through each element of the array using a for loop.\r\n          - Inside the loop, it checks if the current number (nums[i]) is positive and within the range of 1 to n.\r\n          - If the number is valid, it checks whether the number at its correct position (nums[nums[i] - 1]) is \r\n          different from the current number itself. This ensures that the number is not already in its correct place.\r\n          - If the numbers are different, it swaps the current number with the number at its correct position using \r\n          array destructuring ([nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]]). This moves the current \r\n          number to its correct place in the array.\r\n          - The swapping process continues until the number at index i is either non-positive or already in its correct \r\n          place. This step ensures that all positive numbers are placed in their respective positions.\r\n\r\n    Step 2: Find the first missing positive\r\n          - After completing the first pass through the array, the algorithm performs a second pass using another for loop.\r\n          - Inside the loop, it checks if the number at index i is equal to i + 1. If not, it means that i + 1 is \r\n          missing from the array.\r\n          - In this case, the algorithm returns i + 1 as the smallest missing positive integer.\r\n\r\n    -> If all positive integers from 1 to n are present in the array, the function reaches the end without finding a \r\n    missing positive. In this case, it returns n + 1 as the smallest missing positive integer.\r\n\r\n\r\n\r\nThe algorithm meets the given time complexity requirement of O(n) because it performs two passes through the array, \r\nand each pass visits each element once. It also satisfies the space complexity requirement of O(1) since it modifies \r\nthe input array in-place without using any additional data structures.\r\n*/\r\n\r\n\r\n/*\r\nExamples-\r\n\r\nExample 1:\r\nInput: nums = [1, 2, 0]\r\nOutput: 3\r\nExplanation: The smallest missing positive integer in the array is 3.\r\n\r\nExample 2:\r\nInput: nums = [3, 4, -1, 1]\r\nOutput: 2\r\nExplanation: The smallest missing positive integer in the array is 2.\r\n\r\nExample 3:\r\nInput: nums = [7, 8, 9, 11, 12]\r\nOutput: 1\r\nExplanation: The smallest missing positive integer in the array is 1.\r\n*/\r\n\r\n\r\nfunction firstMissingPositive(nums) {\r\n  const n = nums.length;\r\n\r\n  // Step 1: Move positive numbers to their correct positions\r\n  for (let i = 0; i < n; i++) {\r\n    while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] !== nums[i]) {\r\n      [nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]];\r\n    }\r\n  }\r\n\r\n  // Step 2: Find the first missing positive\r\n  for (let i = 0; i < n; i++) {\r\n    if (nums[i] !== i + 1) {\r\n      return i + 1;\r\n    }\r\n  }\r\n\r\n  // If all positive integers are present, return n + 1\r\n  return n + 1;\r\n}"
  },
  {
    "path": "Hash Table/first_missing_positve.py",
    "content": "# first positive missing in python\n'''\nTo find the smallest missing positive integer in an unsorted integer array nums with the given time and space constraints, \nyou can utilize the concept of in-place swapping and indexing.\n\nExplanation:-\n\n    -> Iterate through the array nums and ignore any non-positive numbers (i.e., negative numbers and zero). \n    Also, ignore numbers greater than the length of the array since they cannot be the smallest missing positive integer.\n\n    -> For each positive number num encountered, find its correct index targetIndex as num - 1.\n\n    -> Check if the number at index targetIndex is already in its correct place or not. If it is not, \n    swap the numbers at indices i and targetIndex to move num to its correct place. Continue this swapping \n    process until the number at index i is either non-positive or already in its correct place.\n\n    -> After completing the iteration, perform a second pass through the array. The first index i that does not \n    contain the value i + 1 represents the smallest missing positive integer. Return i + 1.\n'''\n\n# Time complexity O(n) and Space complexity O(1).\n\n'''Examples-\n\nExample 1:\nInput: nums = [1, 2, 0]\nOutput: 3\nExplanation: The smallest missing positive integer in the array is 3.\n\nExample 2:\nInput: nums = [3, 4, -1, 1]\nOutput: 2\nExplanation: The smallest missing positive integer in the array is 2.\n\nExample 3:\nInput: nums = [7, 8, 9, 11, 12]\nOutput: 1\nExplanation: The smallest missing positive integer in the array is 1.\n\n'''\n\ndef firstMissingPositive(nums):\n    n = len(nums)\n\n    # Step 1: Move positive numbers to their correct positions\n    for i in range(n):\n        while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:\n            nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]\n\n    # Step 2: Find the first missing positive\n    for i in range(n):\n        if nums[i] != i + 1:\n            return i + 1\n\n    # If all positive integers are present, return n + 1\n    return n + 1\n\n"
  },
  {
    "path": "Hash Table/first_non_repeated_character.go",
    "content": "/*\n\tThe FirstNonRepeatingCharacter function takes a string as input and returns the index of the\n\tfirst non-repeating character in the string. If all the characters are repeated, then it returns -1.\n\n\tThe function works by first creating an empty map called charFreq to keep track of the frequency of\n\teach character in the string. Then, it iterates through each character in the string using a for loop.\n\n\tInside the loop, it checks if the current character already exists in the charFreq map.\n\n\tIf it does, then it increments its frequency by 1, and if it doesn't, it adds the character to the map\n\twith a frequency of 1.\n\n\tAfter the map is constructed, the function iterates through the string again using another for loop,\n\tthis time tracking the index of each character using the idx variable.\n\n\tFor each character, it checks its frequency in the charFreq map.\n\n\tIf the frequency is 1, then the character is non-repeating and the function returns its index.\n\n\tIf no non-repeating character is found, then the function returns -1.\n\n\tOverall, the function has a time complexity of O(n) since it loops through the string twice, and a space complexity of O(k), where k is the number of unique characters in the string, since the charFreq map stores the frequency of each unique character.\n*/\npackage main\n\nimport \"fmt\"\n\n// This function takes a string as input and returns the index of the first non-repeating character in the string.\nfunc FirstNonRepeatingCharacter(str string) int {\n\t// Create a map to store the frequency of each character in the string.\n\t// The key of the map is a rune, which is an integer representation of a Unicode character.\n\t// The value of the map is an integer representing the frequency of the corresponding character.\n\tcharFreq := make(map[rune]int)\n\t// Loop through each character in the string and update its frequency in the map.\n\tfor _, char := range str {\n\t\tcharFreq[char] += 1\n\t}\n\t// Loop through each character in the string again.\n\tfor idx, char := range str {\n\t\t// If the frequency of the current character is 1, it means it is the first non-repeating character in the string.\n\t\tif charFreq[char] == 1 {\n\t\t\t// Return the index of the non-repeating character.\n\t\t\treturn idx\n\t\t}\n\t}\n\t// If no non-repeating character is found in the string, return -1.\n\treturn -1\n}\n\nfunc main() {\n\tfmt.Println(FirstNonRepeatingCharacter(\"abcdcaf\")); // b index 1\n}"
  },
  {
    "path": "Hash Table/first_repeated_character.go",
    "content": "// Program to find first repeating character in a word\n// Sample Input : \"DataStructures\"\n// Output: a\n\npackage main\n\nimport \"fmt\"\n\nfunc FirstRepeatedCCharacter(word string) byte {\n\tlength := len(word)\n\n\thMap := [256]int{} // Extended Ascii can support 256 different characters\n\t\n\t// initialize hMap values to 0\n\tfor i := 0; i < 256; i++ {\n\t\thMap[i] = 0\n\t}\n\n\t// every time you see a character in a word increment its position in hMap\n\tfor i := 0; i < length; i++ {\n\t\t// if character is already present incase \"1\" then return character\n\t\tif hMap[word[i]] == 1 {\n\t\t\treturn word[i]\n\t\t}\n\t\t// increment value in position of character\n\t\thMap[word[i]]++\n\t}\n\treturn byte(0)\n}\n\nfunc main() {\n\tfmt.Printf(\"%c\",FirstRepeatedCCharacter(\"DataStructures\"))\n}"
  },
  {
    "path": "Hash Table/four_number_sum.java",
    "content": "import java.util.*;\n\n/**\n *\n\n Write a function that takes in a non-empty array of distinct integers and an integer representing a target sum. The function should find all quadruplets in the array that sum up to the target sum and return a two-dimensional array of all these quadruplets in no particular order.\n\n If no four numbers sum up to the target sum, the function should return an empty array.\n Sample Input\n\n array = [7, 6, 4, -1, 1, 2]\n targetSum = 16\n\n Sample Output\n\n [[7, 6, 4, -1], [7, 6, 1, 2]] // the quadruplets could be ordered differently\n\n\n */\npublic class FourNumberSum {\n    public static void main(String[] args) {\n//        int[] array = {7, 6, 4, -1, 1, 2};\n//        int targetSum = 16;\n        int[] array = {2, 2, 2, 2, 2};\n        int targetSum = 8;\n        List<Integer[]> result = solve(array, targetSum);\n        for (var pair: result) {\n            System.out.println(Arrays.toString(pair));\n        }\n    }\n    public static List<Integer[]> solve(int[] array, int targetSum) {\n        // Average: O(n^2) time | O(n^2) space\n        // Worst: O(n^3) time | O(n^2) space\n        Map<Integer, List<Integer[]>> allPairSums = new HashMap<>();\n        List<Integer[]> quardruplets = new ArrayList<>();\n        for (int i = 0; i < array.length - 1; i++) {\n            for (int j = i + 1; j < array.length; j++) {\n                int currentSum = array[i] + array[j];\n                int difference = targetSum - currentSum;\n                if (allPairSums.containsKey(difference)) {\n                    for (Integer[] pair: allPairSums.get(difference)) {\n                        Integer[] newQuadruplet = {pair[0], pair[1], array[i], array[j]};\n                        quardruplets.add(newQuadruplet);\n                    }\n                }\n            }\n            for (int k = 0; k < i; k++) {\n                int currentSum = array[i] + array[k];\n                Integer[] pair = {array[k], array[i]};\n                if(!allPairSums.containsKey(currentSum)) {\n                    List<Integer[]> pairGroup = new ArrayList<>();\n                    pairGroup.add(pair);\n                    allPairSums.put(currentSum, pairGroup);\n                } else {\n                    allPairSums.get(currentSum).add(pair);\n                }\n            }\n        }\n        return quardruplets;\n    }\n}\n"
  },
  {
    "path": "Hash Table/frequency_of_elements.java",
    "content": "/**\n * Problem Description\n * Given an array A. You have some integers given in the array B.\n *\n * For the i-th number, find the frequency of B[i] in the array A and return a list containing all the frequencies.\n *\n *\n *\n * Problem Constraints\n * 1 <= |A| <= 105\n *\n * 1 <= |B| <= 105\n *\n * 1 <= A[i] <= 105\n *\n * 1 <= B[i] <= 105\n *\n *\n *\n * Input Format\n * First argument A is an array of integers.\n *\n * Second argument B is an array of integers denoting the queries.\n *\n *\n *\n * Output Format\n * Return an array of integers containing frequency of the each element in B.\n *\n *\n *\n * Example Input\n * Input 1:\n * A = [1, 2, 1, 1]\n * B = [1, 2]\n * Input 2:\n * A = [2, 5, 9, 2, 8]\n * B = [3, 2]\n *\n *\n * Example Output\n * Output 1:\n * [3, 1]\n * Output 2:\n * [0, 2]\n *\n *\n * Example Explanation\n * For Input 1:\n * The frequency of 1 in the array A is 3.\n * The frequency of 2 in the array A is 1.\n * For Input 2:\n * The frequency of 3 in the array A is 0.\n * The frequency of 2 in the array A is 2.\n */\npackage Hashing;\n\nimport java.util.Arrays;\nimport java.util.HashMap;\n\npublic class FrequencyOfElements {\n    public static void main(String[] args) {\n        int[] array = {2, 5, 9, 2, 8};\n        int[] queries = {3, 2};\n\n        int[] res = solve(array, queries);\n        System.out.println(Arrays.toString(res));\n    }\n\n    public static int[] solve(int[] nums, int[] queries) {\n        // O(N) time | O(Q) space where N is length of array , Q is length of queries\n\n        HashMap<Integer, Integer> hashMap = new HashMap<>();\n\n        for (int num : nums) {\n            if (!hashMap.containsKey(num)) hashMap.put(num, 0);\n\n            hashMap.put(num, hashMap.get(num) + 1);\n        }\n        System.out.println(hashMap);\n\n        int[] res = new int[queries.length];\n\n        for (int i = 0; i < queries.length; i++)\n            if (hashMap.containsKey(queries[i]))\n                res[i] = hashMap.get(queries[i]);\n\n        return res;\n    }\n}\n"
  },
  {
    "path": "Hash Table/group_anagrams.cpp",
    "content": "// Group Anagrams\n/*\n    The function groupAnagrams takes a vector of strings strs as input and returns a vector of vectors of strings res, \n    where each inner vector contains a group of anagrams.\n\n    We create an unordered map mp to store the anagram groups. The keys of the map are the sorted versions of the anagrams, \n    and the values are vectors containing the original strings that belong to that anagram group.\n\n    We iterate through each string in the input vector strs, create a copy of the string t, sort the characters in the copy t, \n    and add the original string s to the corresponding anagram group in the unordered map mp.\n\n    We create a vector res to store the anagram groups and iterate through the unordered map mp. For each anagram group in the map, \n    we add the corresponding vector of original strings to the res vector.\n\n    We return the result vector res containing all the anagram groups.\n\n    In the main function, we create an example input vector strs, call the groupAnagrams function and store the result in the \n    output vector output, and iterate through the output vector to print each anagram group.\n    \n\tThe time complexity of this implementation is O(n * k log k), where n is the length of the input array and k is the \n    length of the longest string in the array. This is due to the time complexity of sorting each string in the array.\n\n\tThe space complexity of this implementation is O(n * k), as we need to store each string in the map along with its corresponding group of anagrams.\n\n*/\n#include <iostream>\n#include <string>\n#include <unordered_map>\n#include <vector>\n#include <algorithm>\nusing namespace std;\n\nvector<vector<string>> groupAnagrams(vector<string>& strs) {\n    unordered_map<string, vector<string>> mp; // create an unordered map to store anagrams\n\n    // iterate through each string in the input vector\n    for (string s : strs) {\n        string t = s; // create a copy of the current string\n        sort(t.begin(), t.end()); // sort the characters in the copy\n        mp[t].push_back(s); // add the original string to the corresponding anagram group\n    }\n\n    vector<vector<string>> res; // create a vector to store the anagram groups\n    for (auto p : mp) { // iterate through the unordered map\n        res.push_back(p.second); // add the anagram group to the result vector\n    }\n\n    return res; // return the result vector containing all the anagram groups\n}\n\nint main() {\n    // create an example input vector\n    vector<string> strs = {\"eat\", \"tea\", \"tan\", \"ate\", \"nat\", \"bat\"};\n\n    // call the groupAnagrams function and store the result in the output vector\n    vector<vector<string>> output = groupAnagrams(strs);\n\n    // iterate through the output vector and print each anagram group\n    for (vector<string> group : output) {\n        for (string s : group) {\n            cout << s << \" \";\n        }\n        cout << endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "Hash Table/group_anagrams.go",
    "content": "// Group Anagrams\n/*\n\tThe program takes a slice of strings as input, where each string is an element in the slice.\n\tThe goal is to group the strings into separate groups where each group contains only anagrams of each other.\n\n\tThe first step in the program is to create a map where the keys are strings and the values are slices of strings.\n\tThis map will be used to store the groups of anagrams.\n\n\tNext, the program loops through each string in the input slice. For each string, the program converts\n\tit to a slice of bytes, sorts the bytes in ascending order, and then converts the sorted slice of bytes back into a string.\n\tThis sorted string is used as the key to the map.\n\n\tIf the key already exists in the map, the string is added to the slice of values associated with that key.\n\tIf the key doesn't exist, a new key-value pair is created with the key being the sorted string and the value\n\tbeing a new slice containing only the current string.\n\n\tOnce all the strings have been processed, the program loops through the map and appends the slice of values\n\tassociated with each key to the output slice. This output slice contains slices of strings, where each slice\n\tis a group of anagrams.\n\n\tFinally, the program returns the output slice.\n\n\tOverall, the program uses the fact that anagrams have the same set of characters (and thus, the same sorted order of characters) \\\n\tto group the input strings efficiently.\n\n\tThe time complexity of this implementation is O(n * k log k), where n is the length of the input array and k is the length of the longest string in the array. This is due to the time complexity of sorting each string in the array.\n\n\tThe space complexity of this implementation is O(n * k), as we need to store each string in the map along with its corresponding group of anagrams.\n*/\npackage main\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n)\n\nfunc groupAnagrams(strs []string) [][]string {\n\t// Create a map to store anagrams and their grouped strings\n\tanagramMap := make(map[string][]string)\n\n\t// Loop through each string in the input array\n\tfor _, str := range strs {\n\t\t// Sort the string to create a unique key for each anagram\n\t\tsortedStr := sortString(str)\n\t\t// Add the string to its corresponding group in the anagramMap\n\t\tanagramMap[sortedStr] = append(anagramMap[sortedStr], str)\n\t}\n\n\t// Create a 2D slice to store the grouped anagrams\n\tgroups := make([][]string, 0, len(anagramMap))\n\n\t// Loop through the anagramMap and append each group of anagrams to the groups slice\n\tfor _, group := range anagramMap {\n\t\tgroups = append(groups, group)\n\t}\n\n\treturn groups\n}\n\n// Helper function to sort a string alphabetically\nfunc sortString(s string) string {\n\tsBytes := []byte(s)\n\tsort.Slice(sBytes, func(i, j int) bool { return sBytes[i] < sBytes[j] })\n\treturn string(sBytes)\n}\nfunc main() {\n    strs := []string{\"eat\", \"tea\", \"tan\", \"ate\", \"nat\", \"bat\"}\n    groups := groupAnagrams(strs)\n    for _, group := range groups {\n        fmt.Println(group)\n    }\n}\n"
  },
  {
    "path": "Hash Table/group_anagrams.java",
    "content": "// Group Anagrams\n/*\n    Explanation:\n\n    The groupAnagrams method takes an array of strings and groups them into a list of anagram groups. To accomplish this, \n    the method first creates a HashMap called anagramGroups to store the groups of anagrams.\n\n    For each string in the input array, the method converts the string to a character array, sorts the array, \n    and converts it back to a string. This sorted string serves as the key for the anagramGroups map. If the sorted \n    string is not already in the map, the method adds it with an empty list as its value. Then, the original string \n    is added to the list of its corresponding anagram group.\n\n    Finally, the method returns a list of the values in the anagramGroups map, which is a list of the anagram groups.\n\n    In the main method, we create an instance of the GroupAnagrams class and call the groupAnagrams method on an example input array.\n    We then print out the resulting list of anagram groups.\n\n\tThe time complexity of this implementation is O(n * k log k), where n is the length of the input array and k is the length of the longest string in the array. This is due to the time complexity of sorting each string in the array.\n\n\tThe space complexity of this implementation is O(n * k), as we need to store each string in the map along with its corresponding group of anagrams.\n\n*/\nimport java.util.*;\n\npublic class group_anagrams{\n    \n    public List<List<String>> groupAnagrams(String[] strs) {\n        // Create a HashMap to store the groups of anagrams\n        Map<String, List<String>> anagramGroups = new HashMap<>();\n        \n        // Loop through each string in the input array\n        for (String str : strs) {\n            // Convert the string to a char array, sort it, and convert it back to a string\n            char[] chars = str.toCharArray();\n            Arrays.sort(chars);\n            String sorted = new String(chars);\n            \n            // If the sorted string is not in the map, add it with an empty list as its value\n            if (!anagramGroups.containsKey(sorted)) {\n                anagramGroups.put(sorted, new ArrayList<String>());\n            }\n            \n            // Add the original string to the list of its anagram group\n            anagramGroups.get(sorted).add(str);\n        }\n        \n        // Return a list of the anagram groups\n        return new ArrayList<>(anagramGroups.values());\n    }\n    \n    public static void main(String[] args) {\n        group_anagrams ga = new group_anagrams();\n        \n        // Example input\n        String[] strs = {\"eat\", \"tea\", \"tan\", \"ate\", \"nat\", \"bat\"};\n        \n        // Group the anagrams\n        List<List<String>> groups = ga.groupAnagrams(strs);\n        \n        // Print the groups\n        for (List<String> group : groups) {\n            System.out.println(group);\n        }\n    }\n}\n"
  },
  {
    "path": "Hash Table/group_anagrams.js",
    "content": "// Group Anagrams\n/*\n    The function groupAnagrams takes an array of strings strs as input, and returns an array of arrays of anagrams. \n    The approach taken is to sort the characters of each string alphabetically, and group strings with the same sorted form together. \n    The resulting groups are stored in an object anagramGroups whose keys are the sorted strings and whose values are arrays of the original strings. \n    Finally, the values of the anagramGroups object are returned as an array.\n\n    To accomplish the sorting and grouping, the split, sort, and join methods are used. First, each string is split into an array of its characters \n    using the split method. Then, the sort method is used to sort the characters alphabetically. Finally, the join method is used to combine the \n    sorted characters back into a string. This sorted string is used as the key for grouping the anagrams in the anagramGroups object.\n\n    The for...of loop is used to iterate over each string in the input array. Inside the loop, the sorted form of the string is computed, \n    and a check is made to see if a group for the sorted form already exists in the anagramGroups object. If it doesn't, a new group is \n    created as an empty array. Then, the original string is added to the appropriate group in the anagramGroups object using the push method.\n\n    Finally, the Object.values method is used to extract the arrays of anagrams from the anagramGroups object, and these arrays are \n    returned as the final result.\n\n\tThe time complexity of this implementation is O(n * k log k), where n is the length of the input array and k is the length of the longest string in the array. This is due to the time complexity of sorting each string in the array.\n\n\tThe space complexity of this implementation is O(n * k), as we need to store each string in the map along with its corresponding group of anagrams.\n\n*/\n/**\n * Given an array of strings, group anagrams together and return them as an array of arrays.\n *\n * @param {string[]} strs - The input array of strings.\n * @returns {string[][]} - An array of arrays of anagrams.\n */\nfunction groupAnagrams(strs) {\n  // Create an empty object to store groups of anagrams.\n  const anagramGroups = {};\n\n  // Loop through each string in the input array.\n  for (const str of strs) {\n    // Sort the characters of the string alphabetically and use the sorted string as a key.\n    const sortedStr = str.split(\"\").sort().join(\"\");\n\n    // If a group for the sorted string doesn't exist yet, create it as an empty array.\n    if (!anagramGroups[sortedStr]) {\n      anagramGroups[sortedStr] = [];\n    }\n\n    // Add the original string to the group of anagrams.\n    anagramGroups[sortedStr].push(str);\n  }\n\n  // Return the values of the anagram groups object as an array.\n  return Object.values(anagramGroups);\n}\n\nconst words = [\"eat\", \"tea\", \"tan\", \"ate\", \"nat\", \"bat\"];\nconsole.log(groupAnagrams(words));\n"
  },
  {
    "path": "Hash Table/group_anagrams.py",
    "content": "# Group Anagrams\n'''\n    The function groupAnagrams takes a list of strings as input and returns a list of lists, where each inner list \n    contains a group of anagrams from the input list.\n\n    The function starts by creating an empty dictionary groups to store the groups of anagrams. The keys of the dictionary \n    will be the unique signatures of the anagrams, and the values will be lists of the actual anagrams.\n\n    Then, the function iterates through each string s in the input list strs. For each string, it sorts the characters \n    of the string to get its unique signature sig. If the signature is not already in the dictionary, a new key-value pair \n    is added to the dictionary with the signature as the key and an empty list as the value. Finally, the current \n    string s is appended to the list of its corresponding signature in the dictionary.\n\n    Once all the strings have been processed, the function returns the values of the dictionary as a list of lists, \n    where each inner list contains a group of anagrams from the input list.\n\n    For example, if the input list is [\"eat\", \"tea\", \"tan\", \"ate\", \"nat\", \"bat\"], \n    the function will return [['eat', 'tea', 'ate'], ['tan', 'nat'], ['bat']], which \n    represents the three groups of anagrams: ['eat', 'tea', 'ate'], ['tan', 'nat'], and ['bat'].\n\n    The time complexity of this implementation is O(n * k log k), where n is the length of the input array and k is the \n    length of the longest string in the array. This is due to the time complexity of sorting each string in the array.\n\n\tThe space complexity of this implementation is O(n * k), as we need to store each string in the map along with its \n    corresponding group of anagrams.\n\n'''\ndef groupAnagrams(strs):\n    # create a dictionary to store the groups of anagrams\n    groups = {}\n    \n    # iterate through each string in the list\n    for s in strs:\n        # sort the characters of the string to get its unique signature\n        # for example, \"eat\" and \"ate\" both have the same signature \"aet\"\n        sig = ''.join(sorted(s))\n        \n        # check if the signature is already in the dictionary\n        # if not, add a new key-value pair with an empty list as the value\n        if sig not in groups:\n            groups[sig] = []\n        \n        # append the current string to the list of its corresponding signature\n        groups[sig].append(s)\n    \n    # return the values of the dictionary as a list of lists\n    return list(groups.values())\n"
  },
  {
    "path": "Hash Table/integer_to_roman.cpp",
    "content": "// Integer to Roman\n/*\n    In this implementation, we use an unordered map to store the mapping between integers and Roman numerals. \n    We then loop through the map from the largest number to the smallest, checking if the current number \n    can be divided by the key of the map. If it can, we append the corresponding Roman numeral to the result \n    string and subtract the key from the number. We continue this process until the number is 0. \n    The final result string is then returned.\n\n    The time complexity of this implementation is O(1) since the size of the map is fixed, and the \n    space complexity is O(1) since we only use a fixed amount of memory to store the map and the result string.\n*/\n#include <iostream>\n#include <unordered_map>\nusing namespace std;\n\nstring intToRoman(int num) {\n    // Initialize the mapping between integers and Roman numerals\n    unordered_map<int, string> map = {\n        {1000, \"M\"}, {900, \"CM\"}, {500, \"D\"}, {400, \"CD\"},\n        {100, \"C\"}, {90, \"XC\"}, {50, \"L\"}, {40, \"XL\"},\n        {10, \"X\"}, {9, \"IX\"}, {5, \"V\"}, {4, \"IV\"}, {1, \"I\"}\n    };\n    \n    // Initialize an empty string to store the result\n    string result = \"\";\n    \n    // Loop through the map from the largest number to the smallest\n    for (auto it = map.rbegin(); it != map.rend(); ++it) {\n        // Check if the current number can be divided by the key of the map\n        while (num >= it->first) {\n            // Append the corresponding Roman numeral to the result string\n            result += it->second;\n            // Subtract the key from the number\n            num -= it->first;\n        }\n    }\n    \n    return result;\n}\n\nint main() {\n    int num = 1994;\n    cout << intToRoman(num) << endl; // Output: \"MCMXCIV\"\n    return 0;\n}\n"
  },
  {
    "path": "Hash Table/integer_to_roman.go",
    "content": "// Integer to Roman\n/*\n\tIn this implementation, we create two arrays symbols and values that hold the Roman numeral symbols and their \n\tcorresponding integer values respectively. We then create a string builder to hold our result.\n\n\tWe loop through the values array, and while the current num is greater than or equal to the current values \n\telement, we subtract the values element from num and append the corresponding symbols element to the result \n\tstring builder. We continue this process until we have gone through all the values elements.\n\n\tFinally, we return the result string.\n*/\npackage main\n\nimport \"strings\"\n\nfunc intToRoman(num int) string {\n\t// Create two arrays to hold the Roman numeral symbols and their corresponding values\n\tsymbols := []string{\"M\", \"CM\", \"D\", \"CD\", \"C\", \"XC\", \"L\", \"XL\", \"X\", \"IX\", \"V\", \"IV\", \"I\"}\n\tvalues := []int{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}\n\n\tvar result strings.Builder\n\t// Loop through the values array and subtract the corresponding value from num while appending the symbol to the result\n\tfor i := 0; i < len(values); i++ {\n\t\tfor num >= values[i] {\n\t\t\tnum -= values[i]\n\t\t\tresult.WriteString(symbols[i])\n\t\t}\n\t}\n\n\treturn result.String()\n}\n\nfunc main() {\n\tprint(intToRoman(8000))\n}"
  },
  {
    "path": "Hash Table/integer_to_roman.java",
    "content": "// Integer to Roman\n/*\n    Here, we create two arrays to store the Roman numerals and their corresponding values. We then use a \n    StringBuilder to build the resulting Roman numeral string. We use a while loop to iterate through \n    the values array until the number is reduced to 0. In each iteration, we check if the current value is \n    less than or equal to the number. If it is, we subtract the value from the number and append the \n    corresponding Roman numeral to the StringBuilder. If it's not, we move to the next value. Finally, \n    we return the resulting Roman numeral string.\n\n    The time complexity of this implementation is O(1), since the maximum number of iterations in the \n    while loop is 13 (the length of the values array). The space complexity is also O(1), since we only \n    use a StringBuilder and two constant-size arrays to store the Roman numerals and values.\n*/\npublic static String intToRoman(int num) {\n    // Create two arrays to store the Roman numerals and their corresponding values\n    String[] romanNumerals = {\"M\", \"CM\", \"D\", \"CD\", \"C\", \"XC\", \"L\", \"XL\", \"X\", \"IX\", \"V\", \"IV\", \"I\"};\n    int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};\n    \n    StringBuilder sb = new StringBuilder();\n    int i = 0;\n    \n    // Iterate through the values array until the number is reduced to 0\n    while (num > 0) {\n        // If the current value is less than or equal to the number, subtract the value and append the corresponding Roman numeral\n        if (values[i] <= num) {\n            num -= values[i];\n            sb.append(romanNumerals[i]);\n        } else {\n            i++;\n        }\n    }\n    \n    return sb.toString();\n}\n"
  },
  {
    "path": "Hash Table/integer_to_roman.js",
    "content": "// Integer to Roman\n/*\n    This solution uses a greedy approach to build the roman numeral string by subtracting the maximum \n    possible value at each step until the input number is zero. The time complexity of this implementation \n    is O(1) since there is a fixed number of roman numerals and the loop will always run 13 times. \n    The space complexity is also O(1) since we only store a single string.\n*/\nfunction intToRoman(num) {\n  // Create arrays for the symbols and their values\n  const symbols = [\n    \"M\",\n    \"CM\",\n    \"D\",\n    \"CD\",\n    \"C\",\n    \"XC\",\n    \"L\",\n    \"XL\",\n    \"X\",\n    \"IX\",\n    \"V\",\n    \"IV\",\n    \"I\",\n  ];\n  const values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];\n\n  let result = \"\"; // Initialize an empty string to store the roman numeral\n\n  // Loop through the values array\n  for (let i = 0; i < values.length; i++) {\n    // While the input num is greater than or equal to the current value\n    while (num >= values[i]) {\n      result += symbols[i]; // Add the corresponding symbol to the result string\n      num -= values[i]; // Subtract the value from the input num\n    }\n  }\n\n  return result; // Return the roman numeral string\n}\n"
  },
  {
    "path": "Hash Table/integer_to_roman.py",
    "content": "# Integer to Roman\n'''\n    The function takes an integer num as input and returns the corresponding Roman numeral as a string. \n    The mapping of values to symbols is defined in a dictionary symbols. The keys in the dictionary are \n    the values that can be used to represent Roman numerals, and the values are the symbols themselves.\n\n    The keys are sorted in descending order in a list called keys. This is done so that we can iterate \n    through the keys in descending order and subtract the largest value from num until num is 0.\n\n    We initialize an empty string called roman to store the Roman numeral representation. We then iterate \n    through the keys in keys and subtract the largest value from num until num is less than the current key. \n    We append the corresponding symbol to roman for each value subtracted.\n\n    Finally, we return the string roman, which is the Roman numeral representation of the input integer num.\n'''\ndef intToRoman(num: int) -> str:\n    # define the mapping of values to symbols\n    symbols = {1: 'I', 4: 'IV', 5: 'V', 9: 'IX', 10: 'X', 40: 'XL', 50: 'L',\n               90: 'XC', 100: 'C', 400: 'CD', 500: 'D', 900: 'CM', 1000: 'M'}\n    \n    # create a list of keys in descending order\n    keys = sorted(symbols.keys(), reverse=True)\n    \n    # initialize an empty string to store the roman numeral representation\n    roman = ''\n    \n    # iterate through the keys and subtract the largest value from the number\n    # until the number is 0\n    for k in keys:\n        while num >= k:\n            roman += symbols[k]\n            num -= k\n    \n    return roman\n"
  },
  {
    "path": "Hash Table/remove_duplicates.go",
    "content": "// Given an array of integers, give an algorithm for removing the duplicates.\npackage main\n\nimport \"fmt\"\n\n// RemoveDuplicates: returns new string without duplicate characters\n// Approach: use hash table to see if value already exists or not, if it does the skip the value\n// else append it to the result string\n// Time Complexity: Θ(n) on average. Space Complexity: O(n).\nfunc RemoveDuplicates(word string) string {\n\tresult := \"\"\n\tmp := map[byte]bool{}\n\tfor i:= 0; i < len(word); i++ {\n\t\tif mp[word[i]] == true {\n\t\t\t// current character exist in hash table so do nothing\n\t\t} else {\n\t\t\t// mark as true(insert into hashtable) and add to result string\n\t\t\tmp[word[i]] = true\n\t\t\tresult = result + string(word[i])\n\t\t}\n\t}\n\treturn result\n}\n\nfunc main() {\n\tfmt.Println(RemoveDuplicates(\"aabbcaaacdd\"));\n}"
  },
  {
    "path": "Hash Table/roman_to_integer.cpp",
    "content": "/*\nRoman numerals are represented by seven different symbols: I, V, X, L, C, D and M.\n\nSymbol       Value\nI             1\nV             5\nX             10\nL             50\nC             100\nD             500\nM             1000\nFor example, 2 is written as II in Roman numeral, just two ones added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.\n\nRoman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:\n\nI can be placed before V (5) and X (10) to make 4 and 9. \nX can be placed before L (50) and C (100) to make 40 and 90. \nC can be placed before D (500) and M (1000) to make 400 and 900.\nGiven a roman numeral, convert it to an integer.\n\n \n\nExample 1:\n\nInput: s = \"III\"\nOutput: 3\nExplanation: III = 3.\nExample 2:\n\nInput: s = \"LVIII\"\nOutput: 58\nExplanation: L = 50, V= 5, III = 3.\nExample 3:\n\nInput: s = \"MCMXCIV\"\nOutput: 1994\nExplanation: M = 1000, CM = 900, XC = 90 and IV = 4.\n \n\nConstraints:\n\n1 <= s.length <= 15\ns contains only the characters ('I', 'V', 'X', 'L', 'C', 'D', 'M').\nIt is guaranteed that s is a valid roman numeral in the range [1, 3999].\n\n*/\n\nclass Solution {\npublic:\n    int romanToInt(string s) {\n        // Map Roman Characters to integer values\n        unordered_map<char, int> mp = {{'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000}, };\n        int len = s.size();\n        int sum = mp[s[len-1]];\n        // start from end and build up the value to start\n        for(int i = len - 2; i >= 0; i--){\n            if(mp[s[i]] < mp[s[i + 1]]){\n                sum -= mp[s[i]]; \n            }\n            else{\n                sum += mp[s[i]];\n            }\n        }\n        return sum;\n    }\n};"
  },
  {
    "path": "Hash Table/roman_to_integer.go",
    "content": "// Roman To Integer\n/*\n\tThis implementation converts a given Roman numeral string to its corresponding integer value.\n\tThe implementation uses a map to store the integer value of each Roman numeral, and then\n\titerates over the input string, checking if the next Roman numeral is greater than the\n\tcurrent one to determine whether to add or subtract the current value from the result.\n\tThe time complexity of this implementation is O(n), where n is the length of the input string,\n\tsince it iterates over the string only once. The space complexity is O(1), since the\n\timplementation only uses a constant amount of extra space to store the map and result variable.\n\n\tTime complexity: O(n), where n is the length of the input string. The program iterates through\n\teach character in the string once and performs a constant number of operations for each character.\n\tTherefore, the time complexity is linear in the length of the input string.\n\n\tSpace complexity: O(1). The program uses a constant amount of extra space to store the result\n\tand the current and previous values. Therefore, the space complexity is constant, or O(1).\n*/\npackage main\n\nimport (\n\t\"fmt\"\n)\n\nfunc romanToInt(s string) int {\n    // Create a map to store the integer value of each Roman numeral\n    romanToIntMap := map[byte]int{\n        'I': 1,\n        'V': 5,\n        'X': 10,\n        'L': 50,\n        'C': 100,\n        'D': 500,\n        'M': 1000,\n    }\n    \n    // Initialize the result variable to 0\n    result := 0\n    \n    // Iterate over the input string\n    for i := 0; i < len(s); i++ {\n        // Get the integer value of the current Roman numeral\n        val := romanToIntMap[s[i]]\n        \n        // Check if the next Roman numeral is greater than the current one\n        if i+1 < len(s) && romanToIntMap[s[i+1]] > val {\n            // If the next Roman numeral is greater, subtract the current value from the result\n            result -= val\n        } else {\n            // If the next Roman numeral is not greater, add the current value to the result\n            result += val\n        }\n    }\n    \n    // Return the final result\n    return result\n}\n\n\n\nfunc main() {\n\tinput := \"IV\"\n    output := romanToInt(input)\n    fmt.Printf(\"Roman numeral %s converted to integer is: %d\\n\", input, output)\n\n}"
  },
  {
    "path": "Hash Table/roman_to_integer.java",
    "content": "// AUTHOR : Sagar Wadhwa\nclass Solution {\n    public int romanToInt(String s) {\n        // Hashmap in java which stores key value pairs. Each key is unique and no key is repeated \n        HashMap<Character,Integer> map = new HashMap<>();\n\n        // Defining the basic rules of mapping from roman numeral to integer numbers.\n        map.put('I',1);\n        map.put('V',5);\n        map.put('X',10);\n        map.put('L',50);\n        map.put('C',100);\n        map.put('D',500);\n        map.put('M',1000);\n\n        //extract the last character of the string, and find it in the map, store this keys value in the \n        // variable named \"res\"\n        int res = map.get(s.charAt(s.length()-1));\n\n        //iterate over the string from the second last character till the first character. Idea to solve\n        // this problem is that in the loop, for every character we check whether the value of the roman \n        // numeral at the i+1 th index is greater than or less than the value of the roman numeral at i th \n        // index. If the value of the roman numeral at the i th index is less than the value of the \n        // roman numeral at i+1 th index, then obviously that means we have to subtract the value of the \n        // roman numeral at the i th index from the result calculated so far. Else we have to add the value \n        // of the roman numeral at the i th index to the result calculated so far. Example: V means five,\n        // but if it is IV, then here the value of the roman numeral I is less than the value of the roman \n        // numeral V, so that means subtract I from V (4). If the string is VI, means 6, then here the value of \n        // V is greater than the value of I, so add I in V, that is 6. \n        // Doing so in an iterative fashion and storing the result and then adding or subtracting values \n        // from it accordingly will give us our final result.\n        for(int i=s.length()-2;i>=0;i--){\n\n            if(map.get(s.charAt(i)) < map.get(s.charAt(i+1))){\n                res -= map.get(s.charAt(i));\n            }else{\n                res += map.get(s.charAt(i));\n            }\n        }\n        return res;\n    }\n}"
  },
  {
    "path": "Hash Table/roman_to_integer.js",
    "content": "// Approach: In case of symbols like IV, CM, XC, etc., the first value is less than the second value.\n// So we have to subtract the first value from the second value to get the exact value.\n// Example: CM --> C=100, M=1000, so CM=1000-100=900.\n// Therefore, we can conclude that in such cases, we have to subtract the first value from the whole result.\n// Time complexity O(1) and Space complexity O(1).\nvar romanToInt = function(s) {\n    let map = new Map(); // Create a hashmap to store (symbol, value) pairs.\n    map['I'] = 1;\n    map['V'] = 5;\n    map['X'] = 10;\n    map['L'] = 50;\n    map['C'] = 100;\n    map['D'] = 500;\n    map['M'] = 1000;\n\n    let arr = [];\n    for (let i = 0; i < s.length; i++) { // Store the value of each symbol in arr from left to right.\n        arr[i] = map[s.charAt(i)];\n    }\n    \n    let ans = 0;\n    for (let i = 0; i < arr.length - 1; i++) { // Traverse from 0 to last-1.\n        // If the i-th element is less than the i+1-th element, then subtract the i-th element.\n        if (arr[i] < arr[i + 1]) {\n            ans = ans - arr[i];\n        }\n        // Otherwise, add the i-th element.\n        else {\n            ans = ans + arr[i];\n        }\n    }\n    // Add the last element because there is no further element to compare.\n    ans = ans + arr[arr.length - 1];\n    return ans;\n};\n"
  },
  {
    "path": "Hash Table/roman_to_integer.py",
    "content": "# Roman to Integer\n'''\n    The function takes a string s as an input and returns the corresponding integer value\n    by converting the string from Roman numerals to its integer value.\n\n    It does this by iterating through the string. If the current character has a lower\n    value than the character after it, the current character value is subtracted from\n    the total, so that it is added correctly.\n\n    Otherwise, the current character value is added to the total.\n\n    Finally, the total integer value is returned.\n'''\n\ndef roman_to_int(s: str) -> int:\n    # define mapping of values to symbols\n    symbols = {\n        'I': 1,\n        'V': 5,\n        'X': 10,\n        'L': 50,\n        'C': 100,\n        'D': 500,\n        'M': 1000\n    }\n\n    # initialise integer to return total value\n    total = 0\n\n    # iterate through characters\n    for i in range(len(s) - 1):\n        # if the symbol after current symbol is less than it,\n        # subtract it from the total value\n        if symbols[s[i]] < symbols[s[i+1]]:\n            total -= symbols[s[i]]\n        # else, just add the corresponding value\n        else:\n            total += symbols[s[i]]\n    # add the last value\n    total += symbols[s[-1]]\n\n    return total"
  },
  {
    "path": "Hash Table/sum_of_unique_elements.java",
    "content": "import java.util.HashMap;\n\n/* \nYou are given an integer array nums. The unique elements of an array are the elements that appear exactly once in the array.\n\nReturn the sum of all the unique elements of nums.\n\n \n\nExample 1:\n\nInput: nums = [1,2,3,2]\nOutput: 4\nExplanation: The unique elements are [1,3], and the sum is 4.\nExample 2:\n\nInput: nums = [1,1,1,1,1]\nOutput: 0\nExplanation: There are no unique elements, and the sum is 0.\nExample 3:\n\nInput: nums = [1,2,3,4,5]\nOutput: 15\nExplanation: The unique elements are [1,2,3,4,5], and the sum is 15.\n \nConstraints:\n\n1 <= nums.length <= 100\n1 <= nums[i] <= 100\n*/\nclass Solution {\n    public int sumOfUnique(int[] nums) {\n       HashMap<Integer,Integer> hm=new HashMap<Integer,Integer>();\n        int sum=0;\n        for(int x:nums)\n        {\n            if(hm.containsKey(x))\n                hm.put(x,hm.get(x)+1);\n            else\n                hm.put(x,1);\n        }\n        for(int x:nums)\n        {\n            if(hm.get(x)== 1)\n                sum+=x;\n        }\n        return sum;\n    }\n}\nclass SumOfUniqueElements {\n    public static void main(String[] args) {\n        int arr[] = {1,2,2,3};\n        Solution s = new Solution();\n        System.out.println(s.sumOfUnique(arr));\n        \n    }\n}\n"
  },
  {
    "path": "Hash Table/three_number_sum.java",
    "content": "import java.util.*;\n\n/**\n *\n\n Write a function that takes in a non-empty array of distinct integers and an integer representing a target sum. The function should find all triplets in the array that sum up to the target sum and return a two-dimensional array of all these triplets. The numbers in each triplet should be ordered in ascending order, and the triplets themselves should be ordered in ascending order with respect to the numbers they hold.\n\n If no three numbers sum up to the target sum, the function should return an empty array.\n Sample Input\n\n array = [12, 3, 1, 2, -6, 5, -8, 6]\n targetSum = 0\n\n Sample Output\n\n [[-8, 2, 6], [-8, 3, 5], [-6, 1, 5]]\n\n\n */\npublic class ThreeNumberSum {\n    // O(n^2) time | O(n) space\n    public static void main(String[] args){\n        int[] array = {12, 3, 1, 2, -6, 5, -8, 6};\n        int targetSum = 0;\n        List<Integer[]> triplets = solve(array, targetSum);\n        for (var triplet: triplets) System.out.println(Arrays.toString(triplet));\n    }\n    public static List<Integer[]> solve(int[] array, int targetSum) {\n        Arrays.sort(array);\n        List<Integer[]> triplets = new ArrayList<>();\n\n        for(int i = 0; i < array.length - 2; i++) {\n            int left = i + 1;\n            int right = array.length - 1;\n            while(left < right) {\n                int currentSum = array[i] + array[left] + array[right];\n                if(currentSum == targetSum) {\n                    Integer[] newTriplet = {array[i], array[left], array[right]};\n                    triplets.add(newTriplet);\n                    left++;\n                    right--;\n                } else if(currentSum < targetSum) left++;\n                else right--;\n            }\n        }\n        return triplets;\n    }\n}"
  },
  {
    "path": "Hash Table/two_sum.cpp",
    "content": "/*\n  Write a function that takes in a non-empty array of distinct integers and an\n  integer representing a target sum. If any two numbers in the input array sum\n  up to the target sum, the function should return them in an array, in any\n  order. If no two numbers sum up to the target sum, the function should return\n  an empty array.\n  Sample Input: [2, 1, 3, -1, 11, 5, 4, 0] Target: 10\n  Output: [-1 11]\n*/\n#include <iostream>\n#include <unordered_map>\n#include <vector>\n\nstd::vector<int> twoNumberSum(std::vector<int>& nums, int target) {\n    // Create an unordered_map to store the indices of the elements in the vector\n    std::unordered_map<int, int> map;\n    \n    // Loop through the vector\n    for (int i = 0; i < nums.size(); i++) {\n        // Calculate the complement of the current element with respect to the target sum\n        int complement = target - nums[i];\n        \n        // Check if the complement is already in the map\n        if (map.count(complement) > 0) {\n            // If the complement is in the map, return the indices of the two elements that sum up to the target\n            return { map[complement], i };\n        }\n        \n        // If the complement is not in the map, add the current element and its index to the map\n        map[nums[i]] = i;\n    }\n    \n    // If no two elements sum up to the target, return an empty vector\n    return {};\n}\n\nint main() {\n    // Example usage\n    std::vector<int> nums = { 2, 7, 11, 15 };\n    int target = 9;\n    std::vector<int> result = twoNumberSum(nums, target);\n    \n    if (result.size() > 0) {\n        std::cout << \"Indices of the two numbers that sum up to \" << target << \": \";\n        for (int i : result) {\n            std::cout << i << \" \";\n        }\n        std::cout << std::endl;\n    } else {\n        std::cout << \"No two numbers found that sum up to \" << target << \".\" << std::endl;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "Hash Table/two_sum.go",
    "content": "/*\n  Write a function that takes in a non-empty array of distinct integers and an\n  integer representing a target sum. If any two numbers in the input array sum\n  up to the target sum, the function should return them in an array, in any\n  order. If no two numbers sum up to the target sum, the function should return\n  an empty array.\n  Sample Input: [2, 1, 3, -1, 11, 5, 4, 0] Target: 10\n  Output: [-1 11]\n*/\npackage main\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n)\n\n// Bruteforce method continuously scan the array\n// for every i run j len(array) times, if target sum is found then return\nfunc TwoNUmberSumBruteForce(array []int, target int) []int {\n\t// nil array to hold result\n\tvar result []int\n\tfor i := 0; i < len(array) - 1; i++ {\n\t\tfor j := i + 1; j < len(array); j++ {\n\t\t\t// look for target\n\t\t\tif array[i] + array[j] == target {\n\t\t\t\t// add found values in array\n\t\t\t\tresult = append(result, array[i])\n\t\t\t\tresult = append(result, array[j])\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t}\n\treturn result \n}\n// Two Pointer approach\n// sort the given array, set i as initial index and j as last\n// add element at i and j and compate with target, if it matches then return\n// if element is greater then target decrease index of j by 1\n// if element is lesser then target increase index of i by 1\nfunc TwoNumberSumTwoPointerMethod(array []int, target int) []int {\n\tvar result []int\n\t// sort the given array in place\n\tsort.Ints(array)\n\tj := len(array) - 1 // set j as last\n\ti := 0 // set i as initial index\n\t// i and j should not overlap\n\tfor i < j { \n\t\t// check if it matches sum\n\t\tif array[i] + array[j] == target {\n\t\t\t// add result in array\n\t\t\tresult = append(result, array[i])\n\t\t\tresult = append(result, array[j])\n\t\t\t// return the result\n\t\t\treturn result\n\t\t} else if array[i] + array[j] > target {\n\t\t\t// elements is greater that means look to left side of j\n\t\t\tj--;\n\t\t} else if array[i] + array[j] < target {\n\t\t\t// // elements is smaller that means look to right side of i\n\t\t\ti++;\n\t\t}\n\t}\n\treturn result\n}\n\nfunc TwoNumberSum(array []int, target int) []int {\n\t// Create map to keep track of what we ahve seen so far\n\tm := make(map[int]int)\n\t // initialize empty array for result\n\tvar result []int\n\t // traverse array\n\tfor i := 0; i < len(array); i++ {\n\t\t// lets say first element in our array is 3, and target sum is 10\n        // then we will look for 7 in our map, if its present then we simply return 7 and 3 \n\t\trequired := target - array[i]\n\t\t// if the required value is found then store result\n\t\tif _, ok := m[required]; ok {\n\t\t\tresult = append(result, required)\n\t\t\tresult = append(result, array[i])\n\t\t\treturn result\n\t\t} else {\n\t\t\t// keep track of what value in array we have seen so far\n\t\t\tm[array[i]] = i\n\t\t}\n\t}\n\treturn result\n}\n\nfunc main() {\n\tarr := []int{2, 1, 3, -1, 11, 5, 4, 0}\n\tmsg := TwoNumberSum(arr, 10)\n\tfmt.Println(msg)\n\tmsg = TwoNUmberSumBruteForce(arr, 10)\n\tfmt.Println(msg)\n\tarr = []int{2, 1, 3, -1, 11, 5, 4, 0, 44}\n\tmsg = TwoNumberSumTwoPointerMethod(arr, 9)\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Hash Table/two_sum.java",
    "content": "/*\n  Write a function that takes in a non-empty array of distinct integers and an\n  integer representing a target sum. If any two numbers in the input array sum\n  up to the target sum, the function should return them in an array, in any\n  order. If no two numbers sum up to the target sum, the function should return\n  an empty array.\n  Sample Input: [2, 1, 3, -1, 11, 5, 4, 0] Target: 10\n  Output: [-1 11]\n*/\nimport java.util.*;\n\npublic class TwoNumberSum {\n    \n    public static void main(String[] args) {\n        int[] array = {3, 5, -4, 8, 11, 1, -1, 6};\n        int targetSum = 10;\n    }\n    \n    // Brute Force Solution\n    // Time complexity: O(N^2);\n    // Space Complexity: O(1);\n    public static int[] TwoSumBruteForce(int[] array, int targetSum) {\n        for(int i = 0; i < array.length - 1; i++) {\n            int firstNum = array[i];\n            for(int j = i + 1; j < array.length; j++) {\n                int secondNum = array[j];\n                if(firstNum + secondNum == targetSum)\n                    return new int[] {firstNum, secondNum};\n            }\n        } return new int[0];\n    }\n\n    // Sorting Solution\n    // Time complexity: O(N log N);\n    // Space Complexity: O(1);\n    public static int[] TwoSumBySorting(int[] array, int targetSum) {\n    // O(nlog(n)) time | O(1) space\n        Arrays.sort(array);\n        int left = 0;\n        int right = array.length - 1;\n        while(left < right) {\n            int firstNum = array[left];\n            int secondNum = array[right];\n            int currentSum = firstNum + secondNum;\n            if(currentSum == targetSum) return new int[] {firstNum, secondNum};\n            else if(currentSum < targetSum) left += 1;\n            else right -= 1;\n        } return new int[0];\n    }\n    \n    // Optimal Solution\n    // Time complexity: O(N);\n    // Space Complexity: O(N);\n    public static int[] TwoSumOptimal(int[] array, int targetSum) {\n        Set<Integer> nums = new HashSet<>();\n        for(int num: array) {\n            int potentialMatch = targetSum - num;\n            if(nums.contains(potentialMatch)) return new int[] {num, potentialMatch};\n            nums.add(num);\n        } return new int[0];\n    }\n}\n"
  },
  {
    "path": "Hash Table/two_sum.js",
    "content": "/*\n  Write a function that takes in a non-empty array of distinct integers and an\n  integer representing a target sum. If any two numbers in the input array sum\n  up to the target sum, the function should return them in an array, in any\n  order. If no two numbers sum up to the target sum, the function should return\n  an empty array.\n  Sample Input: [2, 1, 3, -1, 11, 5, 4, 0] Target: 10\n  Output: [-1 11]\n*/\nfunction twoNumberSum(nums, target) {\n  // Create a new Map object to store the indices of the elements in the array\n  const map = new Map();\n\n  // Loop through the array\n  for (let i = 0; i < nums.length; i++) {\n    // Calculate the complement of the current element with respect to the target sum\n    const complement = target - nums[i];\n\n    // Check if the complement is already in the map\n    if (map.has(complement)) {\n      // If the complement is in the map, return the indices of the two elements that sum up to the target\n      return [map.get(complement), i];\n    }\n\n    // If the complement is not in the map, add the current element and its index to the map\n    map.set(nums[i], i);\n  }\n\n  // If no two elements sum up to the target, return an empty array\n  return [];\n}\n\n// Example usage\nconst nums = [2, 7, 11, 15];\nconst target = 9;\nconst result = twoNumberSum(nums, target);\n\nif (result.length > 0) {\n  console.log(`Indices of the two numbers that sum up to ${target}: ${result}`);\n} else {\n  console.log(`No two numbers found that sum up to ${target}.`);\n}\n"
  },
  {
    "path": "Hash Table/two_sum.py",
    "content": "'''\n  Write a function that takes in a non-empty array of distinct integers and an\n  integer representing a target sum. If any two numbers in the input array sum\n  up to the target sum, the function should return them in an array, in any\n  order. If no two numbers sum up to the target sum, the function should return\n  an empty array.\n  Sample Input: [2, 1, 3, -1, 11, 5, 4, 0] Target: 10\n  Output: [-1 11]\n'''\n# Brute Force Approach\n# Time complexity: O(N^2);\n# Space Complexity: O(1);\nclass Solution:\n    def twoSum(self, nums: List[int], target: int) -> List[int]:\n        for i in range(len(nums)):\n            for j in range(i + 1, len(nums)):\n                if nums[i] + nums[j] == target:\n                    return [i, j]\n        return []\n    \n# Two Pointer approach\n# Time complexity: O(N);\n# Space Complexity: O(N);\nclass Solution:\n    def twoSum(self, nums: List[int], target: int) -> List[int]:\n        # Create map to keep track of what we ahve seen so far\n        numToIndex = {}\n        for i in range(len(nums)):\n            # lets say first element in our array is 3, and target sum is 10\n            # then we will look for 7 in our map, if its present then we simply return 7 and 3 \n            # if the required value is found then store result\n            if target - nums[i] in numToIndex:\n                return [numToIndex[target - nums[i]], i]\n            # keep track of what value in array we have seen so far\n            numToIndex[nums[i]] = i\n        return []"
  },
  {
    "path": "Hash Table/zero_sum_subarray.cpp",
    "content": "/*\n\tYou're given a list of integers nums. Write a function that returns a boolean representing\n\twhether there exists a zero-sum subarray of nums\n\n\tSample Input :  = [-5, -5, 2, 3, -2]\n\tOutput : True\n\tThe subarray [-5, 2, 3] has a sum of 0\n\n    Approach:\n    Time and Space complexity : O(n) time | O(n) space - where n is the length of nums\n    This implementation uses an unordered map to keep track of the prefix sum of the input array nums. \n    We initialize the map with a key-value pair of 0 and -1, since a prefix sum of 0 indicates that the \n    subarray from index 0 to -1 (i.e., an empty subarray) has a sum of 0. We then iterate through the \n    input array nums, adding each element to the running sum sum and checking if the current sum is \n    already in the map. If it is, then we've found a subarray whose sum is 0, so we add the starting and \n    ending indices of the subarray to the result vector and break out of the loop.\n    If we reach the end of the loop without finding a zero sum subarray, then we return an empty vector.\n    Note that this implementation assumes that there is only one zero sum subarray in the input array. \n    If there could be multiple zero sum subarrays, then we would need to modify the implementation to \n    return all of them.\n*/\n#include <iostream>\n#include <unordered_map>\n#include <vector>\n\nusing namespace std;\n\nvector<int> zeroSumSubarray(vector<int>& nums) {\n    vector<int> result;\n    unordered_map<int, int> mp;\n    int sum = 0;\n    mp[0] = -1;\n    \n    for (int i = 0; i < nums.size(); i++) {\n        sum += nums[i];\n        if (mp.find(sum) != mp.end()) {\n            result.push_back(mp[sum] + 1);\n            result.push_back(i);\n            break;\n        }\n        mp[sum] = i;\n    }\n    \n    return result;\n}\n\nint main() {\n    vector<int> nums = {4, 2, -3, 1, 6};\n    vector<int> result = zeroSumSubarray(nums);\n    if (result.empty()) {\n        cout << \"No zero sum subarray found.\" << endl;\n    } else {\n        cout << \"Zero sum subarray found: \";\n        for (int i = result[0]; i <= result[1]; i++) {\n            cout << nums[i] << \" \";\n        }\n        cout << endl;\n    }\n    return 0;\n}\n"
  },
  {
    "path": "Hash Table/zero_sum_subarray.go",
    "content": "/*\n\tYou're given a list of integers nums. Write a function that returns a boolean representing\n\twhether there exists a zero-sum subarray of nums\n\n\tSample Input :  = [-5, -5, 2, 3, -2]\n\tOutput : True\n\tThe subarray [-5, 2, 3] has a sum of 0\n\n    Approach:\n    Time and Space complexity : O(n) time | O(n) space - where n is the length of nums\n    This implementation uses an unordered map to keep track of the prefix sum of the input array nums. \n    We initialize the map with a key-value pair of 0 and -1, since a prefix sum of 0 indicates that the \n    subarray from index 0 to -1 (i.e., an empty subarray) has a sum of 0. We then iterate through the \n    input array nums, adding each element to the running sum sum and checking if the current sum is \n    already in the map. If it is, then we've found a subarray whose sum is 0, so we add the starting and \n    ending indices of the subarray to the result vector and break out of the loop.\n    If we reach the end of the loop without finding a zero sum subarray, then we return an empty vector.\n    Note that this implementation assumes that there is only one zero sum subarray in the input array. \n    If there could be multiple zero sum subarrays, then we would need to modify the implementation to \n    return all of them.\n*/\npackage main\n\nimport \"fmt\"\n\nfunc ZeroSumSubarray(nums []int) bool {\n\tsums := map[int]bool{0: true}\n    currentSum := 0\n    for _, num := range nums {\n        currentSum += num\n        if _, sumIsInSet := sums[currentSum]; sumIsInSet {\n            return true\n        }\n        sums[currentSum] = true\n    }\n    return false\n}\n\nfunc main() {\n\tnums := []int{-5, -5, 2, 3, -2}\n\tfmt.Println(ZeroSumSubarray(nums))\n\tnums = []int{1, 2, 3, 4, 5}\n\tfmt.Println(ZeroSumSubarray(nums))\n}"
  },
  {
    "path": "Hash Table/zero_sum_subarray.java",
    "content": "/*\nQ -> Hash Table: You're given a list of integers nums.\nWrite a function that returns a boolean representing whether there exists a zero-sum subarray of nums in Java\n*/\n\n//Here's a Java code that implements a solution to find if there is a zero-sum subarray in the given list of\n// integers using a hash table.\n\nimport java.util.*;\n\npublic class ZeroSumSubarray {\n\n    public static boolean hasZeroSumSubarray(int[] nums) {\n        Set<Integer> set = new HashSet<>();\n        int sum = 0;\n        for (int i = 0; i < nums.length; i++) {\n            sum += nums[i];\n            if (sum == 0 || set.contains(sum)) {\n                return true;\n            }\n            set.add(sum);\n        }\n        return false;\n    }\n\n    public static void main(String[] args) {\n        int[] nums = {4, -3, 2, 1, 8};\n        boolean hasZeroSumSubarray = hasZeroSumSubarray(nums);\n        System.out.println(hasZeroSumSubarray);\n    }\n}\n\n/*\nExplanation:-\n\nThe above code uses a HashSet to keep track of the prefix sum of the elements of the input array. At each index, it checks if the sum up to that index has already been seen before in the HashSet.\nIf it has been seen, it means that there exists a subarray with a zero sum. If the sum equals zero, then the subarray starts from the beginning of the array.\nThe time complexity of this algorithm is O(n), where n is the size of the input array, since we traverse the input array only once.\nThe space complexity is also O(n), since the HashSet can contain up to n elements in the worst case.\n */\n"
  },
  {
    "path": "Hash Table/zero_sum_subarray.js",
    "content": "/*\n\tYou're given a list of integers nums. Write a function that returns a boolean representing\n\twhether there exists a zero-sum subarray of nums\n\n\tSample Input :  = [-5, -5, 2, 3, -2]\n\tOutput : True\n\tThe subarray [-5, 2, 3] has a sum of 0\n\n    Time and Space complexity : O(n) time | O(n) space - where n is the length of nums\n\n    Approach:\n    The function takes in an array of integers nums. It initializes a set sums to keep track of the subarray sums we've seen so far, \n    and a variable currentSum to keep track of the current sum as we loop through the array.\n\n    We then loop through each number in the array, adding the current number to the current sum. \n    We check if the current sum is zero or if we've seen it before (i.e. if it's already in the sums set). \n    If so, we've found a zero-sum subarray, so we return true.\n\n    If we loop through the entire array without finding a zero-sum subarray, we return false.\n*/\nfunction hasZeroSumSubarray(nums) {\n  const sums = new Set(); // Initialize a set to keep track of the subarray sums\n  let currentSum = 0; // Initialize a variable to keep track of the current sum\n\n  for (const num of nums) {\n    // Loop through each number in the array\n    currentSum += num; // Add the current number to the current sum\n    if (currentSum === 0 || sums.has(currentSum)) {\n      // Check if the current sum is zero or if we've seen it before\n      return true; // If so, we've found a zero-sum subarray, so return true\n    }\n    sums.add(currentSum); // Add the current sum to the set of subarray sums\n  }\n  return false; // If we loop through the entire array without finding a zero-sum subarray, return false\n}\n"
  },
  {
    "path": "Hash Table/zero_sum_subarray.py",
    "content": "'''\n\tYou're given a list of integers nums. Write a function that returns a boolean representing\n\twhether there exists a zero-sum subarray of nums\n\n\tSample Input :  = [-5, -5, 2, 3, -2]\n\tOutput : True\n\tThe subarray [-5, 2, 3] has a sum of 0\n\n    Approach:\n    Time and Space complexity : O(n) time | O(n) space - where n is the length of nums\n    This implementation uses an unordered map to keep track of the prefix sum of the input array nums. \n    We initialize the map with a key-value pair of 0 and -1, since a prefix sum of 0 indicates that the \n    subarray from index 0 to -1 (i.e., an empty subarray) has a sum of 0. We then iterate through the \n    input array nums, adding each element to the running sum sum and checking if the current sum is \n    already in the map. If it is, then we've found a subarray whose sum is 0, so we add the starting and \n    ending indices of the subarray to the result vector and break out of the loop.\n    If we reach the end of the loop without finding a zero sum subarray, then we return an empty vector.\n    Note that this implementation assumes that there is only one zero sum subarray in the input array. \n    If there could be multiple zero sum subarrays, then we would need to modify the implementation to \n    return all of them.\n'''\ndef zero_sum_subarray(nums):\n    # Initialize a set to keep track of previously encountered prefix sums.\n    prefix_sums = set()\n    prefix_sum = 0\n    \n    # Loop through each number in the array.\n    for num in nums:\n        # Add the current number to the running prefix sum.\n        prefix_sum += num\n        \n        # If the current prefix sum is in the set of previous prefix sums,\n        # then we have found a subarray whose sum is zero.\n        if prefix_sum in prefix_sums:\n            return True\n        \n        # Add the current prefix sum to the set of previous prefix sums.\n        prefix_sums.add(prefix_sum)\n    \n    # If no subarray whose sum is zero was found, return False.\n    return False\n"
  },
  {
    "path": "Heaps/heap.cpp",
    "content": "/*\n\tImplement a Min-Heap class that supports\n\n\t\tBuilding a Min Heap from an input array of integers.\n\t\tInserting integers in the heap.\n\t\tRemoving the heap's minimum / root value.\n\t\tPeeking at the heap's minimum / root value.\n\t\tSifting integers up and down the heap, which is to be used when inserting and removing values.\n\n\tNote that the heap should be represented in the form of an array.\n\n\tExplanation:\n\n\tThe code snippet implements a MinHeap data structure in Go.\n\n\t- `NewMinHeap`: This function creates a new MinHeap from an input array and returns a pointer to the MinHeap object.\n\t   It calls the `BuildHeap` method to construct the heap structure.\n\t- `BuildHeap`: This method constructs the heap by iteratively calling `siftDown` on each parent node starting from the\n\t   last non-leaf node.\n\t- `siftDown`: This method corrects the heap property by moving an element down the heap until it reaches its correct position. It compares the element with its children and swaps it with the smaller child if necessary.\n\t- `siftUp`: This method corrects the heap property by moving an element up the heap until it reaches its correct position.\n\t   It compares the element with its parent and swaps it if necessary.\n\t- `Peek`: This method returns the minimum element in the heap (the root of the heap) without removing it.\n\t- `Remove`: This method removes and returns the minimum element in the heap. It swaps the root with the last element,\n\t   removes the last element from the heap, and then calls `siftDown` to maintain the heap property.\n\t- `Insert`: This method inserts a new element into the heap. It appends the element to the end of the heap and then\n\t   calls `siftUp` to maintain the heap property.\n\t- `swap`: This method swaps two elements in the heap given their indices.\n\t- `length`: This method returns the number of elements in the heap.\n\n\tOverall, this code provides a basic implementation of a MinHeap data structure, allowing for efficient insertion, removal,\n\tand retrieval of the minimum element.\n\n\tBuildHeap: O(n) time | O(1) space - where n is the length of the input array\n\tSiftDown: O(log(n)) time | O(1) space - where n is the length of the heap\n\tSiftUp: O(log(n)) time | O(1) space - where n is the length of the heap\n\tPeek: O(1) time | O(1) space\n\tRemove: O(log(n)) time | O(1) space - where n is the length of the heap\n\tInsert: O(log(n)) time | O(1) space - where n is the length of the heap\n\n*/\n#include <vector>\n\nclass MinHeap {\npublic:\n    std::vector<int> heap;  // The heap represented as a vector\n\n    void buildHeap(std::vector<int>& array) {\n        int first = (array.size() - 2) / 2;  // Start from the last parent node\n        for (int currentIdx = first; currentIdx >= 0; currentIdx--) {\n            siftDown(currentIdx, array.size() - 1);\n        }\n    }\n\n    void siftDown(int currentIndex, int endIndex) {\n        int childOneIdx = currentIndex * 2 + 1;  // Calculate the index of the first child\n        while (childOneIdx <= endIndex) {\n            int childTwoIdx = -1;  // Initialize the index of the second child\n            if (currentIndex * 2 + 2 <= endIndex) {\n                childTwoIdx = currentIndex * 2 + 2;  // Calculate the index of the second child if it exists\n            }\n            int indexToSwap = childOneIdx;  // Assume the first child is the one to swap with\n            if (childTwoIdx > -1 && heap[childOneIdx] > heap[childTwoIdx]) {\n                // If the second child exists and is smaller, update the index to swap with\n                indexToSwap = childTwoIdx;\n            }\n            if (heap[currentIndex] > heap[indexToSwap]) {\n                // If the current element is greater than the one to swap with, perform the swap\n                swap(currentIndex, indexToSwap);\n                currentIndex = indexToSwap;\n                childOneIdx = currentIndex * 2 + 1;  // Update the index of the first child\n            } else {\n                return;\n            }\n        }\n    }\n\n    void siftUp() {\n        int currentIdx = heap.size() - 1;  // Start from the last element\n        int parentIdx = (currentIdx - 1) / 2;  // Calculate the index of the parent\n        while (currentIdx > 0) {\n            int current = heap[currentIdx];\n            int parent = heap[parentIdx];\n            if (current < parent) {\n                // If the current element is smaller than the parent, perform the swap\n                swap(currentIdx, parentIdx);\n                currentIdx = parentIdx;\n                parentIdx = (currentIdx - 1) / 2;  // Update the index of the parent\n            } else {\n                return;\n            }\n        }\n    }\n\n    int peek() {\n        if (heap.empty()) {\n            return -1;\n        }\n        return heap[0];  // Return the minimum element at the top of the heap\n    }\n\n    int remove() {\n        int l = heap.size();\n        swap(0, l - 1);  // Swap the root with the last element\n        int peeked = heap[l - 1];  // Remove the last element (minimum) and store it\n        heap.pop_back();\n        siftDown(0, l - 2);  // Sift down the new root element\n        return peeked;\n    }\n\n    void insert(int value) {\n        heap.push_back(value);  // Append the new element to the end of the heap\n        siftUp();  // Sift up the new element to its correct position\n    }\n\n    void swap(int i, int j) {\n        int temp = heap[i];\n        heap[i] = heap[j];\n        heap[j] = temp;  // Swap elements at indices i and j\n    }\n\n    int length() {\n        return heap.size();  // Return the number of elements in the heap\n    }\n};\n\nMinHeap* newMinHeap(std::vector<int>& array) {\n    MinHeap* heap = new MinHeap();  // Create a new MinHeap object\n    heap->buildHeap(array);  // Build the heap using the given array\n    return heap;\n}\n"
  },
  {
    "path": "Heaps/heap.go",
    "content": "/*\n\tImplement a Min-Heap class that supports\n\n\t\tBuilding a Min Heap from an input array of integers.\n\t\tInserting integers in the heap.\n\t\tRemoving the heap's minimum / root value.\n\t\tPeeking at the heap's minimum / root value.\n\t\tSifting integers up and down the heap, which is to be used when inserting and removing values.\n\n\tNote that the heap should be represented in the form of an array.\n\n\tExplanation:\n\n\tThe code snippet implements a MinHeap data structure in Go.\n\n\t- `NewMinHeap`: This function creates a new MinHeap from an input array and returns a pointer to the MinHeap object.\n\t   It calls the `BuildHeap` method to construct the heap structure.\n\t- `BuildHeap`: This method constructs the heap by iteratively calling `siftDown` on each parent node starting from the\n\t   last non-leaf node.\n\t- `siftDown`: This method corrects the heap property by moving an element down the heap until it reaches its correct position. It compares the element with its children and swaps it with the smaller child if necessary.\n\t- `siftUp`: This method corrects the heap property by moving an element up the heap until it reaches its correct position.\n\t   It compares the element with its parent and swaps it if necessary.\n\t- `Peek`: This method returns the minimum element in the heap (the root of the heap) without removing it.\n\t- `Remove`: This method removes and returns the minimum element in the heap. It swaps the root with the last element,\n\t   removes the last element from the heap, and then calls `siftDown` to maintain the heap property.\n\t- `Insert`: This method inserts a new element into the heap. It appends the element to the end of the heap and then\n\t   calls `siftUp` to maintain the heap property.\n\t- `swap`: This method swaps two elements in the heap given their indices.\n\t- `length`: This method returns the number of elements in the heap.\n\n\tOverall, this code provides a basic implementation of a MinHeap data structure, allowing for efficient insertion, removal,\n\tand retrieval of the minimum element.\n\n\tBuildHeap: O(n) time | O(1) space - where n is the length of the input array\n\tSiftDown: O(log(n)) time | O(1) space - where n is the length of the heap\n\tSiftUp: O(log(n)) time | O(1) space - where n is the length of the heap\n\tPeek: O(1) time | O(1) space\n\tRemove: O(log(n)) time | O(1) space - where n is the length of the heap\n\tInsert: O(log(n)) time | O(1) space - where n is the length of the heap\n\n*/\npackage main\n\n// MinHeap represents a min heap data structure.\ntype MinHeap []int\n\n// NewMinHeap creates a new MinHeap from an input array and returns a pointer to it.\nfunc NewMinHeap(array []int) *MinHeap {\n\t// Create a heap from the input array\n\theap := MinHeap(array)\n\tptr := &heap\n\t// Build the heap structure\n\tptr.BuildHeap(array)\n\treturn ptr\n}\n\n// BuildHeap constructs the heap by calling siftDown on each parent node.\nfunc (h *MinHeap) BuildHeap(array []int) {\n\t// Calculate the index of the first parent node\n\tfirst := (len(array) - 2) / 2\n\t// Iterate over each parent node and sift it down\n\tfor currentIdx := first + 1; currentIdx >= 0; currentIdx-- {\n\t\th.siftDown(currentIdx, len(array)-1)\n\t}\n}\n\n// siftDown moves an element down the heap until it reaches its correct position.\nfunc (h *MinHeap) siftDown(currentIndex, endIndex int) {\n\tchildOneIdx := currentIndex*2 + 1\n\tfor childOneIdx <= endIndex {\n\t\tchildTwoIdx := -1\n\t\tif currentIndex*2+2 <= endIndex {\n\t\t\tchildTwoIdx = currentIndex*2 + 2\n\t\t}\n\t\tindexToSwap := childOneIdx\n\t\tif childTwoIdx > -1 && (*h)[childOneIdx] > (*h)[childTwoIdx] {\n\t\t\tindexToSwap = childTwoIdx\n\t\t}\n\t\tif (*h)[currentIndex] > (*h)[indexToSwap] {\n\t\t\th.swap(currentIndex, indexToSwap)\n\t\t\tcurrentIndex = indexToSwap\n\t\t\tchildOneIdx = currentIndex*2 + 1\n\t\t} else {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// siftUp moves an element up the heap until it reaches its correct position.\nfunc (h *MinHeap) siftUp() {\n\tcurrentIdx := h.length() - 1\n\tparentIdx := (currentIdx - 1) / 2\n\tfor currentIdx > 0 {\n\t\tcurrent, parent := (*h)[currentIdx], (*h)[parentIdx]\n\t\tif current < parent {\n\t\t\th.swap(currentIdx, parentIdx)\n\t\t\tcurrentIdx = parentIdx\n\t\t\tparentIdx = (currentIdx - 1) / 2\n\t\t} else {\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// Peek returns the minimum element in the heap without removing it.\nfunc (h MinHeap) Peek() int {\n\tif len(h) == 0 {\n\t\treturn -1\n\t}\n\treturn h[0]\n}\n\n// Remove removes and returns the minimum element in the heap.\nfunc (h *MinHeap) Remove() int {\n\tl := h.length()\n\th.swap(0, l-1)\n\tpeeked := (*h)[l-1]\n\t*h = (*h)[:l-1]\n\th.siftDown(0, l-1)\n\treturn peeked\n}\n\n// Insert inserts a new element into the heap.\nfunc (h *MinHeap) Insert(value int) {\n\t*h = append(*h, value)\n\th.siftUp()\n}\n\n// swap swaps two elements in the heap given their indices.\nfunc (h MinHeap) swap(i, j int) {\n\th[i], h[j] = h[j], h[i]\n}\n\n// length returns the number of elements in the heap.\nfunc (h MinHeap) length() int {\n\treturn len(h)\n}\n"
  },
  {
    "path": "Heaps/heap.java",
    "content": "/*\n\tImplement a Min-Heap class that supports\n\n\t\tBuilding a Min Heap from an input array of integers.\n\t\tInserting integers in the heap.\n\t\tRemoving the heap's minimum / root value.\n\t\tPeeking at the heap's minimum / root value.\n\t\tSifting integers up and down the heap, which is to be used when inserting and removing values.\n\n\tNote that the heap should be represented in the form of an array.\n\n\tExplanation:\n\n\tThe code snippet implements a MinHeap data structure in Go.\n\n\t- `NewMinHeap`: This function creates a new MinHeap from an input array and returns a pointer to the MinHeap object.\n\t   It calls the `BuildHeap` method to construct the heap structure.\n\t- `BuildHeap`: This method constructs the heap by iteratively calling `siftDown` on each parent node starting from the\n\t   last non-leaf node.\n\t- `siftDown`: This method corrects the heap property by moving an element down the heap until it reaches its correct position. It compares the element with its children and swaps it with the smaller child if necessary.\n\t- `siftUp`: This method corrects the heap property by moving an element up the heap until it reaches its correct position.\n\t   It compares the element with its parent and swaps it if necessary.\n\t- `Peek`: This method returns the minimum element in the heap (the root of the heap) without removing it.\n\t- `Remove`: This method removes and returns the minimum element in the heap. It swaps the root with the last element,\n\t   removes the last element from the heap, and then calls `siftDown` to maintain the heap property.\n\t- `Insert`: This method inserts a new element into the heap. It appends the element to the end of the heap and then\n\t   calls `siftUp` to maintain the heap property.\n\t- `swap`: This method swaps two elements in the heap given their indices.\n\t- `length`: This method returns the number of elements in the heap.\n\n\tOverall, this code provides a basic implementation of a MinHeap data structure, allowing for efficient insertion, removal,\n\tand retrieval of the minimum element.\n\n\tBuildHeap: O(n) time | O(1) space - where n is the length of the input array\n\tSiftDown: O(log(n)) time | O(1) space - where n is the length of the heap\n\tSiftUp: O(log(n)) time | O(1) space - where n is the length of the heap\n\tPeek: O(1) time | O(1) space\n\tRemove: O(log(n)) time | O(1) space - where n is the length of the heap\n\tInsert: O(log(n)) time | O(1) space - where n is the length of the heap\n\n*/\nimport java.util.Arrays;\n\npublic class MinHeap {\n    private int[] heap;  // The heap represented as an array\n    private int size;  // The current size of the heap\n\n    public MinHeap(int[] array) {\n        heap = Arrays.copyOf(array, array.length);  // Create a copy of the input array\n        size = array.length;\n        buildHeap();  // Build the heap\n    }\n\n    private void buildHeap() {\n        int first = (size - 2) / 2;  // Start from the last parent node\n        for (int currentIdx = first; currentIdx >= 0; currentIdx--) {\n            siftDown(currentIdx);\n        }\n    }\n\n    private void siftDown(int currentIndex) {\n        int childOneIdx = currentIndex * 2 + 1;  // Calculate the index of the first child\n        while (childOneIdx < size) {\n            int childTwoIdx = -1;  // Initialize the index of the second child\n            if (currentIndex * 2 + 2 < size) {\n                childTwoIdx = currentIndex * 2 + 2;  // Calculate the index of the second child if it exists\n            }\n            int indexToSwap = childOneIdx;  // Assume the first child is the one to swap with\n            if (childTwoIdx > -1 && heap[childOneIdx] > heap[childTwoIdx]) {\n                // If the second child exists and is smaller, update the index to swap with\n                indexToSwap = childTwoIdx;\n            }\n            if (heap[currentIndex] > heap[indexToSwap]) {\n                // If the current element is greater than the one to swap with, perform the swap\n                swap(currentIndex, indexToSwap);\n                currentIndex = indexToSwap;\n                childOneIdx = currentIndex * 2 + 1;  // Update the index of the first child\n            } else {\n                return;\n            }\n        }\n    }\n\n    private void siftUp() {\n        int currentIdx = size - 1;  // Start from the last element\n        int parentIdx = (currentIdx - 1) / 2;  // Calculate the index of the parent\n        while (currentIdx > 0) {\n            int current = heap[currentIdx];\n            int parent = heap[parentIdx];\n            if (current < parent) {\n                // If the current element is smaller than the parent, perform the swap\n                swap(currentIdx, parentIdx);\n                currentIdx = parentIdx;\n                parentIdx = (currentIdx - 1) / 2;  // Update the index of the parent\n            } else {\n                return;\n            }\n        }\n    }\n\n    public int peek() {\n        if (size == 0) {\n            return -1;\n        }\n        return heap[0];  // Return the minimum element at the top of the heap\n    }\n\n    public int remove() {\n        swap(0, size - 1);  // Swap the root with the last element\n        int peeked = heap[size - 1];  // Remove the last element (minimum) and store it\n        size--;\n        siftDown(0);  // Sift down the new root element\n        return peeked;\n    }\n\n    public void insert(int value) {\n        if (size >= heap.length) {\n            heap = Arrays.copyOf(heap, size * 2);  // Resize the array if necessary\n        }\n        heap[size] = value;  // Append the new element to the end of the heap\n        size++;\n        siftUp();  // Sift up the new element to its correct position\n    }\n\n    private void swap(int i, int j) {\n        int temp = heap[i];\n        heap[i] = heap[j];\n        heap[j] = temp;  // Swap elements at indices i and j\n    }\n\n    public int length() {\n        return size;  // Return the number of elements in the heap\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        int[] array = { 9, 4, 7, 1, -2, 6, 5 };\n        MinHeap minHeap = new MinHeap(array);\n\n        System.out.println(\"Peek: \" + minHeap.peek());\n        System.out.println(\"Remove: \" + minHeap.remove());\n        System.out.println(\"Length: \" + minHeap.length());\n\n        minHeap.insert(2);\n        minHeap.insert(-5);\n\n        System.out.println(\"Peek: \" + minHeap.peek());\n        System.out.println(\"Length: \" + minHeap.length());\n    }\n}\n"
  },
  {
    "path": "Heaps/heap.js",
    "content": "/*\n\tImplement a Min-Heap class that supports\n\n\t\tBuilding a Min Heap from an input array of integers.\n\t\tInserting integers in the heap.\n\t\tRemoving the heap's minimum / root value.\n\t\tPeeking at the heap's minimum / root value.\n\t\tSifting integers up and down the heap, which is to be used when inserting and removing values.\n\n\tNote that the heap should be represented in the form of an array.\n\n\tExplanation:\n\n\tThe code snippet implements a MinHeap data structure in Go.\n\n\t- `NewMinHeap`: This function creates a new MinHeap from an input array and returns a pointer to the MinHeap object.\n\t   It calls the `BuildHeap` method to construct the heap structure.\n\t- `BuildHeap`: This method constructs the heap by iteratively calling `siftDown` on each parent node starting from the\n\t   last non-leaf node.\n\t- `siftDown`: This method corrects the heap property by moving an element down the heap until it reaches its correct position. It compares the element with its children and swaps it with the smaller child if necessary.\n\t- `siftUp`: This method corrects the heap property by moving an element up the heap until it reaches its correct position.\n\t   It compares the element with its parent and swaps it if necessary.\n\t- `Peek`: This method returns the minimum element in the heap (the root of the heap) without removing it.\n\t- `Remove`: This method removes and returns the minimum element in the heap. It swaps the root with the last element,\n\t   removes the last element from the heap, and then calls `siftDown` to maintain the heap property.\n\t- `Insert`: This method inserts a new element into the heap. It appends the element to the end of the heap and then\n\t   calls `siftUp` to maintain the heap property.\n\t- `swap`: This method swaps two elements in the heap given their indices.\n\t- `length`: This method returns the number of elements in the heap.\n\n\tOverall, this code provides a basic implementation of a MinHeap data structure, allowing for efficient insertion, removal,\n\tand retrieval of the minimum element.\n\n\tBuildHeap: O(n) time | O(1) space - where n is the length of the input array\n\tSiftDown: O(log(n)) time | O(1) space - where n is the length of the heap\n\tSiftUp: O(log(n)) time | O(1) space - where n is the length of the heap\n\tPeek: O(1) time | O(1) space\n\tRemove: O(log(n)) time | O(1) space - where n is the length of the heap\n\tInsert: O(log(n)) time | O(1) space - where n is the length of the heap\n\n*/\nclass MinHeap {\n  constructor(array) {\n    this.heap = array.slice(); // Create a copy of the input array\n    this.size = array.length;\n    this.buildHeap(); // Build the heap\n  }\n\n  buildHeap() {\n    const first = Math.floor((this.size - 2) / 2); // Start from the last parent node\n    for (let currentIdx = first; currentIdx >= 0; currentIdx--) {\n      this.siftDown(currentIdx);\n    }\n  }\n\n  siftDown(currentIndex) {\n    let childOneIdx = currentIndex * 2 + 1; // Calculate the index of the first child\n    while (childOneIdx < this.size) {\n      let childTwoIdx = -1; // Initialize the index of the second child\n      if (currentIndex * 2 + 2 < this.size) {\n        childTwoIdx = currentIndex * 2 + 2; // Calculate the index of the second child if it exists\n      }\n      let indexToSwap = childOneIdx; // Assume the first child is the one to swap with\n      if (childTwoIdx > -1 && this.heap[childOneIdx] > this.heap[childTwoIdx]) {\n        // If the second child exists and is smaller, update the index to swap with\n        indexToSwap = childTwoIdx;\n      }\n      if (this.heap[currentIndex] > this.heap[indexToSwap]) {\n        // If the current element is greater than the one to swap with, perform the swap\n        this.swap(currentIndex, indexToSwap);\n        currentIndex = indexToSwap;\n        childOneIdx = currentIndex * 2 + 1; // Update the index of the first child\n      } else {\n        return;\n      }\n    }\n  }\n\n  siftUp() {\n    let currentIdx = this.size - 1; // Start from the last element\n    let parentIdx = Math.floor((currentIdx - 1) / 2); // Calculate the index of the parent\n    while (currentIdx > 0) {\n      const current = this.heap[currentIdx];\n      const parent = this.heap[parentIdx];\n      if (current < parent) {\n        // If the current element is smaller than the parent, perform the swap\n        this.swap(currentIdx, parentIdx);\n        currentIdx = parentIdx;\n        parentIdx = Math.floor((currentIdx - 1) / 2); // Update the index of the parent\n      } else {\n        return;\n      }\n    }\n  }\n\n  peek() {\n    if (this.size === 0) {\n      return -1;\n    }\n    return this.heap[0]; // Return the minimum element at the top of the heap\n  }\n\n  remove() {\n    this.swap(0, this.size - 1); // Swap the root with the last element\n    const peeked = this.heap[this.size - 1]; // Remove the last element (minimum) and store it\n    this.size--;\n    this.heap.length = this.size; // Resize the heap array\n    this.siftDown(0); // Sift down the new root element\n    return peeked;\n  }\n\n  insert(value) {\n    this.heap.push(value); // Append the new element to the end of the heap\n    this.size++;\n    this.siftUp(); // Sift up the new element to its correct position\n  }\n\n  swap(i, j) {\n    [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]; // Swap elements at indices i and j\n  }\n\n  length() {\n    return this.size; // Return the number of elements in the heap\n  }\n}\n\n// Example usage:\nconst array = [9, 4, 7, 1, -2, 6, 5];\nconst minHeap = new MinHeap(array);\n\nconsole.log(\"Peek:\", minHeap.peek());\nconsole.log(\"Remove:\", minHeap.remove());\nconsole.log(\"Length:\", minHeap.length());\n\nminHeap.insert(2);\nminHeap.insert(-5);\n\nconsole.log(\"Peek:\", minHeap.peek());\nconsole.log(\"Length:\", minHeap.length());\n"
  },
  {
    "path": "Heaps/heap.py",
    "content": "'''\n\tImplement a Min-Heap class that supports\n\n\t\tBuilding a Min Heap from an input array of integers.\n\t\tInserting integers in the heap.\n\t\tRemoving the heap's minimum / root value.\n\t\tPeeking at the heap's minimum / root value.\n\t\tSifting integers up and down the heap, which is to be used when inserting and removing values.\n\n\tNote that the heap should be represented in the form of an array.\n\n\tExplanation:\n\n\tThe code snippet implements a MinHeap data structure in Go.\n\n\t- `NewMinHeap`: This function creates a new MinHeap from an input array and returns a pointer to the MinHeap object.\n\t   It calls the `BuildHeap` method to construct the heap structure.\n\t- `BuildHeap`: This method constructs the heap by iteratively calling `siftDown` on each parent node starting from the\n\t   last non-leaf node.\n\t- `siftDown`: This method corrects the heap property by moving an element down the heap until it reaches its correct position. It compares the element with its children and swaps it with the smaller child if necessary.\n\t- `siftUp`: This method corrects the heap property by moving an element up the heap until it reaches its correct position.\n\t   It compares the element with its parent and swaps it if necessary.\n\t- `Peek`: This method returns the minimum element in the heap (the root of the heap) without removing it.\n\t- `Remove`: This method removes and returns the minimum element in the heap. It swaps the root with the last element,\n\t   removes the last element from the heap, and then calls `siftDown` to maintain the heap property.\n\t- `Insert`: This method inserts a new element into the heap. It appends the element to the end of the heap and then\n\t   calls `siftUp` to maintain the heap property.\n\t- `swap`: This method swaps two elements in the heap given their indices.\n\t- `length`: This method returns the number of elements in the heap.\n\n\tOverall, this code provides a basic implementation of a MinHeap data structure, allowing for efficient insertion, removal,\n\tand retrieval of the minimum element.\n\n\tBuildHeap: O(n) time | O(1) space - where n is the length of the input array\n\tSiftDown: O(log(n)) time | O(1) space - where n is the length of the heap\n\tSiftUp: O(log(n)) time | O(1) space - where n is the length of the heap\n\tPeek: O(1) time | O(1) space\n\tRemove: O(log(n)) time | O(1) space - where n is the length of the heap\n\tInsert: O(log(n)) time | O(1) space - where n is the length of the heap\n\n'''\nclass MinHeap:\n    def __init__(self):\n        self.heap = []  # The heap represented as a list\n\n    def build_heap(self, array):\n        # Build the heap by calling sift_down on each parent node\n        first = (len(array) - 2) // 2  # Start from the last parent node\n        for current_idx in range(first, -1, -1):\n            self.sift_down(current_idx, len(array) - 1)\n\n    def sift_down(self, current_idx, end_idx):\n        child_one_idx = current_idx * 2 + 1  # Calculate the index of the first child\n        while child_one_idx <= end_idx:\n            child_two_idx = -1  # Initialize the index of the second child\n            if current_idx * 2 + 2 <= end_idx:\n                child_two_idx = current_idx * 2 + 2  # Calculate the index of the second child if it exists\n            index_to_swap = child_one_idx  # Assume the first child is the one to swap with\n            if child_two_idx > -1 and self.heap[child_one_idx] > self.heap[child_two_idx]:\n                # If the second child exists and is smaller, update the index to swap with\n                index_to_swap = child_two_idx\n            if self.heap[current_idx] > self.heap[index_to_swap]:\n                # If the current element is greater than the one to swap with, perform the swap\n                self.swap(current_idx, index_to_swap)\n                current_idx = index_to_swap\n                child_one_idx = current_idx * 2 + 1  # Update the index of the first child\n            else:\n                return\n\n    def sift_up(self):\n        current_idx = len(self.heap) - 1  # Start from the last element\n        parent_idx = (current_idx - 1) // 2  # Calculate the index of the parent\n        while current_idx > 0:\n            current, parent = self.heap[current_idx], self.heap[parent_idx]\n            if current < parent:\n                # If the current element is smaller than the parent, perform the swap\n                self.swap(current_idx, parent_idx)\n                current_idx = parent_idx\n                parent_idx = (current_idx - 1) // 2  # Update the index of the parent\n            else:\n                return\n\n    def peek(self):\n        if not self.heap:\n            return -1\n        return self.heap[0]  # Return the minimum element at the top of the heap\n\n    def remove(self):\n        l = len(self.heap)\n        self.swap(0, l - 1)  # Swap the root with the last element\n        peeked = self.heap.pop()  # Remove the last element (minimum) and store it\n        self.sift_down(0, l - 2)  # Sift down the new root element\n        return peeked\n\n    def insert(self, value):\n        self.heap.append(value)  # Append the new element to the end of the heap\n        self.sift_up()  # Sift up the new element to its correct position\n\n    def swap(self, i, j):\n        self.heap[i], self.heap[j] = self.heap[j], self.heap[i]  # Swap elements at indices i and j\n\n    def length(self):\n        return len(self.heap)  # Return the number of elements in the heap\n\n\ndef new_min_heap(array):\n    heap = MinHeap()  # Create a new MinHeap object\n    heap.build_heap(array)  # Build the heap using the given array\n    return heap\n"
  },
  {
    "path": "Heaps/k_closest.py",
    "content": "class Solution:\n    def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:\n        min_heap = []\n        \n        # For each point, find distance from origin\n        for x,y in points:\n            dist = sqrt(x**2 + y**2)\n            min_heap.append([dist,x,y])\n            \n        # Pop 'k' smallest distances \n        heapify(min_heap)\n        res = []\n        for _ in range(k):\n            _,x,y = heappop(min_heap)\n            res.append([x,y])\n            \n        return res"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) [2022] [Abhisek Kumar Gupta]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Linked List/Add_two_numbers.py",
    "content": "'''Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem :Linked List: Add Two Numbers in Python\nIssue Number : #621\nProblem statement : \n\nExplanation of the below python code :\n\nThis code implements a solution for the \"Add Two Numbers\" problem on LeetCode, where the inputs are two non-empty linked lists representing two non-negative integers. The goal is to return the sum of the two integers as a linked list.\n\nThe function takes in two linked lists, l1 and l2, and creates a new linked list represented by the variable 'dummy' which will store the sum. The current node of the new linked list is represented by the variable 'curr'. The variable 'carry' stores the carry-over value from the previous sum.\n\nThe function then loops through both input linked lists, l1 and l2, as well as any carry-over value from the previous sum. It adds the values of the corresponding nodes in l1 and l2 (if they exist) and any carry-over value from the previous sum. It then calculates the carry-over value and the new value for the current node by dividing the sum by 10 and taking the remainder. The carry-over value is then updated for the next iteration of the loop.\n\nThe new node with the calculated value is added to the end of the new linked list using the 'curr' variable. 'curr' is then updated to point to the new node. Once the loop is completed, the new linked list is returned, but without the initial 'dummy' node, as the first node in the list is actually the second node in the sequence.\n\nOverall, the function creates a new linked list representing the sum of the input linked lists, using a carry-over value to handle any values greater than 10. It runs in linear time in the length of the input linked lists, making it an efficient solution.\n\n\n'''\n\n-------------------------------------------------------------------------//python code begins here----------------------------------------------------------------------------------------------------------------------------------------------------------\n\n# Definition for singly-linked list.\n# class ListNode:\n#     def __init__(self, val=0, next=None):\n#         self.val = val\n#         self.next = next\nclass Solution:\n    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:\n        dummy = ListNode()\n        curr = dummy\n        carry = 0\n        while l1 or l2 or carry:\n            val = carry\n            if l1:\n                val += l1.val\n                l1 = l1.next\n            if l2:\n                val += l2.val\n                l2 = l2.next\n            carry, val = divmod(val, 10)\n            curr.next = ListNode(val)\n            curr = curr.next\n        return dummy.next\n"
  },
  {
    "path": "Linked List/Intersection_LL.cpp",
    "content": "/**\n * Definition for singly-linked list.\n * struct ListNode {\n *     int val;\n *     ListNode *next;\n *     ListNode(int x) : val(x), next(NULL) {}\n * };\n */\nclass Solution {\npublic:\n    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {\n        ListNode *pA = headA;\n        ListNode *pB = headB;\n\n        // Traverse both linked lists until they meet or reach the end (NULL)\n        while (pA != pB) {\n            // Move pointers to the next node\n            pA = (pA != nullptr) ? pA->next : headB;\n            pB = (pB != nullptr) ? pB->next : headA;\n        }\n\n        // Return the intersection node (or NULL if no intersection)\n        return pA;\n    }\n};\n\n/*\nExplanation:\nThe provided code implements the solution to find the intersection point of two singly-linked lists headA and headB. The getIntersectionNode function takes two ListNode pointers as parameters and returns the intersection node if one exists, or NULL if there is no intersection.\n\nThe approach used here is based on the concept of \"runner pointers.\" The pointers pA and pB start from the heads of the two linked lists and traverse through the lists. When a pointer reaches the end of its list, it is redirected to the head of the other list. This ensures that the pointers will meet at the intersection point if it exists, or they will both reach the end of the lists (NULL) simultaneously if there is no intersection.\n  */\n"
  },
  {
    "path": "Linked List/LFU_Cache.cpp",
    "content": "// Question--> LFU Cache\n// Design and implement a data structure for a Least Frequently Used (LFU) cache.\n\n// Implement the LFUCache class:\n\n// LFUCache(int capacity) Initializes the object with the capacity of the data structure.\n// int get(int key) Gets the value of the key if the key exists in the cache. Otherwise, returns -1.\n// void put(int key, int value) Update the value of the key if present, or inserts the key if not already present. When the cache reaches its capacity, it should invalidate and remove the least frequently used key before inserting a new item. For this problem, when there is a tie (i.e., two or more keys with the same frequency), the least recently used key would be invalidated.\n// To determine the least frequently used key, a use counter is maintained for each key in the cache. The key with the smallest use counter is the least frequently used key.\n\n// When a key is first inserted into the cache, its use counter is set to 1 (due to the put operation). The use counter for a key in the cache is incremented either a get or put operation is called on it.\n\n// The functions get and put must each run in O(1) average time complexity\n\n\n// solution -->\n\n//minFreq is the smallest frequency so far\n//The main idea is to put all keys with the same frequency to a linked list so the most recent one can be evicted;\n//mIter stored the key's position in the linked list;\n\n\n#include <bits/stdc++.h>\nusing namespace std;\n\n\nclass LFUCache {\n    int cap;\n    int size;\n    int minFreq;\n    unordered_map<int, pair<int, int>> m; //key to {value,freq};\n    unordered_map<int, list<int>::iterator> mIter; //key to list iterator;\n    unordered_map<int, list<int>>  fm;  //freq to key list;\npublic:\n    LFUCache(int capacity) {\n        // initialize your data structure here\n        cap=capacity;\n        size=0;\n    }\n    \n    int get(int key) {\n        if(m.count(key)==0) return -1; // if key not found return -1;\n        \n        fm[m[key].second].erase(mIter[key]); //erase from old freq list\n        m[key].second++; // increase freq;\n        fm[m[key].second].push_back(key); // add to new freq list;\n        mIter[key]=--fm[m[key].second].end();// point to new freq list;\n        \n        // if old min freq list empty, increase min freq;\n        if(fm[minFreq].size()==0 ) \n              minFreq++;\n        \n        return m[key].first; // return value\n    }\n    \n   void put(int key, int value) {\n        if(cap<=0) return; // corner case\n        \n        int storedValue=get(key); // get value if already present\n\n        // if already present update value, increase freq;\n        if(storedValue!=-1)\n        {\n            m[key].first=value;\n            return;\n        }\n        \n        // if capacity full, erase least freq used element from this list\n        if(size>=cap )\n        {\n            m.erase( fm[minFreq].front() );\n            mIter.erase( fm[minFreq].front() );\n            fm[minFreq].pop_front();\n            size--;\n        }\n        \n        m[key]={value, 1}; // insert new key value pair with freq 1;\n        fm[1].push_back(key); // add to freq list 1;\n        mIter[key]=--fm[1].end(); // point to new freq list;\n        minFreq=1; // since new element added min freq will be 1;\n        size++; // increase size\n    }\n};\n\n\n// https://leetcode.com/problems/lfu-cache/"
  },
  {
    "path": "Linked List/Linked_List_Component.java",
    "content": "\n\n\n/**PROBLEM\n * You are given the head of a linked list containing unique integer values and an integer array nums\n *that is a subset of the linked list values.\n\n*Return the number of connected components in nums where two values are connected if\n *they appear consecutively in the linked list.\n*/\n\n// SAMPLE I/O\n// Input: head = [0,1,2,3], nums = [0,1,3]\n// Output: 2\n// Explanation: 0 and 1 are connected, so [0, 1] and [3] are the two connected components.\n\n// Approach\n/**\n * Creating a HashMap to store all the values of nums[]\n * Iterating list and if current node(head) we check if the hashmap contains the value]\n * if yes the we increment the ans by one and setting the flag to false \n * \n * \n * \n * Time Complexity: O(N)\n * Space Complexity : O(N)\n */\n\n\n/**\n * Definition for singly-linked list.\n * public class ListNode {\n *     int val;\n *     ListNode next;\n *     ListNode() {}\n *     ListNode(int val) { this.val = val; }\n *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }\n * }\n */\nclass Solution {\n    public int numComponents(ListNode head, int[] nums) {\n        // Create a HashMap to store the values from nums as keys and their indices as values\n        HashMap<Integer, Integer> hm = new HashMap<>();\n        for (int i = 0; i < nums.length; i++) {\n            hm.put(nums[i], i);\n        }\n        \n        boolean flag = true; // Flag to track if a connected component is found\n        int ans = 0; // Variable to store the number of connected components\n        \n        // Traverse the linked list\n        while (head != null) {\n            // Check if the current node's value is present in the HashMap\n            while (head != null && hm.containsKey(head.val)) {\n                head = head.next; // Move to the next node\n                \n                // If this is the start of a new connected component, increment the answer\n                if (flag) {\n                    ans += 1;\n                    flag = false;\n                }\n            }\n            flag = true; // Reset the flag\n            \n            if (head != null) {\n                head = head.next; // Move to the next node\n            }\n        }\n        \n        return ans;\n    }\n}\n"
  },
  {
    "path": "Linked List/MiddleOfLinkedList.java",
    "content": "/* QUESTION and SAMPLE I/O\n\n    Given the head of a singly linked list, return the middle node of the linked list.\n    If there are two middle nodes, return the second middle node.\n\n    Sample Input = [1,2,3,4,5]\n    Sample Output = 3\n    \n   APPROACH and EXPLANATION\n   \n    This program is done using two pointers: slow pointer and fast pointer. \n        * Both pointer starts from the head node.\n        * Slow pointer moves one step at a time.\n        * Fast pointer moves two steps at a time.\n        * As the fast pointer reaches the end, slow pointer will be at the middle of the linked list.\n        * Accessing the slow pointer's value for 'val' will give you the value for the middle element of linked list.\n\n\n    Time Complexity: O(n)\n    Space Complexity: O(1)\n\n */\n\n \n/**\n * Definition for singly-linked list.\n * public class ListNode {\n *     int val;\n *     ListNode next;\n *     ListNode() {}\n *     ListNode(int val) { this.val = val; }\n *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }\n * }\n */\n\nclass Solution {\n    public ListNode middleNode(ListNode head) {\n        ListNode slow_pointer = head;       //initialize slow pointer\n        ListNode fast_pointer = head;       //initialize fast pointer\n        while(fast_pointer!=null && fast_pointer.next!=null){\n            slow_pointer = slow_pointer.next;       //moves to next node\n            fast_pointer = fast_pointer.next.next;      //moves two nodes forward\n        }\n        return slow_pointer;\n    }\n}"
  },
  {
    "path": "Linked List/MiddleofLL.py",
    "content": "class ListNode:\n    def __init__(self, value=0, next=None):\n        self.value = value\n        self.next = next\n\ndef find_middle(head):\n    # Initialize slow and fast pointers to the head of the linked list\n    slow_ptr = head\n    fast_ptr = head\n\n    # Traverse the linked list with slow and fast pointers\n    while fast_ptr is not None and fast_ptr.next is not None:\n        # Move slow pointer one step at a time\n        slow_ptr = slow_ptr.next\n        # Move fast pointer two steps at a time\n        fast_ptr = fast_ptr.next.next\n\n    # When the fast pointer reaches the end, the slow pointer will be at the middle\n    return slow_ptr\n\n# Create a sample linked list: 1 -> 2 -> 3 -> 4 -> 5\nhead = ListNode(1)\nhead.next = ListNode(2)\nhead.next.next = ListNode(3)\nhead.next.next.next = ListNode(4)\nhead.next.next.next.next = ListNode(5)\n\n# Find the middle node of the linked list\nmiddle_node = find_middle(head)\n\n# Print the value of the middle node\nprint(\"Middle Node:\", middle_node.value)  # Output: Middle Node: 3\n"
  },
  {
    "path": "Linked List/RemoveKthNodeFromEnd.java",
    "content": "//Problem Number : 19 - Leetcode\n\n/**\n * Definition for singly-linked list.\n * public class ListNode {\n * int val;\n * ListNode next;\n * ListNode() {}\n * ListNode(int val) { this.val = val; }\n * ListNode(int val, ListNode next) { this.val = val; this.next = next; }\n * }\n */\n\n/*\n * Problem Description :\n * Given the head of a linked list, remove the nth node\n * from the end of the list and return its head.\n * \n * linkedlist = 1 -> 2 -> 3 -> 4 -> 5-> null\n * n = 2\n */\n\n/*\n * Approach we follow to solve this Problem.\n * Given : head of linkedlist and n = number of node to remove from end\n * Solution :\n * => Since we have to remove node from end , we need to calculate length of\n * linkedlist.\n * To do so lets create a function calcLength() , it take head node as parameter\n * and return length of linked list .\n * => Store the length of linkedlist in variable namely (len) by calling\n * function calcLength().\n * => To make it simple , lets calculate position of node from start of\n * linkedlist by subtracting length of node with nth node to remove.\n * and store the result in another variable called target. [ target = len - n]\n * => Now, we check for target == 0 and if its true than we have to remove our\n * head and point the head to next element .\n * for ex : head.next = head\n * After just return our head because we have no need to check other part.\n * => create a pointer = 1 and store head of LikedList to temp variable .\n * => After that , we have to iterate over linkedlist till our temp is not equal\n * to null to find our target element.\n * (Note : target element is always prev of node of node to remove for ex : 1-> 2-> 3->4-> 5 \n * In this case 3 is our target because we have to remove 4.)\n * => for each iteration , we check if our target == pointer , In case its true\n * the we have to handle two case :\n * Case 1 : if our target node is last node of linked list ,then point temp to\n * null\n * explanation : 1-> 2-> 3-> 4-> 5 -> null\n * if our target is 5 the our new linkedlist will we like this : 1-> 2-> 3-> 4->\n * null\n * Case 2 : Target is in middle of linkedlist then , update temp pointer to\n * temp.next.next\n * explanation : 1-> 2-> 3-> 4-> 5 -> null\n * let say we have to remove 3 : then temp = 2\n * temp.next = 3 : node to remove\n * temp.next.next = 4\n * output : 1-> 2-> 4-> 5 -> null\n * => increment pointer and update temp to next node.\n * => In last just return node\n */\n\nclass Solution {\n\n    public int calcLength(ListNode head) {\n        int cnt = 0;\n        while (head != null) {\n            cnt++;\n            head = head.next;\n        }\n        return cnt;\n    }\n\n    public ListNode removeNthFromEnd(ListNode head, int n) {\n\n        int len = calcLength(head);\n        int target = len - n;\n        if (target == 0) {\n            head = head.next;\n            return head;\n        }\n        int pointer = 1;\n\n        ListNode temp = head;\n        while (temp != null) {\n            if (pointer == target) {\n                ListNode key = temp.next;\n                if (key == null) {\n                    temp = null;\n                } else {\n                    temp.next = key.next;\n                }\n\n            }\n            pointer++;\n            temp = temp.next;\n        }\n\n        return head;\n\n    }\n}"
  },
  {
    "path": "Linked List/Remove_nth_node_from_end.java",
    "content": "/**\n  Problem :-Remove the nth node from end of the list\n  https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/\n\n  Approach:- \n  1. First find the length of the list and store it in a variable named 'len'.\n  2. Then traverse the list  (len-n)\n  3. Now you are one node behind the node that we have to remove.\n\n  4. Now set the current node's next to the next.next i.e temp.next=temp.next.next.\n\n    Time Complexity : O(N) \n    we traverse the list for calculating its length and removing the node.Hence O(N).\n\n    Space Complexity : O(1)\n    No extra space is required\n\n    Note :- The code is well documented. So take a look.\n\n\n\n */\n\n\n/**\n * Definition for singly-linked list.\n * public class ListNode {\n *     int val;\n *     ListNode next;\n *     ListNode() {}\n *     ListNode(int val) { this.val = val; }\n *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }\n * }\n */\n\nclass Solution {\n    public ListNode removeNthFromEnd(ListNode head, int n) {\n        if (head == null) return head;          // If the head is null, return the head itself\n        if (head.next == null) {                // If there is only one node in the list\n            if (n == 1) return null;            // If n is 1, remove the node and return null\n            return head;                        // Otherwise, return the head itself\n        }\n        \n        ListNode temp = head;                    // Create a temporary node pointing to the head\n\n        int len = size(head);                   // Get the length of the list\n        if (len - n == 0) {                  // If the node to be removed is the head itself\n            head = head.next;                    // Move the head to the next node\n            return head;\n        }\n        \n        len -= n;                   // Calculate the index of the previous node of the node to be removed\n        for (int i = 1; i < len; i++) {      // Traverse to the previous node so we can remove the next node\n            temp = temp.next;\n        }\n        \n        if (temp != null && temp.next != null) {     // If the previous node and the node to be removed exist\n            temp.next = temp.next.next;    // Point the previous node to the node after the one to be removed\n        }\n        \n        return head;  // Return the updated head\n    }\n    \n    int size(ListNode temp) {\n        ListNode s = temp;\n        int n = 0;\n        while (s != null) {  // Traverse the list to count the number of nodes\n            s = s.next;\n            n += 1;\n        }\n        return n;  // Return the size of the list\n    }\n}\n"
  },
  {
    "path": "Linked List/add_two_numbers.cpp",
    "content": "/**\n * Definition for singly-linked list.\n * struct ListNode {\n *     int val;\n *     ListNode *next;\n *     ListNode() : val(0), next(nullptr) {}\n *     ListNode(int x) : val(x), next(nullptr) {}\n *     ListNode(int x, ListNode *next) : val(x), next(next) {}\n * };       \n */\nclass Solution\n{\npublic:\n    ListNode *addTwoNumbers(ListNode *l1, ListNode *l2)\n    {\n        ListNode *ansHead = new ListNode((l1->val + l2->val) % 10);\n        ListNode *ans = ansHead;\n        int carry = (l1->val + l2->val) / 10;\n        l1 = l1->next;\n        l2 = l2->next;\n        while (l1 != NULL && l2 != NULL)\n        {\n            ListNode *temp = new ListNode((l1->val + l2->val + carry) % 10);\n            carry = (l1->val + l2->val + carry) / 10;\n            l1 = l1->next;\n            l2 = l2->next;\n            ans->next = temp;\n            ans = temp;\n        }\n        while (l1 != NULL)\n        {\n            ListNode *temp = new ListNode((l1->val + carry) % 10);\n            carry = (l1->val + carry) / 10;\n            l1 = l1->next;\n            ans->next = temp;\n            ans = temp;\n        }\n        while (l2 != NULL)\n        {\n            ListNode *temp = new ListNode((l2->val + carry) % 10);\n            carry = (l2->val + carry) / 10;\n            l2 = l2->next;\n            ans->next = temp;\n            ans = temp;\n        }\n        if (carry > 0)\n        {\n            ListNode *temp = new ListNode(carry);\n            ans->next = temp;\n            ans = temp;\n        }\n        return ansHead;\n    }\n    ListNode *solve(ListNode *&head1, ListNode *&head2)\n    {\n        if (head1 == NULL)\n        {\n            return head2;\n        }\n        if (head2 == NULL)\n        {\n            return head1;\n        }\n\n        // linked list which contains the final answer\n        ListNode *ansHead = NULL;\n        ListNode *ansTail = NULL;\n\n        int carry = 0;\n        while (head1 != NULL && head2 != NULL)\n        {\n            int sum = head1->val + head2->val + carry;\n            int digit = sum % 10;\n            carry = sum / 10;\n\n            ListNode *newNode = new ListNode(digit);\n            if (ansHead == NULL)\n            {\n                ansHead = newNode;\n                ansTail = newNode;\n            }\n            else\n            {\n                ansTail->next = newNode;\n                ansTail = newNode;\n            }\n            head1 = head1->next;\n            head2 = head2->next;\n        }\n\n        // head1 linked list pending to be solved\n        while (head1 != NULL)\n        {\n            int sum = carry + head1->val;\n            int digit = sum % 10;\n            carry = sum / 10;\n\n            ListNode *newNode = new ListNode(digit);\n            if (ansHead == NULL)\n            {\n                ansHead = newNode;\n                ansTail = newNode;\n            }\n            else\n            {\n                ansTail->next = newNode;\n                ansTail = newNode;\n            }\n            head1 = head1->next;\n        }\n\n        // head2 linked list pending to be solved\n        while (head2 != NULL)\n        {\n            int sum = carry + head2->val;\n            int digit = sum % 10;\n            carry = sum / 10;\n\n            ListNode *newNode = new ListNode(digit);\n            if (ansHead == NULL)\n            {\n                ansHead = newNode;\n                ansTail = newNode;\n            }\n            else\n            {\n                ansTail->next = newNode;\n                ansTail = newNode;\n            }\n            head2 = head2->next;\n        }\n\n        while (carry != 0)\n        {\n            int sum = carry;\n            int digit = sum % 10;\n            carry = sum / 10;\n\n            ListNode *newNode = new ListNode(digit);\n            if (ansHead == NULL)\n            {\n                ansHead = newNode;\n                ansTail = newNode;\n            }\n            else\n            {\n                ansTail->next = newNode;\n                ansTail = newNode;\n            }\n        }\n        return ansHead;\n    }\n};"
  },
  {
    "path": "Linked List/add_two_numbers.js",
    "content": "// Linked List: Add Two Numbers in Javascript #622\n\n/*\n  \n  You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.\n\n\tYou may assume the two numbers do not contain any leading zero, except the number 0 itself.\n\n  Example 1:\n\t- Input: l1 = [2,4,3], l2 = [5,6,4]\n\t- Output: [7,0,8]\n  - Explanation: 342 + 465 = 807.\n\n  Example 2:\n\t- Input: l1 = [0], l2 = [0]\n\t- Output: [0]\n  \n  Example 3:\n\t- Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]\n\t- Output: [8,9,9,9,0,0,0,1]\n  \n\tConstraints:\n\t- The number of nodes in each linked list is in the range [1, 100].\n\t- 0 <= Node.val <= 9\n\t- It is guaranteed that the list represents a number that does not have leading zeros.\n\n*/\n\n/**\n * Definition for singly-linked list.\n * function ListNode(val, next) {\n *     this.val = (val===undefined ? 0 : val)\n *     this.next = (next===undefined ? null : next)\n * }\n */\n/**\n * @param {ListNode} l1\n * @param {ListNode} l2\n * @return {ListNode}\n */\n\nvar addTwoNumbers = function (l1, l2) {\n  const head = new ListNode(); // creating a new LL.\n  let temp = head; // assign head into temp to traverse the LL.\n  let carry = 0; // to store carry that we will get during the add operation.\n\n  while (l1 || l2) {\n    // loop will get executed  until one of the LL becomes null.\n    let sum = carry;\n\n    //perform summation with both LL one by one and assign it to the sum variable.\n    if (l1) {\n      sum += l1.val;\n      l1 = l1.next;\n    }\n\n    if (l2) {\n      sum += l2.val;\n      l2 = l2.next;\n    }\n\n    // to store the carry part we will do sum/10 and store it's floor value to carry variable. For Example:\n    /* \n      if sum = 12\n      so, sum/10 = 1.2\n      and Math.floor(1.2) = 1 and we get our carry part.\n      > carry = 1.\n    */\n    carry = Math.floor(sum / 10);\n    temp.next = new ListNode(sum % 10); // at this point we are removing carry part from sum and adding remaining part into the ll.\n    temp = temp.next;\n  }\n\n  if (carry > 0) {\n    // after the completion of summation, if there is any cary left it will be added to list.\n    temp.next = new ListNode(carry);\n  }\n\n  return head.next; // return the head of the node so ll can be traverse.\n};\n"
  },
  {
    "path": "Linked List/delete_kth_node.js",
    "content": "/*Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem : Remove Kth node from end in Javascript\nIssue Number : #687\nProblem statement : \n\nExplanation of the below Javascript code :\n\nDefine a Node class to represent each node in the linked list.\nCreate a function called removeKthFromEnd that accepts the head of the linked list and the value of k as parameters.\nNow you can create a linked list and call the removeKthFromEnd function to remove the kth node from the end.\n\n\n*/\n\nclass Node {\n  constructor(value) {\n    this.value = value;\n    this.next = null;\n  }\n}\nfunction removeKthFromEnd(head, k) {\n  // Step 1: Create two pointers, fast and slow, and set them both to the head of the linked list.\n  let fast = head;\n  let slow = head;\n\n  // Step 2: Move the fast pointer k nodes ahead.\n  for (let i = 0; i < k; i++) {\n    if (fast === null) {\n      // The linked list does not have k nodes.\n      return head;\n    }\n    fast = fast.next;\n  }\n\n  // Step 3: If the fast pointer reaches the end, the kth node from the end is the head itself.\n  if (fast === null) {\n    head = head.next;\n    return head;\n  }\n\n  // Step 4: Move the fast and slow pointers together until the fast pointer reaches the end.\n  while (fast.next !== null) {\n    fast = fast.next;\n    slow = slow.next;\n  }\n\n  // Step 5: Remove the kth node by updating the next pointer of the previous node.\n  slow.next = slow.next.next;\n\n  // Step 6: Return the modified linked list.\n  return head;\n}\n// Example usage:\nconst head = new Node(1);\nhead.next = new Node(2);\nhead.next.next = new Node(3);\nhead.next.next.next = new Node(4);\nhead.next.next.next.next = new Node(5);\n\nconst k = 2;\nconst modifiedHead = removeKthFromEnd(head, k);\n\n// Display the modified linked list.\nlet current = modifiedHead;\nwhile (current !== null) {\n  console.log(current.value);\n  current = current.next;\n}\n\n/*\nOUTPUT:\n1\n2\n3\n5\n*/\n"
  },
  {
    "path": "Linked List/double_linked_list.go",
    "content": "//  Implementation of a doubly linked list in Go\n/*\n\tIn this implementation, we define a Node struct that contains the data as well as pointers to the previous and next nodes.\n\tWe also define a LinkedList struct that contains a pointer to the head and tail nodes.\n\n\tThe AddNode method adds a new node to the end of the list. If the list is empty, the new node is set as both the head and tail.\n\tOtherwise, the new node is added after the current tail, and the current tail is set as the previous node of the new node.\n\tFinally, the new node is set as the new tail.\n\n\tThe PrintList method traverses the list from the head node and prints the data of each node.\n\n\tIn the main function, we create a new doubly linked list, add some nodes to it, and print the list.\n*/\npackage main\n\nimport \"fmt\"\n\n// Node represents a node in the doubly linked list\ntype Node struct {\n    data int\n    prev *Node\n    next *Node\n}\n\n// LinkedList represents the doubly linked list\ntype LinkedList struct {\n    head *Node\n    tail *Node\n}\n\n// AddNode adds a new node to the end of the doubly linked list\nfunc (list *LinkedList) AddNode(data int) {\n    // Create a new node\n    newNode := &Node{data: data}\n\n    // If the list is empty, set the new node as head and tail\n    if list.head == nil {\n        list.head = newNode\n        list.tail = newNode\n        return\n    }\n\n    // Set the new node as the next node of the current tail\n    list.tail.next = newNode\n\n    // Set the current tail as the previous node of the new node\n    newNode.prev = list.tail\n\n    // Set the new node as the new tail\n    list.tail = newNode\n}\n\n// PrintList prints the doubly linked list\nfunc (list *LinkedList) PrintList() {\n    // Start from the head node\n    currNode := list.head\n\n    // Traverse the list and print the data of each node\n    for currNode != nil {\n        fmt.Printf(\"%d \", currNode.data)\n        currNode = currNode.next\n    }\n}\n\nfunc main() {\n    // Create a new doubly linked list\n    list := &LinkedList{}\n\n    // Add nodes to the list\n    list.AddNode(1)\n    list.AddNode(2)\n    list.AddNode(3)\n\n    // Print the list\n    list.PrintList()\n}\n"
  },
  {
    "path": "Linked List/doubly_linked_list.cpp",
    "content": "/* Name : Aneesh\nGithub username : 007aneesh\nRepository name : data-structures-and-algorithms\n\nProblem : Doubly linked list in c++\nIssue Number : #975\nProblem statement : Given an integer n representing the length of linked list and you have to print linked list from start and end.\n\nSample testcases: \n\nTestcase 1 --> \n\nInput: \n5\n1 2 3 4 5\n\nOutput:\nPrinting forwardly................................\n1\n2\n3\n4\n5\nPrinting backwardly................................\n5\n4\n3\n2\n1\n\n\nTestcase 2 -->\nInput: \n3\n10 20 30\n\nOutput:\nPrinting forwardly................................\n10\n20\n30\nPrinting backwardly................................\n30\n20\n10\n\n\n\nTime Complexity = O(n)\nSpace Complexity = O(n)\n\n\nExplanation:\nIn the main function, the program first takes input n,\nthe number of nodes to be inserted in the linked list.\nThen, in a loop, it takes n values as input and creates new nodes with those values.\nThe nodes are then linked together to form a doubly linked list. \nFinally, it calls the PrintForward and PrintBackward functions\nto print the elements of the list in forward and backward order, respectively.\n*/\n\n// ----------------------------------------------------------------------------- code begins now!\n\n#include <iostream>\nusing namespace std;\n\n// Define a Node class\nclass Node {\npublic:\n    int data;\n    Node* next;\n    Node* prev;\n    Node(int d) {\n        this->data = d;\n        next = NULL;\n        prev = NULL;\n    }\n};\n\n// Function to print the linked list forward\nvoid PrintForward(Node* head) {\n    Node* traverse = head;\n    while (traverse != NULL) {\n        cout << traverse->data << endl;\n        traverse = traverse->next;\n    }\n}\n\n// Function to print the linked list backward\nvoid PrintBackward(Node* tail) {\n    Node* traverse = tail;\n    while (tail != NULL) {\n        cout << traverse->data << endl;\n        traverse = traverse->prev;\n    }\n}\n\nint main() {\n    int n, value;\n    cin>>n; // Read the number of nodes to be created\n    Node *head = nullptr; // Initialize head pointer\n    Node *tail = nullptr; // Initialize tail pointer\n\n    // Read 'n' values and create a doubly linked list\n    for (int i = 0; i < n; i++) {\n        cin >> value; // Read the value for the current node\n        Node* newNode = new Node(value);  // Create a new node with the value\n        \n        // If the list is empty, set the head and tail to the new node\n        if (head == NULL) {\n            head = newNode;\n            tail = newNode;\n        } else {\n            // Add the new node to the end of the list\n            newNode->next = nullptr;\n            newNode->prev = tail;\n            tail->next = newNode;\n            tail = newNode;\n        }\n    }\n\n    // Print the linked list forward\n    cout << \"Printing forwardly................................\" << endl;\n    PrintForward(head);\n\n    // Print the linked list backward\n    cout << \"Printing backwardly................................\" << endl;\n    PrintBackward(tail);\n\n    return 0;\n}\n"
  },
  {
    "path": "Linked List/doubly_linked_list.java",
    "content": "/*A Doubly Linked List is a data structure in which each node contains a reference to the previous node and the next node in the sequence. It extends the functionality of a Singly Linked List by allowing traversal in both forward and backward directions.The first node of the list is referred to as the head, and the last node is referred to as the tail. In this implementation, the Node class represents a node in the doubly linked list. Each node has a data field to store the value, and prev and next fields to maintain references to the previous and next nodes in the list.*/\n\nclass Node {\n    int data;\n    Node prev;\n    Node next;\n    \n    public Node(int data) {\n        this.data = data;\n        this.prev = null;\n        this.next = null;\n    }\n}\n\nclass DoublyLinkedList {\n    Node head;\n    \n    public DoublyLinkedList() {\n        this.head = null;\n    }\n    \n    // Insert a new node at the end of the list\n    public void insert(int data) {\n        Node newNode = new Node(data);\n        \n        if (head == null) {\n            // If the list is empty, make the new node the head\n            head = newNode;\n        } else {\n            Node current = head;\n            \n            // Traverse to the end of the list\n            while (current.next != null) {\n                current = current.next;\n            }\n            \n            // Link the new node to the last node\n            current.next = newNode;\n            newNode.prev = current;\n        }\n    }\n    \n    // Delete a node with the given data value\n    public void delete(int data) {\n        Node current = head;\n        \n        while (current != null) {\n            if (current.data == data) {\n                if (current.prev != null) {\n                    // If the node to be deleted is not the first node\n                    \n                    // Update the previous node's next reference\n                    current.prev.next = current.next;\n                } else {\n                    // If the node to be deleted is the first node\n                    \n                    // Update the head reference to the next node\n                    head = current.next;\n                }\n                \n                if (current.next != null) {\n                    // If the node to be deleted is not the last node\n                    \n                    // Update the next node's previous reference\n                    current.next.prev = current.prev;\n                }\n                \n                break;\n            }\n            \n            current = current.next;\n        }\n    }\n    \n    // Display the elements of the list\n    public void display() {\n        Node current = head;\n        \n        while (current != null) {\n            System.out.print(current.data + \" \");\n            current = current.next;\n        }\n        \n        System.out.println();\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        DoublyLinkedList list = new DoublyLinkedList();\n        \n        list.insert(10);\n        list.insert(20);\n        list.insert(30);\n        list.insert(40);\n        \n        list.display(); // Output: 10 20 30 40\n        \n        list.delete(20);\n        list.delete(40);\n        \n        list.display(); // Output: 10 30\n    }\n}\n\n/* Time complexity: O(n) for insertions and deletions, and O(1) for display.\nSpace complexity: O(1) for all operations */\n"
  },
  {
    "path": "Linked List/doubly_linked_list.js",
    "content": "class Node {\n    constructor(val) {\n        this.val = val\n        this.prev = null\n        this.next = null\n    }\n}\n\nclass DoublyLinkedList {\n    constructor() {\n        this.head = null\n        this.tail = null\n        this.length = 0\n    }\n\n    insertAtTail(val) {\n        const node = new Node(val)\n\n        if (!this.head) {\n            this.head = node\n            this.tail = node\n            this.length++\n        } else {\n            node.prev = this.tail\n            this.tail.next = node\n            this.tail = node\n            this.length++\n        }\n    }\n\n    insertAtHead(val) {\n        const node = new Node(val)\n\n        if (!this.head) {\n            this.head = node\n            this.tail = node\n            this.length++\n        } else {\n            node.next = this.head\n            this.head.prev = node\n            this.head = node\n            this.length++\n        }\n    }\n\n    deleteAtTail() {\n        if (!this.head) throw new Error(\"Empty Linked List!\")\n\n        if (this.length === 1) {\n            this.head = null\n            this.tail = null\n            this.length--\n        } else {\n            this.tail = this.tail.prev\n            this.tail.next = null\n            this.length--\n        }\n    }\n\n    deleteAtHead() {\n        if (!this.head) throw new Error(\"Empty Linked List!\")\n\n        if (this.length === 1) {\n            this.head = null\n            this.tail = null\n            this.length--\n        } else {\n            this.head = this.head.next\n            this.head.prev = null\n            this.length--\n        }\n    }\n\n    print() {\n        if (!this.head) console.log(\"Empty Linked List!\")\n\n        else {\n            let curr = this.head\n            let str = \"null <- \"\n            while (curr) {\n                str += curr.val\n                if (curr.next) {\n                    str += \" <-> \"\n                } else {\n                    str += \" -> null\"\n                }\n                curr = curr.next\n            }\n            console.log(str)\n        }\n    }\n\n    getLength() {\n        return this.length\n    }\n\n    getAtIdx(idx) {\n        if (idx >= this.length || idx < 0) throw new Error(\"Index out of bounds!\")\n\n        else {\n            let currIdx = 0\n            let curr = this.head\n\n            while (currIdx < idx) {\n                curr = curr.next\n                currIdx++\n            }\n\n            return curr.val\n        }\n    }\n\n    putAtIdx(val, idx) {\n        if (idx > this.length || idx < 0) throw new Error(\"Index out of bounds!\")\n\n        const node = new Node(val)\n\n        if (idx === 0) {\n            this.head.prev = node\n            node.next = this.head\n            this.head = node\n        } else {\n            let currIdx = 0\n            let curr = this.head\n\n            while (currIdx < idx) {\n                curr = curr.next\n                currIdx++\n            }\n\n            node.next = curr\n            node.prev = curr.prev\n            curr.prev.next = node\n        }\n\n        this.length++\n    }\n\n    deleteAtIdx(idx) {\n        if (idx >= this.length || idx < 0) throw new Error(\"Index out of bounds!\")\n\n        let currIdx = 0\n        let curr = this.head\n\n        while (currIdx < idx) {\n            curr = curr.next\n            currIdx++\n        }\n\n        curr.prev.next = curr.next\n        curr.next.prev = curr.prev\n        this.length--\n    }\n\n    search(val) {\n        let curr = this.head\n        let currIdx = 0\n\n        while (curr) {\n            if (curr.val === val) return currIdx\n\n            curr = curr.next\n            currIdx++\n        }\n\n        return \"Value not found\"\n    }\n\n    toArray() {\n        let arr = []\n\n        let curr = this.head\n\n        while (curr) {\n            arr.push(curr.val)\n            curr = curr.next\n        }\n\n        return arr\n    }\n}\n\n// SAMPLE USECASE\nconst list = new DoublyLinkedList ()\nlist.insertAtHead (10)\nlist.insertAtTail (20)\nlist.insertAtHead (30)\nlist.insertAtTail (40)\nlist.putAtIdx (100, 2)\nlist.print ()"
  },
  {
    "path": "Linked List/floyds_cycle_detection.cpp",
    "content": "/*\n\nInitialize two-pointers and start traversing the linked list.\nMove the slow pointer by one position.\nMove the fast pointer by two positions.\nIf both pointers meet at some point then a loop exists and if the fast pointer meets the end position then no loop exists.\n\n\nTime complexity: O(n), as the loop is traversed once. \nAuxiliary Space: O(1), only two pointers are used therefore constant space complexity.\n\n*/\n\n\n#include <bits/stdc++.h>\nusing namespace std;\n\nclass Node {\npublic:\n    int data;\n    Node* next;\n \n    Node(int data)\n    {\n        this->data = data;\n        next = NULL;\n    }\n};\n \n// initialize a new head for the linked list\nNode* head = NULL;\nclass Linkedlist {\npublic:\n    // insert new value at the start\n    void insert(int value)\n    {\n        Node* newNode = new Node(value);\n        if (head == NULL)\n            head = newNode;\n        else {\n            newNode->next = head;\n            head = newNode;\n        }\n    }\n \n    // detect if there is a loop\n    // in the linked list\n    bool detectLoop()\n    {\n        Node *slowPointer = head,\n             *fastPointer = head;\n \n        while (slowPointer != NULL\n               && fastPointer != NULL\n               && fastPointer->next != NULL) {\n            slowPointer = slowPointer->next;\n            fastPointer = fastPointer->next->next;\n            if (slowPointer == fastPointer)\n                return 1;\n        }\n \n        return 0;\n    }\n};\n \nint main()\n{\n    Linkedlist l1;\n    // inserting new values\n    l1.insert(10);\n    l1.insert(20);\n    l1.insert(30);\n    l1.insert(40);\n    l1.insert(50);\n \n    // adding a loop for the sake\n    // of this example\n    Node* temp = head;\n    while (temp->next != NULL)\n        temp = temp->next;\n \n    temp->next = head;\n \n    // loop added;\n \n    if (l1.detectLoop())\n        cout << \"Loop exists in the\"\n             << \" Linked List\" << endl;\n    else\n        cout << \"Loop does not exists \"\n             << \"in the Linked List\" << endl;\n \n    return 0;\n}"
  },
  {
    "path": "Linked List/floyds_cycle_detection.go",
    "content": "// Floyds Cycle Detection\n/*\n\tExplanation:\n\tThe Floyd's cycle detection algorithm is a two-pointer algorithm used to detect if a linked list has a\n\tcycle. It works by initializing two pointers, slow and fast, both pointing to the head of the linked list.\n\tThen, it moves the slow pointer by one step and the fast pointer by two steps. If there is a cycle in the linked list,\n\tthe fast pointer will eventually catch up to the slow pointer. If there is no cycle, the fast pointer will reach the\n\tend of the linked list. This algorithm has a time complexity of O(n) and a space complexity of O(1).\n\n\tIn the implementation above, we define a Node struct to represent a node in the linked list.\n\tThe hasCycle function takes the head of the linked list as input and returns a boolean indicating\n\twhether the linked list has a cycle or not. We initialize two pointers, slow and fast, both pointing\n\tto the head of the linked list. We then loop through the linked list while the fast pointer is not\n\tnull and the next of the fast pointer is not null. In each iteration, we move the slow pointer\n\tby one step and the fast pointer by two steps. If the slow and fast pointers meet, we know there\n\tis a cycle and we return true. Otherwise, we continue the loop until the end of the linked list and return false.\n\n\tThe time complexity of Floyd's cycle detection algorithm is O(n), where n is the number of nodes in the linked list.\n\tThis is because in the worst case, we would need to traverse the entire linked list twice: once to reach the point\n\t where the cycle begins, and once more to detect the cycle.\n\n\tThe space complexity of the algorithm is O(1), as we are only using a few constant extra variables to perform\n\tthe detection, regardless of the size of the linked list.\n*/\n\npackage main\n\nimport \"fmt\"\n\n// Definition for singly-linked list.\ntype Node struct {\n    value int\n    next  *Node\n}\n\n\n// DetectCycle detects if there's a cycle in a linked list using Floyd's cycle detection algorithm\nfunc hasCycle(head *Node) bool {\n    // Initialize slow and fast pointers\n    slow, fast := head, head\n\n    // Move slow and fast pointers until they meet or fast pointer reaches end of the list\n    for fast != nil && fast.next != nil {\n        slow = slow.next\n        fast = fast.next.next\n\n        // If slow and fast pointers meet, there's a cycle\n        if slow == fast {\n            return true\n        }\n    }\n\n    // If fast pointer reaches end of the list, there's no cycle\n    return false\n}\n\nfunc main() {\n    // Create a linked list with a cycle\n    head := &Node{value: 1}\n    node2 := &Node{value: 2}\n    node3 := &Node{value: 3}\n    node4 := &Node{value: 4}\n    node5 := &Node{value: 5}\n    head.next = node2\n    node2.next = node3\n    node3.next = node4\n    node4.next = node5\n    node5.next = node2 // Create a cycle\n\n    // Detect cycle in the linked list\n    hasCycle := hasCycle(head)\n    fmt.Println(hasCycle) // Output: true\n}\n"
  },
  {
    "path": "Linked List/floyds_cycle_detection.java",
    "content": "/*\n\nInitialize two-pointers and start traversing the linked list.\nMove the slow pointer by one position.\nMove the fast pointer by two positions.\nIf both pointers meet at some point then a loop exists and if the fast pointer meets the end position then no loop exists.\n\n\nTime complexity: O(n), as the loop is traversed once. \nAuxiliary Space: O(1), only two pointers are used therefore constant space complexity.\n\n*/\n\n\nimport java.util.*;\n \nclass GFG{\n \nstatic class Node {\n    int data;\n    Node next;\n \n    Node(int data)\n    {\n        this.data = data;\n        next = null;\n    }\n};\n \n// initialize a new head for the linked list\nstatic Node head = null;\nstatic class Linkedlist {\n    // insert new value at the start\n    void insert(int value)\n    {\n        Node newNode = new Node(value);\n        if (head == null)\n            head = newNode;\n        else {\n            newNode.next = head;\n            head = newNode;\n        }\n    }\n \n    // detect if there is a loop\n    // in the linked list\n    boolean detectLoop()\n    {\n        Node slowPointer = head,\n             fastPointer = head;\n \n        while (slowPointer != null\n               && fastPointer != null\n               && fastPointer.next != null) {\n            slowPointer = slowPointer.next;\n            fastPointer = fastPointer.next.next;\n            if (slowPointer == fastPointer)\n                return true;\n        }\n \n    return false;\n    }\n}\n \npublic static void main(String[] args)\n{\n    Linkedlist l1 = new Linkedlist();\n    // inserting new values\n    l1.insert(10);\n    l1.insert(20);\n    l1.insert(30);\n    l1.insert(40);\n    l1.insert(50);\n \n    // adding a loop for the sake\n    // of this example\n    Node temp = head;\n    while (temp.next != null)\n        temp = temp.next;\n \n    temp.next = head;\n \n    // loop added;\n \n    if (l1.detectLoop())\n        System.out.print(\"Loop exists in the\"\n            + \" Linked List\" +\"\\n\");\n    else\n        System.out.print(\"Loop does not exists \"\n            + \"in the Linked List\" +\"\\n\");\n \n}\n}"
  },
  {
    "path": "Linked List/intersection_of_two_linked_lists.cpp",
    "content": "/*\n\n\tGiven the heads of two singly linked-lists headA and headB, return the node at which the two lists intersect. If the two linked lists have no intersection at all, return null.\n\n\n\tInput: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3\n\tOutput: Intersected at '8'\n\t\n\tInput: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1\n\tOutput: Intersected at '2'\n\n\tConstraints:\n\n\t> The number of nodes of listA is in the m.\n\t> The number of nodes of listB is in the n.\n\t> 1 <= m, n <= 3 * 104\n\t> 1 <= Node.val <= 105\n\t> 0 <= skipA < m\n\t> 0 <= skipB < n\n\t> intersectVal is 0 if listA and listB do not intersect.\n\t> intersectVal == listA[skipA] == listB[skipB] if listA and listB intersect.\n\n*/\n\n/**\n * Definition for singly-linked list.\n * struct ListNode {\n *     int val;\n *     ListNode *next;\n *     ListNode(int x) : val(x), next(NULL) {}\n * };\n */\nclass Solution {\npublic:\n    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {\n        // Define basic variables needed\n      int len1=0;\n      int len2=0;\n      ListNode* tempA=headA;\n      ListNode* tempB=headB;\n\n      // Calculate the length of both Linked Lists and store in len1 and len2\n      while(tempA!=NULL)\n      {\n          len1++;\n          tempA=tempA->next;\n      } \n      while(tempB!=NULL)\n      {\n          len2++;\n          tempB=tempB->next;\n      } \n\n      // Here, we assume that length of Linked-List A is less than or equal\n        // to that of Linked List B\n      if(len1>len2){\n          swap(headA,headB);\n      }\n\n      // Re-initialize variables\n      tempA=headA;\n      tempB=headB;\n      int n=abs(len2-len1);\n      while(n--)\n      {\n          tempB=tempB->next;\n      }\n\n      // Finally, Find the Intersection Node\n      while(tempA!=tempB)\n      {\n          tempA=tempA->next;\n          tempB=tempB->next;\n      } \n\n      // Return the final answer\n      return tempA;\n    }\n};"
  },
  {
    "path": "Linked List/liniked_list_sort_list.cpp",
    "content": "/*\n    Given the head of a linked list, return the list after sorting it in ascending order.\n    \n    Input: head = [4,2,1,3]\n    Output: [1,2,3,4]\n\n    Input: head = [-1,5,3,4,0]\n    Output: [-1,0,3,4,5]\n\n    Input: head = []\n    Output: []\n    \n\n    Constraints:\n\n    The number of nodes in the list is in the range [0, 5 * 104].\n    -105 <= Node.val <= 105\n    \n    Follow up: Can you sort the linked list in O(n logn) time and O(1) memory (i.e. constant space)?\n*/\n\n/**\n * Definition for singly-linked list.\n * struct ListNode {\n *     int val;\n *     ListNode *next;\n *     ListNode() : val(0), next(nullptr) {}\n *     ListNode(int x) : val(x), next(nullptr) {}\n *     ListNode(int x, ListNode *next) : val(x), next(next) {}\n * };\n */\nclass Solution {\npublic:\n    ListNode* compute_midpoint(ListNode* head){\n        if(head == NULL || head->next == NULL){\n            return head;\n        }\n        ListNode* slow = head;\n        ListNode* fast = head->next;\n        while(fast != NULL && fast->next != NULL){\n            slow = slow->next;\n            fast = fast->next->next;\n        }\n        return slow;\n    }\n    ListNode* merge_two_lists(ListNode* A, ListNode* B){\n        if(A == NULL)\n            return B;\n        else if(B == NULL)\n            return A;\n        ListNode* C = NULL;\n        if(A->val < B->val){\n            C = A;\n            C->next = merge_two_lists(A->next, B);\n        }\n        else{\n            C = B;\n            C->next = merge_two_lists(A, B->next);\n        }\n        return C;\n    }\n    ListNode* sortList(ListNode* head) {\n        if(head == NULL || head->next == NULL)\n            return head;\n        ListNode* mid = compute_midpoint(head);\n        ListNode* A = head; \n        ListNode* B = mid->next;\n        mid->next = NULL;\n        A = sortList(A);\n        B = sortList(B);\n        \n        ListNode* C = merge_two_lists(A, B);\n        return C;\n    }\n};"
  },
  {
    "path": "Linked List/linked_list.go",
    "content": "// Basic implementation of a Singly Linked List PushBack function\n// Sample Input:  PushBack(10), PushBack(20), PushBack(30)\n// Output: 10 -> 20 -> 30 ->\npackage main\n\nimport \"fmt\"\n\n// has two fields [data] of type integer and [next] of type *node (holds the memory address of next node)\ntype node struct {\n\tdata int\n\tnext *node\n}\n//has three fields length, head and tail node\ntype linkedlist struct {\n\tlength int\n\thead   *node\n\ttail   *node\n}\n// Received in *node as an input and nadds it to linkedlist\nfunc (ll *linkedlist) PushBack(n *node) {\n\t// make incoming *node as head and tail node\n\tif ll.head == nil {\n\t\tll.head = n\n\t\tll.tail = n\n\t\tll.length++\n\t} else {\n\t\t// store memory address of incoming node and point tail to the incoming node\n\t\tll.tail.next = n\n\t\tll.tail = n\n\t\tll.length++\n\t}\n}\n// Return's the head if its present or returns error\nfunc (ll linkedlist) Front() (int, error) {\n\tif ll.head == nil {\n\t\treturn 0, fmt.Errorf(\"No Front value present\")\n\t}\n\treturn ll.head.data, nil\n}\n// Return's the tail if its present or returns error\nfunc (ll linkedlist) Back() (int, error) {\n\tif ll.tail == nil {\n\t\treturn 0, fmt.Errorf(\"No tail found\")\n\t}\n\treturn ll.tail.data, nil\n}\n// Delete front node if any\nfunc (ll *linkedlist) DeleteFromFront() {\n\tif ll.head == nil {\n\t\tfmt.Println(\"Nothing to delete\")\n\t\treturn\n\t}\n\tll.head = ll.head.next\n\tll.length--;\n}\n// Delete from back \nfunc (ll *linkedlist) DeleteFromBack() {\n\tif ll.head == nil {\n\t\tfmt.Println(\"Nothing to delete\")\n\t\treturn\n\t}\n\tvar prev *node = nil\n\tvar temp *node = ll.head\n\t// traverse to second last element\n\tfor temp.next != nil {\n\t\tprev = temp\n\t\ttemp = temp.next\n\t}\n\t// point second last to nil\n\tprev.next = nil\n}\n\n// Traverse the linkedlist and print data\nfunc (ll linkedlist) Display() {\n\t// go till last and keep printing, \n\tfor ll.head != nil {\n\t\tfmt.Printf(\"%v -> \", ll.head.data)\n\t\tll.head = ll.head.next // at some point this will point ti nil so loop terminates\n\t}\n}\nfunc main() {\n\tlist := linkedlist{}\n\tmsg, err := list.Back()\n\tfmt.Println(\"\\n\",msg, err)\n\tlist.DeleteFromBack()\n\tmsg, err = list.Front()\n\tfmt.Println(\"\\n\",msg, err)\n\tnode1 := &node{data: 10}\n\tnode2 := &node{data: 20}\n\tnode3 := &node{data: 30}\n\tnode4 := &node{data: 40}\n\tlist.PushBack(node1)\n\tlist.PushBack(node2)\n\tlist.PushBack(node3)\n\tlist.PushBack(node4)\n\tlist.Display()\n\tmsg, err = list.Front()\n\tfmt.Println(\"\\n\",msg, err)\n\tmsg, err = list.Back()\n\tfmt.Println(\"\\n\",msg, err)\n\tlist.DeleteFromFront()\n\tlist.Display()\n\tlist.DeleteFromBack()\n\tfmt.Println(\"\")\n\tlist.Display()\n}"
  },
  {
    "path": "Linked List/linked_list.js",
    "content": "/* \n    insertAtTail (val)\n    insertAtHead (val)\n    deleteAtTail ()\n    deleteAtHead ()\n    getLength ()\n    print ()\n    getAtIdx (idx)\n    putAtIdx (val, idx)\n    deleteAtIdx (idx)\n    search (val)\n    toArray ()\n    reverse ()\n*/\n\nclass Node {\n    constructor(val) {\n        this.val = val\n        this.next = null\n    }\n}\n\nclass LinkedList {\n    constructor() {\n        this.head = null\n        this.tail = null\n        this.length = 0\n    }\n\n    insertAtTail(val) {\n        const node = new Node(val)\n\n        if (!this.head) {\n            this.head = node\n            this.tail = node\n            this.length++\n        } else {\n            this.tail.next = node\n            this.tail = node\n            this.length++\n        }\n    }\n\n    insertAtHead(val) {\n        const node = new Node(val)\n\n        if (!this.head) {\n            this.head = node\n            this.tail = node\n            this.length++\n        } else {\n            node.next = this.head\n            this.head = node\n            this.length++\n        }\n    }\n\n    print() {\n        if (this.length === 0) console.log (\"Empty Linked List!\")\n        else {\n            let curr = this.head\n            let str = ''\n\n            while (curr) {\n                str += curr.val + ' -> '\n                curr = curr.next\n            }\n\n            console.log(str + 'null')\n        }\n    }\n\n    deleteAtTail() {\n        if (!this.head) console.log(\"Empty Linked List!\")\n\n        else {\n            let curr = this.head\n            let prev = this.head\n\n            while (curr.next) {\n                prev = curr\n                curr = curr.next\n            }\n\n            prev.next = null\n            this.tail = prev\n            this.length--\n        }\n    }\n\n    deleteAtHead() {\n        if (!this.head) console.log(\"Empty Linked List!\")\n\n        else {\n            let curr = this.head\n            this.head = curr.next\n            this.length--\n        }\n    }\n\n\n    getLength() {\n        return this.length\n    }\n\n    getAtIdx (idx) {\n        if (idx >= this.length || idx < 0) throw new Error (\"Index out of bounds\")\n\n        else {\n            let currIdx = 0\n            let curr = this.head\n\n            while (currIdx < idx) {\n                currIdx++\n                curr = curr.next\n            }\n\n            return curr.val\n        } \n    }\n\n    putAtIdx (val, idx) {\n        if (idx > this.length || idx < 0) throw new Error (\"Index out of bounds\")\n\n        const node = new Node (val)\n\n        if (!this.head) {\n            this.head = node\n            this.length++\n            return\n        }\n\n        let currIdx = 0\n        let curr = this.head\n        let prev = this.head\n\n        while (currIdx < idx) {\n            currIdx++\n            prev = curr\n            curr = curr.next\n        }\n\n        prev.next = node\n        node.next = curr\n        this.length++\n    }\n\n    deleteAtIdx (idx) {\n        if (idx >= this.length || idx < 0) throw new Error (\"Index out of bounds\")\n\n        else {\n            let currIdx = 0\n            let curr = this.head\n            let prev = this.head\n\n            while (currIdx < idx) {\n                currIdx++\n                prev = curr\n                curr = curr.next\n            }\n\n            prev.next = curr.next\n            this.length--\n        }\n    }\n\n    search (val) {\n        if (!this.head) return \"Empty Linked List!\"\n        if (!this.head.next && this.head.val !== val) return null\n        if (!this.head.next && this.head.val === val) return 0\n        \n        let currIdx = 0\n        let curr = this.head\n\n        while (curr) {\n            if (curr.val === val) return currIdx\n            currIdx++\n            curr = curr.next\n        }\n\n        return null\n    }\n\n    toArray () {\n        const arr = []\n        if (!this.head) return null\n\n        let curr = this.head\n\n        while (curr) {\n            arr.push (curr.val)\n            curr = curr.next\n        }\n\n        return arr\n    }\n\n    reverse () {\n        if (!this.head) throw new Error (\"Empty Linked List\")\n        if (!this.head.next) return\n\n        let prev = null\n        let curr = this.head\n        let next = curr.next\n\n        while (curr) {\n            next = curr.next\n            curr.next = prev\n            prev = curr\n            curr = next\n        }\n\n        this.head = prev\n    }\n}\n\n// SAMPLE USECASE\n\nconst list = new LinkedList()\nlist.insertAtTail (10)\nlist.insertAtTail (20)\nlist.insertAtTail (30)\nlist.insertAtTail (40)\nlist.insertAtTail (50)\nlist.reverse ()\nlist.print ()"
  },
  {
    "path": "Linked List/linked_list.py",
    "content": "# Implementation of Singly Linked List in Python\n'''\n    This implementation defines a Node class to represent a node in the linked list, and a LinkedList \n    class to represent the linked list itself. The LinkedList class has methods to insert nodes at the \n    beginning or end of the list, delete nodes from the list, and print the list. Each node has two \n    attributes: its data and a reference to the next node in the list (next). \n    The LinkedList class has one attribute: the head node of the list (head). When a new node is \n    inserted at the beginning of the list, its next attribute is set to the current head node, and the \n    head attribute is set to the new node. When a new node is inserted at the end of the list, it is \n    appended to the last node's next attribute. When a node is deleted, the list is traversed to find \n    the node with the given data, and its next attribute is set to the node after it. Finally, the \n    print_list method traverses the list and prints each node's data.\n'''\n# Define a class to represent a node in the linked list\nclass Node:\n    def __init__(self, data):\n        # Each node has two attributes: data and a reference to the next node\n        self.data = data\n        self.next = None\n\n# Define a class to represent the linked list itself\nclass LinkedList:\n    def __init__(self):\n        # Each linked list has one attribute: the head node (which initially is None)\n        self.head = None\n    \n    # Method to insert a new node at the beginning of the linked list\n    def insert_at_beginning(self, data):\n        # Create a new node\n        new_node = Node(data)\n        \n        # Set the next node of the new node to be the current head node\n        new_node.next = self.head\n        \n        # Set the head node to be the new node\n        self.head = new_node\n    \n    # Method to insert a new node at the end of the linked list\n    def insert_at_end(self, data):\n        # Create a new node\n        new_node = Node(data)\n        \n        # If the list is empty, set the head node to be the new node\n        if self.head is None:\n            self.head = new_node\n            return\n        \n        # Traverse to the last node in the list\n        current_node = self.head\n        while current_node.next:\n            current_node = current_node.next\n        \n        # Set the next node of the last node to be the new node\n        current_node.next = new_node\n    \n    # Method to delete the first occurrence of a node with the given data\n    def delete_node(self, data):\n        # If the list is empty, do nothing\n        if self.head is None:\n            return\n        \n        # If the node to be deleted is the head node, set the head node to be the next node\n        if self.head.data == data:\n            self.head = self.head.next\n            return\n        \n        # Traverse the list to find the node to be deleted\n        current_node = self.head\n        while current_node.next:\n            if current_node.next.data == data:\n                current_node.next = current_node.next.next\n                return\n            current_node = current_node.next\n    \n    # Method to print the linked list\n    def print_list(self):\n        # Traverse the list and print each node's data\n        current_node = self.head\n        while current_node:\n            print(current_node.data, end=\" -> \")\n            current_node = current_node.next\n        print(\"None\")\n"
  },
  {
    "path": "Linked List/linked_list_add_two_numbers.py",
    "content": "'''\nYou are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.\n\nYou may assume the two numbers do not contain any leading zero, except the number 0 itself.\n\nExample 1:\nInput: l1 = [2,4,3], l2 = [5,6,4]\nOutput: [7,0,8]\nExplanation: 342 + 465 = 807.\n\nExample 2:\nInput: l1 = [0], l2 = [0]\nOutput: [0]\n\nExample 3:\nInput: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]\nOutput: [8,9,9,9,0,0,0,1]\n \n\nConstraints:\n\nThe number of nodes in each linked list is in the range [1, 100].\n0 <= Node.val <= 9\nIt is guaranteed that the list represents a number that does not have leading zeros.\n\nComplexity\nTime complexity : O(max(l1,l2)).\nSpace complexity : O(n).\n\n'''\n\n# Definition for singly-linked list.\n# class ListNode:\n#     def __init__(self, val=0, next=None):\n#         self.val = val\n#         self.next = next\nclass Solution:\n    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:\n        carry = 0\n        head = ListNode('*');\n        header_pointer = head;\n        while(l1 != None or l2 != None):\n            temp = carry\n            if(l1 == None):\n                temp += l2.val\n                l2 = l2.next\n            elif(l2 == None):\n                temp += l1.val\n                l1 = l1.next\n            else:\n                temp += l1.val+l2.val\n                l1 = l1.next\n                l2 = l2.next\n            head.next = ListNode(temp % 10)\n            carry = temp // 10\n            head = head.next\n        if(carry != 0):\n            head.next = ListNode(carry)\n            head = head.next\n        return header_pointer.next\n"
  },
  {
    "path": "Linked List/linked_list_compute_middle.cpp",
    "content": "// Given the head of a singly linked list, return the middle node of the linked list.\n// If there are two middle nodes, return the second middle node.\n\n//  Input: head = [1,2,3,4,5]\n// Output: [3,4,5]\n// Explanation: The middle node of the list is node 3.\n\n// TIME ANS SPACE COMPLEXITY OF THE SOLUTION IS :: \n// Time complexity: O(n)\n// Space complexity: O(1)\n\n#include <bits/stdc++.h>\nusing namespace std;\n\n// creating Node manualy\nclass Node\n{\npublic:\n    int data;\n    Node *next;\n\n    Node()\n    {\n        this->data = 0;\n        this->next = NULL;\n    }\n    Node(int data)\n    {\n        this->data = data;\n        this->next = NULL;\n    }\n};\n\nNode *middleNode(Node *head)\n{\n\n    Node *slow = head;\n    Node *fast = head;\n\n    // Move slow pointer by one node at a time and fast pointer two nodes at a time.\n    // While fast pointer reaches the end, slow pointer must have reached the middle node.\n\n    while (fast != NULL)\n    {\n        fast = fast->next;\n        if (fast != NULL)\n        {\n            fast = fast->next;\n            slow = slow->next;\n        }\n    }\n    return slow; // return slow as ans\n}\n\nint main()\n{\n    // creating nodes.\n    Node *first = new Node(1);\n    Node *second = new Node(2);\n    Node *third = new Node(3);\n    Node *fourth = new Node(4);\n    Node *fifth = new Node(5);\n\n    // head of linked list\n    Node *head = first;\n\n    // Creating connection of nodes\n    first->next = second;\n    second->next = third;\n    third->next = fourth;\n    fourth->next = fifth;\n\n    cout << \"The middle node of the list is node \" << middleNode(head)->data << endl;\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_compute_middle.java",
    "content": "/* \nIn this code, the ListNode class represents a node in the linked list, with an integer value val and a reference to the next node next. The FindMiddleLinkedList class has a findMiddle method that takes a ListNode as its input and returns the middle node of the linked list using the fast and slow pointers algorithm.\n\n*/\nclass ListNode {\n    int val;\n    ListNode next;\n\n    ListNode(int val) {\n        this.val = val;\n        this.next = null;\n    }\n}\n\nclass FindMiddleLinkedList {\n    public ListNode findMiddle(ListNode head) {\n        // Create two pointers, slow and fast, both initially pointing to the head of the linked list.\n        ListNode slow = head;\n        ListNode fast = head;\n\n        // Move the slow pointer one step at a time and the fast pointer two steps at a time, until the fast pointer reaches the end of the list.\n        while (fast != null && fast.next != null) {\n            slow = slow.next;\n            fast = fast.next.next;\n        }\n\n        // When the fast pointer reaches the end of the list, the slow pointer will be pointing to the middle of the list.\n        return slow;\n    }\n\n    public static void main(String[] args) {\n        // Create a sample linked list\n        ListNode head = new ListNode(1);\n        head.next = new ListNode(2);\n        head.next.next = new ListNode(3);\n        head.next.next.next = new ListNode(4);\n        head.next.next.next.next = new ListNode(5);\n\n        // Create an instance of the FindMiddleLinkedList class\n        FindMiddleLinkedList f = new FindMiddleLinkedList();\n\n        // Call the findMiddle method to get the middle node of the linked list\n        ListNode middleNode = f.findMiddle(head);\n\n        // Print the value of the middle node\n        System.out.println(\"The middle node has value: \" + middleNode.val);\n    }\n}\n"
  },
  {
    "path": "Linked List/linked_list_delete_at_any_pos.cpp",
    "content": "// Insert at any position in a LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nint length(node* head){\n    int len = 0;\n    while(head != NULL){\n        head = head->next;\n        len++;\n    }\n    return len;\n}\nvoid insert_at_head(node *&head, int data){\n    node *n = new node(data);\n    n->next = head;\n    head = n;\n}\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid insert_at_anypos(node *&head, int data, int pos){\n    if(head == NULL || pos == 0){\n        insert_at_head(head, data);\n    }\n    else if(pos > length(head)){\n        insert_at_tail(head, data);\n    }\n    else{\n        node* temp = head;\n        node *n = new node(data);\n        for(int i = 0; i < pos - 1; i++){\n            temp = temp->next;\n        }\n        n->next = temp->next;\n        temp->next = n;\n    }\n}\nvoid delete_at_head(node *&head){\n    if(head == NULL){\n        return;\n    }\n    node *temp = head;\n    head = head->next;\n    delete temp;\n}\nvoid delete_at_tail(node *&head){\n    node *prev = NULL;\n    node *temp = head;\n    while(temp->next != NULL){\n        prev = temp;\n        temp = temp->next;\n    }\n    prev->next = NULL;\n    delete temp;\n}\nvoid delete_at_any_pos(node *&head, int pos){\n    if(pos == 0 || pos == 1){\n        delete_at_head(head);\n        return;\n    }\n    else if(pos > length(head)){\n        delete_at_tail(head);\n    }\n    else{\n        node *prev = NULL;\n        node *temp = head;\n        for(int i = 0; i < pos - 1; i++){\n            prev = temp;\n            temp = temp->next;\n        }\n        prev->next = temp->next;\n        delete temp;\n    }\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nint main(){\n    node *head = NULL;\n    insert_at_head(head, 1);\n    insert_at_head(head, 2);\n    insert_at_head(head, 3);\n    insert_at_anypos(head, 6, 10);\n    insert_at_tail(head, 33);\n    insert_at_head(head, 44);\n    insert_at_anypos(head, 66, 4);\n    insert_at_tail(head, 100);\n    insert_at_anypos(head, 11, 3);\n    print_linked_list(head);\n    delete_at_any_pos(head, 2);\n    delete_at_any_pos(head, 3);\n    delete_at_any_pos(head, 4);\n    insert_at_anypos(head, 22, 2);\n    cout << endl;\n    print_linked_list(head);\n    delete_at_any_pos(head, 2);\n    cout << endl;\n    print_linked_list(head);\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_delete_at_head.cpp",
    "content": "// Delete from Head in a LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_head(node *&head, int data){\n    node *n = new node(data);\n    n->next = head;\n    head = n;\n}\nvoid delete_at_head(node *&head){\n    if(head == NULL){\n        return;\n    }\n    node *temp = head;\n    head = head->next;\n    delete temp;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nint main(){\n    node *head = NULL;\n    insert_at_head(head, 1);\n    insert_at_head(head, 2);\n    insert_at_head(head, 3);\n    print_linked_list(head);\n    cout << endl;\n    delete_at_head(head);\n    delete_at_head(head);\n    print_linked_list(head);\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_delete_at_tail.cpp",
    "content": "// Delete from Tail in a  LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\n\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid delete_at_tail(node *&head){\n    node *prev = NULL;\n    node *temp = head;\n    while(temp->next != NULL){\n        prev = temp;\n        temp = temp->next;\n    }\n    prev->next = NULL;\n    delete temp;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nint main(){\n    node *head = NULL;\n    insert_at_tail(head, 20);\n    insert_at_tail(head, 33);\n    insert_at_tail(head, 100);\n    insert_at_tail(head, 200);\n    insert_at_tail(head, 201);\n    insert_at_tail(head, 202);\n    print_linked_list(head);\n    cout << endl;\n    delete_at_tail(head);\n    delete_at_tail(head);\n\n    print_linked_list(head);\n    return 0;\n}\n"
  },
  {
    "path": "Linked List/linked_list_delete_node.go",
    "content": "/*\n\tWe are given a pointer to a node (not the tail node) in a singly linked list. Delete that node from the\n\tlinked list.\n*/\npackage main\n\n/*\n\tApproach:\n\t1. We can move the data from the next node into the current node\n\t2. Delete the next node.\n\tTime Complexity: O(1). Space Complexity: O(1).\n*/\nfunc deleteNode(node *ListNode) {\n\ttemp = node.next\n\tnode.data = node.next.data\n\tnode.next = temp.next\n\ttemp = nil\n}"
  },
  {
    "path": "Linked List/linked_list_even_or_odd.go",
    "content": "/*\n\tCheck whether the given Linked List length is even or odd?\n\n\tApproach:\n\tUse a 2x pointer. Take a pointer that moves at 2x [two nodes at a time]. At the end, if the length is even,\n\tthen the pointer will be nil; otherwise it will point to the last node.\n*/\n// Time Complexity: O(⌊n/2⌋) ≈O(n). Space Complexity: O(1).\npackage main\n\n// has two fields [data] of type integer and [next] of type *node (holds the memory address of next node)\ntype node struct {\n\tdata int\n\tnext *node\n}\n//has three fields length, head and tail node\ntype LinkedList struct {\n\tlength int\n\thead   *node\n\ttail   *node\n}\n\nfunc (ll *LinkedList) IsLengthEven() bool {\n\tcurrent := ll.head\n\tfor current != nil && current.next != nil {\n\t\tcurrent = current.next.next\n\t}\n\tif current != nil {\n\t\treturn false\n\t}\n\treturn true\n}"
  },
  {
    "path": "Linked List/linked_list_find_length.cpp",
    "content": "// Find length of a LinkedList\n// Program Author : Abhisek Kumar Gupta \n\n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nint length(node* head){\n    int len = 0;\n    while(head != NULL){\n        head = head->next;\n        len++;\n    }\n    return len;\n}\nvoid insert_at_head(node *&head, int data){\n    node *n = new node(data);\n    n->next = head;\n    head = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nint main(){\n    node *head = NULL;\n    insert_at_head(head, 1);\n    insert_at_head(head, 2);\n    insert_at_head(head, 3);\n    print_linked_list(head);\n    int len = length(head);\n    cout << endl <<len;\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_insert_at_any_pos.cpp",
    "content": "// Insert at any position in a LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nint length(node* head){\n    int len = 0;\n    while(head != NULL){\n        head = head->next;\n        len++;\n    }\n    return len;\n}\nvoid insert_at_head(node *&head, int data){\n    node *n = new node(data);\n    n->next = head;\n    head = n;\n}\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid insert_at_anypos(node *&head, int data, int pos){\n    if(head == NULL || pos == 0){\n        insert_at_head(head, data);\n    }\n    else if(pos > length(head)){\n        insert_at_tail(head, data);\n    }\n    else{\n        node* temp = head;\n        node *n = new node(data);\n        for(int i = 0; i < pos - 1; i++){\n            temp = temp->next;\n        }\n        n->next = temp->next;\n        temp->next = n;\n    }\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nint main(){\n    node *head = NULL;\n    insert_at_head(head, 1);\n    insert_at_head(head, 2);\n    insert_at_head(head, 3);\n    insert_at_anypos(head, 6, 10);\n    insert_at_tail(head, 33);\n    insert_at_head(head, 44);\n    insert_at_anypos(head, 66, 4);\n    insert_at_tail(head, 100);\n    insert_at_anypos(head, 11, 3);\n    print_linked_list(head);\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_insert_at_head.cpp",
    "content": "// Search recursively in a LinkedList\n// Program Author : Abhisek Kumar Gupta \n\n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_head(node *&head, int data){\n    node *n = new node(data);\n    n->next = head;\n    head = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nint main(){\n    node *head = NULL;\n    insert_at_head(head, 1);\n    insert_at_head(head, 2);\n    insert_at_head(head, 3);\n    print_linked_list(head);\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_insert_at_tail.cpp",
    "content": "// Insert at Tail in a LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\n\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nint main(){\n    node *head = NULL;\n    insert_at_tail(head, 20);\n    insert_at_tail(head, 33);\n    insert_at_tail(head, 100);\n    insert_at_tail(head, 200);\n    print_linked_list(head);\n    \n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_kth_from_end.go",
    "content": "// Finding Kth node from end of a LinkedList\npackage main\n\n/*\nApproach\n1. Make two pointers slow and fast and keep them both on the head of the linked list.\n2. Now, move the fast pointer k steps away from the slow pointer.\n3. Now, move the fast pointer and the slow pointer each one step at a time till\n   the fast pointer reaches the tail of the linked list. When the fast pointer reaches the tail,\n   the node at which the slow pointer resides will be our answer.\n\nTime and space complexity\n\n\tTime complexity of the solution is O(n) as we have traversed the linked list once.\n\tWe have traversed it in two parts.\n\tFirst we traversed k elements and then we traversed the remaining (size minus k) elements.\n\n\tSpace complexity is O(1) as we have not used any extra space for the solution.\n\n\n*/\nfunc kthFromEnd(head *ListNode, n int) *ListNode {\n    first, second := head, head\n    for ; n > 0; n-- {\n        second = second.next\n    }\n    for ; second.next != nil; first, second = first.next, second.next {\n    }\n    first.next = first.next.next\n    return first\n}  "
  },
  {
    "path": "Linked List/linked_list_kth_node_from_end.cpp",
    "content": "// Finding Kth node from end of a LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nnode* kth_node_from_end(node *head, int k){\n    if(head->next == NULL || head == NULL){\n        return head;\n    }\n    node *slow = head;\n    node *fast = head;\n    while(k--){\n        fast = fast->next;\n    }\n    while(fast){\n        fast = fast->next;\n        slow = slow->next;\n    }\n    return slow;\n}\nint main(){\n    node *head = NULL;\n    makeLinkedList(head);\n    print_linked_list(head);\n    int k;\n    cin >> k;\n    node *kth_node = kth_node_from_end(head, k);\n    cout << endl;\n    cout << kth_node->data << endl;\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_linear_search.cpp",
    "content": "// Search linearly in a LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nbool linear_search(node *head, int key){\n    if(head == NULL){\n        return false;\n    }\n    else{\n        node *temp = head;\n        while(temp != NULL){\n            if(temp->data == key){\n                return true;\n            }\n            temp = temp->next;\n        }    \n    }\n    return false;\n}\nvoid insert_at_head(node *&head, int data){\n    node *n = new node(data);\n    n->next = head;\n    head = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nint main(){\n    node *head = NULL;\n    insert_at_head(head, 1);\n    insert_at_head(head, 2);\n    insert_at_head(head, 3);\n    print_linked_list(head);\n    cout << endl;\n    if(linear_search(head, 1)){\n        cout << \"Found\";\n    }\n    else{\n        cout << \"Not Found\";\n    }\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_merge_k_sorted_lists.cpp",
    "content": "// Merge K sorted LinkedLists\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\n\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nistream& operator>>(istream &is, node *&head){\n    makeLinkedList(head);\n    return is;\n}\nostream& operator<<(ostream &os, node *&head){\n    print_linked_list(head);\n    return os;\n}\nnode* merge_two_lists(node *a, node *b){\n    if(a == NULL){\n        return b;\n    }\n    else if(b == NULL){\n        return a;\n    }\n    node *c = NULL;\n    if(a->data < b->data){\n        c = a;\n        c->next = merge_two_lists(a->next, b);\n    }\n    else{\n        c = b;\n        c->next = merge_two_lists(a, b->next);\n    }\n    return c;\n}\nnode* merge_k_lists(node *arr[], int last){\n    while(last != 0){\n        int i = 0, j = last;\n        while(i < j){\n            arr[i] = merge_two_lists(arr[i], arr[j]);\n            i++;\n            j--;\n            if(i >= j)\n                last = j;\n        }\n    }\n    return arr[0];\n}\nint main(){\n\n   int n;\n   cin >> n;\n   node *arr[n];\n   for(int i = 0; i < n; i++){\n      arr[i] = NULL;\n   }\n   for(int i = 0; i < n; i++){\n       cin >> arr[i];\n   }\n   cout << endl;\n   for(int i = 0; i < n; i++){\n       cout << arr[i] << endl;;\n   }\n   node *head = merge_k_lists(arr, n-1);\n   cout << head;\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_merge_two_sorted_linked_list.cpp",
    "content": "// Merge two sorted LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\n\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nistream& operator>>(istream &is, node *&head){\n    makeLinkedList(head);\n    return is;\n}\nostream& operator<<(ostream &os, node *&head){\n    print_linked_list(head);\n    return os;\n}\nnode* merge_two_lists(node *a, node *b){\n    if(a == NULL){\n        return b;\n    }\n    else if(b == NULL){\n        return a;\n    }\n    node *c = NULL;\n    if(a->data < b->data){\n        c = a;\n        c->next = merge_two_lists(a->next, b);\n    }\n    else{\n        c = b;\n        c->next = merge_two_lists(a, b->next);\n    }\n    return c;\n}\nint main(){\n    node *head = NULL;\n    node *head2 = NULL;\n    cin >> head >> head2;\n    cout << head  << endl << head2;\n    cout << endl;\n    node *x = merge_two_lists(head, head2);\n    cout << x << endl;\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_mergesort_an_unsorted_list.cpp",
    "content": "// MergeSort an unsorted LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nnode* compute_midpoint(node *head){\n    if(head->next == NULL || head == NULL){\n        return head;\n    }\n    node *slow = head;\n    node *fast = head->next;\n    while(fast != NULL && fast->next != NULL){\n        fast = fast->next->next;\n        slow = slow->next;\n    }\n    return slow;\n}\nistream& operator>>(istream &is, node *&head){\n    makeLinkedList(head);\n    return is;\n}\nostream& operator<<(ostream &os, node *&head){\n    print_linked_list(head);\n    return os;\n}\nnode* merge_two_lists(node *a, node *b){\n    if(a == NULL){\n        return b;\n    }\n    else if(b == NULL){\n        return a;\n    }\n    node *c = NULL;\n    if(a->data < b->data){\n        c = a;\n        c->next = merge_two_lists(a->next, b);\n    }\n    else{\n        c = b;\n        c->next = merge_two_lists(a, b->next);\n    }\n    return c;\n}\nnode* mergeSort(node* head){\n    if(head == NULL || head->next == NULL){\n        return head;\n    }\n    node *mid = compute_midpoint(head);\n    node *a = head;\n    node *b = mid->next;\n    mid->next = NULL;\n    a = mergeSort(a);\n    b = mergeSort(b);\n    node *c = merge_two_lists(a, b);\n    return c;\n}\nint main(){\n    node *head = NULL;\n    node *head2 = NULL;\n    cin >> head;\n    cout << head  << endl;\n    node *x = mergeSort(head);\n    cout << x << endl;\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_middle.go",
    "content": "/**\n * Given the head of a singly linked list, return the middle node of the linked list. If there are two middle nodes, return the second middle node.\n *\n * Example #1:\n * Input: head = [1,2,3,4,5]\n * Output: [3,4,5]\n * Explanation: The middle node of the list is node 3.\n * \n * Example #2:\n * Input: head = [1,2,3,4,5,6]\n * Output: [4,5,6]\n * Explanation: Since the list has two middle nodes with values 3 and 4, we return the second one.\n *\n * Constraints: \n * The number of nodes in the list is in the range [1, 100].\n * 1 <= Node.val <= 100\n * \n * Definition for singly-linked list.\n * type ListNode struct {\n *     Val int\n *     Next *ListNode\n * }\n *\n * Solution: to find the middle of a linked list, we can use two pointers (\"slow\" and \"fast\"). They should both start at head. \n * While traversing the list, we move the slow pointer one node at a time and the fast pointer two nodes at a time. \n * When the fast pointer reaches the end of the linked list, the slow pointer will be pointing to the middle node.\n *\n * Time complexity: O(n), space complexity: O(n)\n */\n func middleNode(head *ListNode) *ListNode {\n    slow, fast := head, head\n    \n    for (fast != nil && fast.Next != nil) {\n        slow = slow.Next\n        fast = fast.Next.Next\n    }\n\n    return slow\n}\n"
  },
  {
    "path": "Linked List/linked_list_middle.js",
    "content": "/* \n    Given the head of a singly linked list, return the middle node of the linked list.\n\n    If there are two middle nodes, return the second middle node.\n\n    Example 1:\n\n    Input: head = [1,2,3,4,5]\n    Output: [3,4,5]\n    Explanation: The middle node of the list is node 3.\n\n    Example 2:\n\n    Input: head = [1,2,3,4,5,6]\n    Output: [4,5,6]\n    Explanation: Since the list has two middle nodes with values 3 and 4, we return the second one.\n    \n    Constraints:\n\n    The number of nodes in the list is in the range [1, 100].\n    1 <= Node.val <= 100\n*/\n\n/**\n * Definition for singly-linked list.\n * function ListNode(val, next) {\n *     this.val = (val===undefined ? 0 : val)\n *     this.next = (next===undefined ? null : next)\n * }\n */\n/**\n * @param {ListNode} head\n * @return {ListNode}\n */\nvar middleNode = function(head) {\n    let curr = head // Initialize the current node to the head\n    let size = 0 // Initialize the size to 0\n\n    // Traverse the Linked List\n    while (curr) { \n        size += 1 // Keep track of the size of the Linked List\n        curr = curr.next\n    } // curr is equal to null at the end of the loop\n\n    let mid = Math.floor(size / 2) + 1 // Calculate the middle of the List\n    let count = 0 \n    curr = head // Reset current to head\n\n    // Traverse the Linked List\n    while (curr) {\n        count += 1 // Keep track of the number of visited nodes in the List\n\n        if (count === mid) return curr // When middle node found, return it\n\n        curr = curr.next\n    }\n};"
  },
  {
    "path": "Linked List/linked_list_odd_even.cpp",
    "content": "// OddEven LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    cout << endl;\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nnode* oddEvenLinkedList(node *head){\n    if(head == NULL || head->next == NULL){\n        return head;\n    }\n    node *odd = head;\n    node *even = head->next;\n    node *evenhead = even;\n    while(even != NULL && even->next != NULL){\n        odd->next = even->next;\n        odd = odd->next;\n        even->next = odd->next;\n        even = even->next;\n    }\n    odd->next = evenhead;\n    return head;\n}\nint main(){\n    node *head = NULL;\n    makeLinkedList(head);\n    print_linked_list(head);\n    oddEvenLinkedList(head);\n    print_linked_list(head);\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_pallindrome.cpp",
    "content": "/*\n    Given the head of a singly linked list, return true if it is a \n    palindrome\n    or false otherwise.\n\n    \n\n    Example 1:\n\n\n    Input: head = [1,2,2,1]\n    Output: true\n    Example 2:\n\n\n    Input: head = [1,2]\n    Output: false\n    \n\n    Constraints:\n\n    The number of nodes in the list is in the range [1, 105].\n    0 <= Node.val <= 9\n    \n\n    Follow up: Could you do it in O(n) time and O(1) space?\n*/\n/**\n * Definition for singly-linked list.\n * struct ListNode {\n *     int val;\n *     ListNode *next;\n *     ListNode() : val(0), next(nullptr) {}\n *     ListNode(int x) : val(x), next(nullptr) {}\n *     ListNode(int x, ListNode *next) : val(x), next(next) {}\n * };\n */\n\n// Time Complexity : O(n) Space Complexity: O(n)\n// TODO: Implement O(n) Time and  O(1) space solution\nclass Solution {\npublic:\n    bool isPalindrome(ListNode* head) {\n        vector<int> contents;\n        while(head != NULL) {\n            int val = head->val;\n            contents.push_back(val);\n            head = head->next;\n        }\n        int low = 0, high = contents.size() - 1;\n        while(low <= high) {\n            if(contents[low] == contents[high]){\n                low++;\n                high--;\n            }\n            else {\n                return false;\n            }\n        }\n        return true;\n    }\n};"
  },
  {
    "path": "Linked List/linked_list_recursive_search.cpp",
    "content": "// Search recursively in a LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nbool recursive_search(node *head, int key){\n    if(head == NULL){\n        return false;\n    }\n    if(head->data == key){\n        return true;\n    }\n    else{\n        recursive_search(head->next, key);\n    }\n}\nvoid insert_at_head(node *&head, int data){\n    node *n = new node(data);\n    n->next = head;\n    head = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nint main(){\n    node *head = NULL;\n    insert_at_head(head, 1);\n    insert_at_head(head, 2);\n    insert_at_head(head, 3);\n    print_linked_list(head);\n    cout << endl;\n    if(recursive_search(head, 3)){\n        cout << \"Found\";\n    }\n    else{\n        cout << \"Not Found\";\n    }\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_remove_dups.cpp",
    "content": "// Remove duplicates from an unsorted linked list \n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass Node{\n    public:\n        int data;\n        Node *next;\n\n        Node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(Node *&head, int data){\n    if(head == NULL){\n        head = new Node(data);\n        return;\n    }\n    Node *n = new Node(data);\n    Node *temp = head;\n    while(temp->next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(Node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid make_linked_list(Node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nvoid remove_duplicates(Node *&head){\n    set<int> S;\n    Node *temp = head;\n    Node *prev = NULL;\n    Node *remove = NULL;\n    while(temp != NULL){\n        if(S.find(temp->data) != S.end()){\n            remove = temp;\n            prev->next = temp->next;\n        }\n        else{\n            S.insert(temp->data);\n            prev = temp;\n        }\n        temp = temp->next;\n        delete remove;\n    }\n}\nvoid remove_duplicates_without_buffer(Node *&head){\n    Node *current = head;\n    Node *remove = NULL;\n    while(current != NULL){\n        Node *runner = current;\n        while(runner->next != NULL){\n            if(runner->next->data == current->data){\n                remove = runner->next;\n                runner->next = runner->next->next;\n                delete remove;\n            }\n            else{\n                runner = runner->next;\n            }\n        }\n        current = current->next;\n    }\n}\nint main(){\n    Node *head = NULL;\n    /*\n    make_linked_list(head);\n    print_linked_list(head);\n    cout << endl;\n    remove_duplicates(head);\n    print_linked_list(head);\n    */\n    make_linked_list(head);\n    print_linked_list(head);\n    cout << endl;\n    remove_duplicates_without_buffer(head);\n    print_linked_list(head);\n}"
  },
  {
    "path": "Linked List/linked_list_remove_kth_node_from_end.py",
    "content": "# PROBLEM TO SOLVE\n\"\"\"\n    Remove the Nth node from the end of the linked list\n    assume input is always valid and that k will be a non-negative number\n    that is less than the length of the list\n\"\"\"\n\n# define node used in linked list\nclass node:\n    def __init__(self,v=0,n=None):\n        self.val = v\n        self.next = n\n\n# function to create list of length n, node values start at 1 and incrament\n# this is NOT part of the algorithm, just part of the setup\ndef create_list(n):\n    if n <= 0:\n        raise Exception()\n    head = node(1)\n    curr = head\n    for i in range(2,n+1):\n        next = node(i)\n        curr.next = next \n        curr=curr.next\n    return head\ndef print_list(head):\n    while head:\n        print(head.val)\n        head = head.next\n\n# helper function (used in both recursive and iterative)\ndef __remove_node(prev,curr):\n    prev.next = curr.next\n# recursive function\ndef recursive(head, n):\n    # create nested helper function called rec\n    # this allows us to keep the function signature of recursive clean and consistant with iterative\n    # in real life the client does not usually care if your function is iterative or recursive\n    # so you want both functions to have just two arguments when the client calls them\n    def rec(lag,lead, k):\n        # move lead up k nodes before we even start moving lag\n        if k > 0:\n            k -= 1\n            lead = lead.next\n        else:\n            if not lead: # base case 1: remove head if lead goes passed last node\n                return head.next\n            elif not lead.next: # base case 2: skip kth node if lead is on last node\n                lag.next = lag.next.next\n                return head\n            else: # move both nodes up until lead is at the last node\n                lead = lead.next\n                lag = lag.next\n        return rec(lag,lead,k) # call the recursive case\n    # if we did not create a helper function, the client would need to call recursive\n    # with 3 arguments instead of 2 which is confusing.\n    return rec(head,head,n)\n\n\n# iterative function\ndef iterative(head,k):\n    # start lag and lead at head\n    lag = lead = head\n    # lead gets a headstart, it moves up k nodes before lag starts moving\n    for _ in range(k):\n        lead = lead.next\n    # if lead made it passed the end, then lag must still be at head\n    if not lead:\n        return lag.next\n    # we want to keep moving both lead and lag by one until lead is at the last node\n    # keep in mind that we want to stop lag one bofore the node we want to delete.\n    # this is because need to skip over the kth node from the end\n    while lead.next:\n        lead = lead.next\n        lag = lag.next\n    # we skip the kth from end node by assiging lag.next to lag.next.next\n    # pythons built in garbage collection will recognize that the kth node\n    # is unreachable and will delete it for us, no need to call del!\n    lag.next = lag.next.next\n    return head\n\n# text functions below main\nif __name__ == \"__main__\":\n    head = create_list(9)\n    print(\"before removal\")\n    print_list(head)\n    print(\"after removing 2nd from last node iteratively\")\n    rem_head = iterative(head,2)\n    print_list(rem_head)\n    head = create_list(9)\n    print(\"after removing 3rd from last recursivly\")\n    rem_head = recursive(head,3)\n    print_list(rem_head)\n"
  },
  {
    "path": "Linked List/linked_list_remove_nth_node_from_end.cpp",
    "content": "/*\nGiven the head of a linked list, remove the nth node from the end of the list and return its head.\n\nInput: head = [1,2,3,4,5], n = 2\nOutput: [1,2,3,5]\nExample 2:\n\nInput: head = [1], n = 1\nOutput: []\nExample 3:\n\nInput: head = [1,2], n = 1\nOutput: [1]\n \n\nConstraints:\n\nThe number of nodes in the list is sz.\n1 <= sz <= 30\n0 <= Node.val <= 100\n1 <= n <= sz\n \n*/\n#include<bits/stdc++.h>\n/**\n * Definition for singly-linked list.\n * struct ListNode {\n *     int val;\n *     ListNode *next;\n *     ListNode() : val(0), next(nullptr) {}\n *     ListNode(int x) : val(x), next(nullptr) {}\n *     ListNode(int x, ListNode *next) : val(x), next(next) {}\n * };\n */\n\n\n/*\nIn order to solve this problem in only one pass and O(1) extra space, \nhowever, we would need to find a way to both reach the end of the list with one pointer \nand also reach the n'th node from the end simultaneously with a second pointer.\nTo do that, we can simply stagger our two pointers by n nodes by giving the first pointer \n(fast) a head start before starting the second pointer (slow). Doing this will cause \nslow to reach the n'th node from the end at the same time that fast reaches the end.\n*/\n\nclass Solution {\npublic:\n    ListNode* removeNthFromEnd(ListNode* head, int n) {\n        ListNode* slow = head;\n        ListNode* fast = head;\n        if(head == NULL || head->next == NULL)\n            return NULL;\n        while(n--){\n            fast = fast->next;\n        }\n        if(fast == NULL)\n            return slow->next;\n        while(fast->next != NULL){\n            slow = slow->next;\n            fast = fast->next;\n        }\n        ListNode* temp = slow->next;\n        slow->next = slow->next->next;\n        delete temp;\n        return head;\n    }\n};"
  },
  {
    "path": "Linked List/linked_list_remove_nth_node_from_end.py",
    "content": "class Solution:\n    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:\n        dummy_header = ListNode('*')\n        dummy_header.next=head\n        slow = dummy_header\n        fast = dummy_header\n\n        for _ in range(1,n+2):\n            fast=fast.next\n        \n        while(fast!=None):\n            slow = slow.next\n            fast = fast.next\n        \n        slow.next = slow.next.next\n        return dummy_header.next\n"
  },
  {
    "path": "Linked List/linked_list_reverse.cpp",
    "content": "// Reverse a linkedlist iteratively\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nvoid reverse_linked_list(node *&head){\n    node *current = head;\n    node *next = NULL;\n    node *prev = NULL;\n    while(current != NULL){\n        next = current->next;\n        current->next = prev;\n        prev = current;\n        current = next;\n    }\n    head = prev;\n}\nint main(){\n    node *head = NULL;\n    makeLinkedList(head);\n    print_linked_list(head);\n    cout << endl;\n    reverse_linked_list(head);\n    print_linked_list(head); \n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_reverse.js",
    "content": "//Problem statement-Given the head of a singly linked list, reverse the list, and return the reversed list.\n\n// Iteratively \n* @param {ListNode} head\n * @return {ListNode}\n */\nvar reverseList = function(head) {\n  // Handling the edge cases if head node is null or when single node is there \n        if (head === null || head.next === null) {\n            return head;\n        }\n  // Using three pointer approach \n        let prev = null;\n        let curr = head;\n        let fwd = null;\n        while (curr !== null) {\n          // Updatng the value of each of the pointers \n            fwd = curr.next;\n            curr.next = prev;\n            prev = curr;\n            curr = fwd;\n        }\n  // Returning the head of the reversed linked list \n        return prev;    \n};\n// Time complexity - O(N)\n// Space complexity - O(1)\n\n// Recursively \nvar reverseList = function(head) {\n  // Base case- If the head is null or single node is there\n  if (head === null || head.next === null) {\n    return head;\n  }\n\n  // Recursively reverse the remaining list starting from the next node \n  const reversedList = reverseList(head.next);\n\n  // Reversing the links between the current and next node \n  head.next.next = head;\n  head.next = null;\n\n  // Returning the head of the reversed linked list \n  return reversedList; \n};\n// Time complexity - O(N)\n// Space complexity - O(N)\n"
  },
  {
    "path": "Linked List/linked_list_reverse_recursive.cpp",
    "content": "// Reverse a linkedlist recursively\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\n\nnode* recursive_reverse(node *head){\n    if(head->next == NULL || head == NULL){\n        return head;\n    }    \n    node *mini_head = recursive_reverse(head->next);\n    node *current = head;\n    current->next->next = current;\n    current->next = NULL;    \n    return mini_head;\n}\nint main(){\n    node *head = NULL;\n    makeLinkedList(head);\n    print_linked_list(head);\n    cout << endl;\n    head = recursive_reverse(head);\n    print_linked_list(head); \n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_sum_lists.cpp",
    "content": "// sum Lists : you have two numbers represented by a linked list \n// where each node contains a single digit, write a function \n// to add two numbers and returns the sum as linked list\n// Program Author: Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\nclass Node{\n    public:\n        int data;\n        Node *next;\n\n        Node(int d){\n            data = d;\n        }\n};\n\nvoid insert_at_head(Node *&head, int data){\n    Node *new_node = new Node(data);\n    new_node->next = head;\n    head = new_node;\n}\nvoid print_linked_list(Node *head){\n    if(head == NULL)\n        return;\n    cout << head->data << \"->\";\n    print_linked_list(head->next);    \n}\nvoid make_linked_list(Node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_head(head, data);\n        cin >> data;\n    }\n}\nNode* add_lists(Node *l1, Node *l2, int carry){\n    \n    if(l1 == NULL && l2 == NULL && carry == 0)\n        return NULL;\n    int value = carry;\n    \n    if(l1 != NULL)\n        value += l1->data;\n\n    if(l2 != NULL)\n        value += l2->data;\n    \n    Node *result = new Node(value % 10);\n\n    if(l1 != NULL || l2 != NULL)\n        result->next = add_lists(l1 == NULL ? NULL : l1->next, l2 == NULL ? NULL : l2->next, value >= 10 ? 1 : 0);\n    else\n        result->next = NULL;\n\n    return result;\n}\nint main(){\n    Node *head1 = NULL;\n    Node *head2 = NULL;\n    make_linked_list(head1);\n    make_linked_list(head2);\n    print_linked_list(head1);\n    cout << endl;\n    print_linked_list(head2);\n    Node *result = add_lists(head1, head2, 0);\n    cout << endl;\n    print_linked_list(result);\n}"
  },
  {
    "path": "Linked List/linked_list_swap_nodes_in_pair.cpp",
    "content": "// Swap adjacant Nodes in pair Recursive\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    cout << endl;\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nnode* swapNodesInPairRecursive(node *head){\n    if(head == NULL || head->next == NULL){\n        return head;\n    }\n    node *newHead = swapNodesInPairRecursive(head->next->next);\n    node *temp = head->next;\n    temp->next = head;\n    head->next = newHead;\n    return temp;\n}\nint main(){\n    node *head = NULL;\n    makeLinkedList(head);\n    print_linked_list(head);\n    head = swapNodesInPairRecursive(head);\n    print_linked_list(head);\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_swap_nodes_in_pair_iterative.cpp",
    "content": "// Swap adjacant Nodes in Pair Iterative\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    cout << endl;\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\n\nnode* swapNodesInPairIterative(node *head){\n    node *dummy = new node(0);\n    node *prev = dummy;\n    node *curr = head;\n    node *second = NULL;\n    node *nextPair = NULL;\n    while(curr && curr->next){\n        nextPair = curr->next->next;\n        second = curr->next;\n\n        second->next = curr;\n        curr->next = nextPair;\n        prev->next = second;\n\n        prev = curr;\n        curr = nextPair;\n    }\n    return dummy->next;\n\n}  \nint main(){\n    node *head = NULL;\n    makeLinkedList(head);\n    print_linked_list(head);\n    head = swapNodesInPairIterative(head);\n    print_linked_list(head);\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_take_input.cpp",
    "content": "// Finding Midpoint of a LinkedList\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    cout << endl;\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\n\nint main(){\n    node *head = NULL;\n    makeLinkedList(head);\n    print_linked_list(head);\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_take_input_as_array_operator_overloading.cpp",
    "content": "// Take Input in a LinkedList as an array with \"Operator overloading\"\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\n\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nistream& operator>>(istream &is, node *&head){\n    makeLinkedList(head);\n    return is;\n}\nostream& operator<<(ostream &os, node *&head){\n    print_linked_list(head);\n    return os;\n}\nint main(){\n\n   int n;\n   cin >> n;\n   node *arr[n];\n   for(int i = 0; i < n; i++){\n      arr[i] = NULL;\n   }\n   for(int i = 0; i < n; i++){\n       cin >> arr[i];\n   }\n   cout << endl;\n   for(int i = 0; i < n; i++){\n       cout << arr[i] << endl;;\n   }\n    return 0;\n}"
  },
  {
    "path": "Linked List/linked_list_take_input_operator_overloading.cpp",
    "content": "// Take Input in a LinkedList with \"Operator overloading\"\n// Program Author : Abhisek Kumar Gupta \n#include<bits/stdc++.h>\nusing namespace std;\nclass node{\n    public:\n        int data;\n        node* next;\n\n        node(int d){\n            data = d;\n            next = NULL;\n        }\n};\n\nvoid insert_at_tail(node *&head, int data){\n    if(head == NULL){\n        head = new node(data);\n        return;\n    }\n    node *n = new node(data);\n    node * temp = head;\n    while(temp -> next != NULL){\n        temp = temp->next;\n    }\n    temp->next = n;\n}\nvoid print_linked_list(node *head){\n    while(head != NULL){\n        cout << head->data << \"->\";\n        head = head->next;\n    }\n}\nvoid makeLinkedList(node *&head){\n    int data;\n    cin >> data;\n    while(data != -1){\n        insert_at_tail(head, data);\n        cin >> data;\n    }\n}\nistream& operator>>(istream &is, node *&head){\n    makeLinkedList(head);\n    return is;\n}\nostream& operator<<(ostream &os, node *&head){\n    print_linked_list(head);\n    return os;\n}\nint main(){\n    /*node *head = NULL;\n    node *head2 = NULL;\n    cin >> head >> head2;\n    cout << head  << endl << head2;\n    */\n   int n;\n   cin >> n;\n   node *arr[n];\n   for(int i = 0; i < n; i++){\n      arr[i] = NULL;\n   }\n   for(int i = 0; i < n; i++){\n       cin >> arr[i];\n   }\n   cout << endl;\n   for(int i = 0; i < n; i++){\n       cout << arr[i] << endl;;\n   }\n    return 0;\n}"
  },
  {
    "path": "Linked List/recursive and iterative in  singly linkedlist.py",
    "content": "'''\nIssue#528\nDate:16/06/2023\nInput:\nLinked List: Reverse Linked List Recursively and Iteratively in Python \n\nExample 1:\nEnter the values for the linked list (space-separated): 1 2 3 4 5\nChoose the reversal method (iterative or recursive): iterative\n5 4 3 2 1\n\nExplanation:\n*The `create_linked_list()` function:\n   - This function prompts the user to enter values for the linked list, which are expected to be space-separated.\n   - The input values are split into a list of strings using the `split()` method.\n   - The function then iterates over the input values, creating a new `ListNode` object for each value.\n   - The `next` pointers of the nodes are appropriately set to form the linked list.\n   - Finally, the function returns the head of the linked list.\n\n* The `reverse_linked_list_iterative()` function:\n   - This function takes the head of a linked list as input.\n   - It initializes two pointers: `prev` and `current`. `prev` is initially set to `None`, and `current` is set to the head.\n   - The function iterates over the linked list using a while loop.\n   - In each iteration, it stores the next node in a variable called `next_node`.\n   - Then, it updates the `next` pointer of the current node to point to the previous node (`prev`).\n   - The `prev` pointer is updated to the current node, and the `current` pointer is updated to the next node (`next_node`).\n   - This process continues until `current` becomes `None`, which means the end of the original linked list has been reached.\n   - Finally, the function returns the new head of the reversed linked list, which is stored in `prev`.\n\n* The `reverse_linked_list_recursive()` function:\n   - This function is a recursive implementation of reversing a linked list.\n   - It takes the head of a linked list as input.\n   - First, it checks two base cases: if the head is `None` or the head's `next` pointer is `None`. In these cases, it simply returns the head as it is.\n   - If the base cases are not met, it recursively calls itself on the next node (`head.next`) to reverse the remaining sublist.\n   - Once the recursion reaches the last node in the original linked list, it starts updating the `next` pointers to reverse the sublist.\n   - The `next` pointer of the current node (`head`) is set to the previous node (`head.next.next`), effectively reversing the connection.\n   - The `next` pointer of the current node is then set to `None` to complete the reversal.\n   - Finally, the function returns the new head of the reversed linked list.\n\nTime Complexity:\nO(n)(both recursive and iterative method)\nSpace Complexity:\nIterative approach: O(1) space complexity.\nRecursive approach: O(n) space complexity.\n'''\nclass ListNode:\n    def __init__(self, val=0, next=None):\n        self.val = val\n        self.next = next\n\ndef create_linked_list():\n    # Take user input for the linked list values\n    values = input(\"Enter the values for the linked list (space-separated): \").split()\n    \n    # Create the linked list from the input values\n    head = None\n    prev = None\n    \n    for val in values:\n        node = ListNode(int(val))\n        \n        if not head:\n            head = node\n        else:\n            prev.next = node\n        \n        prev = node\n    \n    return head\n\ndef reverse_linked_list_iterative(head):\n    prev = None\n    current = head\n    \n    while current:\n        next_node = current.next\n        current.next = prev\n        prev = current\n        current = next_node\n    \n    return prev\n\ndef reverse_linked_list_recursive(head):\n    if not head or not head.next:\n        return head\n    \n    reversed_list = reverse_linked_list_recursive(head.next)\n    head.next.next = head\n    head.next = None\n    \n    return reversed_list\n\ndef reverse_linked_list(head, method='iterative'):\n    if method == 'iterative':\n        return reverse_linked_list_iterative(head)\n    elif method == 'recursive':\n        return reverse_linked_list_recursive(head)\n    else:\n        raise ValueError('Invalid method specified.')\n\n# Create the linked list based on user input\nhead = create_linked_list()\n\n# Ask the user to choose the reversal method\nmethod = input(\"Choose the reversal method (iterative or recursive): \")\n\n# Reverse the linked list using the chosen method\nreversed_list = reverse_linked_list(head, method=method)\n\n# Traverse the reversed linked list and print the values\ncurrent = reversed_list\nwhile current:\n    print(current.val, end=' ')\n    current = current.next\n\n\n"
  },
  {
    "path": "Linked List/reverse_linked_list.go",
    "content": "// Implementation of reversing a linked list recursively and iteratively\n/*\n\tIn this code, we define a ListNode struct which represents a node in the linked list. We then define two functions:\n\tReverseListIteratively and ReverseListRecursively which reverse the linked list iteratively and recursively, respectively.\n\tIn ReverseListIteratively, we declare two pointers prev and curr, initialize curr to head, and iterate over the\n\tlinked list until curr becomes nil. In each iteration, we store the Next pointer of curr in a temporary variable\n\tnextTemp, point curr.Next to prev, update prev to curr, and update curr to nextTemp. Finally, we return prev,\n\twhich now points to the new head of the reversed linked list.\n\n\tIn ReverseListRecursively, we first check if head is nil or if head.Next is nil, in which case we return head itself.\n\tOtherwise, we call ReverseListRecursively on head.Next, which returns the new head of the reversed linked list.\n\tWe then set head.Next.Next to head and head.Next to nil. Finally, we return the new head.\n\n\tIn the main function, we create a linked list 1 -> 2 -> 3 -> 4 -> 5, reverse it both iteratively and recursively,\n\tand print out the reversed linked lists.\n*/\npackage main\n\nimport \"fmt\"\n\n// ListNode represents a node in the linked list\ntype ListNode struct {\n    Val  int\n    Next *ListNode\n}\n\n// ReverseListIteratively reverses a linked list iteratively\nfunc ReverseListIteratively(head *ListNode) *ListNode {\n    var prev, curr *ListNode\n    curr = head\n\n    for curr != nil {\n        nextTemp := curr.Next\n        curr.Next = prev\n        prev = curr\n        curr = nextTemp\n    }\n\n    return prev\n}\n\n// ReverseListRecursively reverses a linked list recursively\nfunc ReverseListRecursively(head *ListNode) *ListNode {\n    if head == nil || head.Next == nil {\n        return head\n    }\n\n    newHead := ReverseListRecursively(head.Next)\n    head.Next.Next = head\n    head.Next = nil\n\n    return newHead\n}\n\nfunc main() {\n    // Create a linked list: 1 -> 2 -> 3 -> 4 -> 5\n    head := &ListNode{1, &ListNode{2, &ListNode{3, &ListNode{4, &ListNode{5, nil}}}}}\n\n    // Reverse the linked list iteratively\n    reversedListIteratively := ReverseListIteratively(head)\n    fmt.Println(\"Reversed linked list (iteratively):\")\n    for reversedListIteratively != nil {\n        fmt.Printf(\"%d \", reversedListIteratively.Val)\n        reversedListIteratively = reversedListIteratively.Next\n    }\n    fmt.Println()\n\n\thead = &ListNode{1, &ListNode{2, &ListNode{3, &ListNode{4, &ListNode{5, nil}}}}}\n    // Reverse the linked list recursively\n    reversedListRecursively := ReverseListRecursively(head)\n    fmt.Println(\"Reversed linked list (recursively):\")\n    for reversedListRecursively != nil {\n        fmt.Printf(\"%d \", reversedListRecursively.Val)\n        reversedListRecursively = reversedListRecursively.Next\n    }\n    fmt.Println()\n}\n"
  },
  {
    "path": "Linked List/reverse_linked_list.java",
    "content": "/**\n * Definition for singly-linked list.\n * public class ListNode {\n *     int val;\n *     ListNode next;\n *     ListNode() {}\n *     ListNode(int val) { this.val = val; }\n *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }\n * }\n */\n\n/*Explaination of the code which reverses the linked list\n* --> Initially we are given the head of the linked list. The approach used here is that\n* for reversing the linked list we can take the user of three pointers\n*\n* --> These pointers are named as prev, curr, and right. Initially prev points to NULL, curr\n* points to the current node (node of which the pointer has to be reversed) and the right node\n* which always points to the node next to the current\n*\n* --> Idea here is that at each pass we will be reversing the pointer of the current node and\n* move all the pointers forward by one step\n*\n* --> So initially, the current node points to head node, it's pointer is reversed and is made to\n* point to he NULL, since now this first node becomes the last node.\n*\n* --> To move forward, prev is now at the location of current node, current node moves by\n* one step, by making it point to the location where right is pointing now. (Using right pointer\n* since the track of the next node is lost as we have reveresed the pointer).\n*\n* --> Loop stops when the current node becomes null. At the itereation, last node is being pointed\n* by prev, which is now the first node logically, so assign head to prev.\n*\n* --> Example input: 1->2->3->4->5\n*     Output : 5->4->3->2->1\n* */\nclass Solution {\n    public ListNode reverseList(ListNode head) {\n        ListNode prev=null;\n        ListNode curr=head;\n        while(curr!=null){\n            ListNode right=curr.next;\n            curr.next=prev;\n            prev=curr;\n            curr=right;\n        }\n        head=prev;\n        return head;\n    }\n}"
  },
  {
    "path": "Linked List/singly_linked_list.cpp",
    "content": "// Implementation of singly LinkedList\n\n// Author : Mohit Singh\n/*Search for a node in the list\nYou can determine and retrieve a specific node from the front, end, or anywhere in the list.\nThe worst-case​ Time Complexity for retrieving a node from anywhere in the list is O(n).\n\nAdd a node to the list\nYou can add a node at the front, end, or anywhere in the linked list.\nThe worst-case Time Complexities for performing these operations are:\nAdd an item to the front of the list: O(1)\nAdd an item to the end of the list: O(n)\nAdd an item a​nywhere in the list: O(n)\n\nRemove a node from the list\nYou can remove a node from the front, end, or anywhere in the list.\nThe worst-case Time Complexities for performing this operation are:\nRemove an item from the front of the list: O(1)\nRemove an item from the end of the list: O(n)\nRemove an item from anywhere in the list: O(n)\n\nTime complexity :  O(n)\nSpace complexity : O(n)\n*/\n\n#include <iostream>\nusing namespace std;\n\n// Making a node struct containing an int data and a pointer\n// to next node\nstruct Node\n{\n    int data;\n    Node *next;\n\n    // Parameterised constructor with default argument\n    Node(int val = 0) : data(val), next(nullptr) {}\n    // Parameterise constructor\n    Node(int val, Node *tempNext) : data(val), next(tempNext) {}\n};\n\nclass LinkedList\n{\n    // Head pointer\n    Node *head;\n\npublic:\n    // default constructor. Initializing head pointer\n    LinkedList() : head(nullptr)\n    {\n    }\n\n    // inserting elements (At start of the list)\n    void insert(int val)\n    {\n        // make a new node\n        Node *new_node = new Node(val);\n\n        // If list is empty, make the new node, the head\n        if (head == nullptr)\n        {\n            head = new_node;\n        }\n        // else, make the new_node the head and its next, the previous\n        // head\n        else\n        {\n            new_node->next = head;\n            head = new_node;\n        }\n    }\n\n    // loop over the list. return true if element found\n    bool search(int val)\n    {\n        Node *temp = head;\n        while (temp != nullptr)\n        {\n            if (temp->data == val)\n                return true;\n            temp = temp->next;\n        }\n        return false;\n    }\n\n    void remove(int val)\n    {\n        Node *temp = head;\n        // If the head is to be deleted\n        if (temp != nullptr && temp->data == val)\n        {\n            head = temp->next;\n            delete temp;\n            return;\n        }\n        // Else loop over the list and search for the node to delete\n        else\n        {\n            Node *curr = head;\n            while (temp != nullptr && temp->data != val)\n            {\n                // When node is found, delete the node and modify the pointers\n                curr = temp;\n                temp = temp->next;\n            }\n            // If values is not found in the linked list\n            if (!temp)\n            {\n                cout << \"Value not found\" << endl;\n                return;\n            }\n\n            curr->next = temp->next;\n            delete temp;\n        }\n    }\n\n    void display()\n    {\n        Node *temp = head;\n        while (temp != nullptr)\n        {\n            cout << temp->data << \" \";\n            temp = temp->next;\n        }\n        cout << endl;\n    }\n};\n\nint main()\n{\n\n    LinkedList l;\n    // inserting elements\n    l.insert(6);\n    l.insert(9);\n    l.insert(1);\n    l.insert(3);\n    l.insert(7);\n    cout << \"Current Linked List: \";\n    l.display();\n\n    cout << \"Deleting 1: \";\n    l.remove(1);\n    l.display();\n\n    cout << \"Deleting 13: \";\n    l.remove(13);\n\n    cout << \"Searching for 7: \";\n    cout << l.search(7) << endl;\n\n    cout << \"Searching for 13: \";\n    cout << l.search(13) << endl;\n}"
  },
  {
    "path": "Linked List/singly_linked_list.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\n/*\n   insertAtTail (val)\n   insertAtHead (val)\n   deleteAtTail ()\n   deleteAtHead ()\n   getLength ()\n   print ()\n   getAtIdx (idx)\n   replaceAtIdx (val, idx)\n   deleteAtIdx (idx)\n   search (val)\n   toArray ()\n   reverse ()\n*/\n\n// struct for a node type, we use interface{} to allow for any type of value, you could replace this\n// with another value if you want to have more control over the type of value that can be inserted\ntype node struct {\n\tval  interface{}\n\tnext *node\n}\n\n// struct for the linked list type\ntype linkedList struct {\n\thead   *node\n\ttail   *node\n\tlength int\n}\n\n// constructor for a node type\nfunc newNode(val interface{}) *node {\n\treturn &node{val: val, next: nil}\n}\n\n// constructor for a linked list type\nfunc newLinkedList() *linkedList {\n\treturn &linkedList{head: nil, tail: nil, length: 0}\n}\n\n// function for linked lists to check if the linked list is empty\nfunc (l *linkedList) IsEmpty() bool {\n\treturn l.head == nil\n}\n\n// function for linked lists to insert a value at the tail of the linked list\nfunc (l *linkedList) insertAtTail(val interface{}) {\n\tnode := newNode(val)\n\tif l.IsEmpty() {\n\t\tl.head = node\n\t\tl.tail = l.head\n\t\tl.length += 1\n\t\treturn\n\t} else {\n\t\tnode := node\n\t\tl.tail.next = node\n\t\tl.tail = node\n\t\tl.length += 1\n\t}\n}\n\n// function for linked lists to insert a value at the head of the linked list\n\nfunc (l *linkedList) insertAtHead(val interface{}) {\n\t// create a new node\n\tnode := newNode(val)\n\t// check if the list is empty\n\tif l.IsEmpty() {\n\t\t// if it is, set the head and tail to the new node and increase the length\n\t\tl.head = node\n\t\tl.tail = l.head\n\t\tl.length += 1\n\t\treturn\n\t} else {\n\t\t// if it is not, set the new node's next to the current head and set the head to the new node\n\t\tnode.next = l.head\n\t\tl.head = node\n\t\tl.length += 1\n\t}\n\n}\n\nfunc (l *linkedList) print() {\n\tc := l.head\n\tfor c != nil {\n\t\tfmt.Printf(\"%v\", c.val)\n\t\tif c.next == nil {\n\t\t\tfmt.Println()\n\t\t\tbreak\n\t\t}\n\t\tc = c.next\n\n\t\tfmt.Print(\" -> \")\n\t}\n\tfmt.Printf(\"Current Length: %v\\n\", l.length)\n\n}\n\n// function for linked lists to delete a node at the tail of the linked list\nfunc (l *linkedList) deleteAtTail() {\n\tif l.IsEmpty() {\n\t\tfmt.Println(\"Empty List\")\n\t\treturn\n\t}\n\n\tif l.head.next == nil {\n\t\tl.head = nil\n\t\tl.tail = nil\n\t\tl.length -= 1\n\t\treturn\n\t}\n\n\tc := l.head\n\tfor {\n\t\tif c.next.next == nil {\n\t\t\tc.next = nil\n\t\t\tl.tail = c\n\t\t\tl.length -= 1\n\t\t\treturn\n\t\t}\n\t\tc = c.next\n\t}\n\n}\n\n// function for linked lists to delete a node at the head of the linked list\nfunc (l *linkedList) deleteAtHead() {\n\tif l.IsEmpty() {\n\t\tfmt.Println(\"Empty List\")\n\t\treturn\n\t}\n\n\tif l.head.next == nil {\n\t\tl.head = nil\n\t\tl.tail = nil\n\t\tl.length -= 1\n\t\treturn\n\t}\n\n\tl.head = l.head.next\n\tl.length -= 1\n}\n\n// function for linked lists to get the length of the linked list\nfunc (l *linkedList) getLength() int {\n\treturn l.length\n}\n\n// function of a linked list to get the value at a given index\nfunc (l *linkedList) getAtIdx(idx int) (interface{}, error) {\n\tif idx >= l.length {\n\t\treturn nil, errors.New(\"index out of range\")\n\t}\n\n\tc := l.head\n\tfor i := 0; i < idx; i++ {\n\t\tc = c.next\n\t}\n\n\treturn c.val, nil\n}\n\n// function of a linked list to replace the value at a given index\n// index starts at 0\nfunc (l *linkedList) replaceAtIdx(val interface{}, idx int) error {\n\tif idx >= l.length {\n\t\treturn errors.New(\"index out of range\")\n\t}\n\n\tc := l.head\n\tfor i := 0; i < idx; i++ {\n\t\tc = c.next\n\t}\n\n\tc.val = val\n\treturn nil\n}\n\n// function of a linked list to delete the value at a given index\nfunc (l *linkedList) deleteAtIdx(idx int) error {\n\tif idx >= l.length {\n\t\treturn errors.New(\"index out of range\")\n\t}\n\n\tc := l.head\n\tfor i := 0; i < idx-1; i++ {\n\t\tc = c.next\n\t}\n\n\tc.next = c.next.next\n\tl.length -= 1\n\treturn nil\n}\n\n// function to find the index of a given value\n// returns -1 and an error if the value is not found\nfunc (l *linkedList) search(val interface{}) (int, error) {\n\tc := l.head\n\tfor i := 0; i < l.length; i++ {\n\t\tif c.val == val {\n\t\t\treturn i, nil\n\t\t}\n\t\tc = c.next\n\t}\n\n\treturn -1, errors.New(\"value not found\")\n}\n\n// function to convert a linked list to an array\nfunc (l *linkedList) toArray() []interface{} {\n\tarr := make([]interface{}, l.length)\n\tc := l.head\n\tfor i := 0; i < l.length; i++ {\n\t\tarr[i] = c.val\n\t\tc = c.next\n\t}\n\n\treturn arr\n}\n\n// function to reverse the linked list\n// This is a recursive implementation to show something different\nfunc (l *linkedList) reverse() error {\n\tif l.IsEmpty() {\n\t\treturn errors.New(\"Empty List\")\n\t}\n\tl.head = reverseListRecursive(l.head)\n\treturn nil\n}\n\n// recursive function to reverse a linked list recursively\nfunc reverseListRecursive(head *node) *node {\n\tif head == nil || head.next == nil {\n\t\treturn head\n\t}\n\n\trest := reverseListRecursive(head.next)\n\thead.next.next = head\n\thead.next = nil\n\n\treturn rest\n}\n\n// example of a linked list\nfunc main() {\n\tlist := newLinkedList()\n\n\tlist.insertAtHead(1)\n\tlist.insertAtTail(2)\n\tlist.insertAtTail(3)\n\tlist.insertAtTail(4)\n\tlist.insertAtTail(5)\n\tlist.insertAtTail(6)\n\tlist.insertAtTail(7)\n\tlist.insertAtTail(8)\n\tlist.insertAtTail(9)\n\tlist.insertAtTail(10)\n\tlist.insertAtTail(11)\n\tlist.print()\n\n\tlist.deleteAtTail()\n\tlist.print()\n\n\terr := list.replaceAtIdx(9000, 4)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t}\n\tlist.print()\n\n\ti, err := list.search(9000)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t} else {\n\t\tfmt.Println(i)\n\t}\n\n\terr = list.reverse()\n\tif err != nil {\n\t\tfmt.Println(err)\n\t}\n\n\tlist.print()\n\tidx, err := list.search(3)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t} else {\n\t\tfmt.Println(idx)\n\t}\n\tfmt.Println(list.toArray())\n\n}\n"
  },
  {
    "path": "Linked List/singly_linked_list.java",
    "content": "// Linked list: Implement Singly linked list in Java #982\n\n/*\nAPPROACH :Node Class: The Node class is defined to represent a single node in the linked list. It has two instance variables: data to store the value and next to store the reference to the next node.\n\nInsertion at the Start: The insertStart method allows inserting a new node at the beginning of the linked list. It creates a new node with the given data value and sets its next reference to the current head. Then, it updates the head to point to the newly inserted node.\n\nDeletion from the Start: The delete method removes the first node from the linked list. It checks if the head is null, indicating an empty list. If not, it updates the head to point to the next node, effectively removing the first node.\n\nDisplay: The display method is used to print the elements of the linked list. It starts from the head node and iterates through the list by moving to the next node until the current node becomes null. During each iteration, it prints the data value of the current node.\n\nMain Method: The main method demonstrates the usage of the linked list implementation. It creates an empty list by initializing the head to null. It then performs several insertions using the insertStart method to add nodes at the beginning of the list. After that, it calls the display method to print the elements of the list. Next, it performs several deletions using the delete method to remove nodes from the beginning of the list. Finally, it calls the display method again to print the updated list.\n*/\n\nimport java.lang.*;\n\n// Node Class\nclass Node {\n    int data;\n    Node next;\n\n    Node(int x) // parameterized constructor\n    {\n        data = x;\n        next = null;\n    }\n}\n\nclass Main\n{\n    static Node insertStart(Node head, int data)\n    {\n        // Creating newNode memory & assigning data value\n        Node newNode = new Node(data);\n\n        // assigning this newNode's next as current head node\n        newNode.next = head;\n        // re-assigning head to this newNode\n        head = newNode;\n\n        return head;\n    }\n\n    public static Node delete(Node head)\n    {\n        if (head == null){\n            System.out.println(\"List is empty, not possible to delete\");\n            return head;\n        }\n\n        System.out.println(\"Deleted: \" + head.data);\n        // move head to next node\n        head = head.next;\n\n        return head;\n    }\n\n    static void display(Node node) {\n\n        //as linked list will end when Node is Null\n        while (node != null) {\n            System.out.print(node.data + \" \");\n            node = node.next;\n        }\n        System.out.println(\"\");\n    }\n\n    public static void main(String args[])\n    {\n        Node head = null;\n        head = insertStart(head,6);\n        head = insertStart(head,5);\n        head = insertStart(head,4);\n        head = insertStart(head,3);\n        head = insertStart(head,2);\n        head = insertStart(head,1);\n\n        display(head);\n\n        head = delete(head);\n        head = delete(head);\n        head = delete(head);\n\n        display(head);\n\n\n    }\n}\n\n/*\nthe space complexity is O(n), and the time complexity for each operation is either O(1) or O(n), depending on the specific operation being performed.\n*/\n"
  },
  {
    "path": "Linked List/singly_linked_list.py",
    "content": "'''\nThis is an implementation of a singly linked list in Python with a Node class and a LinkedList class. The Node class represents each element of the linked list and the LinkedList class has methods to manipulate the list, including append, prepend, delete_node, and print_list.\n'''\n\nclass Node:\n    def __init__(self, data):\n        self.data = data\n        self.next = None  # The next node in the list\n\nclass LinkedList:\n    def __init__(self):\n        self.head = None  # The first node in the list\n\n    def append(self, data):\n        new_node = Node(data)\n        if not self.head:  # If the list is empty, set the new node as the head\n            self.head = new_node\n            return\n        curr_node = self.head\n        while curr_node.next:  # Traverse to the last node in the list\n            curr_node = curr_node.next\n        curr_node.next = new_node  # Set the next node of the last node to the new node\n\n    def prepend(self, data):\n        new_node = Node(data)\n        new_node.next = self.head  # Set the next node of the new node to the current head\n        self.head = new_node  # Set the new node as the new head\n\n    def delete_node(self, data):\n        if not self.head:  # If the list is empty, do nothing\n            return\n        if self.head.data == data:  # If the head is the node to delete, set the next node as the new head\n            self.head = self.head.next\n            return\n        curr_node = self.head\n        while curr_node.next:  # Traverse the list until the last node\n            if curr_node.next.data == data:  # If the next node is the node to delete, set the next node of the current node to the node after the next node\n                curr_node.next = curr_node.next.next\n                return\n            curr_node = curr_node.next\n\n    def print_list(self):\n        curr_node = self.head\n        while curr_node:  # Traverse the list and print each node's data\n            print(curr_node.data)\n            curr_node = curr_node.next\n\n"
  },
  {
    "path": "Linked List/sll.go",
    "content": "/*\n\tThe linked list consists of a series of structures called nodes. We can think of each node as a record. The first part\n\tof the record is a field that stores the data, and the second part of the record is a field that stores a pointer to a\n\tnode. So, each node contains two fields: a data field and a next field which is a pointer used to link one node to\n\tthe next node. Generally, \"linked list\" means a singly linked list. This list consists of a number of nodes in which\n\teach node has a pointer to the following element. The link of the last node in the list is nil, which indicates\n\tthe end of the list.\n\n\tBasic Operations on a List\n\t\t--> Traversing the list\n\t\t--> Inserting an item in the list\n\t\t--> Deleting an item from the list\n*/\npackage main\n\nimport \"fmt\"\n\n// Linked list node contains a pointer to the next node as well as data.\n// The generic behavior is achieved by marking the data field as type interface\ntype ListNode struct { // define a ListNode in a sll\n\tdata interface{} // datum\n\tnext *ListNode // pointer to next ListNode\n}\n\ntype LinkedList struct {\n\thead *ListNode\n\tsize int\n}\n\nfunc (ll *LinkedList) Display() error {\n\tif ll.head == nil {\n\t\treturn fmt.Errorf(\"Display: List is empty\")\n\t}\n\tcurrent := ll.head\n\tfor current != nil {\n\t\tfmt.Printf(\"%v->\", current.data)\n\t\tcurrent = current.next\n\t}\n\tfmt.Println()\n\treturn nil\n\t\n}\n// Length: returns the linked list size\nfunc (ll *LinkedList) Length() int {\n\tsize := 0\n\tcurrent := ll.head\n\tfor current != nil {\n\t\tsize++\n\t\tcurrent = current.next\n\t}\n\treturn size\n}\n// InsertAtBeginning: Update the next pointer of new node to point to the current head\n// Update the head pointer to point to the new node\nfunc (ll *LinkedList) InsertAtBeginning(data interface{}) {\n\tnode := &ListNode{\n\t\tdata: data,\n\t}\n\t// if there is no head then set new node as head\n\tif ll.head == nil {\n\t\tll.head = node\n\t} else {\n\t\tnode.next = ll.head\n\t\tll.head = node\n\t}\n\tll.size++\n\treturn\n}\n// InsertAtEnd: We need to modify two next pointers, new node next pointer points to nil\n// Last nodes next pointer points to the new node\nfunc (ll *LinkedList) InsertAtEnd(data interface{}) {\n\tnode := &ListNode{\n\t\tdata: data,\n\t}\n\tif ll.head == nil {\n\t\tll.head = node\n\t} else {\n\t\tcurrent := ll.head\n\t\tfor current.next != nil {\n\t\t\tcurrent = current.next\n\t\t}\n\t\tcurrent.next = node\n\t}\n\tll.size++\n\treturn\n}\n// InsertAtAnyPos: To add an element at pos 3 we stop at pos 2, That means we traverse \n// 2 nodes and insert the new node.\n// Prev will point to the predecessor of new node and next pointer of new node \n// points to the next node of the prev node\nfunc (ll *LinkedList) InsertAtAnyPos(data interface{}, position int) error {\n\t// base case check position valid or not\n\tif position < 1 || position > ll.size + 1 {\n\t\treturn fmt.Errorf(\"insert: Error out of bounds\")\n\t}\n\tnewNode := &ListNode{data, nil}\n\tvar prev, current *ListNode\n\tprev = nil\n\tcurrent = ll.head\n\tfor position > 1 {\n\t\tprev = current\n\t\tcurrent = current.next\n\t\tposition--\n\t}\n\tif prev != nil {\n\t\tprev.next = newNode\n\t\tnewNode.next = current\n\t} else {\n\t\tnewNode.next = current\n\t\tll.head = newNode\n\t}\n\tll.size++\n\treturn nil\n}\n// DeleteFirst: create a temporaty node which will point to the same node as that of head\n// and move the head nodes pointer to the next node and dispose temporary node\n// Time Complexity: O(1), for scanning the list of size. Space Complexity: O(1).\nfunc (ll *LinkedList) DeleteFirst() (interface{}, error) {\n\tif ll.head == nil {\n\t\treturn nil, fmt.Errorf(\"deleteFront: List is empty\")\n\t}\n\tdata := ll.head.data\n\tll.head = ll.head.next\n\tll.size--\n\treturn data, nil\n}\n// DeleteLast: traverse the list, while traversingmaintain the previous node address.\n// by the time we reach end of list we have two pointers, one pointing to the tail node and\n// other pointing to the node before tail node\n// Time Complexity: O(n), for scanning the list of size 􀝊. Space Complexity: O(1).\nfunc (ll *LinkedList) DeleteLast() (interface{}, error) {\n\tif ll.head == nil {\n\t\treturn nil, fmt.Errorf(\"deleteLast: List is empty\")\n\t}\n\tvar prev *ListNode\n\tcurrent := ll.head\n\t// last and second last node\n\tfor current.next != nil {\n\t\tprev = current\n\t\tcurrent = current.next\n\t}\n\tif prev != nil {\n\t\tprev.next = nil\n\t} else {\n\t\tll.head = nil\n\t}\n\tll.size--\n\treturn current.data, nil\n}\n// DeleteFromAnyPos: maintain the previous node while traversing the list.\n// Once we find the node to be deleted, \n// change the previous node's next pointer to the next pointer of the node to be deleted\n// Time Complexity: O(n). In the worst case, we may need to delete the node from the end of the linked list.\n// Space Complexity: O(1).\nfunc (ll *LinkedList) DeleteFromAnyPos(position int) (interface{}, error) {\n\tif position < 1 || position > ll.size + 1 {\n\t\treturn nil, fmt.Errorf(\"insert: Index out of bounds\")\n\t}\n\tvar prev, current *ListNode\n\tprev = nil\n\tcurrent = ll.head\n\tpos := 0\n\t// delete head and set head as next node\n\tif position == 1 {\n\t\tll.head = ll.head.next\n\t} else { // maintain two nodes\n\t\tfor pos != position - 1 {\n\t\t\tpos = pos + 1\n\t\t\tprev = current\n\t\t\tcurrent = current.next\n\t\t}\n\t\tif current != nil {\n\t\t\tprev.next = current.next\n\t\t}\n\t}\n\tll.size--\n\treturn current.data, nil\n}"
  },
  {
    "path": "Linked List/sort_linked_list.cpp",
    "content": "/*\n    Given the head of a linked list, return the list after sorting it in ascending order.\n*/\n\n/**\n * Definition for singly-linked list.\n * struct ListNode {\n *     int val;\n *     ListNode *next;\n *     ListNode() : val(0), next(nullptr) {}\n *     ListNode(int x) : val(x), next(nullptr) {}\n *     ListNode(int x, ListNode *next) : val(x), next(next) {}\n * };\n */\nclass Solution {\npublic:\n    ListNode* compute_midpoint(ListNode* head){\n        if(head == NULL || head->next == NULL){\n            return head;\n        }\n        ListNode* slow = head;\n        ListNode* fast = head->next;\n        while(fast != NULL && fast->next != NULL){\n            slow = slow->next;\n            fast = fast->next->next;\n        }\n        return slow;\n    }\n    ListNode* merge_two_lists(ListNode* A, ListNode* B){\n        if(A == NULL)\n            return B;\n        else if(B == NULL)\n            return A;\n        ListNode* C = NULL;\n        if(A->val < B->val){\n            C = A;\n            C->next = merge_two_lists(A->next, B);\n        }\n        else{\n            C = B;\n            C->next = merge_two_lists(A, B->next);\n        }\n        return C;\n    }\n    ListNode* sortList(ListNode* head) {\n        if(head == NULL || head->next == NULL)\n            return head;\n        ListNode* mid = compute_midpoint(head);\n        ListNode* A = head; \n        ListNode* B = mid->next;\n        mid->next = NULL;\n        A = sortList(A);\n        B = sortList(B);\n        \n        ListNode* C = merge_two_lists(A, B);\n        return C;\n    }\n};"
  },
  {
    "path": "Math/Basic_operations.py",
    "content": "def divide(dividend, divisor):\n    if divisor == 0:\n        raise ZeroDivisionError(\"Division by zero\")\n    if dividend == 0:\n        return 0\n\n    negative = (dividend < 0) ^ (divisor < 0)\n    dividend = abs(dividend)\n    divisor = abs(divisor)\n\n    quotient = 0\n    while dividend >= divisor:\n        dividend -= divisor\n        quotient += 1\n\n    if negative:\n        quotient = -quotient\n\n    INT_MAX = 2**31 - 1\n    INT_MIN = -2**31\n    if quotient > INT_MAX:\n        return INT_MAX\n    elif quotient < INT_MIN:\n        return INT_MIN\n    else:\n        return quotient\n\n# Take user input for dividend and divisor\ndividend = int(input(\"Enter the dividend: \"))\ndivisor = int(input(\"Enter the divisor: \"))\n\n# Perform the division and print the result\nresult = divide(dividend, divisor)\nprint(f\"The result of {dividend} divided by {divisor} is: {result}\")\n"
  },
  {
    "path": "Math/Count.go",
    "content": "class Solution {\npublic:\n    int countNumbersWithUniqueDigits(int n) {\n        if (n == 0) {\n            return 1; // There's only one number with 0 digits, which is 0.\n        }\n        \n        int result = 10; // For n = 1, there are 10 numbers with unique digits (0-9).\n        int uniqueDigits = 9;\n        int availableDigits = 9;\n        \n        for (int i = 2; i <= n && availableDigits > 0; i++) {\n            uniqueDigits *= availableDigits;\n            result += uniqueDigits;\n            availableDigits--;\n        }\n        \n        return result;\n    }\n};\n"
  },
  {
    "path": "Math/Factorial.cpp",
    "content": "/*\nExplanation:\n- The `factorial` function takes an integer `num` as input and calculates its factorial. The factorial of a non-negative integer N is the product of all positive integers less than or equal to N.\n- In the function, we have a base case that handles the special case when `num` is 0. The factorial of 0 is defined as 1, so we return 1 for `num` equal to 0.\n- For non-zero `num`, we use recursion to calculate the factorial. We call the `factorial` function with `num - 1`, and then multiply the result by `num`.\n- The recursion continues until we reach the base case when `num` becomes 0, and the recursive calls start to return their values and calculate the final factorial.\n\nTime Complexity: The time complexity of the `factorial` function is O(N), where N is the value of the input number. This is because the function makes N recursive calls to calculate the factorial.\n  \nSpace Complexity: The space complexity is O(N) due to the recursion stack space used during the recursive calls. Each recursive call adds a new stack frame, and in the worst case, there will be N stack frames corresponding to the N recursive calls.\n\nSample Input:\nNumber: 5\n\nSample Output:\nFactorial of 5 is 120\n*/\n\n#include <iostream>\n\n// Function to calculate factorial\nunsigned long long factorial(int num) {\n    // Base case: factorial of 0 is 1\n    if (num == 0) {\n        return 1;\n    }\n\n    // Recursive case: calculate factorial using recursion\n    return num * factorial(num - 1);\n}\n\nint main() {\n    // Sample input\n    int num = 5;\n\n    // Calculate the factorial of the number\n    unsigned long long result = factorial(num);\n\n    // Print the result\n    std::cout << \"Factorial of \" << num << \" is \" << result << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Math/Factorial.go",
    "content": "/*\nApproach and Explanation:\nThe factorial of a non-negative integer `n` is given by the product of all positive integers less than or equal to `n`. The factorial function is typically implemented using recursion. In this implementation, we check the base case where the input `n` is less than or equal to 1, and in that case, we return 1. Otherwise, we recursively call the factorial function with `n-1` and multiply it with `n`. This process continues until the base case is reached.\n\nThe code prompts the user to enter a number, reads the input, and then calls the `factorial` function to calculate the factorial of the entered number. The result is then printed on the console.\n\nTime and Space Complexity:\nThe time complexity of this implementation is O(n) because the recursive function is called once for each integer from `n` to 1.\n\nThe space complexity is O(n) as well since each recursive call adds a new frame to the call stack.\n\nSample Input and Output:\nEnter a number: 5\nThe factorial of 5 is: 120\n*/\n\n\npackage main\n\nimport (\n\t\"fmt\"\n)\n\n// Function to calculate the factorial of a number\nfunc factorial(n int) int {\n\tif n <= 1 {\n\t\treturn 1\n\t}\n\treturn n * factorial(n-1)\n}\n\nfunc main() {\n\t// Getting user input\n\tvar number int\n\tfmt.Print(\"Enter a number: \")\n\tfmt.Scanln(&number)\n\n\t// Calculating and printing the factorial\n\tresult := factorial(number)\n\tfmt.Printf(\"The factorial of %d is: %d\\n\", number, result)\n}\n\n\n"
  },
  {
    "path": "Math/Factorial.java",
    "content": "/*\nWhat is a factorial of a number?\nThe factorial of a non-negative integer n is the product of all positive integers less than or equal to n. It is denoted by n!. For example, the factorial of 5 is 5! = 5 x 4 x 3 x 2 x 1 = 120.\n\nApproach:\nThe recursive approach is used to calculate the factorial. The function `factorial()` takes an integer `n` as input. In each recursive call, we check if `n` is either 0 or 1 (base case), and if so, we return 1. Otherwise, we multiply `n` with the factorial of `n-1` and return the result.\n\nTime Complexity: O(n)\nThe time complexity of this algorithm is O(n) because the recursion depth is equal to n, and in each recursion, we perform a constant-time operation.\n\nSpace Complexity: O(n)\nThe space complexity is O(n) because, in the worst-case scenario, the recursion depth can reach up to n. So, n frames will be added to the call stack.\n\nSample Input: 5\nSample Output: Factorial of 5 is: 120\n\n*/\n\npublic class Factorial {\n  // Recursive function to calculate the factorial\n  public static int factorial(int n) {\n    // Base case: if n is 0 or 1, the factorial is always 1\n    if (n == 0 || n == 1) {\n      return 1;\n    }\n    \n    // Recursive case: multiply n with factorial of (n-1)\n    return n * factorial(n - 1);\n  }\n\n  public static void main(String[] args) {\n    int number = 5; // Sample input: calculate factorial of 5\n    int result = factorial(number);\n    System.out.println(\"Factorial of \" + number + \" is: \" + result);\n  }\n}\n\n"
  },
  {
    "path": "Math/Factorial.py",
    "content": "'''\nApproach:\nWe will take the number as input from the user and calculate its factorial.\nTo calculate the factorial, we will start from 1 and multiply it with all the numbers from 1 to n.\nFinally, we will return the factorial.\n\nTime Complexity: O(n)\nSpace Complexity: O(1)\n\nSample Input: 5\nSample Output: Factorial of 5 is 120\n'''\n\n# Initializing the factorial to 1\nfact = 1\ndef factorial(num):\n  # If the number is 0 or 1, then the factorial is 1.\n  if num == 0 or num == 1:\n  return 1\n  # Calculating factorial by multiplying every number from 1 to num\n  for i in range(1, num+1):\n    fact *= i\n  return fact\n\n#Taking input from user\nnum = int(input(\"Enter a number: \"))\n#Calculating and printing the factorial of the number\nprint(\"Factorial of\", num, \"is\", factorial(num))\n\n\n"
  },
  {
    "path": "Math/Hamming_distance.py",
    "content": "'''\n    The Hamming distance between two integers is the number of positions at which the corresponding bits are different.\n\n    Given two integers x and y, return the Hamming distance between them.\n\n    Example 1:\n    Input: x = 1, y = 4\n    Output: 2\n    Explanation:\n    1   (0 0 0 1)\n    4   (0 1 0 0)\n        ↑   ↑\n    The above arrows point to positions where the corresponding bits are different.\n    \n    Example 2:\n    Input: x = 3, y = 1\n    Output: 1\n\n    Constraints:\n    0 <= x, y <= 231 - 1\n'''\nclass Solution:\n    def totalHammingDistance(self, nums: List[int]) -> int:\n        '''By using bit manipulation, as all the array elements are 32-bit array elements, we calculate all the number of set bits and unset bits as we need to consider the permutations, we take setbits*unsetbits.'''\n        hamming_dist,n = 0,len(nums)\n        for i in range(32):\n            count = 0\n            for element in nums:\n                #Right shifting the element by the index and performing &1 lets us know if a bit is set or not\n                if((element>>i)&1):\n                    count+=1\n            #Adding all the combinations where there are set and unset bits.\n            hamming_dist+=count*(n-count)\n        return hamming_dist"
  },
  {
    "path": "Math/Hammingdistance.cpp",
    "content": "#include <vector>\n\nclass Solution {\npublic:\n    int totalHammingDistance(std::vector<int>& nums) {\n        // Get the number of elements in the input vector\n        int n = nums.size();\n        // Initialize the variable to store the total Hamming distance\n        int ans = 0;\n        \n        // Iterate through each bit position (from 0 to 31)\n        for (int i = 0; i < 32; i++) {\n            // Initialize a variable to count the number of set bits at the current bit position\n            int count = 0;\n            \n            // Iterate through all elements in the vector\n            for (int k = 0; k < n; k++) {\n                // Count the number of set bits at the current bit position for each element\n                count += (nums[k] >> i) & 1;\n            }\n            \n            // Update the total Hamming distance by adding the product of set bits and unset bits\n            ans += count * (n - count);\n        }\n        \n        // Return the total Hamming distance\n        return ans;\n    }\n};\n\n/*\nThis program defines a Solution class with a totalHammingDistance method that calculates the total Hamming distance for the input vector nums. The outer loop iterates over each bit position (from 0 to 31), and the inner loop counts the number of set bits at that bit position for all elements in the vector. It then updates the ans variable by adding the product of the count of set bits and the count of unset bits at that position.\n\nThis code efficiently calculates the total Hamming distance for a vector of integers by considering each bit position separately. */\n"
  },
  {
    "path": "Math/K_closest.cpp",
    "content": "/*\n Author: SUYASH SINGH\n\nProblem statement:-Find K Closest Elements\nGiven a sorted integer array arr, two integers k and x, return the k closest integers to x in the array. The result should also be sorted in ascending order.\n\nAn integer a is closer to x than an integer b if:\n\n|a - x| < |b - x|, or\n|a - x| == |b - x| and a < b\nExplaination:\n\nInput: points = [[1,3],[-2,2]], k = 1\nOutput: [[-2,2]]\nExplanation:\nThe distance between (1, 3) and the origin is sqrt(10).\nThe distance between (-2, 2) and the origin is sqrt(8).\nSince sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.\nWe only want the closest k = 1 points from the origin, so the answer is just [[-2,2]].\nExample 2:\nInput: points = [[3,3],[5,-1],[-2,4]], k = 2\nOutput: [[3,3],[-2,4]]\nExplanation: The answer [[-2,4],[3,3]] would also be accepted.\n*/\n\n#include <iostream>\n#include <vector>\n#include <queue>\n#include <cmath>\n\nusing namespace std;\n\nclass Solution {\npublic:\n    vector<vector<int>> kClosest(vector<vector<int>>& points, int k) {\n        // Answer vector\n        vector<vector<int>> result(k);\n        // Max heap storage initialization\n        priority_queue<vector<int>> maxHeap;\n        // Construction of max heap\n        for (auto& p : points) {\n            int x = p[0], y = p[1];\n             // Calculate the squared distance from the origin using the formula x^2 + y^2\n            // Store the distance along with the coordinates (x, y) in the maxHeap\n            maxHeap.push({x * x + y * y, x, y});\n            // If the size of the maxHeap exceeds k, remove the point with the maximum distance\n            if (maxHeap.size() > k) {\n                maxHeap.pop();\n            }\n        }\n        // Extract the k closest points from the maxHeap and store them in the result vector\n        for (int i = k - 1; i >= 0; --i) {\n            vector<int> top = maxHeap.top();\n            maxHeap.pop();\n            result[i] = {top[1], top[2]};\n        }\n        \n        // Return the result vector containing the k closest points\n        \n        return result;\n    }\n};\n\nint main() {\n    vector<vector<int>> points = {{1, 3}, {-2, 2}, {5, -1}, {0, 0}, {3, 4}};\n    int k = 3;\n    \n    Solution solution;\n    vector<vector<int>> closestPoints = solution.kClosest(points, k);\n    \n    cout << \"The \" << k << \" closest points to the origin are:\\n\";\n    for (const auto& point : closestPoints) {\n        cout << \"(\" << point[0] << \", \" << point[1] << \")\\n\";\n    }\n    \n    return 0;\n}/*\nTime Complexity:\n\nConstructing the maxHeap:  the overall time complexity is O(N log K).\nExtracting the k closest points: O(K log K). We extract the top element from the maxHeap k times, each operation taking O(log K) time. Hence, the time complexity is O(K log K).\nTherefore, the overall time complexity of the solution is O(N log K), where N is the number of points and K is the value of k.\n\nSpace Complexity:\n\nThe maxHeap stores at most k elements, so the space complexity for the maxHeap is O(K).\nThe result vector stores k closest points, resulting in O(K) space.\nApart from these, the solution uses a constant amount of space for variables and temporary storage.*/\n"
  },
  {
    "path": "Math/K_closest_points_to_origin.java",
    "content": "/**\n   Time Complexity: O(nlog(n)), Space Complexity: O(n)\n\n   Given an array of points where points[i] = [xi, yi] represents a point on the X-Y plane and an integer k, return the k closest points to the origin (0, 0).\n   The distance between two points on the X-Y plane is the Euclidean distance (i.e., √(x1 - x2)^2 + (y1 - y2)^2).\n   You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in).\n   \n   Example 1:\n   Input: points = [[1,3],[-2,2]], k = 1\n   Output: [[-2,2]] \n   \n   Explanation:\n   The distance between (1, 3) and the origin is sqrt(10).\n   The distance between (-2, 2) and the origin is sqrt(8).\n   Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.\n   We only want the closest k = 1 points from the origin, so the answer is just [[-2,2]].\n   \n\n   Example 2:\n   Input: points = [[3,3],[5,-1],[-2,4]], k = 2\n   Output: [[3,3],[-2,4]]\n\n   Explanation: The answer [[-2,4],[3,3]] would also be accepted.\n\n**/\n\n\nclass Solution {\n    public int[][] kClosest(int[][] points, int k) {\n        \n\n\t  /**\n            The solution is very simple, for each point(x, y) we calculate the euclidean distance between \n            (x, y) and the origin point (0, 0), then add all the distances in Priority Queue (Minimum Heap).\n            The priority queue will sort them in increasing order. \n\n\n            NOTE that we need to return the points not the distances, that's why we make Priority Queue of Pair<Double, Pair<Integer, Integer>>. \n        **/\n\n        PriorityQueue<Pair<Double, Pair<Integer, Integer>>> pq =\n            new PriorityQueue<>(new SortBySmallerDistanceComparator());\n        \n        for (int i = 0; i < points.length; ++i)\n        {\n            int x = points[i][0], y = points[i][1];\n            double distance = Math.sqrt(x * x + y * y);\n            pq.add(new Pair(distance, new Pair(x, y)));\n        }\n        \n        int [][]closestK = new int[k][2];\n        \n        for(int i = 0; i < k; ++i)\n        {\n            closestK[i][0] = pq.peek().getValue().getKey();\n            closestK[i][1] = pq.peek().getValue().getValue();\n            pq.poll();\n\n        }\n        \n        return closestK;\n    \n    }\n\n\n    /*\n      Compartor to sort the points based on the distance (smaller).\n    */\n    \n    class SortBySmallerDistanceComparator implements Comparator<Pair<Double, Pair<Integer, Integer>>>\n    {\n        @Override\n        public int compare(Pair<Double, Pair<Integer, Integer>> a, \n                           Pair<Double, Pair<Integer, Integer>> b) {\n                   return (a.getKey() - b.getKey()) <= 0 ? -1 : 1;\n       }\n    }\n    \n}\n"
  },
  {
    "path": "Math/K_closest_points_to_origin.py",
    "content": "'''\n    Given an array of points where points[i] = [xi, yi] represents a point on the X-Y plane and an integer k, return the k closest points to the origin (0, 0).\n\n    The distance between two points on the X-Y plane is the Euclidean distance (i.e., √(x1 - x2)2 + (y1 - y2)2).\n\n    You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in).\n\n    Example 1:\n    Input: points = [[1,3],[-2,2]], k = 1\n    Output: [[-2,2]]\n    Explanation:\n    The distance between (1, 3) and the origin is sqrt(10).\n    The distance between (-2, 2) and the origin is sqrt(8).\n    Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.\n    We only want the closest k = 1 points from the origin, so the answer is just [[-2,2]].\n    \n    Example 2:\n    Input: points = [[3,3],[5,-1],[-2,4]], k = 2\n    Output: [[3,3],[-2,4]]\n    Explanation: The answer [[-2,4],[3,3]] would also be accepted.\n    \n    Constraints:\n    1 <= k <= points.length <= 104\n    -104 < xi, yi < 104\n'''\nimport math\nclass Solution:\n    def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:\n        distance_arr=[]\n        #calculating the distance from center\n        for i in points:\n            distance_arr.append(math.sqrt(pow(i[0],2)+pow(i[1],2)))\n        #Mapping the values of distance and point\n        #Also considering the collision if two points have same distance from origin\n        hash_map={}\n        for i in range(len(points)):\n            if(distance_arr[i] in hash_map):\n                hash_map[distance_arr[i]].append(points[i])\n            else:\n                hash_map[distance_arr[i]] = [points[i]]\n\n        #sorting distances\n        distance_arr.sort()\n\n        #Retrieving the values in the order of distance from distance_arr\n        final_arr,count = [],0\n        for i in range(len(points)):\n            for j in hash_map[distance_arr[i]]:\n                final_arr.append(j)\n                count+=1\n            if(count>=k):\n                break\n        return final_arr"
  },
  {
    "path": "Math/Number_of_Substrings_With_Only_1s.cpp",
    "content": "/*\nGiven a binary string s, return the number of substrings with all characters 1's. Since the answer may be too large, return it modulo 109 + 7.\n\n \n\nExample 1:\n\nInput: s = \"0110111\"\nOutput: 9\nExplanation: There are 9 substring in total with only 1's characters.\n\"1\" -> 5 times.\n\"11\" -> 3 times.\n\"111\" -> 1 time.\nExample 2:\n\nInput: s = \"101\"\nOutput: 2\nExplanation: Substring \"1\" is shown 2 times in s.\nExample 3:\n\nInput: s = \"111111\"\nOutput: 21\nExplanation: Each substring contains only 1's characters.\n \n\nConstraints:\n\n1 <= s.length <= 105\ns[i] is either '0' or '1'.\n\nApproach: First we count continuos number of ones and if we have n continuos 1's than total substring = (n*(n+1))/2. Using this we can count all substring and add them and return.\nusing this property (a*b)%mod = ((a%mod)*(b%mod))%mod\n*/\nclass Solution {\npublic:\n    int mod = 1000000007;\n    int numSub(string s) {\n        long long cnt = 0,ans=0;\n        for(int i = 0;i<s.size();i++){\n            if(s[i]=='1'){\n                cnt++;\n            }else{\n                ans = (ans+((cnt%mod)*(cnt+1)%mod)%mod/2)%mod;\n                cnt=0;\n            }\n        }\n        ans = (ans+((cnt%mod)*(cnt+1)%mod)/2)%mod;\n        return (int)(ans);\n    }\n};\n"
  },
  {
    "path": "Math/PowXn.go",
    "content": "/* Implement pow(x, n), which calculates x raised to the power n (i.e., xn). in Go\n\n--- Recursion Approach ---\n\nExample 1:\nInput: x = 2, n = 10\nOutput: 1024\n\nExample 2:\nInput: x = 2.10000, n = 3\nOutput: 9.26100\n\nExample 3:\nInput: x = 2.00000, n = -2\nOutput: 0.25000\n\nExplanation: 2^(-2) = 1/(2^2) = 1/4 = 0.25\n \n*/\n\npackage main\nimport \"fmt\"\n\nfunc Pow(x float64, n int) float64 {\n    switch {\n        case n == 0:  return 1\n        case n == 1:  return x\n        case n < 0: return Pow(1/x, -n)                \n        case n %2 == 0: return Pow(x*x, n/2)        \n    }\n    return  x*Pow(x*x, n/2)\n}\n\nfunc main() {\n    var x float64 = 2\n    var y int = 10\n    fmt.Print(Pow(x, y))\n}"
  },
  {
    "path": "Math/PowXn.java",
    "content": "/* Implement pow(x, n), which calculates x raised to the power n (i.e., xn).\n\n ----Divide and Conqueror APPROACH----\n\nExample 1:\n\nInput: x = 2.00000, n = 10\nOutput: 1024.00000\nExample 2:\n\nInput: x = 2.10000, n = 3\nOutput: 9.26100\nExample 3:\n\nInput: x = 2.00000, n = -2\nOutput: 0.25000\nExplanation: 2-2 = 1/22 = 1/4 = 0.25\n \n\nConstraints:\n\n-100.0 < x < 100.0\n-231 <= n <= 231-1\nn is an integer.\n-104 <= xn <= 104\n*/\n\nclass Solution {\n    public double myPow(double x, int n) {\n     double temp;\n        if( n == 0)\n            return 1;\n        temp = myPow(x, n/2); \n          \n        if (n%2 == 0)\n            return temp*temp;\n        else\n        {\n            if(n > 0)\n                return x * temp * temp;\n            else\n                return (temp * temp) / x;\n        }\n        \n    }\n}\nclass PowXn {\n    public static void main(String[] args) {\n       double x=2.00;\n       int y=10;\n       Solution s=new Solution();\n       System.out.println(s.myPow(x,y));\n    }\n}"
  },
  {
    "path": "Math/PowXn.py",
    "content": "# Implement pow(x, n), which calculates x raised to the power n (i.e., xn). in Go\n\n# --- Recursion Approach ---\n\n# Example 1:\n# Input: x = 2, n = 10\n# Output: 1024\n\n# Example 2:\n# Input: x = 2.10000, n = 3\n# Output: 9.26100\n\n# Example 3:\n# Input: x = 2.00000, n = -2\n# Output: 0.25000\n# Explanation: 2^(-2) = 1/(2^2) = 1/4 = 0.25\n\ndef power(x, n):\n    if n == 0: return 1\n    elif n<0: return power(1/x, -n)\n    else: return (x*power(x, n-1))\n\n\nif __name__ == '__main__':\n    x = 2\n    n = 3\n    print(power(x, n))"
  },
  {
    "path": "Math/Reverse_Integer.cpp",
    "content": "/* Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range [-231, 231 - 1], then return 0.\n\nAssume the environment does not allow you to store 64-bit integers (signed or unsigned).\nExample 1:\n\nInput: x = 123\nOutput: 321\nExample 2:\n\nInput: x = -123\nOutput: -321\nExample 3:\n\nInput: x = 120\nOutput: 21\n \n\nConstraints:\n\n-2^31 <= x <= 2^31  - 1\n*/ \n// function for reversing the integer;\n\n  int reverse(int x) {\n        int ans =0;\n        if(x > INT_MAX || x < INT_MIN) // checking the integer is in range of -2^31 <= x <= 2^31  - 1\n           return 0;  \n        while(x != 0){\n        if(ans > INT_MAX/10 || ans < INT_MIN/10) // -2^31 <= x <= 2^31  - 1 this condition for border values of range\n           return  0;\n            ans =  ans*10; // we increaing the unit position each itereation\n            ans += x%10;   // here we finding the last unit elemet so that we can add in ans\n            x /=10;   // decreamenting the value or we can say elemenating the last unit element that we are find\n\n        }\n        return ans;  // returning the ans;\n    }\n"
  },
  {
    "path": "Math/Sum_four.cpp",
    "content": "#include <iostream>\n#include <vector>\n#include <algorithm>\n\nusing namespace std;\n\nvector<vector<int>> fourSum(vector<int>& nums, int target) {\n    vector<vector<int>> result;\n    \n    int n = nums.size();\n    \n    if (n < 4) {\n        return result;\n    }\n    \n    sort(nums.begin(), nums.end());\n    \n    for (int i = 0; i < n - 3; i++) {\n        // Avoid duplicates\n        if (i > 0 && nums[i] == nums[i - 1]) {\n            continue;\n        }\n        \n        for (int j = i + 1; j < n - 2; j++) {\n            // Avoid duplicates\n            if (j > i + 1 && nums[j] == nums[j - 1]) {\n                continue;\n            }\n            \n            int left = j + 1;\n            int right = n - 1;\n            \n            while (left < right) {\n                int sum = nums[i] + nums[j] + nums[left] + nums[right];\n                \n                if (sum < target) {\n                    left++;\n                } else if (sum > target) {\n                    right--;\n                } else {\n                    result.push_back({nums[i], nums[j], nums[left], nums[right]});\n                    \n                    // Avoid duplicates\n                    while (left < right && nums[left] == nums[left + 1]) {\n                        left++;\n                    }\n                    while (left < right && nums[right] == nums[right - 1]) {\n                        right--;\n                    }\n                    \n                    left++;\n                    right--;\n                }\n            }\n        }\n    }\n    \n    return result;\n}\n\nint main() {\n    vector<int> nums = {1, 0, -1, 0, -2, 2};\n    int target = 0;\n    \n    vector<vector<int>> result = fourSum(nums, target);\n    \n    for (vector<int>& quad : result) {\n        cout << \"[\";\n        for (int i = 0; i < 4; i++) {\n            cout << quad[i];\n            if (i < 3) {\n                cout << \", \";\n            }\n        }\n        cout << \"]\" << endl;\n    }\n    \n    return 0;\n}\n"
  },
  {
    "path": "Math/circle.cpp",
    "content": "class Solution {\n    public int[] countPoints(int[][] points, int[][] queries) {\n        int[] answer = new int[queries.length];\n        \n        for (int j = 0; j < queries.length; j++) {\n            int centerX = queries[j][0];\n            int centerY = queries[j][1];\n            int radius = queries[j][2];\n            \n            for (int i = 0; i < points.length; i++) {\n                int pointX = points[i][0];\n                int pointY = points[i][1];\n                \n                // Check if the point (pointX, pointY) is inside the circle.\n                if (isInsideCircle(pointX, pointY, centerX, centerY, radius)) {\n                    answer[j]++;\n                }\n            }\n        }\n        \n        return answer;\n    }\n    \n    private boolean isInsideCircle(int x, int y, int centerX, int centerY, int radius) {\n        int distanceSquared = (x - centerX) * (x - centerX) + (y - centerY) * (y - centerY);\n        return distanceSquared <= radius * radius;\n    }\n}\n"
  },
  {
    "path": "Math/count_numbers_with_unique_digits.java",
    "content": "/* Implement countNumbersWithUniqueDigits(n), which calculates the number of \nall numbers with unique digits, x, where 0 <= x < 10^n.\n\nExplanation:\n- For n=0, the answer is 1 (only the number 0, here considered to have 0 digits).\n- For n=1, the answer is the number of one-digit numbers with unique digits (9), \n  plus the result for n=0 (1).\n- For n=2, the answer is the number of two-digit numbers with unique digits (between \n  10 and 99), plus the result for n=1. The number of two-digit numbers with unique digits \n  is 9*9 (9 possible first digits between 1-9, then 9 possible second digits between 0-9 \n  that are different from the first digit).\n- For n=3, the answer is the number of three-digit number with unique digits (between 100 \n  and 999), plus the result for n=2. The number of three-digit numbers with unique digits \n  is 9*9*8 (9 possible first digits between 1-9, then 9 possible second digits between 0-9 \n  that are different from the first digit, then 8 possible third digits between 0-9 that are \n  different from the first two).\n- And so on, using recursive calls of the same function.\nNote: There are no numbers with 11 or more digits that have unique digits. So for n>=10, the\nresult will be the same for any n.\n\nExample 1:\nInput: n=3\nOutput: 739\n\nExample 2:\nInput: n=6\nOutput: 168571\n\nExample 3:\nInput: n=8\nOutput: 2345851\n\nConstraints:\nn >= 0\n\nTime complexity: O(n)\nSpace complexity: O(n)\n\n*/\n\nclass Solution {\n\n    public int countNumbersWithUniqueDigits(int n) {\n\n        if (n==0) {\n            return 1;\n        }\n\n        int counter = 9;\n        for (int i=1; i<n; i++) {\n            counter *= (10-i);\n        }\n\n        return counter+countNumbersWithUniqueDigits(n-1);\n\n    }\n\n}\n"
  },
  {
    "path": "Math/count_primes.cpp",
    "content": "/*\n    Given an integer n, return the number of prime numbers that are strictly less than n.\n\n    Example 1:\n    Input: n = 10\n    Output: 4\n    Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7.\n\n    Example 2:\n    Input: n = 0\n    Output: 0\n\n    Example 3:\n    Input: n = 1\n    Output: 0\n    Constraints:\n    0 <= n <= 5 * 106\n*/\n\n// Refer to Sieve Of Eratosthenes explanation under Math folder\nclass Solution {\npublic:\n    int countPrimes(int n) {\n        if(n <= 1) return 0;\n        bool seive[n];\n        for(int i = 0; i < n; i++) \n            seive[i] = true;\n        seive[0] = false; seive[1] = false;\n        for(int i = 2; i * i < n; i++){\n            if(seive[i]){\n                for(int j = i * i; j < n; j += i){\n                    seive[j] = false;\n                }\n            }\n        }\n        return count(seive, seive + n, true);\n    }\n};"
  },
  {
    "path": "Math/count_primes.java",
    "content": "/* Implement countPrimes(n), which calculates the number of primes that are strictly smaller than n.\n\nExample 1:\nInput: n=0\nOutput: 0\n\nExample 2:\nInput: n=10\nOutput: 4\n\nExample 3:\nInput: n=155\nOutput: 36\n\nExample 4:\nInput: n=5000000\nOuput: 348513\n\nConstraints:\n0 <= n <= 5 * 10^6\n\nTime complexity: O(n^2)\nSpace complexity: O(n)\n\n*/\n\nclass Solution {\n\n    int countPrimes(int n) {\n        if (n<=2) {\n            return 0;\n        }\n        \n        int counter = 0;\n        /* notPrimesArray: Array in which every cell represents whether \n        its index number is non-prime or not. Initially every number is \n        considered prime (default value: false), but the opposite might be \n        determined later. */\n        boolean[] notPrimesArray = new boolean[n];\n        \n        for (int i=2; i<n; i++) {\n            /* Any product of i>=2 multiplied by any integer j>=2 is not prime.\n            So the corresponding value of i*j in the array is changed to true. \n            This will only affect cells with an index number higher than the \n            current i, as i*j>i for any j>=2.*/\n            for (int j=2; i*j<n; j++) {\n                notPrimesArray[i*j] = true;\n            }\n\n            /* If a number is non-prime, the counter is updated. */\n            if (notPrimesArray[i]==false) {\n                counter++;\n            }\n        }\n\n        return counter;\n    }\n\n};\n"
  },
  {
    "path": "Math/count_unique_digits.cpp",
    "content": "/*\n\tGiven an integer n, return the count of all numbers with unique digits, x, where 0 <= x < 10n.\n\n\tInput: n = 2\n\tOutput: 91\n\n\tInput: n = 0\n\tOutput: 1\n\n\tConstraints:\n\t> 0 <= n <= 8\n*/\n\nclass Solution {\npublic:\n\n/* \n        By using concepts of permutation and combination, we can count the unique  numbers for N digits.\n    For the first digit we can choose any 1 digit from 1-9\n    For the latter digits we can choose any 1 digit from 0-9 except the digits     already used \n\n*/\n    int countNumbersWithUniqueDigits(int n) {\n        int ans=0;\n        for(int i=0;i<n;i++)\n        {\n            int temp=1;\n            int k=i;\n            // for the latter digits we can choose any 1 digit from 0-9 except the digits already used\n            for(int j=0;j<k;j++)\n            {\n                temp*=(9-j);\n            }\n            // for the first digit we can choose any 1 digit from 1-9\n            ans=ans + 9*temp;\n        }\n\n        // Return the final answer\n        return ans+1;\n    }\n};"
  },
  {
    "path": "Math/count_unique_digits.go",
    "content": "// Implementation of Count Numbers with Unique Digits\n/*\n   This function takes an integer n as input and returns the count of all positive numbers with unique digits that have n\n   digits or less. The function first handles the base case where n = 0 (only 1 possible number, 0). For n > 0,\n   the function initializes the count to 10 (digits 0-9), and then iterates through each number of digits from 2 to n.\n   For each number of digits, the function calculates the number of possible unique numbers and adds it to the total count.\n   The number of possible unique numbers for i digits is calculated by first choosing the first digit (9 choices) and then\n   choosing each subsequent digit (8 choices for the second digit, 7 choices for the third digit, and so on).\n   The product of all these choices is the total number of possible unique numbers for i digits.\n   This calculation is repeated for each number of digits from 2 to n, and the total count is returned at the end.\n\n   For example, if n = 2, the function should return 91. There are 10 possible numbers with 1 digit (0-9), and\n   91 possible numbers with 2 digits (10-99) that have unique digits\n*/\npackage main\n\nimport (\n\t\"fmt\"\n)\n\nfunc countNumbersWithUniqueDigits(n int) int {\n    // Base case: n = 0, only 1 possible number (0)\n    if n == 0 {\n        return 1\n    }\n    \n    // For n > 0, initialize count to 10 (digits 0-9)\n    count := 10\n    \n    // Calculate count for 2 to n digits\n    for i := 2; i <= n; i++ {\n        // For each number of digits, calculate the number of possible unique numbers\n        // First digit can be 1-9 (9 choices), subsequent digits can be any of the remaining 9-1 = 8 choices\n        // Multiply the choices together to get the total number of possible unique numbers\n        // Add this count to the total count\n        currCount := 9\n        for j := 1; j < i; j++ {\n            currCount *= 10 - j\n        }\n        count += currCount\n    }\n    \n    return count\n}\n\nfunc main() {\n    // Test case with n = 2\n    fmt.Println(countNumbersWithUniqueDigits(2)) // Output: 91\n}\n"
  },
  {
    "path": "Math/factorial.py",
    "content": "'''\nApproach:\nWe will take the number as input from the user and calculate its factorial.\nTo calculate the factorial, we will start from 1 and multiply it with all the numbers from 1 to n.\nFinally, we will return the factorial.\n\nTime Complexity: O(n)\nSpace Complexity: O(1)\n\nSample Input: 5\nSample Output: Factorial of 5 is 120\n'''\n\n# Initializing the factorial to 1\nfact = 1\ndef factorial(num):\n  # If the number is 0 or 1, then the factorial is 1.\n  if num == 0 or num == 1:\n  return 1\n  # Calculating factorial by multiplying every number from 1 to num\n  for i in range(1, num+1):\n    fact *= i\n  return fact\n\n#Taking input from user\nnum = int(input(\"Enter a number: \"))\n#Calculating and printing the factorial of the number\nprint(\"Factorial of\", num, \"is\", factorial(num))\n\n\n"
  },
  {
    "path": "Math/factorial_iterative.js",
    "content": "// Program to find factorial till a given number\nfunction factorialIterative(number) {\n    var factorialResult = 1;\n\n    if (number == 0) {\n        return 0;\n    }\n\n    for (i = 1; i <= number; i++) {\n        factorialResult *= i;\n    }\n    return factorialResult;\n}\n\n// Driver code\nconsole.log(factorialIterative(2));\nconsole.log(factorialIterative(3));\nconsole.log(factorialIterative(4));\nconsole.log(factorialIterative(5));\n"
  },
  {
    "path": "Math/find_longest_increasing_subsequence.cpp",
    "content": "/*\n    Given an integer array nums, return the length of the longest strictly increasing subsequence.\n\n    Example 1:\n    Input: nums = [10,9,2,5,3,7,101,18]\n    Output: 4\n    Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.\n\n    Example 2:\n    Input: nums = [0,1,0,3,2,3]\n    Output: 4\n    Explanation: The longest increasing subsequence is [0,1,2,3], therefore the length is 4.\n\n    Example 3:\n    Input: nums = [7,7,7,7,7,7,7]\n    Output: 1\n\n    Explanation of the approach:\n    1. We will use the concept of Dynamic Programming to solve this problem.\n    2. We will create a dp array of size n, where n is the size of the given array.\n    3. We will initialize the dp array with 1, as the length of the longest increasing subsequence ending at any index is atleast 1.\n    4. We will iterate over the array from the second index to the last index.\n    5. For each index, we will iterate over the array from the first index to the current index.\n    6. If the current element is greater than the element at the inner loop, then we will update the dp array at the current index with the maximum of the current value and the value at the inner loop + 1.\n    7. We will return the maximum value in the dp array.\n\n    Time Complexity: O(N^2), where N is the size of the given array.\n    Space Complexity: O(N), where N is the size of the given array.\n\n*/\n\nclass Solution{\npublic:\n    int lengthOfLIS(vector<int> &nums)\n    {\n        // Initializing the dp array with 1, as the length of the longest increasing subsequence ending at any index is atleast 1.\n        vector<int> dp(nums.size(), 1);\n        // Iterating over the array from the second index to the last index.\n        for (int i = 1; i < nums.size(); i++)\n        {\n            // Iterating over the array from the first index to the current index.\n            for (int j = 0; j < i; j++)\n            {\n                // If the current element is greater than the element at the inner loop, then we will update the dp array at the current index with the maximum of the current value and the value at the inner loop + 1.\n                // This is because, if the current element is greater than the element at the inner loop, then we can add the current element to the increasing subsequence ending at the inner loop element, and the length of the increasing subsequence ending at the current element will be the length of the increasing subsequence ending at the inner loop element + 1.\n                // We will take the maximum of the current value and the value at the inner loop + 1, because we want to find the length of the longest increasing subsequence ending at the current element.\n                // We will update the dp array at the current index with the maximum of the current value and the value at the inner loop + 1.\n                if (nums[i] > nums[j])\n                    dp[i] = max(dp[i], dp[j] + 1);\n            }\n        }\n        // Returning the maximum value in the dp array.\n        return *max_element(dp.begin(), dp.end());\n    }\n};"
  },
  {
    "path": "Math/hamming_distance.cpp",
    "content": "/*\nExample:\nInput: nums = [4,14,2]\nOutput: 6\n\nExplanation: \nIn binary representation, the 4 is 0100, 14 is 1110, and 2 is 0010 (just\nshowing the four bits relevant in this case).\nThe answer will be:\nHammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6.\n\nDetailed Explanation:\nThe totalHammingDistance function takes a reference to a vector of integers nums, and returns the total Hamming distance between all possible pairs of elements in the vector.\n\nIn the function, we initialize the answer ans to 0, and the size of the vector n is obtained using the size() method of the vector. We then loop through all 32 bits (since we are dealing with 32-bit integers), and for each bit position i, we count the number of elements in nums with the i-th bit set by looping through all elements and checking if the bit is set using bitwise AND operator &.\n\nThe count c is then multiplied by (n-c), which gives the number of pairs with different bits at the i-th position. This count is added to the answer ans. Finally, the function returns the total Hamming distance.\nThe main function is just an example usage, where we create a vector nums and call the totalHammingDistance method of a Solution object to get the total Hamming distance between all possible pairs of elements in nums.\n*/\n// code:\n\n#include<iostream>\n#include <vector>\n\nusing namespace std;\n\nclass Solution {\npublic:\n    int totalHammingDistance(vector<int>& nums) {\n        int ans = 0;\n        int n = nums.size();\n        for(int i = 0; i < 32; i++) {\n            int c = 0;\n            for(int j = 0; j < n; j++) {\n                if((nums[j] & (1 << i))) {\n                    c++;\n                }\n            }\n            ans += (c * (n - c));\n        }\n        return ans;\n    }\n};\n\nint main() {\n    // Example usage\n    vector<int> nums = {4, 14, 2};\n    Solution s;\n    int result = s.totalHammingDistance(nums);\n    return 0;\n}\n\n"
  },
  {
    "path": "Math/is_power_of_two.js",
    "content": "// Whether the provided number is power of two\n\n// Time complexity - O(log n)\nfunction isPowerOfTwo(inputNumber) {\n    if (inputNumber <= 1) {\n        return false;\n    }\n\n    var dividedNumber = inputNumber;\n\n    while (dividedNumber !== 1) {\n        if (dividedNumber % 2 !== 0) {\n            return false;\n        }\n        dividedNumber = dividedNumber / 2;\n    }\n    return true;\n}\n\n// Time complexity - O(1)\nfunction isPowerOfTwoConst(inputNumber) {\n    if (inputNumber <= 1) {\n        return false;\n    }\n\n    return (\n        parseInt(Math.ceil(Math.log(n) / Math.log(2))) ==\n        parseInt(Math.floor(Math.log(n) / Math.log(2)))\n    );\n}\n\n// Time complexity - O(log n)\nfunction isPowerOfTwoConst(inputNumber) {\n    if (inputNumber <= 1) {\n        return false;\n    }\n\n    return (\n        parseInt(Math.ceil(Math.log(n) / Math.log(2))) ==\n        parseInt(Math.floor(Math.log(n) / Math.log(2)))\n    );\n}\n\n//Driver code\nconsole.log(isPowerOfTwo(8));\nconsole.log(isPowerOfTwo(1));\nconsole.log(isPowerOfTwo(7));\nconsole.log(isPowerOfTwo(6));\nconsole.log(isPowerOfTwo(16));\nconsole.log(isPowerOfTwo(32));\n"
  },
  {
    "path": "Math/is_prime.js",
    "content": "// Whether the given number is a prime nujmber or not\n// Time complexity O(n)\nfunction isPrime(input) {\n  for (i = 2; i < input; i++) {\n    if (input % i == 0) {\n      return \"The number is not a prime number\";\n      break;\n    } else {\n      continue;\n    }\n  }\n  return \"Given number is a prime number\";\n}\n\n// Driver code\nconsole.log(isPrime(6));\n\n// Time complexity: O(sqrt(n))\n// Space complexity: O(1)\nconst isPrime = (num) => {\n  for (let i = 2, s = Math.sqrt(num); i <= s; i++) {\n    if (num % i === 0) return false;\n  }\n  return num > 1;\n};\n\nconsole.log(isPrime(10));\n\n// Time complexity - O(logn)\nfunction isPrimeLogn(input) {\n  for (i = 2; i < Math.sqrt(input); i++) {\n    if (input % i == 0) {\n      return \"The number is not a prime number\";\n      break;\n    } else {\n      continue;\n    }\n  }\n  return \"Given number is a prime number\";\n}\n\n// Driver code\nconsole.log(isPrime(6));\nconsole.log(isPrimeLogn(7));\n"
  },
  {
    "path": "Math/k_closest_points_to_origin.cpp",
    "content": "/*\n\tGiven an array of points where points[i] = [xi, yi] represents a point on the X-Y plane and an integer k, return the k closest points to the origin (0, 0).\n\tYou may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in).\n\n\tInput: points = [[1,3],[-2,2]], k = 1\n\tOutput: [[-2,2]]\n\n\tInput: points = [[3,3],[5,-1],[-2,4]], k = 2\n\tOutput: [[3,3],[-2,4]]\n\n\tConstraints:\n\t>  1 <= k <= points.length <= 104\n\t>  -104 < xi, yi < 104\n\n*/\nclass Solution {\npublic:\n    vector<vector<int>> kClosest(vector<vector<int>>& points, int k) {\n        // Lets define some variables we will be needing\n        vector<vector<int>> ans;\n        vector<pair<double,int>> sorted;\n        \n        // For each point in the list points lets store distance_from_origin and point index as a pair\n        for(int i=0;i<points.size();i++)\n        {\n            double dist=sqrt((double)pow(points[i][0],2)+(double)pow(points[i][1],2));\n            sorted.push_back({dist,i});\n        }\n\n        // Now, sort the list of pairs in ascending order of distance from origin\n        sort(sorted.begin(),sorted.end());\n\n        //Store the first k points by extracting index from list of pairs into ans\n        int ind=0;\n        while(k--)\n        {\n            int pInd=sorted[ind].second;\n            ans.push_back(points[pInd]);\n            ind++;\n        }\n\n        // Return the final list of points ans\n        return ans;\n    }\n};"
  },
  {
    "path": "Math/missing_number.py",
    "content": "# Given an array arr[] of size N with integers in the range of [0, N], the task is to find the missing number\r\n#  from the first N integers.\r\n# Note: There are no duplicates in the list\r\n\r\n#ISSUE 1445\r\n\r\n# This code  calculates the sum of the given list and the sum of consecutive numbers up to the\r\n#  maximum value. The missing number is obtained by subtracting the list sum from the calculated sum,\r\n#  and it is printed as the output.\r\n\r\n# input the list\r\nlist1 = list(map(int, input().split()))\r\n# calculate sum of the list\r\ns = sum(list1)\r\n#find the max of the array and calculate sum of n natural numbers\r\nn = max(list1)\r\nans = (n*(n+1))//2 \r\nprint(ans-s)\r\n\r\n# Time complexity is O(n)"
  },
  {
    "path": "Math/modular_expo_itera.cpp",
    "content": "// Modular exponentiation is exponentiation performed over a modulus. \n// It is useful in computer science, especially in the field of public-key cryptography, \n// where it is used in both Diffie-Hellman Key Exchange and RSA public/private keys.\n// Sample Input : 10 3\n// Output : 1000\n// Iterative approach\n#include<bits/stdc++.h>\nusing namespace std;\nint modular_expo(int x, int n, int mod){\n   int ans = 1;\n   while(n >= 1){\n       if(n % 2 == 0){\n          x = ((x % mod) * (x % mod)) % mod;\n          n /= 2;\n       }\n       else{\n           ans = ((ans % mod) * (x % mod)) % mod;\n           n--;\n       }\n   }\n   return ans;\n}\nint main(){\n\tint mod = 1000000007;\n    cout << modular_expo(5, 3, mod);\nreturn 0;\n}\n"
  },
  {
    "path": "Math/modular_expo_recursive.cpp",
    "content": "// Modular exponentiation is exponentiation performed over a modulus. \n// It is useful in computer science, especially in the field of public-key cryptography, \n// where it is used in both Diffie-Hellman Key Exchange and RSA public/private keys.\n// Sample Input : 10 3\n// Output : 1000\n// recursive approach\n#include<bits/stdc++.h>\nusing namespace std;\nint modular_expo(int x, int n, int mod){\n    if(n == 0)\n        return 1;\n    else if(n % 2 == 0){\n        int y = modular_expo(x, n / 2, mod);\n        return (y * y) % mod;\n    }\n    else{\n        return ((x % mod) * modular_expo(x, n - 1, mod)) % mod;\n    }    \n}\nint main(){\n\tint n, x, mod = 1000000007;\n    cin >> x >> n;\n    cout << modular_expo(x, n, mod);\nreturn 0;\n}\n"
  },
  {
    "path": "Math/num_points_inside_a_circle.cpp",
    "content": "/*\n    You are given an array points where points[i] = [xi, yi] is the coordinates of the ith point on a 2D plane. Multiple points can have the same coordinates.\n    You are also given an array queries where queries[j] = [xj, yj, rj] describes a circle centered at (xj, yj) with a radius of rj.\n    For each query queries[j], compute the number of points inside the jth circle. Points on the border of the circle are considered inside.\n    Return an array answer, where answer[j] is the answer to the jth query.\n\n    Example 1:\n    Input: points = [[1,3],[3,3],[5,3],[2,2]], queries = [[2,3,1],[4,3,1],[1,1,2]]\n    Output: [3,2,2]\n    Explanation: \n    queries[0] is the first circle [2,3,1], which include the points [1,3], [2,2] and [3,3].\n    queries[1] is the second circle [4,3,1], which include the points [3,3] and [5,3].\n    and queries[2] is the third circle [1,1,2], which include the point [1,3] and [2,2].\n\n\n    Example 2:\n    Input: points = [[1,1],[2,2],[3,3],[4,4],[5,5]], queries = [[1,2,2],[2,2,2],[4,3,2],[4,3,3]]\n    Output: [2,3,2,4]\n    Explanation: \n    queries[0] is the first circle [1,2,2], which include the points [1,1] and [2,2].\n    queries[1] is the second circle [2,2,2], which include the points [1,1], [2,2] and [3,3].\n    queries[2] is the third circle [4,3,2], which include the points [3,3] and [4,4].\n    and queries[3] is the fourth circle [4,3,3], which include the points [2,2], [3,3], [4,4] and [5,5].\n\n    Explanation of the approach:\n    1. We will use the formula of distance between two points to find the distance between the center of the circle and the given point.\n    2. If the distance is less than or equal to the radius of the circle, then the point lies inside the circle.\n\n    Time Complexity: O(N * Q), where N is the number of points and Q is the number of queries.\n    Space Complexity: O(1)\n*/\n\nclass Solution\n{\npublic:\n    vector<int> countPoints(vector<vector<int>> &points, vector<vector<int>> &queries)\n    {\n        vector<int> ans;\n        // Iterating over the queries.\n        for (int i = 0; i < queries.size(); i++)\n        {\n            // Initializing the count to 0. This will store the number of points inside the circle.\n            int count = 0;\n            // Iterating over the points.\n            for (int j = 0; j < points.size(); j++)\n            {\n                // Calculating the distance between the center of the circle and the given point.\n                int distance = pow(points[j][0] - queries[i][0], 2) + pow(points[j][1] - queries[i][1], 2);\n                // If the distance is less than or equal to the radius of the circle, then the point lies inside the circle.\n                if (distance <= pow(queries[i][2], 2))\n                    count++; // If the point lies inside the circle, then increment the count.\n            }\n            // Pushing the count to the answer vector.\n            ans.push_back(count);\n        }\n        return ans;\n    }\n\n    // Further reading: https://www.geeksforgeeks.org/queries-points-number-points-lie-given-circle/\n};"
  },
  {
    "path": "Math/num_points_inside_a_circle.js",
    "content": "// Program Author : TheCodeVenturer[Niraj Modi]\n/*\n    Program Definition : Queries on Number of Points inside a circle\n        Description : you are given n points in a cartesian plane [points] and a queries array\n                      Where each element inside it is an array each consisting of [xj, yj, rj] where,\n                      (xj,yj) is centre of the circle and rj is radius of the circle \n                      Now, you are required to find no.of points inside the circle\n    \n    Approach:\n        The only possible soln somehow will be that you have to calculate distance of each point from the centre of each circle\n        and if the distance <= radius then the point is inside the the circle else not\n\n        Distance Formula = ((x1-x2)**2 + (y1-y2)**2)**(1/2)\n    Complexity:\n\t\tThe time complexity of this solution is O(m*n) where m = points.length and n = queries.length \n\t\tThe space complexity is O(1),we are not using any Auxiliary Spaces.\n    Sample input/outputs:\n\t\tExample 1:\n\t\tInput: \n            points = [[1,3],[3,3],[5,3],[2,2]]\n            queries = [[2,3,1],[4,3,1],[1,1,2]]\n\t\tOutput: [3,2,2]\n\t\tExample 1:\n\t\tInput: \n            points = [[1,1],[2,2],[3,3],[4,4],[5,5]]\n            queries = [[1,2,2],[2,2,2],[4,3,2],[4,3,3]]\n\t\tOutput: [2,3,2,4]\n */\n\nvar countPoints = function(points, queries) {\n    sol=[]          // Initialising solution array\n    for(let query of queries){\n        var count=0     //no.of points inside that circle is initially zero\n        for(let point of points){\n            d = Math.sqrt((query[0]-point[0])**2+(query[1]-point[1])**2)        //calculating distance between the points\n            if(d<=query[2])count++                                              //if it is <= radius it is inside the circle\n        }\n        sol.push(count)                                                         //finally add the solution to solution array\n    }\n    return sol\n};\n\npoints = [[1,3],[3,3],[5,3],[2,2]]\nqueries = [[2,3,1],[4,3,1],[1,1,2]]\nconsole.log(countPoints(points,queries))"
  },
  {
    "path": "Math/num_points_inside_a_circle.py",
    "content": "# Program Author : TheCodeVenturer[Niraj Modi]\n'''\n    Program Definition : Queries on Number of Points inside a circle\n        Description : you are given n points in a cartesian plane [points] and a queries array\n                      Where each element inside it is an array each consisting of [xj, yj, rj] where,\n                      (xj,yj) is centre of the circle and rj is radius of the circle \n                      Now, you are required to find no.of points inside the circle\n    \n    Approach:\n        The only possible soln somehow will be that you have to calculate distance of each point from the centre of each circle\n        and if the distance <= radius then the point is inside the the circle else not\n\n        Distance Formula = ((x1-x2)**2 + (y1-y2)**2)**(1/2)\n    Complexity:\n\t\tThe time complexity of this solution is O(m*n) where m = points.length and n = queries.length \n\t\tThe space complexity is O(1),we are not using any Auxiliary Spaces.\n    Sample input/outputs:\n\t\tExample 1:\n\t\tInput: \n            points = [[1,3],[3,3],[5,3],[2,2]]\n            queries = [[2,3,1],[4,3,1],[1,1,2]]\n\t\tOutput: [3,2,2]\n\t\tExample 1:\n\t\tInput: \n            points = [[1,1],[2,2],[3,3],[4,4],[5,5]]\n            queries = [[1,2,2],[2,2,2],[4,3,2],[4,3,3]]\n\t\tOutput: [2,3,2,4]\n'''\nclass Solution:\n    def countPoints(self, points: list[list[int]], queries: list[list[int]]) -> list[int]:\n        sol :list = []  #Initialising solution array\n        for x1,y1,r in queries:\n            count:int=0     #no.of points inside that circle is initially zero\n            for x2,y2 in points:\n                d = ((x2-x1)**2 + (y2-y1)**2)**(1/2)  #calculating distance between the points\n                if(d<=r):        #if it is <= radius it is inside the circle\n                    count+=1\n            sol.append(count)       #finally add the count to solution array\n        return sol\n    \n\npoints = [[1,3],[3,3],[5,3],[2,2]]\nqueries = [[2,3,1],[4,3,1],[1,1,2]]\nprint(Solution().countPoints(points,queries))"
  },
  {
    "path": "Math/num_steps_reduce_to_zero.Go",
    "content": "/*\n    Given an integer num, return the number of steps to reduce it to zero.\n\n    In one step, if the current number is even, you have to divide it by 2, otherwise, you have to subtract 1 from it.\n\n    Example 1:\n    Input: num = 14\n    Output: 6\n    Explanation: \n    Step 1) 14 is even; divide by 2 and obtain 7. \n    Step 2) 7 is odd; subtract 1 and obtain 6.\n    Step 3) 6 is even; divide by 2 and obtain 3. \n    Step 4) 3 is odd; subtract 1 and obtain 2. \n    Step 5) 2 is even; divide by 2 and obtain 1. \n    Step 6) 1 is odd; subtract 1 and obtain 0.\n    \n    Example 2:\n    Input: num = 8\n    Output: 4\n    Explanation: \n    Step 1) 8 is even; divide by 2 and obtain 4. \n    Step 2) 4 is even; divide by 2 and obtain 2. \n    Step 3) 2 is even; divide by 2 and obtain 1. \n    Step 4) 1 is odd; subtract 1 and obtain 0.\n    \n    Example 3:\n    Input: num = 123\n    Output: 12\n\n    Constraints: 0 <= num <= 106\n*/\nfunc numberOfSteps(num int) int {\n    var steps = 0\n    for num != 0 {\n        if num % 2 == 0 {\n            num /= 2\n            steps++\n        } else {\n            num -= 1\n            steps++\n        }\n    }\n    return steps\n}\n"
  },
  {
    "path": "Math/num_steps_reduce_to_zero.cpp",
    "content": "/*\n    Given an integer num, return the number of steps to reduce it to zero.\n\n    In one step, if the current number is even, you have to divide it by 2, otherwise, you have to subtract 1 from it.\n\n    Example 1:\n    Input: num = 14\n    Output: 6\n    Explanation: \n    Step 1) 14 is even; divide by 2 and obtain 7. \n    Step 2) 7 is odd; subtract 1 and obtain 6.\n    Step 3) 6 is even; divide by 2 and obtain 3. \n    Step 4) 3 is odd; subtract 1 and obtain 2. \n    Step 5) 2 is even; divide by 2 and obtain 1. \n    Step 6) 1 is odd; subtract 1 and obtain 0.\n    \n    Example 2:\n    Input: num = 8\n    Output: 4\n    Explanation: \n    Step 1) 8 is even; divide by 2 and obtain 4. \n    Step 2) 4 is even; divide by 2 and obtain 2. \n    Step 3) 2 is even; divide by 2 and obtain 1. \n    Step 4) 1 is odd; subtract 1 and obtain 0.\n    \n    Example 3:\n    Input: num = 123\n    Output: 12\n\n    Constraints: 0 <= num <= 106\n*/\nclass Solution {\npublic:\n    int numberOfSteps(int num) {\n        // We initialize the step counter.\n        int steps = 0;\n        // While the number is still not zero...\n        while (num != 0) {\n            // ...we check if it is odd or even.\n            // If it is even...\n            if (num % 2 == 0) {\n                // ...we divide it by 2 and increase the step counter.\n                num /= 2;\n                steps++;\n            // If it is odd...\n            } else {\n                // ...we substract 1 and increase the step counter.\n                num -= 1;\n                steps++;\n            }\n        }\n        // Finally, we return the step counter.\n        return steps;\n    }\n};\n"
  },
  {
    "path": "Math/num_steps_reduce_to_zero.java",
    "content": "/*\n    Given an integer num, return the number of steps to reduce it to zero.\n\n    In one step, if the current number is even, you have to divide it by 2, otherwise, you have to subtract 1 from it.\n\n    Example 1:\n    Input: num = 14\n    Output: 6\n    Explanation: \n    Step 1) 14 is even; divide by 2 and obtain 7. \n    Step 2) 7 is odd; subtract 1 and obtain 6.\n    Step 3) 6 is even; divide by 2 and obtain 3. \n    Step 4) 3 is odd; subtract 1 and obtain 2. \n    Step 5) 2 is even; divide by 2 and obtain 1. \n    Step 6) 1 is odd; subtract 1 and obtain 0.\n    \n    Example 2:\n    Input: num = 8\n    Output: 4\n    Explanation: \n    Step 1) 8 is even; divide by 2 and obtain 4. \n    Step 2) 4 is even; divide by 2 and obtain 2. \n    Step 3) 2 is even; divide by 2 and obtain 1. \n    Step 4) 1 is odd; subtract 1 and obtain 0.\n    \n    Example 3:\n    Input: num = 123\n    Output: 12\n\n    Constraints: 0 <= num <= 106\n*/\nclass Solution {\n    public int numberOfSteps(int num) {\n        // We initialize the step counter.\n        int steps = 0;\n        // While the number is still not zero...\n        while (num != 0) {\n            // ...we check if it is odd or even.\n            // If it is even...\n            if (num % 2 == 0) {\n                // ...we divide it by 2 and increase the step counter.\n                num /= 2;\n                steps++;\n            // If it is odd...\n            } else {\n                // ...we substract 1 and increase the step counter.\n                num -= 1;\n                steps++;\n            }\n        }\n        // Finally, we return the step counter.\n        return steps;\n    }\n}\n"
  },
  {
    "path": "Math/num_steps_reduce_to_zero.js",
    "content": "/*\n    Given an integer num, return the number of steps to reduce it to zero.\n\n    In one step, if the current number is even, you have to divide it by 2, otherwise, you have to subtract 1 from it.\n\n    Example 1:\n    Input: num = 14\n    Output: 6\n    Explanation: \n    Step 1) 14 is even; divide by 2 and obtain 7. \n    Step 2) 7 is odd; subtract 1 and obtain 6.\n    Step 3) 6 is even; divide by 2 and obtain 3. \n    Step 4) 3 is odd; subtract 1 and obtain 2. \n    Step 5) 2 is even; divide by 2 and obtain 1. \n    Step 6) 1 is odd; subtract 1 and obtain 0.\n    \n    Example 2:\n    Input: num = 8\n    Output: 4\n    Explanation: \n    Step 1) 8 is even; divide by 2 and obtain 4. \n    Step 2) 4 is even; divide by 2 and obtain 2. \n    Step 3) 2 is even; divide by 2 and obtain 1. \n    Step 4) 1 is odd; subtract 1 and obtain 0.\n    \n    Example 3:\n    Input: num = 123\n    Output: 12\n\n    Constraints: 0 <= num <= 106\n*/\n/**\n * @param {number} num\n * @return {number}\n */\nvar numberOfSteps = function (num) {\n  // We initialize the step counter.\n  let steps = 0;\n  // While the number is still not zero...\n  while (num != 0) {\n    // ...we check if it is odd or even.\n    // If it is even...\n    if (num % 2 == 0) {\n      // ...we divide it by 2 and increase the step counter.\n      num /= 2;\n      steps++;\n      // If it is odd...\n    } else {\n      // ...we substract 1 and increase the step counter.\n      num -= 1;\n      steps++;\n    }\n  }\n  // Finally, we return the step counter.\n  return steps;\n};\n"
  },
  {
    "path": "Math/num_steps_reduce_to_zero.py",
    "content": "'''\n    Given an integer num, return the number of steps to reduce it to zero.\n\n    In one step, if the current number is even, you have to divide it by 2, otherwise, you have to subtract 1 from it.\n\n    Example 1:\n    Input: num = 14\n    Output: 6\n    Explanation: \n    Step 1) 14 is even; divide by 2 and obtain 7. \n    Step 2) 7 is odd; subtract 1 and obtain 6.\n    Step 3) 6 is even; divide by 2 and obtain 3. \n    Step 4) 3 is odd; subtract 1 and obtain 2. \n    Step 5) 2 is even; divide by 2 and obtain 1. \n    Step 6) 1 is odd; subtract 1 and obtain 0.\n    \n    Example 2:\n    Input: num = 8\n    Output: 4\n    Explanation: \n    Step 1) 8 is even; divide by 2 and obtain 4. \n    Step 2) 4 is even; divide by 2 and obtain 2. \n    Step 3) 2 is even; divide by 2 and obtain 1. \n    Step 4) 1 is odd; subtract 1 and obtain 0.\n    \n    Example 3:\n    Input: num = 123\n    Output: 12\n\n    Constraints: 0 <= num <= 106\n'''\nclass Solution(object):\n    def numberOfSteps(self, num):\n        \"\"\"\n        :type num: int\n        :rtype: int\n        \"\"\"\n        steps = 0\n        while num != 0:\n            if num % 2 == 0:\n                num = num / 2\n                steps = steps + 1\n            else:\n                num = num - 1\n                steps = steps + 1\n        return steps\n"
  },
  {
    "path": "Math/number_of_substrings_with_only_1s.js",
    "content": "/*\n  PROBLEM STATEMENT:\n  \n  Given a binary string s, return the number of substrings with all characters 1's. Since the answer may be too large, return it modulo 109 + 7.\n  \n  EXAMPLE 1:\n      Input: s = \"0110111\"\n      Output: 9\n      Explanation: There are 9 substring in total with only 1's characters.\n      \"1\" -> 5 times.\n      \"11\" -> 3 times.\n      \"111\" -> 1 time.\n  EXAMPLE 2:\n      Input: s = \"101\"\n      Output: 2\n      Explanation: Substring \"1\" is shown 2 times in s.\n      \n  CONSTRAINT:\n      Constraints:\n      1 <= s.length <= 105\n      s[i] is either '0' or '1'.\n*/\n\n/* Explaination\n\n The function begins by initializing two variables - \"count\" and \"answer\" - to 0. \n \"count\" will be used to keep track of the current number of consecutive 1's in the string,\n while \"answer\" will eventually store the final answer.\n\nThe constant \"mod\" is defined to be 10^9+7, which will be used to take modulo of the answer\nat each step, in order to prevent overflow.\n\nThe function then iterates through the input string using a for loop.\nFor each character in the string, it checks if it is a 1 or a 0. If it is a 1,\nthe \"count\" variable is incremented by 1. If it is a 0, the \"count\" variable is reset to 0.\n\nAt each step of the loop, the value of \"count\" is added to \"answer\" and then taken modulo \"mod\".\nThis is done to count the number of substrings with all 1's and prevent overflow of the result.\n\nAfter the loop has finished, the final value of \"answer\" is returned as the solution to the problem.\n\n\n*/\n\n\nvar numSub = function(s) {\n  // count stores the current number of consecutive 1's\n  var count=0;\n  // answer storese the final answer to be returned\n  var answer=0;\n  // we mod the sum at each step so that they don't overflow\n  const mod=1000000007;\n  // iterate the entire string\n  for(let i=0;i<s.length;i++){\n      // if we find 1, we update the count=count+1 \n      // if we find 0, we update the count=0\n      count=s.charAt(i)==\"1\"?count+1:0;\n      // we add the value of count to the answer (adding number of substring at each step)\n      answer=(answer+count)%mod;\n  }\n  // return the final answer.\n  return answer;\n};\n\n\n/* Time and Space complexity\n\nThe time complexity of this code is O(n),\nwhere n is the length of the input string s. This is because we iterate through the entire string once,\nand each operation inside the loop takes O(1) time.\n\nThe space complexity of this code is O(1),\nbecause we only use a fixed amount of extra space to store the variables count, answer, mod, and i.\nWe do not use any additional space that depends on the length of the input string.\n\n\n\n\n\n\n\n\n*/\n"
  },
  {
    "path": "Math/op.js",
    "content": "function divide(dividend, divisor) {\n    // Handle special cases\n    if (divisor === 0) {\n        throw new Error(\"Division by zero\");\n    }\n    if (dividend === 0) {\n        return 0;\n    }\n    \n    // Determine the sign of the result\n    const negativeResult = (dividend < 0) ^ (divisor < 0);\n    \n    // Make dividend and divisor positive for easier calculations\n    dividend = Math.abs(dividend);\n    divisor = Math.abs(divisor);\n    \n    let quotient = 0;\n    \n    while (dividend >= divisor) {\n        dividend -= divisor;\n        quotient++;\n    }\n    \n    if (negativeResult) {\n        quotient = -quotient;\n    }\n    \n    // Check for overflow\n    if (quotient < -(2**31) || quotient > 2**31 - 1) {\n        return 2**31 - 1; // Return INT_MAX for overflow\n    }\n    \n    return quotient;\n}\n\n// Example usage:\nconst dividend = 10;\nconst divisor = 3;\nconst result = divide(dividend, divisor);\nconsole.log(result); // Output should be 3\n"
  },
  {
    "path": "Math/palindrome_number.java",
    "content": "/* Question : Given an integer x, return true if x is a palindrome, and false otherwise.\n\nExample 1:\n\nInput: x = 121\nOutput: true\nExplanation: 121 reads as 121 from left to right and from right to left.\nExample 2:\n\nInput: x = -121\nOutput: false\nExplanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.\nExample 3:\n\nInput: x = 10\nOutput: false\nExplanation: Reads 01 from right to left. Therefore it is not a palindrome.\n \n\nConstraints:\n\n-231 <= x <= 231 - 1 */\n\nclass Solution {\n    public boolean isPalindrome(int x) {\n        if(x < 0){\n            return false;\n        }\n      \n        //Checking if the number is equal to its reverse, if true, it is a palindrome\n        return x == rev(x);\n    }\n  \n  \n    // Function to find reverse of a number\n  \n    public int reverse(int n){\n        int reverse = 0;\n        while(n != 0){\n            int digit = n % 10;\n            rev = digit + reverse * 10;\n            n /= 10;\n        }\n        \n        return reverse;\n    }\n}\n \n"
  },
  {
    "path": "Math/pallindrome_number.cpp",
    "content": "/*\n    Given an integer x, return true if x is a palindrome, and false otherwise.\n    \n    Example 1:\n    Input: x = 121\n    Output: true\n    Explanation: 121 reads as 121 from left to right and from right to left.\n    \n    Example 2:\n    Input: x = -121\n    Output: false\n    Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.\n    \n    Example 3:\n    Input: x = 10\n    Output: false\n\n    Explanation: Reads 01 from right to left. Therefore it is not a palindrome.\n    \n\n    Constraints:\n\n    -231 <= x <= 231 - 1\n*/\n\nclass Solution {\npublic:\n    bool isPalindrome(int x) {\n        int temp = x;\n        if(x < 0)\n            return false;\n        long long new_num = 0;\n        while(x) {\n            int rem = x % 10;\n            new_num = (new_num * 10) + rem;\n            x /= 10;\n        }\n        return new_num == temp;\n    }\n};"
  },
  {
    "path": "Math/pallindrome_number.py",
    "content": "'''\n    Given an integer x, return true if x is a \n    palindrome\n    , and false otherwise.\n\n    Example 1:\n    Input: x = 121\n    Output: true\n    Explanation: 121 reads as 121 from left to right and from right to left.\n    \n    Example 2:\n    Input: x = -121\n    Output: false\n    Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.\n    \n    Example 3:\n    Input: x = 10\n    Output: false\n    Explanation: Reads 01 from right to left. Therefore it is not a palindrome.\n    Constraints:\n    -231 <= x <= 231 - 1\n\n    Follow up: Could you solve it without converting the integer to a string?\n'''\nclass Solution:\n    def isPalindrome(self, x: int) -> bool:\n        #check if the number is less than zero.\n        if x < 0:\n            return False\n        #Then, calculating the reverse of the number to see if it is equal to the original number.\n        rev = 0\n        original_value = x\n        while x != 0:\n            rev = rev * 10 + x % 10\n            x = x // 10\n        return rev == original_value"
  },
  {
    "path": "Math/powXn.cpp",
    "content": "/*\nImplement pow(x, n), which calculates x raised to the power n (i.e., xn).\n\n \n\nExample 1:\n\nInput: x = 2.00000, n = 10\nOutput: 1024.00000\nExample 2:\n\nInput: x = 2.10000, n = 3\nOutput: 9.26100\nExample 3:\n\nInput: x = 2.00000, n = -2\nOutput: 0.25000\nExplanation: 2-2 = 1/22 = 1/4 = 0.25\n \n\nConstraints:\n\n-100.0 < x < 100.0\n-231 <= n <= 231-1\nn is an integer.\n-104 <= xn <= 104\n\nif it we solve it though simply by recursion it will give time complexity of O(n)\n so we will use divide and conquer approach that leads to O(logn) time complexity\n  eg. 3^7 dive seven by two 333 * 333 3 than in 333 divide by two 3 * 3 3 \n  on conquering 93 * 93 than again conquer 27 * 27 * 3 final output is 218\n*/ \n\nclass Solution {\npublic:\n    double pow(double x, int n)\n    {\n        if(x==0)return 0;\n        if(n==0)return 1;\n         double res=pow(x,n/2);\n         res=res*res;\n        if(n%2)res=x*res;\n        return res;\n    }\n    double myPow(double x, int n) {\n        if(n<0)return pow(1/x,n);\n        return pow(x,n);\n    }\n};"
  },
  {
    "path": "Math/powXn.js",
    "content": "// Implement pow(x, n), which calculates x raised to the power n (i.e., xn).\n// Time complexity: O(log n) | Space complexity: O(log n)\n\nfunction pow(x, n) {\n  // Any number raised to 0 is 1)\n  if (n === 0) return 1\n  // Power of a negative number is the reciprocal of power of positive number\n  if (n < 0) return 1 / pow(x, -n)\n  // If n is even, calculate pow(x, n / 2) and return the square of it\n  if (n % 2 === 0) return pow(x, n / 2) * pow(x, n / 2)\n  // If n is odd, return x * pow(x, n - 1) (x raised to odd power n can be represented as x * x^(n-1))\n  return x * pow(x, n - 1)\n}\n\n// Sample inputs and outputs\nconsole.log(pow(2, 10)) // 1024\nconsole.log(pow(2, -3)) // 0.125\nconsole.log(pow(3, 3)) // 27\nconsole.log(pow(3, 0)) // 1"
  },
  {
    "path": "Math/prime_factorization.cpp",
    "content": "// Prime factorisation is a method to find the prime factors of a given number, say a composite number. \n// These factors are nothing but the prime numbers. A prime number is a number \n// which has only two factors, i.e. 1 and the number itself. For example, 2 is a prime number which has two factors, 2 × 1\n// Sample Input: 10\n// Output \n// 2->1 Times\n// 5->1 Times\n#include<bits/stdc++.h>\nusing namespace std;\n\nint f[100], expo[100], len = -1;\nvoid prime_factor(int n){\n    int d = 2;\n    if(n == 1){\n        len++;\n        f[len] = 2;\n        expo[len] = 0;\n        return;\n    }\n    while(n > 1 && 1ll * d * d <= n){\n        int k = 0;\n        while(n % d == 0){\n            n = n / d;\n            k++;\n        }\n        if(k > 0){\n            len++;\n            f[len] = d;\n            expo[len] = k;\n        }\n        d++;\n    }\n    if(n > 1){\n        len++;\n        f[len] = n;\n        expo[len] = 1;\n    }\n}\nint main(){\n\tint n;\n    cin >> n;\n    prime_factor(n);\n    for(int i = 0; i <= len; i++){\n        cout << f[i] << \"->\" << expo[i] << \" Times\" << endl;\n    }\n\t\nreturn 0;\n}\n"
  },
  {
    "path": "Math/shuffle_an_array.cpp",
    "content": "/*\n\tGiven an integer array nums, design an algorithm to randomly shuffle the array. All permutations of the array should be equally likely as a result of the shuffling.\n\n\tImplement the Solution class:\n\tSolution(int[] nums) Initializes the object with the integer array nums.\n\tint[] reset() Resets the array to its original configuration and returns it.\n\tint[] shuffle() Returns a random shuffling of the array.\n\n\tInput\n\t[\"Solution\", \"shuffle\", \"reset\", \"shuffle\"]\n\t[[[1, 2, 3]], [], [], []]\n\tOutput\n\t[null, [3, 1, 2], [1, 2, 3], [1, 3, 2]]\n\n\tConstraints:\n\t> 1 <= nums.length <= 50\n\t> -106 <= nums[i] <= 106\n\t> All the elements of nums are unique.\n\t> At most 104 calls in total will be made to reset and shuffle.\n*/\n\n/*\n    APPROACH\n\n    1. Use two lists to store the original nums array. \n    2. We can keep one array as it is and return it whenever the reset() function is called.\n    3. We use the second list to shuffle the permutation of elements and return a shuffled array when shuffle() function is called.\n    4. For shuffling, choose 2 indices on random basis from the array and swap them. Repeat for n times. (n=size of the array)\n\n*/\n// O(N) Time-Complexity and O(N) Space-Complexity Solution\nclass Solution {\npublic:\n    // lets make 2 variables, one to store the shuffled version of the given array and the other to store the original version\n    vector<int> shuffled;\n    vector<int> original;\n    Solution(vector<int>& nums) {\n        // Push the elements of given array to required variables as Initialization \n        for(int i=0;i<nums.size();i++)\n        {\n            shuffled.push_back(nums[i]);\n            original.push_back(nums[i]);\n        }\n    }\n    \n    vector<int> reset() {\n        // Return the variable storing the original version of the array\n        return original;\n    }\n    \n    vector<int> shuffle() {\n        int N=shuffled.size();\n        // shuffle the variable storing the shuffled version of the array randomly\n       for(int i=0;i<N;i++)\n       {\n           int ind1=rand()%N;\n           int ind2=rand()%N;\n           swap(shuffled[ind1],shuffled[ind2]);\n       } \n       // return the newly shuffled version as answer\n       return shuffled;\n    }\n};\n\n/**\n * Your Solution object will be instantiated and called as such:\n * Solution* obj = new Solution(nums);\n * vector<int> param_1 = obj->reset();\n * vector<int> param_2 = obj->shuffle();\n */"
  },
  {
    "path": "Math/shuffle_an_array.py",
    "content": "#Problem statement - Given an integer array nums, design an algorithm to randomly shuffle the array. \n# All permutations of the array should be equally likely as a result of the shuffling.\n# Complete the provided functions \n\nclass Solution:\n\n    def __init__(self, nums: List[int]):\n        #the value of nums is stored as an instance variable that can be accessed and used by other methods within the class\n        self.nums =  nums\n\n              \n    def reset(self) -> List[int]:\n        #returning the original array after reseting it \n        return self.nums\n\n    def shuffle(self) -> List[int]:\n        s = [x for x in self.nums]\n        random.shuffle(s)\n        return s\n# Time complexity - O(N), where N is the length of the input list self.nums \n#Space compelxity - O(N)\n\n\n# Your Solution object will be instantiated and called as such:\n# obj = Solution(nums)\n# param_1 = obj.reset()\n# param_2 = obj.shuffle()\n"
  },
  {
    "path": "Math/sieve_of_eratosthenes.cpp",
    "content": "// In mathematics, the sieve of Eratosthenes is an ancient algorithm for finding all prime numbers up to any given limit.\n// It does so by iteratively marking as composite (i.e., not prime) the multiples of each prime, \n// starting with the first prime number, 2. The multiples of a given prime are generated as a sequence of numbers \n// starting from that prime, with constant difference between them that is equal to that prime. \n// This is the sieve's key distinction from using trial division to sequentially test each candidate \n// number for divisibility by each prime. Once all the multiples of each discovered prime have been marked as composites, \n// the remaining unmarked numbers are primes. Source(https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)\n\n// Sample INput: 100\n// Output :  2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97\n\n#include<bits/stdc++.h>\nusing namespace std;\nconst int nmax = 100001;\nbool is_prime[nmax];\nvoid seive_of_ero(int n){\n    for(int i = 2; i <= n; i++){\n        is_prime[i] = true;\n    }\n    for(int i = 2; i <= n / 2; i++){\n        if(is_prime[i]){\n            for(int j = i * 2; j <= n; j += i){\n                is_prime[j] = false;\n            }\n        }\n    }\n}\nint main(){\n\tint n;\n    cin >> n;\n    seive_of_ero(n);\n    for(int i = 0; i <= 500; i++){\n        if(is_prime[i])\n        cout << i << \" \" << endl;\n    }\n\t\nreturn 0;\n}\n"
  },
  {
    "path": "Math/substrings_with_1s.py",
    "content": "'''Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem : Number of Substrings With Only 1s in Python\nIssue Number : #518\nProblem statement : \n\nExplanation of the below Python code :\n\nThe implementation is quite similar to the C++ implementation. We iterate over the string s using a for loop and keep track of the count of consecutive 1's using the variable count. Whenever we encounter a '0', we calculate the number of substrings that can be formed using the formula n*(n+1)/2, add it to the final answer ans, and reset the value of count to 0. Finally, we calculate the number of substrings for the last substring of consecutive 1's, add it to the final answer ans, and return the result modulo 10^9 + 7. Note that we have used the integer division operator // to perform the division in Python.\n\n\n\n'''\n\n----------------------------------------------------------------------------------------------//Python code begins here--------------------------------------------------------------------------------------------------------------------------------------\nclass Solution:\n    def numSub(self, s: str) -> int:\n        count = 0  # count the number of consecutive ones\n        ans = 0    # variable to store the final answer\n        for i in range(len(s)):\n            if s[i] == '1':\n                count += 1\n            else:\n                # calculate the number of possible substrings that can be formed\n                # from the current consecutive ones and add it to the final answer\n                ans = (ans + (count*(count+1))//2) % (10**9 + 7)\n                count = 0\n        # handle the case when the string ends with consecutive ones\n        ans = (ans + (count*(count+1))//2) % (10**9 + 7)\n        return ans\n"
  },
  {
    "path": "Math/unique_digits.cpp",
    "content": "/*Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem : Count Numbers with Unique Digits in C++\nIssue Number : #500\nProblem statement : \n\nExplanation of the below C++ code :\n\nIn this implementation, we first handle the base case of n = 0 by returning 1. Then, we initialize the answer ans to 10 since there are 10 unique digits between 0 and 9. We also initialize the variables unique_digits and available_digits to 9 since we can't use 0 as the first digit.\n\nNext, we enter a loop that runs n-1 times (since we have already considered the case of i = 1). In each iteration of the loop, we compute unique_digits as the product of the current value of unique_digits and available_digits. We then add unique_digits to the answer ans and decrement available_digits. This is because we can't use the digits that have already been used for the previous digits.\n\nFinally, we return the value of ans.\n\nThe time complexity of this algorithm is O(n), where n is the input parameter representing the number of digits.\n\nThe space complexity of this algorithm is O(1), as we are only using a constant amount of extra memory to store the variables ans, unique_digits, and available_digits, regardless of the input size.\n\n*/\n-------------------------------------------------------------------------//C++ code begins here----------------------------------------------------------------------------\n\nclass Solution {\npublic:\n    int countNumbersWithUniqueDigits(int n) {\n        if (n == 0) {\n            return 1;   // return 1 for n = 0\n        }\n        int ans = 10;   // start with 10 unique digits, as we can have numbers 0-9\n        int unique_digits = 9;  // start with 9 digits, as we cannot use 0 as first digit\n        int available_digits = 9;   // remaining available digits\n        while (n-- > 1 && available_digits > 0) {\n            unique_digits *= available_digits; // calculate number of unique numbers that can be formed\n            ans += unique_digits; // add number of unique numbers to the answer\n            available_digits--; // reduce available digits by 1\n        }\n        return ans; // return final answer\n    }\n};\n"
  },
  {
    "path": "Math/unique_digits.java",
    "content": "/*Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem : Count Numbers with Unique Digits in Java\nIssue Number : #501\nProblem statement : \n\nExplanation of the below Java code :\n\nWe handle the base case of n = 0 by returning 1. We initialize the answer ans to 10 since there are 10 unique digits between 0 and 9. We also initialize the variables unique_digits and available_digits to 9 since we can't use 0 as the first digit.\n\nWe then enter a loop that runs n-1 times (since we have already considered the case of i = 1). In each iteration of the loop, we compute unique_digits as the product of the current value of unique_digits and available_digits. We then add unique_digits to the answer ans and decrement available_digits. This is because we can't use the digits that have already been used for the previous digits.\n\nFinally, we return the value of ans.\n\nThe time complexity of the given code is O(n), where n is the input parameter, because the loop runs n-1 times.\n\nThe space complexity is O(1), because the amount of memory used by the algorithm does not depend on the size of the input n. The algorithm only uses a few constant amount of variables for computation, such as ans, unique_digits and available_digits.\n\nTherefore, the time complexity of the code is linear and the space complexity is constant.\n\n\n*/\n\n--------------------------------------------------------------------------------------------------------//Java code begins here---------------------------------------------------------------------------------------------------------------------------------\n\n\nclass Solution {\n    public int countNumbersWithUniqueDigits(int n) {\n        if (n == 0) {\n            return 1;   // return 1 for n = 0\n        }\n        int ans = 10;   // start with 10 unique digits, as we can have numbers 0-9\n        int unique_digits = 9;  // start with 9 digits, as we cannot use 0 as first digit\n        int available_digits = 9;   // remaining available digits\n        while (n-- > 1 && available_digits > 0) {\n            unique_digits *= available_digits; // calculate number of unique numbers that can be formed\n            ans += unique_digits; // add number of unique numbers to the answer\n            available_digits--; // reduce available digits by 1\n        }\n        return ans; // return final answer\n    }\n}\n"
  },
  {
    "path": "Math/unique_digits.py",
    "content": "'''\n    Given an integer n, return the count of all numbers with unique digits, x, where 0 <= x < 10n.\n\n    Example 1:\n    Input: n = 2\n    Output: 91\n    Explanation: The answer should be the total numbers in the range of 0 ≤ x < 100, excluding 11,22,33,44,55,66,77,88,99\n    \n    Example 2:\n    Input: n = 0\n    Output: 1\n    \n    Constraints:\n    0 <= n <= 8\n'''\nclass Solution:\n    def countNumbersWithUniqueDigits(self, n: int) -> int:\n        '''For n = 0, ans = 1\n        For n = 1, ans = 10\n        If we take 2 digit number, we have 9 options for first digit (1 - 9)\n     and 9 options for second digit(0 & all other digits except the one taken as first digit (to keep      digits unique)) therefore ans += (9 * 9)\n    Similarly if we take 3 digit number we have 8 options for third digit, therefore ans += (9 * 9 * 8)'''\n        if(n==0): return 1 \n        if(n==1): return 10\n        unique = 10\n        digits = 9\n        for i in range(2,n+1):\n            digits*=(10-i+1)\n            unique+=digits\n        return unique\n    "
  },
  {
    "path": "Math/unique_integers_that_sum_up_to_0.cpp",
    "content": "/*\n    Given an integer n, return any array containing n unique integers such that they add up to 0.\n\n    Example 1:\n    Input: n = 5\n    Output: [-7,-1,1,3,4]\n    Explanation: These arrays also are accepted [-5,-1,1,2,3] , [-3,-1,2,-2,4].\n    \n    Example 2:\n    Input: n = 3\n    Output: [-1,0,1]\n    \n    Example 3:\n    Input: n = 1\n    Output: [0]\n    \n    Constraints:\n    1 <= n <= 1000\n*/\n\nclass Solution {\npublic:\n    vector<int> sumZero(int n) {\n        int A[n];\n        for(int i = 0; i < n; i++){ A[i] = 0; }\n        int start = 0;\n        int end = n - 1;\n        int i = 1;\n        // populate start and end with n and -n\n        while(start < end) {\n            A[start] = i;\n            A[end] = -i;\n            i++;\n            start++;\n            end--;\n        }\n        vector<int> R;\n        for(int a: A){\n            R.push_back(a);\n        }\n        return R;\n    }\n};"
  },
  {
    "path": "Misc/tictactoe.java",
    "content": "/*\n This Java code defines a simple command-line Tic-Tac-Toe game that allows two players (X and O) to take turns making moves on a 3x3 game board. Here's an explanation of the code:\n\n1. Constants:\n   - `X` and `O` are integer constants representing the two players, with `X` assigned the value `1` and `O` assigned the value `-1`.\n   - `EMPTY` is an integer constant representing an empty cell on the game board, with a value of `0`.\n\n2. Game Board:\n   - The game board is represented by a 3x3 integer array called `board`.\n   - The `player` variable indicates which player's turn it is. It is initially set to `X`.\n\n3. Constructor:\n   - The `TicTacToe` class has a constructor that initializes a new game by clearing the board and setting the `player` to `X`.\n\n4. `clearBoard` Method:\n   - The `clearBoard` method initializes the game board by setting all cells to `EMPTY` and resets the `player` to `X`.\n\n5. `putMark` Method:\n   - The `putMark` method allows a player to make a move at a specified position (i, j).\n   - It checks for valid coordinates and an empty cell. If the move is valid, the player's mark is placed, and the turn is switched to the other player.\n   - If the move is invalid, an `IllegalArgumentException` is thrown.\n\n6. `isWin` Method:\n   - The `isWin` method checks if a player has won the game. It returns `true` if any of the winning conditions (e.g., a row, column, or diagonal with all marks of the same player) are met. Otherwise, it returns `false`.\n\n7. `winner` Method:\n   - The `winner` method determines the winner of the game. It checks for both `X` and `O` as potential winners using the `isWin` method and returns the result (positive for `X`, negative for `O`, or `0` for a tie).\n\n8. `toString` Method:\n   - The `toString` method converts the current game state to a human-readable string, representing the game board. It uses \"X\" and \"O\" to denote player marks and empty spaces as \" \" (space).\n\n9. `main` Method:\n   - In the `main` method, a new Tic-Tac-Toe game is created.\n   - A series of moves are made using `putMark`, and the game state is printed after each move.\n   - The final outcome of the game is determined using the `winner` method, and the result is displayed as \"X wins,\" \"O wins,\" or \"Tie.\"\n\nThe code provides a basic implementation of a command-line Tic-Tac-Toe game with validation for player moves and win conditions. It demonstrates how to represent the game board, make moves, and check for a win or tie in the game.\n */\npublic class TicTacToe {\n    public static final int X = 1, O = -1;\n    public static final int EMPTY = 0;\n    private int board[][] = new int[3][3];\n    private int player;\n\n    public TicTacToe() {\n        clearBoard();\n    }\n    public void clearBoard()  {\n        for (int i = 0; i < 3; i++)\n            for (int j = 0; j < 3; j++)\n                board[i][j] = EMPTY;\n        player = X;\n    }\n\n    public void putMark(int i, int j) throws IllegalArgumentException {\n        if ((i < 0) || (i > 2) || (j < 0) || (j > 2))\n            throw new IllegalArgumentException(\"Invalid board position\");\n        if (board[i][j] != EMPTY)\n            throw new IllegalArgumentException(\"Board Position occupied\");\n        board[i][j] = player;\n        player = -player; // switch players\n    }\n\n    public boolean isWin(int mark) {\n        return ((board[0][0] + board[0][1] + board[0][2] == mark * 3)\n                || (board[1][0] + board[1][1] + board[1][2] == mark * 3)\n                || (board[2][0] + board[2][1] + board[2][2] == mark * 3)\n                || (board[0][0] + board[1][0] + board[2][0] == mark * 3)\n                || (board[0][1] + board[1][1] + board[2][1] == mark * 3)\n                || (board[0][2] + board[1][2] + board[2][2] == mark * 3)\n                || (board[0][0] + board[1][1] + board[2][2] == mark * 3)\n                || (board[2][0] + board[1][1] + board[0][2] == mark * 3)\n        );\n    }\n    public int winner() {\n        if(isWin(X))\n            return (X);\n        else if (isWin(O))\n            return (O);\n        else\n            return (0);\n    }\n\n    public String toString() {\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                switch (board[i][j]) {\n                    case X: sb.append(\"X\"); break;\n                    case O: sb.append(\"O\"); break;\n                    case EMPTY: sb.append(\" \"); break;\n                }\n                if (j < 2) sb.append(\"|\");\n            }\n            if(i < 2) sb.append(\"\\n-----\\n\");\n        }\n        return sb.toString();\n    }\n\n    public static void main(String[] args) {\n        TicTacToe game = new TicTacToe();\n        game.putMark(0, 0); game.putMark(0, 2);\n        game.putMark(2, 2); game.putMark(1, 2);\n        game.putMark(2, 0); game.putMark(1, 1);\n        game.putMark(1, 0);\n\n\n        System.out.println(game);\n        int winningPlayer = game.winner();\n        String[] outcome = {\"O wins\", \"Tie\", \"X wins\"};\n        System.out.println(outcome[1 + winningPlayer]);\n    }\n\n\n}\n {\n    \n}\n"
  },
  {
    "path": "Patterns/CompleteSquare.java",
    "content": "/*\n    pattern to print:\nfor input:5\n    * * * * *\n    * * * * *\n    * * * * *\n    * * * * *\n    * * * * *\n\n    APPROACH:\n        1) Identify the numbers of rows for the outer for loop\n        2) Identify the relation of column with respect to row.\n        3) for each loop , print the respective element.\n */\npublic class CompleteSquare {\n\n    public static void main(String[] args) {\n        int size = 5;\n        for(int row=1;row <= size;row++) {\n            for (int col = 1;col<=size;col++) {\n                System.out.print(\"* \");\n            }\n            System.out.println();\n        }\n    }\n}\n\n"
  },
  {
    "path": "Patterns/HollowPattern.cpp",
    "content": "Program: To generate a hollow pattern using asterisks ('*'). The program will take an integer 'n' as input, which represents the size of the pattern, and it will produce a hollow pattern of the given size.\n\nApproach:\n1. We will use nested loops to iterate through rows and columns and print '*' at specific positions to form the hollow pattern.\n2. For each row, we will check if it's the first row, last row, first column, or last column. If so, we will print a '*' character. Otherwise, we will print a space ' '.\n3. This way, we will create the desired hollow pattern.\n\nTime Complexity: O(n^2)\n- The program uses two nested loops to print the pattern, one for rows and one for columns. So, the time complexity is proportional to the square of 'n'.\n\nSpace Complexity: O(1)\n- The program uses a constant amount of extra space, as it only prints characters and does not use any additional data structures that depend on the input size 'n'.\n\nSample Input: 5\nSample Output:\n* * * * * \n*       * \n*       * \n*       * \n* * * * *\n\nIn this example, the input 'n' is 5, and the program generates a hollow pattern of size 5x5 using asterisks.  \n*/\n\n#include <iostream>\nusing namespace std;\n\nvoid printHollowPattern(int n) {\n    // Iterate through each row\n    for (int i = 0; i < n; i++) {\n        // Iterate through each column in the row\n        for (int j = 0; j < n; j++) {\n            // Check if it's the first row, last row, first column, or last column\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                cout << \"* \";\n            } else {\n                cout << \"  \";\n            }\n        }\n        // Move to the next line after each row is printed\n        cout << endl;\n    }\n}\n\nint main() {\n    int size;\n    cout << \"Enter the size of the pattern: \";\n    cin >> size;\n\n    printHollowPattern(size);\n    return 0;\n}\n\n"
  },
  {
    "path": "Patterns/HollowPattern.go",
    "content": "/*\nProgram: To generate a hollow pattern using asterisks ('*'). The program will take an integer 'n' as input, which represents the size of the pattern, and it will produce a hollow pattern of the given size.\n\nApproach:\n1. We will use nested loops to iterate through rows and columns and print '*' at specific positions to form the hollow pattern.\n2. For each row, we will check if it's the first row, last row, first column, or last column. If so, we will print a '*' character. Otherwise, we will print a space ' '.\n3. This way, we will create the desired hollow pattern.\n\nTime Complexity: O(n^2)\n- The program uses two nested loops to print the pattern, one for rows and one for columns. So, the time complexity is proportional to the square of 'n'.\n\nSpace Complexity: O(1)\n- The program uses a constant amount of extra space, as it only prints characters and does not use any additional data structures that depend on the input size 'n'.\n\nSample Input: 5\nSample Output:\n* * * * * \n*       * \n*       * \n*       * \n* * * * *\n\nIn this example, the input 'n' is 5, and the program generates a hollow pattern of size 5x5 using asterisks.\n*/\n\npackage main\n\nimport \"fmt\"\n\nfunc printHollowPattern(n int) {\n\t// Iterate through each row\n\tfor i := 0; i < n; i++ {\n\t\t// Iterate through each column in the row\n\t\tfor j := 0; j < n; j++ {\n\t\t\t// Check if it's the first row, last row, first column, or last column\n\t\t\tif i == 0 || i == n-1 || j == 0 || j == n-1 {\n\t\t\t\tfmt.Print(\"* \")\n\t\t\t} else {\n\t\t\t\tfmt.Print(\"  \")\n\t\t\t}\n\t\t}\n\t\t// Move to the next line after each row is printed\n\t\tfmt.Println()\n\t}\n}\n\nfunc main() {\n\tvar size int\n\tfmt.Print(\"Enter the size of the pattern: \")\n\tfmt.Scan(&size)\n\n\tprintHollowPattern(size)\n}\n\n"
  },
  {
    "path": "Patterns/HollowPattern.java",
    "content": "/*\nProgram: To generate a hollow pattern using asterisks ('*'). The program will take an integer 'n' as input, which represents the size of the pattern, and it will produce a hollow pattern of the given size.\n\nApproach:\n1. We will use nested loops to iterate through rows and columns and print '*' at specific positions to form the hollow pattern.\n2. For each row, we will check if it's the first row, last row, first column, or last column. If so, we will print a '*' character. Otherwise, we will print a space ' '.\n3. This way, we will create the desired hollow pattern.\n\nTime Complexity: O(n^2)\n- The program uses two nested loops to print the pattern, one for rows and one for columns. So, the time complexity is proportional to the square of 'n'.\n\nSpace Complexity: O(1)\n- The program uses a constant amount of extra space, as it only prints characters and does not use any additional data structures that depend on the input size 'n'.\n\nSample Input: 6\nSample Output:\n* * * * * * \n*         * \n*         * \n*         * \n*         * \n* * * * * *\n\n*/\n\nimport java.util.Scanner;\n\npublic class HollowPattern {\n    public static void printHollowPattern(int n) {\n        // Iterate through each row\n        for (int i = 0; i < n; i++) {\n            // Iterate through each column in the row\n            for (int j = 0; j < n; j++) {\n                // Check if it's the first row, last row, first column, or last column\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    System.out.print(\"* \");\n                } else {\n                    System.out.print(\"  \");\n                }\n            }\n            // Move to the next line after each row is printed\n            System.out.println();\n        }\n    }\n\n    public static void main(String[] args) {\n        Scanner scanner = new Scanner(System.in);\n        System.out.print(\"Enter the size of the pattern: \");\n        int size = scanner.nextInt();\n\n        printHollowPattern(size);\n    }\n}\n"
  },
  {
    "path": "Patterns/HollowPattern.py",
    "content": "'''\nProblem: Python program to generate a hollow pattern using asterisks ('*'). The program will take an integer 'n' as input, which represents the size of the pattern, and it will produce a hollow pattern of the given size.\n\nApproach:\n1. We will iterate through rows and columns and print '*' at specific positions to form the hollow pattern.\n2. For each row, we will check if it's the first row, last row, first column, or last column. If so, we will print a '*' character. Otherwise, we will print a space ' '.\n3. This way, we will create the desired hollow pattern.\n\nTime Complexity: O(n^2)\n- The program uses two nested loops to print the pattern, one for rows and one for columns. So, the time complexity is proportional to the square of 'n'.\n\nSpace Complexity: O(1)\n- The program uses a constant amount of extra space, as it only prints characters and does not use any additional data structures that depend on the input size 'n'.\n\nSample Input: 8\nSample Output:\n```\n* * * * * * * * \n*             * \n*             * \n*             * \n*             * \n*             * \n*             * \n* * * * * * * *\n```\n\nIn this example, the input 'n' is 8, and the program generates a hollow pattern of size 8x8 using asterisks.\n'''\n\ndef print_hollow_pattern(n):\n    # Iterate through each row\n    for i in range(n):\n        # Iterate through each column in the row\n        for j in range(n):\n            # Check if it's the first row, last row, first column, or last column\n            if i == 0 or i == n - 1 or j == 0 or j == n - 1:\n                print('*', end=' ')\n            else:\n                print(' ', end=' ')\n        # Move to the next line after each row is printed\n        print()\n      \n# Sample input: n = 5\n# Expected output:\n# * * * * * \n# *       * \n# *       * \n# *       * \n# * * * * *\nprint_hollow_pattern(5)\n\n"
  },
  {
    "path": "Patterns/Ladder_Pattern.java",
    "content": "/*\nProblem: Given an integer N, the task is to print the ladder with N steps using ‘*’. The ladder will be with the gap of 3 spaces between two side rails.\n\nApproach:\nFirst, we take input from the user for the number of steps in the ladder.\nWe then iterate from 1 to N, where N is the number of steps, to print each step of the ladder.\nInside the loop, we call the printSideRail() function to print a side rail at the beginning of each step.\nWe then call the printStep(stepNumber) function to print the actual step. This function prints stepNumber asterisks with 3 spaces between each asterisk.\nFinally, we again call the printSideRail() function to print a side rail at the end of each step and move to the next line to start a new step.\n\nNote: The number of spaces between the asterisks in each step can be adjusted by modifying the value inside the 'printSideRail()' and 'printStep(stepNumber)' functions.\n\nTime complexity: O(N) for given input N steps\nAuxiliary Space:  O(1) as constant extra space is used\n\n*/\n\nimport java.util.Scanner;\n\npublic class LadderPattern {\n    public static void main(String[] args) {\n        Scanner sc = new Scanner(System.in);\n        System.out.print(\"Enter the number of steps in the ladder: \");\n        int N = sc.nextInt();\n        \n        // Print the ladder with N steps\n        for (int i = 1; i <= N; i++) {\n            printSideRail();\n            printStep(i);\n            printSideRail();\n            System.out.println();\n        }\n    }\n    \n    // Function to print a side rail\n    public static void printSideRail() {\n        System.out.print(\"*   \");\n    }\n    \n    // Function to print a step\n    public static void printStep(int stepNumber) {\n        for (int i = 1; i <= stepNumber; i++) {\n            System.out.print(\"*   \");\n        }\n    }\n}\n\n/*\n\nEnter the number of steps in the ladder: 5\n*   * \n*   *   * \n*   *   *   * \n*   *   *   *   * \n*   *   *   *   *   * \n\n*/\n"
  },
  {
    "path": "Patterns/ReverseRightTrianglePattern.java",
    "content": "/*\n    Reverse Right Triangular Pattern\n    Approach:\n        1) Identify the numbers of rows for the outer for loop\n        2) Identify the relation of column with respect to row.\n            In this case col = size-row+1\n        3) for each loop , print the respective element.\n\n    TIME COMPLEXITY: O(N^2)\n    SPACE COMPLEXITY: O(1)\n     Eg: For size = 5,\n        OUTPUT:\n                * * * * *\n                * * * *\n                * * *\n                * *\n                *\n */\npublic class ReverseRightTrianglePattern {\n\n    public static void main(String[] args) {\n        int size = 5;\n        pattern(size);\n    }\n\n    public  static void pattern(int size) {\n        for(int row=1;row<=size;row++) {\n            for(int col=1;col<=size-row+1;col++) {\n                System.out.print(\"* \");\n            }\n            System.out.println();\n        }\n    }\n}"
  },
  {
    "path": "Patterns/RightPascalTriangle.java",
    "content": "/*\n    Right Pascal Triangle pattern in java\n    Approach:\n        1) Identify the numbers of rows for the outer for loop\n        2) Identify the relation of column with respect to row.\n            In this case col = size-row+1\n        3) for each loop , print the respective element.\n\n    TIME COMPLEXITY: O(N^2)\n    SPACE COMPLEXITY: O(1)\n     Eg: For size = 5,\n        OUTPUT:\n                * \n                * * \n                * * * \n                * * * * \n                * * * \n                * * \n                *\n */\npublic class RightPascalTriangle {\n\n    public static void main(String[] args) {\n        int size = 4;\n        pattern(size);\n    }\n\n    public static void pattern(int size) {\n        for(int row=0;row< 2*size-1;row++){\n            int totalcol = row < size?row:2*size-row-2;\n            for(int col =0;col <=totalcol;col++){\n                System.out.print(\"* \");\n            }\n            System.out.println();\n        }\n    }\n}\n\n"
  },
  {
    "path": "Patterns/StarDiamond.java",
    "content": "/*\n   DIAMOND PATTERN\n      *\n     * *\n    * * *\n   * * * *\n    * * *\n     * *\n      *\n      \n   APPROACH:\n        1) Identify the numbers of rows for the outer for loop\n        2) Identify the relation of column with respect to row.\n        3) for each loop , print the respective element.\n */\npublic class StarDiamond {\n\n    public static void main(String[] args) {\n        int size = 5;\n        pattern(size);\n    }\n\n    public static void pattern(int size) {\n        for (int row=1;row< 2*size;row++) {\n            int totalcolsinrow = row <= size ? row:2*size-row;\n            int spaces = size-totalcolsinrow;\n\n            for(int i =1;i<=spaces;i++) {\n                System.out.print(\" \");\n            }\n            for(int col =1;col<=totalcolsinrow;col++) {\n                System.out.print(\"* \");\n            }\n            System.out.println();\n        }\n    }\n}\n\n"
  },
  {
    "path": "Patterns/diamond_pattern.cpp",
    "content": "/*\nApproach:\n1. We use two nested loops to iterate through each row and each column of the diamond pattern.\n2. The first loop is used to iterate through the rows of the diamond. It starts from 0 and goes up to n-1 rows for the upper half of the diamond.\n3. Inside the first loop, we use a nested loop to print spaces before the pattern of each row. The number of spaces decreases by 1 as we move down the rows.\n4. Again inside the first loop, we use another nested loop to print the pattern of asterisks (*) for each row. The number of asterisks increases by 2 as we move down the rows.\n5. After printing each row, we move to the next line using `cout << endl;`.\n6. Now, we need to print the lower half of the diamond. For this, we use another loop that starts from n-2 (as we have already printed the top-most row in the first loop) and moves down to 0 rows.\n7. Inside this loop, we print the spaces and pattern the same way as in the first loop.\n8. Finally, we have the main function where we take input from the user for the number of rows and call the `printDiamondPattern` function.\n\nTime Complexity: O(n^2) - as we use nested loops to iterate through each row and each column of the diamond pattern.\n\nSpace Complexity: O(1) - as we only use a constant amount of additional space for variables.\n\nSample Input:\nEnter the number of rows: 5\n\nSample Output:\n    *\n   ***\n  *****\n *******\n*********\n *******\n  *****\n   ***\n    *\n*/\n\n\n#include <iostream>\nusing namespace std;\n\nvoid printDiamondPattern(int n) {\n    // Print the upper half of the diamond\n    for (int i = 0; i < n; i++) {\n        // Print spaces before the pattern for each row\n        for (int j = 0; j < n - i - 1; j++) {\n            cout << \" \";\n        }\n        \n        // Print the pattern for each row\n        for (int j = 0; j < 2 * i + 1; j++) {\n            cout << \"*\";\n        }\n        \n        cout << endl; // Move to the next line\n    }\n    \n    // Print the lower half of the diamond\n    for (int i = n-2; i >= 0; i--) {\n        // Print spaces before the pattern for each row\n        for (int j = 0; j < n - i - 1; j++) {\n            cout << \" \";\n        }\n        \n        // Print the pattern for each row\n        for (int j = 0; j < 2 * i + 1; j++) {\n            cout << \"*\";\n        }\n        \n        cout << endl; // Move to the next line\n    }\n}\n\nint main() {\n    int n;\n    cout << \"Enter the number of rows: \";\n    cin >> n;\n    \n    printDiamondPattern(n);\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "Patterns/diamond_pattern.go",
    "content": "/*\nIn this code, the user enters a number, and the program will print a diamond pattern with that number as the widest point.\n\nExplanation of the approach:\n- We define two helper functions: `printSpaces` and `printStars`. These functions are used to print the desired spaces and stars, respectively.\n- The `printDiamondPattern` function takes an integer `n` as input. It prints the upper half and lower half of the diamond pattern using a combination of spaces and stars.\n- In the upper half, the number of spaces in each row decreases by 1, while the number of stars increases by 2.\n- In the lower half, the number of spaces in each row increases by 1, while the number of stars decreases by 2.\n- The `main` function prompts the user to enter a number and calls the `printDiamondPattern` function to print the diamond pattern.\n\nTime Complexity: The time complexity of this code is O(n^2), where n is the number entered by the user. This is because there are two nested loops used to print the diamond pattern.\n\nSpace Complexity: The space complexity of this code is O(1), as there are no additional data structures used that depend on the input size.\n\nSample Input:\nEnter a number for the widest point of the diamond: 5\n\nSample Output:\n    *\n   ***\n  *****\n *******\n*********\n *******\n  *****\n   ***\n    *\n\n*/\n\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\nfunc printSpaces(num int) {\n\tfor i := 1; i <= num; i++ {\n\t\tfmt.Print(\" \")\n\t}\n}\n\nfunc printStars(num int) {\n\tfor i := 1; i <= num; i++ {\n\t\tfmt.Print(\"* \")\n\t}\n}\n\nfunc printDiamondPattern(n int) {\n\t// upper half of the diamond\n\tfor i := 0; i < n; i++ {\n\t\tprintSpaces(n - i - 1)\n\t\tprintStars(2*i + 1)\n\t\tfmt.Println()\n\t}\n\n\t// lower half of the diamond\n\tfor i := 0; i < n-1; i++ {\n\t\tprintSpaces(i + 1)\n\t\tprintStars(2*(n-i-1) - 1)\n\t\tfmt.Println()\n\t}\n}\n\nfunc main() {\n\tvar num int\n\tfmt.Print(\"Enter a number for the widest point of the diamond: \")\n\tfmt.Scan(&num)\n\n\tprintDiamondPattern(num)\n}\n\n"
  },
  {
    "path": "Patterns/diamond_pattern.java",
    "content": "/*\nApproach:\n1. We take the number of rows for the diamond pattern as input.\n2. We start by printing the upper half of the diamond pattern. In each row, we first print the required spaces and then print the required number of asterisks.\n3. After the upper half, we print the lower half of the diamond pattern using a similar logic.\n\nTime Complexity: The time complexity of this code is O(n^2) as we use nested loops to print the pattern.\n\nSpace Complexity: The space complexity of this code is O(1) as we are not using any additional data structures.\n\nSample Input: 5\n\nSample Output:\n    *\n   ***\n  *****\n *******\n*********\n *******\n  *****\n   ***\n    *\n*/\n\npublic class DiamondPattern {\n\n    public static void main(String[] args) {\n        int n = 5; // Specify the number of rows for the diamond pattern\n        printDiamondPattern(n);\n    }\n\n    public static void printDiamondPattern(int n) {\n        if (n <= 0) {\n            System.out.println(\"Number of rows should be positive.\");\n            return;\n        }\n\n        // Printing upper half of the diamond pattern\n        for (int i = 1; i <= n; i++) {\n            for (int j = 1; j <= n - i; j++) {\n                System.out.print(\" \");\n            }\n            for (int k = 1; k <= i * 2 - 1; k++) {\n                System.out.print(\"*\");\n            }\n            System.out.println();\n        }\n\n        // Printing lower half of the diamond pattern\n        for (int i = n - 1; i >= 1; i--) {\n            for (int j = 1; j <= n - i; j++) {\n                System.out.print(\" \");\n            }\n            for (int k = 1; k <= i * 2 - 1; k++) {\n                System.out.print(\"*\");\n            }\n            System.out.println();\n        }\n    }\n\n\n"
  },
  {
    "path": "Patterns/diamond_pattern.py",
    "content": "'''\nApproach:\n- The code above prints a diamond pattern with `n` rows. The approach used is to iterate through each row of the diamond pattern, calculate the number of spaces and asterisks in each row based on the current row number, and then print the spaces and asterisks accordingly.\n- In the upper half of the diamond, the number of spaces decreases by 1 and the number of asterisks increases by 2 in each row. In the lower half of the diamond, the number of spaces increases by 1 and the number of asterisks decreases by 2 in each row.\n\nSample input: `4`, the function `print_diamond_pattern(4)`\n\nSample Output:\n   *\n  ***\n *****\n*******\n *****\n  ***\n   *\n\nTime Complexity: The time complexity of this code is O(n^2), where n is the input parameter representing the number of rows in the diamond pattern. This is because we need to loop through each row and perform a constant number of operations for each row.\n\nSpace Complexity: The space complexity of this code is O(1), as we are not using any additional data structures whose space requirements depend on the input size.\n\nNOTE: This code assumes that the input `n` is a positive integer greater than 0. It does not handle invalid inputs or edge cases where `n` is negative or zero.\n'''\n\ndef print_diamond_pattern(n):\n    # Calculate the number of rows in the diamond pattern\n    num_rows = 2 * n - 1\n\n    # Iterate through each row of the diamond pattern\n    for i in range(num_rows):\n\n        # Calculate the number of spaces and asterisks in each row\n        if i < n:  # Upper half of the diamond\n            num_spaces = n - i - 1\n            num_asterisks = 2 * i + 1\n        else:  # Lower half of the diamond\n            num_spaces = i - n + 1\n            num_asterisks = 2 * (num_rows - i) - 1\n\n        # Print the spaces before the asterisks\n        for _ in range(num_spaces):\n            print(\" \", end=\"\")\n\n        # Print the asterisks\n        for _ in range(num_asterisks):\n            print(\"*\", end=\"\")\n\n        # Move to the next line\n        print()\n\n# Testing the function with a sample input\nprint_diamond_pattern(4)\n\n"
  },
  {
    "path": "Patterns/numerical_pattern.java",
    "content": "/*\nProblem:\nThis program prints a pattern of numbers in an organized way.\nThe numbers start from 1 and increase in a triangular pattern.\nEach row in the pattern contains the numbers from 1 to the row number.\nThe row numbers increase from 1 to the given input number.\n \nApproach:\n- Use nested loops to iterate through each row and each number within the row.\n- The outer loop controls the row number and runs from 1 to the input number.\n- The inner loop prints the numbers for each row and runs from 1 to the row number.\n- Print each number followed by a space.\n- After each row is printed, insert a new line.\n\nTime Complexity: O(n^2), where n is the given input number. This is because we have nested loops that iterate n times.\nSpace Complexity: O(1) as no extra space is required other than the given input.\n \nSample Input 1:\n5\nSample Output 1:\n1\n1 2\n1 2 3\n1 2 3 4\n1 2 3 4 5\n \nSample Input 2:\n3\nSample Output 2:\n1\n1 2\n1 2 3\n*/\n\npublic class NumericalPattern {\n    public static void printPattern(int n) {\n        for (int i = 1; i <= n; i++) {           // iterate through each row\n            for (int j = 1; j <= i; j++) {       // iterate through each number within the row\n                System.out.print(j + \" \");      // print the number followed by a space\n            }\n            System.out.println();               // insert a new line after each row\n        }\n    }\n    \n    public static void main(String[] args) {\n        int n = 5;   // sample input\n        printPattern(n);\n    }\n}\n"
  },
  {
    "path": "Patterns/triangular_pattern.java",
    "content": "/*\nApproach:\n- Initialize the `rows` variable to determine the number of rows in the pattern.\n- Initialize the `count` variable to keep track of the current number.\n- Use nested `for` loops to iterate through the rows and columns.\n- Print the current `count` value and increment it after printing.\n- Move to the next line after each row by using `System.out.println()`.\n\nTime Complexity: The nested loops iterate through the rows and columns of the pattern, resulting in a time complexity of O(rows^2).\n\nSpace Complexity: The space complexity is O(1) as we only require a few variables to store the number of rows, current count, and loop indices.\n\nSample Input (rows = 5):\n5\n\nSample Output:\n1 \n2 3 \n4 5 6 \n7 8 9 10 \n11 12 13 14 15 \n*/\n\n//Java code for generating a number pattern in a triangular pattern, starting from 1:\n\npublic class triangular_pattern {\n    public static void main(String[] args) {\n        int rows = 5; // number of rows in the pattern\n\n        int count = 1; // variable to keep track of the current number\n      \n        // loop through the rows\n        for (int i = 1; i <= rows; i++) {\n            // loop through the columns\n            for (int j = 1; j <= i; j++) {\n                System.out.print(count + \" \");\n                count++;\n            }\n            System.out.println(); // move to the next line after each row\n        }\n    }\n}\n\n"
  },
  {
    "path": "Patterns/triangular_pattern.py",
    "content": "'''\nExplanation:\n1. The code defines a function `print_triangular_pattern()` that takes a parameter `n`. This parameter determines the number of rows in the triangular pattern.\n2. Inside the function, `num` is initialized to 1, which is the starting number of the pattern.\n3. The code then uses nested loops. The outer loop runs from 1 to `n`, which represents the number of rows.\n4. The inner loop runs from 1 to the current row number (i). It prints the numbers in each row in increasing order.\n5. After printing all the numbers in a row, the code moves to the next line using `print()` to create a new row.\n6. Ultimately, the pattern is printed as a set of rows, forming a triangular shape.\n\nTime Complexity: The time complexity of this code is O(n^2), where n is the number of rows. This is because we have two nested loops, one iterating n times and the other iterating up to the current row number.\n\nSpace Complexity: The space complexity of this code is O(1), as we are not using any additional data structures that depend on the input size.\n\nSample Input:\nn = 5\n\nSample Output:\n1 \n2 3 \n4 5 6 \n7 8 9 10 \n11 12 13 14 15\n\n'''\n\n#code in Python that prints a number pattern in a triangular pattern starting from 1:\n\ndef print_triangular_pattern(n):\n    num = 1  # Initialize the starting number\n\n    for i in range(1, n + 1):  # Iterate through each row\n        for j in range(1, i + 1):  # Print numbers in each row\n            print(num, end=\" \")\n            num += 1  # Increment the number for the next iteration\n        print()  # Move to the next line after each row\n\n\n# Example usage\nn = 5\nprint_triangular_pattern(n)\n\n\n"
  },
  {
    "path": "Priority Queues/In_Place_HeapSort.cpp",
    "content": "/*\nGiven an integer array of size N. Sort this array (in decreasing order) using heap sort.\nNote: Space complexity should be O(1).\nInput Format:\n\nThe first line of input contains an integer, that denotes the value of the size of the array or N.\nThe following line contains N space separated integers, that denote the value of the elements of the array.\n\nOutput Format :\n\nThe first and only line of output contains array elements after sorting. The elements of the array in the output are separated by single space.\n\nConstraints :\n\n1 <= n <= 10^6\nTime Limit: 1 sec\n\nSample Input 1:\n\n6\n2 6 8 5 4 3\n\nSample Output 1:\n\n8 6 5 4 3 2\n\nExplaination :\n    The code implements the heap sort algorithm, which is a sorting algorithm that works by first building a max heap. A max heap is a binary tree where the value of each parent node is greater than or equal to the value of each of its child nodes.\n\n    The heap sort algorithm works by repeatedly swapping the root element of the heap with the last element of the array and then rebuilding the heap without the root element. This process is repeated until the array is sorted.\n\n    The code first defines a function called heapSort(). This function takes two parameters: an array of integers and the size of the array. The function builds a max heap from the bottom up and then sorts the array by repeatedly swapping the root element with the last element and rebuilding the heap.\n\n    The main function of the code prompts the user to enter the size of the array and then prompts the user to enter the elements of the array. The main function then calls the heapSort() function and prints the sorted array.\n\n    The intuition behind the heap sort algorithm is that it takes advantage of the fact that a max heap is already partially sorted. By repeatedly swapping the root element with the last element of the array and rebuilding the heap, the algorithm is able to sort the array in a relatively efficient way.\n\n    The heap sort algorithm is a divide-and-conquer algorithm, which means that it breaks the problem of sorting an array into smaller and smaller subproblems until they are trivial to solve. This makes the algorithm very efficient for sorting large arrays.\n*/\n#include <iostream>\n\nusing namespace std;\n\nvoid heapSort(int arr[], int n)\n{\n    // This function sorts an array using the heap sort algorithm.\n    // The algorithm works by first building a max heap.\n    // Then, the root of the heap is swapped with the last element of the array.\n    // The heap is then rebuilt without the root element.\n    // This process is repeated until the array is sorted.\n\n    for (int i = 1; i < n; i++)\n    {\n        // Recursively build a max heap from the bottom up.\n        int childIndex = i;\n        while (childIndex > 0)\n        {\n            int parentIndex = (childIndex - 1) / 2;\n            if (arr[childIndex] < arr[parentIndex])\n            {\n                // Swap the child and parent.\n                int temp = arr[childIndex];\n                arr[childIndex] = arr[parentIndex];\n                arr[parentIndex] = temp;\n            }\n            else\n            {\n                // The heap is already a max heap.\n                break;\n            }\n            childIndex = parentIndex;\n        }\n    }\n\n    // Sort the array by repeatedly swapping the root element with the last element and rebuilding the heap.\n    int j = n;\n    while (j > 1)\n    {\n        // Swap the root element with the last element.\n        int temp = arr[0];\n        arr[0] = arr[j - 1];\n        arr[j - 1] = temp;\n        j--;\n\n        // Rebuild the heap without the root element.\n        int parentIndex = 0;\n        int rightChildIndex = 2 * parentIndex + 2;\n        int leftChildIndex = 2 * parentIndex + 1;\n        while (leftChildIndex < j)\n        {\n            // Find the minimum child.\n            int minIndex = parentIndex;\n            if (arr[leftChildIndex] < arr[minIndex])\n            {\n                minIndex = leftChildIndex;\n            }\n            if (rightChildIndex < j && arr[rightChildIndex] < arr[minIndex])\n            {\n                minIndex = rightChildIndex;\n            }\n\n            // Swap the minimum child with the parent.\n            int temp = arr[minIndex];\n            arr[minIndex] = arr[parentIndex];\n            arr[parentIndex] = temp;\n\n            if (parentIndex == minIndex)\n            {\n                // The heap is already a max heap.\n                break;\n            }\n            parentIndex = minIndex;\n            rightChildIndex = 2 * parentIndex + 2;\n            leftChildIndex = 2 * parentIndex + 1;\n        }\n    }\n}\n\nint main()\n{\n    int size;\n    cin >> size;\n\n    int *input = new int[size];\n\n    for (int i = 0; i < size; i++)\n    {\n        cin >> input[i];\n    }\n\n    heapSort(input, size);\n\n    for (int i = 0; i < size; i++)\n    {\n        cout << input[i] << \" \";\n    }\n\n    delete[] input;\n}\n"
  },
  {
    "path": "Priority Queues/buy_the_ticket.cpp",
    "content": "/*\nYou want to buy a ticket for a well-known concert which is happening in your city. But the number of tickets available is limited. Hence the sponsors of the concert decided to sell tickets to customers based on some priority.\nA queue is maintained for buying the tickets and every person is attached with a priority (an integer, 1 being the lowest priority).\nThe tickets are sold in the following manner -\n\n1. The first person (pi) in the queue requests for the ticket.\n2. If there is another person present in the queue who has higher priority than pi, then ask pi to move at end of the queue without giving him the ticket.\n3. Otherwise, give him the ticket (and don't make him stand in queue again).\n\nGiving a ticket to a person takes exactly 1 minute and it takes no time for removing and adding a person to the queue. And you can assume that no new person joins the queue.\nGiven a list of priorities of N persons standing in the queue and the index of your priority (indexing starts from 0). Find and return the time it will take until you get the ticket.\nInput Format:\n\nThe first line of input contains an integer, that denotes the value of total number of people standing in queue or the size of the array of priorities. Let us denote it with the symbol N.\nThe following line contains N space separated integers, that denote the value of the elements of the array of priorities.\nThe following contains an integer, that denotes the value of index of your priority. Let us denote it with symbol k.\n\nOutput Format :\n\nThe first and only line of output contains the time required for you to get the ticket.\n\nConstraints:\n\nTime Limit: 1 sec\n\nSample Input 1 :\n\n3\n3 9 4\n2\n\nSample Output 1 :\n\n2\n\nSample Output 1 Explanation :\n\nPerson with priority 3 comes out. But there is a person with higher priority than him. So he goes and then stands in the queue at the end. Queue's status :  {9, 4, 3}. Time : 0 secs.\nNext, the person with priority 9 comes out. And there is no person with higher priority than him. So he'll get the ticket. Queue's status :  {4, 3}. Time : 1 secs.\nNext, the person with priority 4 comes out (which is you). And there is no person with higher priority than you. So you'll get the ticket. Time : 2 secs.\n\nSample Input 2 :\n\n5\n2 3 2 2 4\n3\n\nSample Output 2 :\n\n4\n\nExplaination :\n    The code first defines two data structures: a priority queue and a queue. The priority queue is used to store the priorities of all the people in the queue, and the queue is used to store the indices of the people in the queue.\n\n    The function buyTicket() takes three parameters: an array of priorities, the number of people in the queue, and the index of the person who is buying the ticket. The function first pushes all the priorities into the priority queue. Then, it pushes all the indices into the queue.\n\n    The function then enters a loop. In each iteration of the loop, the function checks if the priority of the person at the front of the queue is equal to the priority of the person who is buying the ticket. If it is, the function increments the time by 1, pops the person at the front of the queue, and pops the person at the front of the queue. If it is not, the function pops the person at the front of the queue and pushes them back into the queue.\n\n    The function continues looping until the person who is buying the ticket is at the front of the queue. The function then returns the time it took for the person to buy the ticket.\n\n    The main function of the code first prompts the user to enter the number of people in the queue. Then, it creates an array of priorities and prompts the user to enter the priorities of all the people in the queue. Finally, it prompts the user to enter the index of the person who is buying the ticket, and it prints the time it took for the person to buy the ticket.\n\n*/\n\n#include <iostream>\n#include <vector>\n#include <queue>\nusing namespace std;\n\nint buyTicket(int *arr, int n, int k)\n{\n    // Initialize a priority queue to store the priorities of all the people in the queue.\n    priority_queue<int> pq;\n    // Initialize a queue to store the indices of all the people in the queue.\n    queue<int> indices;\n    // Push all the priorities into the priority queue.\n    for (int i = 0; i < n; i++)\n    {\n        pq.push(arr[i]);\n    }\n    // Push all the indices into the queue.\n    for (int i = 0; i < n; i++)\n    {\n        indices.push(i);\n    }\n    // Initialize the time it took for the person to buy the ticket.\n    int time = 0;\n    // Loop until the person who is buying the ticket is at the front of the queue.\n    while (!indices.empty())\n    {\n        // Check if the priority of the person at the front of the queue is equal to the priority of the person who is buying the ticket.\n        if (arr[indices.front()] == pq.top() && indices.front() == k)\n        {\n            time++;\n            pq.pop();\n            indices.pop();\n            break;\n        }\n        // If the priorities match, increment the time by 1 and break out of the loop.\n        if (arr[indices.front()] == pq.top())\n        {\n            time++;\n            pq.pop();\n            indices.pop();\n        }\n        // If the priorities do not match, pop the person at the front of the queue and push them back into the queue.\n        else\n        {\n            int temp = indices.front();\n            indices.pop();\n            indices.push(temp);\n        }\n    }\n    // Return the time it took for the person to buy the ticket.\n    return time;\n}\n\nint main()\n{\n    // Prompt the user to enter the number of people in the queue.\n    int n;\n    cin >> n;\n    // Create an array of priorities and prompt the user to enter the priorities of all the people in the queue.\n    int *arr = new int[n];\n    for (int i = 0; i < n; i++)\n    {\n        cin >> arr[i];\n    }\n\n    // Prompt the user to enter the index of the person who is buying the ticket.\n    int k;\n    cin >> k;\n\n    // Print the time it took for the person to buy the ticket.\n    cout << buyTicket(arr, n, k);\n\n    // Delete the array of priorities.\n    delete[] arr;\n}"
  },
  {
    "path": "Priority Queues/check_max_heap.cpp",
    "content": "/*\nGiven an array of integers, check whether it represents max-heap or not. Return true if the given array represents max-heap, else return false.\nInput Format:\n\nThe first line of input contains an integer, that denotes the value of the size of the array. Let us denote it with the symbol N.\nThe following line contains N space separated integers, that denote the value of the elements of the array.\n\nOutput Format :\n\nThe first and only line of output contains true if it represents max-heap and false if it is not a max-heap.\n\nConstraints:\n\n1 <= N <= 10^5\n1 <= Ai <= 10^5\nTime Limit: 1 sec\n\nSample Input 1:\n\n8\n42 20 18 6 14 11 9 4\n\nSample Output 1:\n\ntrue\n\nExplaination :\n    The code first defines a function called isMaxHeap(). This function takes two parameters: an array of integers and the size of the array. The function recursively checks if the array is a max heap. A max heap is a binary tree where the value of each parent node is greater than or equal to the value of each of its child nodes.\n\n    The function starts by checking the last element of the array. If the parent of the last element is smaller than the last element, the function returns false. Otherwise, the function recursively checks the parent of the last element. This process continues until the function reaches the root of the tree.\n\n    If the function reaches the root of the tree and all of the parent nodes are greater than or equal to their child nodes, the function returns true. Otherwise, the function returns false.\n\n    The main function of the code prompts the user to enter the size of the array and then prompts the user to enter the elements of the array. The main function then calls the isMaxHeap() function and prints the result.\n\n*/\n\n#include <iostream>\nusing namespace std;\n\nbool isMaxHeap(int arr[], int n)\n{\n\n    // This function recursively checks if the array is a max heap.\n    // The function starts at the last element of the array and checks if the parent is smaller than the child.\n    // If the parent is smaller than the child, the function returns false.\n    // Otherwise, the function recursively checks the parent of the child.\n\n    int childIndex = n - 1;\n    while (childIndex >= 0)\n    {\n        int parentIndex = (childIndex - 1) / 2;\n        // Check if the parent is smaller than the child.\n        if (arr[parentIndex] < arr[childIndex])\n        {\n            return false;\n        }\n        // Recursively check the parent of the child.\n        childIndex--;\n    }\n    // The array is a max heap.\n    return true;\n}\n\nint main()\n{\n\n    // Prompt the user to enter the size of the array.\n    int n;\n    cin >> n;\n\n    // Create an array and prompt the user to enter the elements of the array.\n    int *arr = new int[n];\n    for (int i = 0; i < n; i++)\n    {\n        cin >> arr[i];\n    }\n\n    // Check if the array is a max heap.\n    cout << (isMaxHeap(arr, n) ? \"true\\n\" : \"false\\n\");\n\n    // Delete the array.\n    delete[] arr;\n}\n"
  },
  {
    "path": "Priority Queues/kth_largest_element.cpp",
    "content": "/*\nGiven an array A of random integers and an integer k, find and return the kth largest element in the array.\nNote: Try to do this question in less than O(N * logN) time.\nInput Format :\n\nThe first line of input contains an integer, that denotes the value of the size of the array. Let us denote it with the symbol N.\nThe following line contains N space separated integers, that denote the value of the elements of the array.\nThe following contains an integer, that denotes the value of k.\n\nOutput Format :\n\nThe first and only line of output contains the kth largest element\n\nConstraints :\n\n1 <= N, Ai, k <= 10^5\nTime Limit: 1 sec\n\nSample Input 1 :\n\n6\n9 4 8 7 11 3\n2\n\nSample Output 1 :\n\n9\n\nSample Input 2 :\n\n8\n2 6 10 11 13 4 1 20\n4\n\nSample Output 2 :\n\n10\n\nExplaination :\n    The code uses a min-heap priority queue (pq) to find the kth largest element in the given array. It initializes the priority queue with the first k elements of the array. Then, it iterates over the remaining elements of the array and compares each element with the smallest element (top) of the priority queue. If the current element is larger, it replaces the smallest element in the priority queue. Finally, it returns the top element of the priority queue, which will be the kth largest element.\n\n    Note: The code dynamically allocates memory for the array using new and deallocates it using delete[] to ensure proper memory management.\n\n*/\n#include <iostream>\n#include <vector>\n#include <queue>\nusing namespace std;\n\n// Function to find the kth largest element in an array\nint kthLargest(int *arr, int n, int k)\n{\n    // Create a min-heap priority queue\n    priority_queue<int, vector<int>, greater<int>> pq;\n\n    // Insert the first k elements into the priority queue\n    for (int i = 0; i < k; i++)\n    {\n        pq.push(arr[i]);\n    }\n\n    // Iterate over the remaining elements in the array\n    for (int i = k; i < n; i++)\n    {\n        // If the current element is greater than the smallest element in the priority queue (top),\n        // replace the smallest element with the current element\n        if (arr[i] > pq.top())\n        {\n            pq.push(arr[i]);\n            pq.pop();\n        }\n    }\n\n    // The top element of the priority queue will be the kth largest element\n    return pq.top();\n}\n\nint main()\n{\n    int n;\n    cin >> n;\n\n    // Dynamically allocate memory for the array\n    int *arr = new int[n];\n\n    // Read the elements of the array from the user\n    for (int i = 0; i < n; i++)\n    {\n        cin >> arr[i];\n    }\n\n    int k;\n    cin >> k;\n\n    // Call the kthLargest function to find the kth largest element\n    cout << kthLargest(arr, n, k);\n\n    // Deallocate the memory for the array\n    delete[] arr;\n}\n"
  },
  {
    "path": "Priority Queues/kth_smallest_element.cpp",
    "content": "/*\nYou are given with an integer k and an array of integers that contain numbers in random order. Write a program to find k smallest numbers from given array. You need to save them in an array and return it.\nTime complexity should be O(n * logk) and space complexity should not be more than O(k).\nNote: Order of elements in the output is not important.\nInput Format :\n\nThe first line of input contains an integer, that denotes the value of the size of the array. Let us denote it with the symbol N.\nThe following line contains N space separated integers, that denote the value of the elements of the array.\nThe following line contains an integer, that denotes the value of k.\n\nOutput Format :\n\nThe first and only line of output print k smallest elements. The elements in the output are separated by a single space.\n\nConstraints:\n\nTime Limit: 1 sec\n\nSample Input 1 :\n\n13\n2 12 9 16 10 5 3 20 25 11 1 8 6\n4\n\nSample Output 1 :\n\n1 2 3 5\n\nExplaination :\n\n    The code first defines a function called kSmallest(). This function takes three parameters: an array of integers, the size of the array, and the number of smallest elements to find. The function uses a priority queue to find the k smallest elements in the array.\n\n    The code then defines a main function. The main function prompts the user to enter the size of the array and the number of smallest elements to find. The main function then creates an array of integers and prompts the user to enter the elements of the array. The main function then calls the kSmallest() function and prints the k smallest elements in the array.\n\n    The kSmallest() function works as follows:\n\n        The function first creates a priority queue and pushes the first k elements of the array onto the priority queue.\n        The function then iterates through the remaining elements of the array. If the current element is less than the top element of the priority queue, the function pushes the current element onto the priority queue and pops the top element of the priority queue.\n        The function then returns a vector of the elements in the priority queue.\n\n\n*/\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <queue>\nusing namespace std;\n\n// This function finds the k smallest elements in an array.\nvector<int> kSmallest(int arr[], int n, int k)\n{\n\n    // Create a priority queue and push the first k elements of the array onto the priority queue.\n    priority_queue<int> pq;\n    for (int i = 0; i < k; i++)\n    {\n        pq.push(arr[i]);\n    }\n\n    // Iterate through the remaining elements of the array.\n    // If the current element is less than the top element of the priority queue,\n    // push the current element onto the priority queue and pop the top element of the priority queue.\n    for (int i = k; i < n; i++)\n    {\n        if (arr[i] < pq.top())\n        {\n            pq.push(arr[i]);\n            pq.pop();\n        }\n    }\n\n    // Return a vector of the elements in the priority queue.\n    vector<int> vec;\n    while (!pq.empty())\n    {\n        vec.push_back(pq.top());\n        pq.pop();\n    }\n    return vec;\n}\n\n// This is the main function.\nint main()\n{\n\n    // Prompt the user to enter the size of the array and the number of smallest elements to find.\n    int size;\n    cin >> size;\n\n    // Create an array of integers.\n    int *input = new int[size];\n\n    // Prompt the user to enter the elements of the array.\n    for (int i = 0; i < size; i++)\n    {\n        cin >> input[i];\n    }\n\n    // Prompt the user to enter the number of smallest elements to find.\n    int k;\n    cin >> k;\n\n    // Call the `kSmallest()` function and print the k smallest elements in the array.\n    vector<int> output = kSmallest(input, size, k);\n\n    // Sort the output vector in ascending order.\n    sort(output.begin(), output.end());\n\n    // Print the output vector.\n    for (int i = 0; i < output.size(); i++)\n    {\n        cout << output[i] << \" \";\n    }\n\n    // Delete the array.\n    delete[] input;\n    return 0;\n}\n"
  },
  {
    "path": "Priority Queues/merge_k_sorted_arrays.cpp",
    "content": "/*\nGiven k different arrays, which are sorted individually (in ascending order). You need to merge all the given arrays such that output array should be sorted (in ascending order).\nHint : Use Heaps.\nInput Format:\n\nThe first line of input contains an integer, that denotes value of k.\nThe following lines of input represent k sorted arrays. Each sorted array uses two lines of input. The first line contains an integer, that denotes the size of the array. The following line contains elements of the array.\n\nOutput Format:\n\nThe first and only line of output contains space separated elements of the merged and sorted array, as described in the task.\n\nConstraints:\n\n0 <= k <= 1000\n0 <= n1, n2 <= 10000\nTime Limit: 1 second\n\nSample Input 1:\n\n4\n3\n1 5 9\n2\n45 90\n5\n2 6 78 100 234\n1\n0\n\nSample Output 1:\n\n0 1 2 5 6 9 45 78 90 100 234\n\nExplaination :\n    The intuition behind the code is to use a min-heap (priority queue) to merge K sorted arrays efficiently.\n\n    By taking the first element from each array and inserting it into the priority queue, the smallest element is always at the top. This ensures that when elements are extracted from the priority queue, they are in sorted order.\n\n    The code iteratively extracts the smallest element from the priority queue, adds it to the merged sorted array, and checks if there are remaining elements in the array from which the extracted element came. If so, the next element from that array is inserted into the priority queue.\n\n    This process continues until all elements from all arrays are processed and added to the merged sorted array.\n\n    By utilizing the min-heap property of the priority queue, the code efficiently merges the sorted arrays in a way that the overall time complexity is optimized. The priority queue allows for easy retrieval of the smallest element, resulting in an overall time complexity of O(N log K), where N is the total number of elements across all arrays and K is the number of arrays.\n*/\n#include <iostream>\n#include <vector>\n#include <queue>\nusing namespace std;\n\nvector<int> mergeKSortedArrays(vector<vector<int> *> input)\n{\n    // Create a min-heap priority queue to store elements from different arrays\n    priority_queue<pair<int, pair<int, int>>, vector<pair<int, pair<int, int>>>, greater<pair<int, pair<int, int>>>> pq;\n\n    // Insert the first element from each array into the priority queue\n    for (int i = 0; i < input.size(); i++)\n    {\n        pair<int, pair<int, int>> p;\n        p.first = input[i]->at(0); // value of the element\n        p.second.first = i;        // array number\n        p.second.second = 0;       // index of the element\n        pq.push(p);\n    }\n\n    // Initialize a vector to store the merged sorted array\n    vector<int> ans;\n\n    // Process the priority queue until it becomes empty\n    while (!pq.empty())\n    {\n        pair<int, pair<int, int>> p = pq.top();\n        pq.pop();\n\n        // Add the minimum element to the result vector\n        ans.push_back(p.first);\n\n        int arrNo = p.second.first;      // array number\n        int index = p.second.second + 1; // index of the next element in the array\n\n        // If there are still elements remaining in the array, add the next element to the priority queue\n        if (index < input[arrNo]->size())\n        {\n            p.first = input[arrNo]->at(index); // value of the element\n            p.second.second = index;           // update the index\n            pq.push(p);\n        }\n    }\n\n    // Return the merged sorted array\n    return ans;\n}\n\nint main()\n{\n    int k;\n    cin >> k; // Number of sorted arrays\n\n    vector<vector<int> *> input; // Vector to store the arrays\n\n    // Read the size and elements of each array\n    for (int j = 1; j <= k; j++)\n    {\n        int size;\n        cin >> size; // Size of the array\n\n        // Create a dynamically allocated vector for the current array\n        vector<int> *current = new vector<int>;\n\n        // Read the elements of the array\n        for (int i = 0; i < size; i++)\n        {\n            int a;\n            cin >> a;              // Element of the array\n            current->push_back(a); // Add the element to the current array\n        }\n\n        // Add the current array to the vector of arrays\n        input.push_back(current);\n    }\n\n    // Merge the sorted arrays using the mergeKSortedArrays function\n    vector<int> output = mergeKSortedArrays(input);\n\n    // Print the merged sorted array\n    for (int i = 0; i < output.size(); i++)\n    {\n        cout << output[i] << \" \";\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "Priority Queues/running_median.cpp",
    "content": "/*\nYou are given a stream of 'N' integers. For every 'i-th' integer added to the running list of integers, print the resulting median.\nPrint only the integer part of the median.\nInput Format :\n\nThe first line of input contains an integer 'N', denoting the number of integers in the stream.\n\nThe second line of input contains 'N' integers separated by a single space.\n\nOutput Format :\n\nPrint the running median for every integer added to the running list in one line (space-separated).\n\nInput Constraints\n\n0 <= N <= 10 ^ 5\n1 <= ARR[i] <= 10 ^ 5\n\nTime Limit: 1 sec\n\nSample Input 1 :\n\n6\n6 2 1 3 7 5\n\nSample Output 1 :\n\n6 4 2 2 3 4\n\nExplanation of Sample Output 1 :\n\nS = {6}, median = 6\nS = {6, 2} -> {2, 6}, median = 4\nS = {6, 2, 1} -> {1, 2, 6}, median = 2\nS = {6, 2, 1, 3} -> {1, 2, 3, 6}, median = 2\nS = {6, 2, 1, 3, 7} -> {1, 2, 3, 6, 7}, median = 3\nS = {6, 2, 1, 3, 7, 5} -> {1, 2, 3, 5, 6, 7}, median = 4\n\nSample Input 2 :\n\n5\n5 4 3 2 1\n\nSample Output 2 :\n\n5 4 4 3 3\n\nExplaination :\n\n    The code aims to efficiently find and print the median of a stream of integers as they are read one by one. It achieves this by using two priority queues: `min` and `max`. These priority queues divide the elements encountered so far into the lower and higher halves, allowing for the calculation of the median.\n\n    When reading the integers one by one, the code follows these steps:\n\n    1. For the first element, it is pushed into the `max` priority queue. At this point, the median is simply the first element.\n\n    2. For subsequent elements, the code compares each element with the current median (which is the top element of the `max` priority queue). If the new element is smaller, it is pushed into the `max` priority queue. This ensures that the lower half of the elements is stored in `max`, with the maximum element of the lower half at the top.\n\n    3. If the new element is larger than the current median, it is pushed into the `min` priority queue. This ensures that the higher half of the elements is stored in `min`, with the minimum element of the higher half at the top.\n\n    4. After each insertion, the code checks the size difference between the `min` and `max` priority queues. If the difference exceeds 1, it rebalances the queues by transferring the top element from the larger queue to the smaller one. This ensures that the size difference between the two halves remains at most 1, allowing for accurate median calculations.\n\n    5. To calculate and print the median, the code checks the total number of elements (c) in both priority queues. If c is even, the median is the average of the top elements of `min` and `max`. If c is odd, the median is the top element of the priority queue with more elements.\n\n    By using two priority queues to maintain the lower and higher halves of the elements encountered so far, the code efficiently updates and calculates the median of the stream of integers in a scalable manner. The rebalancing step ensures that the size difference between the two halves remains at most 1, allowing for accurate median calculations even as new elements are added to the stream.\n\n*/\n#include <iostream>\n#include <queue>\nusing namespace std;\n\nvoid findMedian(int *arr, int n)\n{\n    priority_queue<int, vector<int>, greater<int>> min; // Min-heap to store the higher half of the elements encountered\n    priority_queue<int> max;                            // Max-heap to store the lower half of the elements encountered\n\n    for (int i = 0; i < n; i++)\n    {\n        if (i == 0)\n        {\n            max.push(arr[i]); // For the first element, push it into the max heap\n        }\n        else\n        {\n            if (max.top() > arr[i])\n            {\n                max.push(arr[i]); // If the new element is smaller than the current median, push it into the max heap\n            }\n            else\n            {\n                min.push(arr[i]); // If the new element is larger than the current median, push it into the min heap\n            }\n        }\n\n        if (int(min.size() - max.size()) > 1)\n        {\n            int temp = min.top();\n            min.pop();\n            max.push(temp); // Rebalance the heaps by transferring the top element from min heap to max heap\n        }\n        else if (int(max.size() - min.size()) > 1)\n        {\n            int temp = max.top();\n            max.pop();\n            min.push(temp); // Rebalance the heaps by transferring the top element from max heap to min heap\n        }\n\n        int c = max.size() + min.size(); // Total count of elements\n\n        if (c % 2 == 0)\n        {\n            cout << (min.top() + max.top()) / 2 << \" \"; // If total count is even, median is the average of the top elements of both heaps\n        }\n        else\n        {\n            if (min.size() > max.size())\n            {\n                cout << min.top() << \" \"; // If total count is odd and min heap has more elements, median is the top element of min heap\n            }\n            else\n            {\n                cout << max.top() << \" \"; // If total count is odd and max heap has more elements, median is the top element of max heap\n            }\n        }\n    }\n\n    cout << endl;\n}\n\nint main()\n{\n    int n;\n    cin >> n; // Number of elements\n\n    int *arr = new int[n]; // Dynamically allocate memory for the array\n\n    for (int i = 0; i < n; ++i)\n    {\n        cin >> arr[i]; // Read the elements of the array\n    }\n\n    findMedian(arr, n); // Find and print the median of the stream\n\n    delete[] arr; // Deallocate the memory\n\n    return 0;\n}\n"
  },
  {
    "path": "Queue/queue.cpp",
    "content": "// Implement Queue data structure in C++\n/*\n    In this implementation, the Queue class has private member variables front, rear, and arr to keep track of the front and rear \n    indices of the queue and the elements in the queue, respectively. The class also has public member functions isFull(), isEmpty(), \n    enqueue(), dequeue(), peek(), and print() for checking if the queue is full or empty, adding elements to the rear of the queue, \n    removing elements from the front of the queue, peeking at the element at the front of the queue, and printing the elements in the \n    queue, respectively. The main() function demonstrates how to use the Queue class by creating a new queue object q, adding three \n    elements to the queue, removing one element from the front of the queue, peeking at the element at the front of the queue, and \n    printing the elements in the queue\n*/\n#include <iostream>\nusing namespace std;\n\nconst int MAX_SIZE = 100; // maximum size of the queue\n\nclass Queue {\nprivate:\n    int front, rear;\n    int arr[MAX_SIZE];\npublic:\n    Queue() {\n        front = -1; // initialize front and rear to -1 to indicate the queue is empty\n        rear = -1;\n    }\n\n    bool isFull() {\n        return rear == MAX_SIZE - 1; // check if the rear index is at the maximum size\n    }\n\n    bool isEmpty() {\n        return front == -1 && rear == -1; // check if both front and rear indices are at -1, indicating an empty queue\n    }\n\n    void enqueue(int x) {\n        if (isFull()) {\n            cout << \"Error: Queue is full\" << endl;\n            return;\n        }\n        if (isEmpty()) {\n            front = rear = 0; // if the queue is empty, set both front and rear to 0 to add the first element\n        }\n        else {\n            rear++; // increment rear to add the new element\n        }\n        arr[rear] = x; // add the new element to the rear of the queue\n    }\n\n    void dequeue() {\n        if (isEmpty()) {\n            cout << \"Error: Queue is empty\" << endl;\n            return;\n        }\n        if (front == rear) {\n            front = rear = -1; // if the queue has only one element, set both front and rear indices to -1 to indicate an empty queue\n        }\n        else {\n            front++; // increment front to remove the element\n        }\n    }\n\n    int peek() {\n        if (isEmpty()) {\n            cout << \"Error: Queue is empty\" << endl;\n            return -1;\n        }\n        return arr[front]; // return the element at the front of the queue\n    }\n\n    void print() {\n        if (isEmpty()) {\n            cout << \"Queue is empty\" << endl;\n            return;\n        }\n        cout << \"Queue: \";\n        for (int i = front; i <= rear; i++) {\n            cout << arr[i] << \" \"; // print each element in the queue from front to rear\n        }\n        cout << endl;\n    }\n};\n\nint main() {\n    Queue q;\n    q.enqueue(1);\n    q.enqueue(2);\n    q.enqueue(3);\n    q.print(); // output: Queue: 1 2 3\n    q.dequeue();\n    q.print(); // output: Queue: 2 3\n    cout << \"Front element: \" << q.peek() << endl; // output: Front element: 2\n    return 0;\n}\n"
  },
  {
    "path": "Queue/queue.go",
    "content": "// Queue Data Structure\n/*\n\tIn this implementation, we define a struct for the queue that has a slice to store the values and pointers to the \n\tfront and rear of the queue. We also define methods for checking if the queue is empty, adding an element to the \n\trear of the queue, and removing an element from the front of the queue.\n\n\tThe NewQueue() function creates a new queue and initializes its front and rear pointers to nil. The IsEmpty() \n\tmethod checks if the queue is empty by checking if the front pointer is nil. The Enqueue() method adds an \n\telement to the rear of the queue by appending it to the slice and updating the rear pointer. The Dequeue() \n\tmethod removes an element from the front of the queue by removing it from the slice and updating the front \n\tpointer.\n\n\tIn the main() function, we create a new queue, add some elements to it, and then dequeue them one \n\tby one and print their values.\n*/\npackage main\n\nimport \"fmt\"\n\n// Define a struct for queue that has a slice to store values and pointers to the front and rear of the queue\ntype Queue struct {\n    values []int\n    front  *int\n    rear   *int\n}\n\n// Function to create a new queue and initialize its front and rear pointers\nfunc NewQueue() *Queue {\n    q := Queue{values: make([]int, 0), front: nil, rear: nil}\n    return &q\n}\n\n// Function to check if the queue is empty\nfunc (q *Queue) IsEmpty() bool {\n    return q.front == nil\n}\n\n// Function to add an element to the rear of the queue\nfunc (q *Queue) Enqueue(val int) {\n    // If the queue is empty, set both front and rear pointers to the new element\n    if q.front == nil {\n        q.front = &val\n        q.rear = &val\n    } else {\n        // Otherwise, add the new element to the rear of the queue and update the rear pointer\n        q.values = append(q.values, val)\n        q.rear = &q.values[len(q.values)-1]\n    }\n}\n\n// Function to remove an element from the front of the queue and return its value\nfunc (q *Queue) Dequeue() (int, error) {\n    // If the queue is empty, return an error\n    if q.front == nil {\n        return 0, fmt.Errorf(\"queue is empty\")\n    }\n\n    // Get the value of the element at the front of the queue\n    val := *q.front\n\n    // If there is only one element in the queue, set both front and rear pointers to nil\n    if len(q.values) == 1 {\n        q.front = nil\n        q.rear = nil\n    } else {\n        // Otherwise, remove the front element from the slice and update the front pointer\n        q.values = q.values[1:]\n        q.front = &q.values[0]\n    }\n\n    // Return the value of the dequeued element\n    return val, nil\n}\n\nfunc main() {\n    // Create a new queue\n    q := NewQueue()\n\n    // Add some elements to the queue\n    q.Enqueue(10)\n    q.Enqueue(20)\n    q.Enqueue(30)\n\n    // Dequeue elements from the queue and print their values\n    for !q.IsEmpty() {\n        val, err := q.Dequeue()\n        if err != nil {\n            fmt.Println(err)\n        } else {\n            fmt.Println(val)\n        }\n    }\n}\n"
  },
  {
    "path": "Queue/queue.java",
    "content": "// 1. Queue Using Array:\n// 2. Queue Using LinkedList:\n/*\n    In this implementation, we use an array to store the elements of the queue, and we keep track of the front and rear indices, as well as the current size of the queue.\n    The enqueue operation adds an item to the rear of the queue, while the dequeue operation removes an item from the front of the queue.\n    The isEmpty and isFull methods check whether the queue is empty or full, respectively, while the size method returns the current size of the queue.\n\n*/  \n// 1. Queue Using Array:\npublic class Queue {\n        private int maxSize;\n        private int[] queueArray;\n        private int front;\n        private int rear;\n        private int currentSize;\n\n        public Queue(int size) {\n            this.maxSize = size;\n            this.queueArray = new int[size];\n            this.front = 0;\n            this.rear = -1;\n            this.currentSize = 0;\n        }\n\n        public void enqueue(int item) {\n            if (isFull()) {\n                System.out.println(\"Queue is full\");\n                return;\n            }\n            rear++;\n            if (rear == maxSize) {\n                rear = 0;\n            }\n            queueArray[rear] = item;\n            currentSize++;\n        }\n\n        public int dequeue() {\n            if (isEmpty()) {\n                System.out.println(\"Queue is empty\");\n                return -1;\n            }\n            int temp = queueArray[front];\n            front++;\n            if (front == maxSize) {\n                front = 0;\n            }\n            currentSize--;\n            return temp;\n        }\n\n        public boolean isEmpty() {\n            return currentSize == 0;\n        }\n\n        public boolean isFull() {\n            return currentSize == maxSize;\n        }\n\n        public int size() {\n            return currentSize;\n        }\n    }    \n\n\n    \n\n// Here's an example implementation of a Queue data structure in Java using a linked list\n/*\n    In this implementation, we use a linked list to store the elements of the queue, and we keep track of the front and rear nodes, as well as the current size of the queue.\n    The enqueue operation adds a new node to the rear of the linked list, while the dequeue operation removes the head node from the linked list.\n    The isEmpty method checks whether the queue is empty, while the size method returns the current size of the queue.\n    Note that this implementation uses generics to allow the queue to store elements of any type.\n*/\n// 2. Queue Using LinkedList:\npublic class Queue<T> {\n        private Node<T> front;\n        private Node<T> rear;\n        private int size;\n\n        public Queue() {\n            front = null;\n            rear = null;\n            size = 0;\n        }\n\n        private static class Node<T> {\n            T data;\n            Node<T> next;\n\n            public Node(T data) {\n                this.data = data;\n                this.next = null;\n            }\n        }\n\n        public void enqueue(T item) {\n            Node<T> newNode = new Node<>(item);\n            if (isEmpty()) {\n                front = newNode;\n            } else {\n                rear.next = newNode;\n            }\n            rear = newNode;\n            size++;\n        }\n\n        public T dequeue() {\n            if (isEmpty()) {\n                System.out.println(\"Queue is empty\");\n                return null;\n            }\n            T item = front.data;\n            front = front.next;\n            if (front == null) {\n                rear = null;\n            }\n            size--;\n            return item;\n        }\n\n        public boolean isEmpty() {\n            return size == 0;\n        }\n\n        public int size() {\n            return size;\n        }\n    }    \n\n"
  },
  {
    "path": "Queue/queue.js",
    "content": "// 1. Queue Using Array:\n// 2. Queue Using LinkedList:\n/*\n    In this implementation, we use an array to store the elements of the queue, and we keep track of the front and rear indices, as well as the current size of the queue.\n    The enqueue operation adds an item to the rear of the queue, while the dequeue operation removes an item from the front of the queue.\n    The isEmpty and isFull methods check whether the queue is empty or full, respectively, while the size method returns the current size of the queue.\n\n*/\n// 1. Queue Using Array:\nclass Queue {\n  constructor() {\n    this.items = [];\n  }\n\n  enqueue(element) {\n    this.items.push(element);\n  }\n\n  dequeue() {\n    if (this.isEmpty()) {\n      return \"Underflow\";\n    }\n    return this.items.shift();\n  }\n\n  front() {\n    if (this.isEmpty()) {\n      return \"No elements in Queue\";\n    }\n    return this.items[0];\n  }\n\n  isEmpty() {\n    return this.items.length === 0;\n  }\n\n  printQueue() {\n    let str = \"\";\n    for (let i = 0; i < this.items.length; i++) {\n      str += this.items[i] + \" \";\n    }\n    return str;\n  }\n}\n\n// Here's an example implementation of a Queue data structure in Java using a linked list\n/*\n    In this implementation, we use a linked list to store the elements of the queue, and we keep track of the front and rear nodes, as well as the current size of the queue.\n    The enqueue operation adds a new node to the rear of the linked list, while the dequeue operation removes the head node from the linked list.\n    The isEmpty method checks whether the queue is empty, while the size method returns the current size of the queue.\n    Note that this implementation uses generics to allow the queue to store elements of any type.\n*/\n// 2. Queue Using LinkedList:\nclass Node {\n  constructor(data) {\n    this.data = data;\n    this.next = null;\n  }\n}\n\nclass Queue {\n  constructor() {\n    this.front = null;\n    this.rear = null;\n    this.size = 0;\n  }\n\n  enqueue(data) {\n    let newNode = new Node(data);\n    if (this.rear === null) {\n      this.front = newNode;\n      this.rear = newNode;\n    } else {\n      this.rear.next = newNode;\n      this.rear = newNode;\n    }\n    this.size++;\n  }\n\n  dequeue() {\n    if (this.front === null) {\n      return \"Underflow\";\n    }\n    let removedNode = this.front;\n    this.front = this.front.next;\n    if (this.front === null) {\n      this.rear = null;\n    }\n    this.size--;\n    return removedNode.data;\n  }\n\n  isEmpty() {\n    return this.size === 0;\n  }\n\n  getFront() {\n    return this.front ? this.front.data : \"No elements in Queue\";\n  }\n\n  printQueue() {\n    let str = \"\";\n    let temp = this.front;\n    while (temp) {\n      str += temp.data + \" \";\n      temp = temp.next;\n    }\n    return str;\n  }\n}\n"
  },
  {
    "path": "Queue/queue.py",
    "content": "# Implement Queue Data Structure\n'''\n    This implementation uses a Python list to store the items in the queue. The __init__() method initializes \n    an empty list. The is_empty() method checks whether the list is empty or not by checking the length of \n    the list. The enqueue() method adds an item to the back of the queue by appending it to the end of the \n    list. The dequeue() method removes and returns the item at the front of the queue by using the pop() \n    method to remove the first item in the list. If the list is empty, the method raises an IndexError. \n    The peek() method returns the item at the front of the queue without removing it by returning the \n    first item in the list. If the list is empty, the method raises an IndexError. The size() method \n    returns the number of items in the list by returning the length of the list.\n'''\nclass Queue:\n    def __init__(self):\n        \"\"\"\n        Initializes an empty queue.\n        \"\"\"\n        self.items = []\n\n    def is_empty(self):\n        \"\"\"\n        Returns True if the queue is empty, False otherwise.\n        \"\"\"\n        return len(self.items) == 0\n\n    def enqueue(self, item):\n        \"\"\"\n        Adds the given item to the back of the queue.\n        \"\"\"\n        self.items.append(item)\n\n    def dequeue(self):\n        \"\"\"\n        Removes and returns the item at the front of the queue.\n        If the queue is empty, raises an IndexError.\n        \"\"\"\n        if self.is_empty():\n            raise IndexError(\"Queue is empty\")\n        return self.items.pop(0)\n\n    def peek(self):\n        \"\"\"\n        Returns the item at the front of the queue without removing it.\n        If the queue is empty, raises an IndexError.\n        \"\"\"\n        if self.is_empty():\n            raise IndexError(\"Queue is empty\")\n        return self.items[0]\n\n    def size(self):\n        \"\"\"\n        Returns the number of items in the queue.\n        \"\"\"\n        return len(self.items)\n"
  },
  {
    "path": "Queue/queue_using_stack.js",
    "content": "/*\nImplement a first in first out (FIFO) queue using only two stacks. \nThe implemented queue should support all the functions of a normal queue (push, peek, pop, and empty).\n\nImplement the MyQueue class:\n\nvoid push(int x) Pushes element x to the back of the queue.\n- method adds an element to the back of the queue by pushing it onto stack1. \n\n\nint pop() Removes the element from the front of the queue and returns it.\n- method removes and returns the front element of the queue by first checking if stack2 is empty.\n- if it is, reversing the elements from stack1 onto stack2 so that the front element \n  of the queue is now at the top of stack2. \n- Then it pops the top element from stack2.\n\n\nint peek() Returns the element at the front of the queue.\n- returns the front element of the queue without removing it. \n- First checking if stack2 is empty\n- if it is, reversing the elements from stack1 onto stack2 so that the front element of the queue is now at the top of stack2.\n- Then it returns the top element of stack2.\n\n\nboolean empty() Returns true if the queue is empty, false otherwise.\n- returns a boolean indicating whether the queue is empty or not. \n- It returns true if both stack1 and stack2 are empty, and false otherwise.\n*/\n\nvar MyQueue = function() {\n    this.stack1 = [];\n    this.stack2 = [];\n};\n\n\n/** \n * @param {number} x\n * @return {void}\n */\nMyQueue.prototype.push = function(x) {\n    this.stack1.push(x);\n};\n\n\n/**\n * @return {number}\n */\nMyQueue.prototype.pop = function() {\n    if (this.stack2.length === 0) {\n        if (this.stack1.length === 0) {\n          return \"Underflow\";\n        }\n        while (this.stack1.length > 0) {\n          this.stack2.push(this.stack1.pop());\n        }\n      }\n    return this.stack2.pop();\n};\n\n/**\n * @return {number}\n */\nMyQueue.prototype.peek = function() {\n    if (this.stack2.length === 0) {\n        if (this.stack1.length === 0) {\n          return \"Queue is empty\";\n        }\n        while (this.stack1.length > 0) {\n          this.stack2.push(this.stack1.pop());\n        }\n      }\n    return this.stack2[this.stack2.length - 1];\n};\n\n/**\n * @return {boolean}\n */\nMyQueue.prototype.empty = function() {\n    return this.stack1.length === 0 && this.stack2.length === 0;\n};\n\n\n// MyQueue object will be instantiated and called as such:\nlet myQueue = new MyQueue();\nvar param_0 = myQueue.push(1); // queue is: [1]\nvar param_1 = myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)\nvar param_2 = myQueue.peek(); // return 1\nvar param_3 = myQueue.pop(); // return 1, queue is [2]\nvar param_4 = myQueue.empty(); // return false\n\n"
  },
  {
    "path": "Queue/queue_using_stacks.go",
    "content": "type MyQueue struct {\n    stack1 []int\n    stack2 []int\n}\n\n/** Initialize your data structure here. */\nfunc Constructor() MyQueue {\n    return MyQueue{}\n}\n\n/** Push element x to the back of queue. */\nfunc (this *MyQueue) Push(x int) {\n    this.stack1 = append(this.stack1, x)\n}\n\n/** Removes the element from in front of queue and returns that element. */\nfunc (this *MyQueue) Pop() int {\n    if len(this.stack2) == 0 {\n        this.moveElements()\n    }\n    element := this.stack2[len(this.stack2)-1]\n    this.stack2 = this.stack2[:len(this.stack2)-1]\n    return element\n}\n\n/** Get the front element. */\nfunc (this *MyQueue) Peek() int {\n    if len(this.stack2) == 0 {\n        this.moveElements()\n    }\n    return this.stack2[len(this.stack2)-1]\n}\n\n/** Returns whether the queue is empty. */\nfunc (this *MyQueue) Empty() bool {\n    return len(this.stack1) == 0 && len(this.stack2) == 0\n}\n\n/** Move elements from stack1 to stack2. */\nfunc (this *MyQueue) moveElements() {\n    for len(this.stack1) > 0 {\n        element := this.stack1[len(this.stack1)-1]\n        this.stack1 = this.stack1[:len(this.stack1)-1]\n        this.stack2 = append(this.stack2, element)\n    }\n}\n\n/*\n\nThe MyQueue struct is defined with two slices: stack1 and stack2. stack1 represents the main stack where elements are pushed initially, and stack2 is used to reverse the order of elements for queue operations.\n\nThe Constructor function is a constructor for the MyQueue struct. It initializes an empty MyQueue instance and returns it.\n\nThe Push method takes an integer x and appends it to the stack1 slice, which represents the back of the queue.\n\nThe Pop method removes and returns the element from the front of the queue. It checks if stack2 is empty, and if so, it calls the moveElements method to transfer elements from stack1 to stack2. This ensures that the elements in stack2 are in the correct order for queue operations. The last element of stack2 is then removed and returned as the result.\n\nThe Peek method returns the element at the front of the queue without removing it. It performs the same check as the Pop method to ensure that the elements in stack2 are up to date, and then returns the last element in stack2.\n\nThe Empty method checks if both stack1 and stack2 are empty, indicating whether the queue is empty or not.\n\nThe moveElements method is used to transfer elements from stack1 to stack2 in the correct order. It pops elements from stack1 and appends them to stack2 until stack1 is empty. This ensures that the elements in stack2 are in the reversed order, mimicking the behavior of a queue.\nTime Complexity:\n\nThe Push operation has a time complexity of O(1) because it simply appends an element to the stack1 slice.\nThe Pop operation has an amortized time complexity of O(1). When stack2 is not empty, popping an element is a constant-time operation. If stack2 is empty, the moveElements method is called, which transfers all elements from stack1 to stack2. This transfer operation takes O(n) time, where n is the number of elements in stack1. However, each element is transferred at most twice in total (once from stack1 to stack2 and once from stack2 back to stack1 in future push operations). Therefore, the average time complexity per pop operation is O(1).\nThe Peek operation has the same amortized time complexity as Pop, which is O(1).\nThe Empty operation has a time complexity of O(1) because it checks the lengths of both stack1 and stack2 to determine if the queue is empty.\nSpace Complexity:\n\nThe space complexity of the MyQueue struct is O(n), where n is the number of elements stored in the queue. This includes the space required for the stack1 and stack2 slices.\nIn the worst case, when all elements are stored in stack1, the space complexity is O(n). However, when elements are transferred from stack1 to stack2, the space complexity remains O(n) because each element is moved and stored only once\n\n*/\n"
  },
  {
    "path": "Queue/queues_using_stacks.py",
    "content": "''' Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem : Implement Queue using Stacks in Python\nIssue Number : #256\nProblem statement :\n\nExplanation of the below python code :\n\nIn the above code, the Queue class represents a queue implemented using two stacks. The enqueue method simply adds the element to the first stack (stack1). The dequeue method pops an element from the second stack (stack2) if it's not empty. If stack2 is empty, it transfers all elements from stack1 to stack2 in reverse order and then pops an element from stack2.\n\nThe program provides the user with a menu to select the operation they want to perform - enqueue, dequeue, or quit. The user can input the value to enqueue, and the program prints the enqueued or dequeued value accordingly.\n\nSummary about the code and time complexity:\n\nThis code implements a queue using two stacks.\nThe enqueue operation is simply implemented by appending an element to one of the stacks, while the dequeue operation involves reversing the order of the elements by popping from one stack and pushing onto the other, and then popping the top element from the second stack.\nThe time complexity of the enqueue operation is O(1), while the time complexity of the dequeue operation is O(n) in the worst case, where n is the number of elements in the queue. This is because in the worst case, all the elements will need to be moved from one stack to the other during the dequeue operation.\n\n\n\n----------------------------------------------------------------------------------------------------------//Python code begins here-----------------------------------------------------------------------------------------------------------------------\n'''\n\nclass Queue:\n    def __init__(self):\n        # Initialize two empty stacks\n        self.stack1 = []\n        self.stack2 = []\n\n    def enqueue(self, val):\n        # Add an element to the end of the queue by appending it to stack1\n        self.stack1.append(val)\n\n    def dequeue(self):\n        # If stack2 is empty, reverse the order of the elements by popping from stack1 and pushing onto stack2\n        if not self.stack2:\n            while self.stack1:\n                self.stack2.append(self.stack1.pop())\n        # If stack2 is still empty, the queue is empty, so return None\n        if not self.stack2:\n            return None\n        # Otherwise, pop the top element from stack2 and return it\n        return self.stack2.pop()\n\n# Create an instance of the Queue class\nqueue = Queue()\n\n# Enter into an infinite loop to prompt the user for operations\nwhile True:\n    print(\"Select operation -\\n\"\n          \"1. Enqueue\\n\"\n          \"2. Dequeue\\n\"\n          \"3. Quit\")\n\n    # Prompt the user for their choice of operation\n    choice = int(input(\"Enter choice: \"))\n\n    if choice == 1:\n        # If the user selects option 1, prompt them for a value to enqueue and enqueue it\n        val = int(input(\"Enter value to enqueue: \"))\n        queue.enqueue(val)\n        print(\"Enqueued value:\", val)\n    elif choice == 2:\n        # If the user selects option 2, dequeue a value and print it, or indicate that the queue is empty\n        val = queue.dequeue()\n        if val:\n            print(\"Dequeued value:\", val)\n        else:\n            print(\"Queue is empty.\")\n    elif choice == 3:\n        # If the user selects option 3, quit the loop\n        break\n    else:\n        # If the user selects an invalid option, prompt them to try again\n        print(\"Invalid choice. Please try again.\")\n\n"
  },
  {
    "path": "Queue/stack_using_queue.cpp",
    "content": "// ISSUE # 258\n/* Aim : To implement Stack data structure using two Queues. \nInspired from - https://leetcode.com/problems/implement-stack-using-queues/\nContributor - github user - harsh9607\n\nLOGIC : We have two queues q1 and q2 within the Class Queue_As_stack . The Logic is to use the front of q1 to behave as top of the stack. q2 is used\nas a helper queue. So whenever we want to add a new element we transfer all existing elements from q1 into q2 . When q1 is empty we push the new element.\nThen we transfer back all the elements originally in q1 from q2. \n\nApproach In short : a) Push all from q1 -> q2  b) Insert new element c) Push all from q2 -> q1     \n\nEXAMPLES : Say we want to input three numbers in a stack - 1 , 2 , 3 \n           Implementation will be as follows\n           q1 :  <empty>  \n           q2 :  <empty>\n           >> 1\n           q1 : 1 \n           q2 : <empty>\n           \n           >> 2\n           ( existing data structure ) \n           q1 : 1\n           q2 : <empty> \n           (Step a ) Transfer from q1 ->  q2  \n           q1 : <empty>\n           q2 : 1 \n           Step b ) Insert new element to q1 \n           q1 : 2\n           q2 : 1\n           Step c ) Transfer all from q2 -> q1  \n           q1 : 2 , 1 \n           q2 : <empty> \n           \n           >> 3 \n           ( existing data structure ) \n           q1 : 2 , 1 \n           q2 : <empty> \n           (Step a ) Transfer from q1 ->  q2  \n           q1 : <empty>\n           q2 : 2 , 1\n           Step b ) Insert new element to q1 \n           q1 : 3\n           q2 : 2 , 1\n           Step c ) Transfer all from q2 -> q1  \n           q1 : 3 , 2 , 1 \n           q2 : <empty>  \n  \n    \n*/\n#include<iostream>\n#include<queue>\nusing namespace std; \n\nclass Queue_As_stack {\npublic : queue<int> q1,q2; \n\t   void PUSH(int d) {\n\t\t   if (q1.empty())\n\t\t   {\n\t\t\t   q1.push(d);\n\t\t   }\n\n\t\t   else\n\t\t   {\n\t\t\t   while (!q1.empty())\n\t\t\t   {\n\t\t\t\t   q2.push(q1.front());\n\t\t\t\t   q1.pop();\n\t\t\t   }\n\t\t\t   q1.push(d);\n\t\t\t   while (!q2.empty())\n\t\t\t   {\n\t\t\t\t   q1.push(q2.front());\n\t\t\t\t   q2.pop();\n\t\t\t   }\n\t\t   }\n\t   }\n\n      // Pops out top of stack \n\t\t   void POP()\n\t\t   {\n\t\t\t   q1.pop();\n\t\t   }\n       \n      // Returns the top of stack\n\t\t   int TOP()\n\t\t   {\n\t\t\t   return q1.front();\n\t\t   }\n\t\t\t // It displays as well as empties the stack. \n\t\t   void DISPLAY()\n\t\t   {\n\n\t\t\t   while (!q1.empty())\n\t\t\t   {\n\t\t\t\t   cout << q1.front() << endl;\n\t\t\t\t   q1.pop();\n\t\t\t   }\n\n\t\t   }\n       // To check if stack is empty  \n       bool EMPTY()\n       {\n            if(q1.empty())\n            {\n            return true; \n            }\n            return false;\n       }\n};\n\n\n\nint main()\n{\n\tQueue_As_stack Q1;\n\tfor (int i = 1; i <= 10; i++) {\n\t\tQ1.PUSH(i);\n\t\t\n\t}\n\t\n\tQ1.POP();\n\t\n\tQ1.DISPLAY();\n\t\n\tif(Q1.EMPTY())\n\t{\n\t    cout<<\"Stack is empty ! \";\n\t}\n\n\treturn 0;\n}\n"
  },
  {
    "path": "README.md",
    "content": "<a href=\"https://flutter.dev/\">\n  <h1 align=\"center\">\n    <picture>\n      <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/akgmage/go-web/master/templates/assets/DSA.png\">\n      <img alt=\"Data Structures & Algorithms\" src=\"https://raw.githubusercontent.com/akgmage/go-web/master/templates/assets/DSA.png\">\n    </picture>\n  </h1>\n</a>\n\n# Implementation of well known Data Structures and Algorithms\n\nContributions are welcome!\nYou can join the fun by following our [contributing guide](https://github.com/akgmage/data-structures-and-algorithms/blob/main/CONTRIBUTING.md).\n\n# Table of contents\n\n- [Intro](https://github.com/akgmage/data-structures-and-algorithms#intro)\n  - [Time complexity](https://github.com/akgmage/data-structures-and-algorithms#time-complexity)\n  - [Calculation Rules](https://github.com/akgmage/data-structures-and-algorithms#calculation-rules)\n  - [Loops](https://github.com/akgmage/data-structures-and-algorithms#loops)\n  - [Order of Magnitude](https://github.com/akgmage/data-structures-and-algorithms#order-of-magnitude)\n  - [Phases](https://github.com/akgmage/data-structures-and-algorithms#phases)\n  - [Several Variables](https://github.com/akgmage/data-structures-and-algorithms#several-variables)\n  - [Recursion](https://github.com/akgmage/data-structures-and-algorithms#recursion)\n  - [Complexity classes](https://github.com/akgmage/data-structures-and-algorithms#complexity-classes)\n  - [Estimating efficiency](https://github.com/akgmage/data-structures-and-algorithms#estimating-efficiency)\n- [Data structures](https://github.com/akgmage/data-structures-and-algorithms#data-structures)\n- [Sorting](https://github.com/akgmage/data-structures-and-algorithms#sorting)\n  - [Well Known Sorting Algorithms](https://github.com/akgmage/data-structures-and-algorithms#well-known-sorting-algorithms)\n- [Binary Search](https://github.com/akgmage/data-structures-and-algorithms#binary-search)\n  - [Method 1](https://github.com/akgmage/data-structures-and-algorithms#method-1)\n  - [Example](https://github.com/akgmage/data-structures-and-algorithms#example)\n  - [Method 2](https://github.com/akgmage/data-structures-and-algorithms#method-2)\n- [Greedy algorithms](https://github.com/akgmage/data-structures-and-algorithms#greedy-algorithms)\n  - [Coin problem](https://github.com/akgmage/data-structures-and-algorithms#coin-problem)\n  - [General case](https://github.com/akgmage/data-structures-and-algorithms#general-case)\n- [Dynamic programming](https://github.com/akgmage/data-structures-and-algorithms#dynamic-programming)\n  - [Coin problem](https://github.com/akgmage/data-structures-and-algorithms#coin-problem-1)\n  - [Using memoization](https://github.com/akgmage/data-structures-and-algorithms#using-memoization)\n- [Amortized analysis](https://github.com/akgmage/data-structures-and-algorithms#amortized-analysis)\n- [Pattern 1: Two Pointers](https://github.com/akgmage/data-structures-and-algorithms#pattern-1-two-pointers)\n  - [Practice problems for two pointers](https://github.com/akgmage/data-structures-and-algorithms#practice-problems-for-two-pointers)\n- [Pattern 2: Fast and Slow Pointers](https://github.com/akgmage/data-structures-and-algorithms#pattern-2-fast-and-slow-pointers)\n  - [Practice problems for fast and slow pointers](https://github.com/akgmage/data-structures-and-algorithms#practice-problems-for-fast-and-slow-pointers)\n- [Pattern 3: Sliding Window](https://github.com/akgmage/data-structures-and-algorithms#pattern-3-sliding-window)\n  - [Practice problems for sliding window](https://github.com/akgmage/data-structures-and-algorithms#practice-problems-for-sliding-window)\n- [Pattern 4: Merge Interval](https://github.com/akgmage/data-structures-and-algorithms#pattern-4-merge-interval)\n  - [Practice problems for merge intervals](https://github.com/akgmage/data-structures-and-algorithms#practice-problems-for-merge-intervals)\n- [Pattern 5: In-place Reversal of a Linked List](https://github.com/akgmage/data-structures-and-algorithms#pattern-5-in-place-reversal-of-a-linked-list)\n  - [Practice problems for in-place reversal of a linked list](https://github.com/akgmage/data-structures-and-algorithms#practice-problems-for-in-place-reversal-of-a-linked-list)\n- [Pattern 6: Two Heaps](https://github.com/akgmage/data-structures-and-algorithms#pattern-6-two-heaps)\n  - [Practice problems for two heaps](https://github.com/akgmage/data-structures-and-algorithms#practice-problems-for-two-heaps)\n- [Pattern 7: K-way Merge](https://github.com/akgmage/data-structures-and-algorithms#pattern-7-k-way-merge)\n  - [Practice problems for k-way Merge](https://github.com/akgmage/data-structures-and-algorithms#practice-problems-for-k-way-merge)\n- [Pattern 8: Top K Elements](https://github.com/akgmage/data-structures-and-algorithms#pattern-8-top-k-elements)\n  - [Practice problems for Top K Elements](https://github.com/akgmage/data-structures-and-algorithms#practice-problems-for-top-k-elements)\n\n# Intro\n\nThe design of algorithms consists of problem solving and mathematical\nthinking. Skills for analyzing problems and solving them creatively are needed.\nAn algorithm for solving a problem has to be both correct and efficient, and the\ncore of the problem is often about inventing an efficient algorithm.\n\n# Time complexity\n\nThe efficiency of algorithms is important. Usually, it is easy to design an algorithm that solves the problem slowly, but the real challenge is to invent a fast algorithm. The time complexity of an algorithm estimates how much time the algorithm will use for some input. The idea is to represent the efficiency as a function whose parameter is the size of the input. By calculating the time complexity, we can find out whether the algorithm is fast enough without implementing it.\n\n## Calculation rules\n\nThe time complexity of an algorithm is denoted `O(...)` where the three dots represent some function. Usually, the variable n denotes the input size. For example, if the input is an array of numbers, n will be the size of the array, and if the input is a string, n will be the length of the string.\n\n## Loops\n\nA common reason why an algorithm is slow is that it contains many loops that go through the input. The more nested loops the algorithm contains, the slower it is. If there are k nested loops, the time complexity is O(n^k).\n\nFor example, the time complexity of the following code is O(n):\n\n```cpp\nfor (int i = 1; i <= n; i++) {\n  // code\n}\n```\n\nAnd the time complexity of the following code is O(n^2):\n\n```cpp\nfor (int i = 1; i <= n; i++) {\n  for (int j = 1; j <= n; j++) {\n    // code\n  }\n}\n```\n\n## Order of magnitude\n\nA time complexity does not tell us the exact number of times the code inside a loop is executed, but it only shows the order of magnitude. In the following examples, the code inside the loop is executed 3n, n + 5 and [n / 2] times, but the time complexity of each code is O(n).\n\n```cpp\nfor (int i = 1; i <= 3*n; i++) {\n  // code\n}\n```\n\n```cpp\nfor (int i = 1; i <= n+5; i++) {\n  // code\n}\n```\n\n```cpp\nfor (int i = 1; i <= n; i += 2) {\n// code\n}\n```\n\nAs another example, the time complexity of the following code is O(n^2):\n\n```cpp\nfor (int i = 1; i <= n; i++) {\n  for (int j = i+1; j <= n; j++) {\n    // code\n  }\n}\n```\n\n## Phases\n\nIf the algorithm consists of consecutive phases, the total time complexity is the largest time complexity of a single phase. The reason for this is that the slowest phase is usually the bottleneck of the code. For example, the following code consists of three phases with time complexities O(n), O(n^2) and O(n). Thus, the total time complexity is O(n^2).\n\n```cpp\nfor (int i = 1; i <= n; i++) {\n  // code\n}\nfor (int i = 1; i <= n; i++) {\n  for (int j = 1; j <= n; j++) {\n    // code\n  }\n}\nfor (int i = 1; i <= n; i++) {\n// code\n}\n```\n\n## Several variables\n\nSometimes the time complexity depends on several factors. In this case, the time complexity formula contains several variables. For example, the time complexity of the following code is O(nm):\n\n```cpp\nfor (int i = 1; i <= n; i++) {\n  for (int j = 1; j <= m; j++) {\n    // code\n  }\n}\n```\n\n## Recursion\n\nThe time complexity of a recursive function depends on the number of times the function is called and the time complexity of a single call. The total time complexity is the product of these values.  \nFor example, consider the following function:\n\n```cpp\nvoid f(int n) {\n  if (n == 1) return;\n  f(n-1);\n}\n```\n\nThe call f(n) causes n function calls, and the time complexity of each call is O(1).\nThus, the total time complexity is O(n).\n\nAs another example, consider the following function:\n\n```cpp\nvoid g(int n) {\n  if (n == 1) return;\n  g(n-1);\n  g(n-1);\n}\n```\n\nIn this case each function call generates two other calls, except for n = 1. Let us see what happens when g is called with parameter n. The following table shows the function calls produced by this single call:\n\nfunction call number of calls  \ng(n)&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp; 1  \ng(n - 1)&emsp;&emsp;&emsp;&emsp;&emsp;&nbsp;&nbsp; 2  \ng(n - 2)&emsp;&emsp;&emsp;&emsp;&emsp;&nbsp;&nbsp; 4  \n.... &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;  \ng(1) &emsp;&emsp;&emsp;&emsp;&emsp;&emsp; 2^(n - 1)\n\nBased on this, the time complexity is\n1 + 2 + 4 + ... + 2^(n - 1) = 2^(n - 1) = O(2^n).\n\n# Complexity classes\n\nThe following list contains common time complexities of algorithms:\n\nO(1) : The running time of a constant-time algorithm does not depend on the input size. A typical constant-time algorithm is a direct formula that calculates the answer.\n\nO(logn) : A logarithmic algorithm often halves the input size at each step. The running time of such an algorithm is logarithmic, because log base 2 n equals the number of times n must be divided by 2 to get 1.\n\nO(√n) : A square root algorithm is slower than O(logn) but faster than O(n). A special property of square roots is that √n = n / √n , so the square root √n lies, in some sense, in the middle of the input.\n\nO(n) : A linear algorithm goes through the input a constant number of times. This is often the best possible time complexity, because it is usually necessary to access each input element at least once before reporting the answer.\n\nO(nlogn) : This time complexity often indicates that the algorithm sorts the input, because the time complexity of efficient sorting algorithms is O(nlogn). Another possibility is that the algorithm uses a data structure where each operation takes O(logn) time.\n\nO(n^2) : A quadratic algorithm often contains two nested loops. It is possible to go through all pairs of the input elements in O(n^2) time.\n\nO(n^3) : A cubic algorithm often contains three nested loops. It is possible to go through all triplets of the input elements in O(n^3) time.\n\nO(2^n) : This time complexity often indicates that the algorithm iterates through all subsets of the input elements. For example, the subsets of {1,2,3} are Φ, {1}, {2}, {3}, {1,2}, {1,3}, {2,3} and {1,2,3}.\n\nO(n!) : This time complexity often indicates that the algorithm iterates through all permutations of the input elements. For example, the permutations of {1,2,3} are (1,2,3), (1,3,2), (2,1,3 , (2,3,1), (3,1,2) and (3,2,1).\n\nAn algorithm is polynomial if its time complexity is at most O(n^k) where k is a constant. All the above time complexities except O(2^n) and O(n!) are polynomial.  \nIn the practice, the constant k is usually small, and therefore a polynomial time complexity roughly means that the algorithm is efficient. Still, there are many important problems for which no polynomial algorithm is known, i.e., nobody knows how to solve them efficiently. NP-hard problems are an important set of problems, for which no polynomial algorithm is known.\n\n# Estimating efficiency\n\nBy calculating the time complexity of an algorithm, it is possible to check, before implementing the algorithm, that it is efficient enough for the problem. The starting point for estimations is the fact that a modern computer can perform some hundreds of millions of operations in a second. For example, assume that the time limit for a problem is one second and the input size is n = 10 ^ 5. If the time complexity is O(n^2), the algorithm will perform about (10 ^ 5) ^ 2 = 10 ^ 10 operations. This should take at least some tens of seconds, so the algorithm seems to be too slow for solving the problem.\n\nOn the other hand, given the input size, we can try to guess the required time complexity of the algorithm that solves the problem. The following table contains some useful estimates assuming a time limit of one second.  \ninput size required time complexity  \nn <= 10&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&nbsp;O(n!)  \nn <= 20&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp; O(2 ^ n)  \nn <= 500&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&nbsp;&nbsp; O(n ^ 3)  \nn <= 5000&emsp;&emsp;&emsp;&emsp;&emsp;&emsp; O(n ^ 2)  \nn <= 10 ^ 6&emsp;&emsp;&emsp;&emsp;&emsp; O(nlogn) or O(n)  \nn is large&emsp;&emsp;&emsp;&emsp;&emsp; O(1) or O(logn)\n\nFor example, if the input size is n = 10 ^ 5, it is probably expected that the time complexity of the algorithm is O(n) or O(nlogn). This information makes it easier to design the algorithm, because it rules out approaches that would yield an algorithm with a worse time complexity. Still, it is important to remember that a time complexity is only an estimate of efficiency, because it hides the constant factors. For example, an algorithm that runs in O(n) time may perform n/2 or 5n operations. This has an important effect on the actual running time of the algorithm.\n\n# Data structures\n\nA data structure is a way to store data in the memory of a computer. It is\nimportant to choose an appropriate data structure for a problem, because each\ndata structure has its own advantages and disadvantages. The crucial question\nis: which operations are efficient in the chosen data structure?\n\n- `Dynamic arrays` : A dynamic array is an array whose size can be changed during the execution of the program.\n- `Set structures` : A set is a data structure that maintains a collection of elements. The basic operations of sets are element insertion, search and removal.\n- `Map structures` : A map is a generalized array that consists of key-value-pairs. While the keys in an ordinary array are always the consecutive integers 0,1,...,n-1, where n is the size of the array, the keys in a map can be of any data type and they do not have to be consecutive values.\n- `Deque` : A deque is a dynamic array whose size can be efficiently changed at both ends of the array. Like a vector, a deque provides the functions push_back and pop_back, but it also includes the functions push_front and pop_front which are not available in a vector.\n- `Stack` : A stack is a data structure that provides two O(1) time operations: adding an element to the top, and removing an element from the top. It is only possible to access the top element of a stack.\n- `Queue` : A queue also provides two O(1) time operations: adding an element to the end of the queue, and removing the first element in the queue. It is only possible to access the first and last element of a queue.\n- `Priority queue` : A priority queue maintains a set of elements. The supported operations are insertion and, depending on the type of the queue, retrieval and removal of either the minimum or maximum element. Insertion and removal take O(logn) time, and retrieval takes O(1) time. While an ordered set efficiently supports all the operations of a priority queue, the benefit of using a priority queue is that it has smaller constant factors. A priority queue is usually implemented using a heap structure that is much simpler than a balanced binary tree used in an ordered set.\n\n# Sorting\n\nSorting is a fundamental algorithm design problem. Many efficient algorithms\nuse sorting as a subroutine, because it is often easier to process data if the\nelements are in a sorted order.\nFor example, the problem ”does an array contain two equal elements?” is easy\nto solve using sorting. If the array contains two equal elements, they will be next\nto each other after sorting, so it is easy to find them. Also, the problem ”what is\nthe most frequent element in an array?” can be solved similarly.\nThere are many algorithms for sorting, and they are also good examples of\nhow to apply different algorithm design techniques. The efficient general sorting\nalgorithms work in O(nlogn) time, and many algorithms that use sorting as a\nsubroutine also have this time complexity.\n\n```js\nheights = [6, 5, 4, 5, 2, 3];\nheights.sort();\nOutput: [2, 3, 4, 5, 5, 6];\n```\n\nEven though languages have built-in sorting method, sorting is a great example of how there may be many ways to think about the same problem, some perhaps better than others. Understanding sorting is a traditional first step towards mastery of algorithms and computer science.\n\n### Well known sorting algorithms\n\n- Bubble Sort [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/bubble_sort.go) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/bubble_sort.cpp) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/bubble_sort.java) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/bubble_sort.js) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/bubble_sort.py)\n- Insertion Sort [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/insertion_sort.go) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/insertion_sort.cpp) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/insertion_sort.java) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/insertion_sort.js) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/insertion_sort.py)\n- Selection Sort [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/selection_sort.go) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/selection_sort.cpp) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/selection_sort.java) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/selection_sort.js) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/selection_sort.py)\n- Merge Sort [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/merge_sort.go) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/merge_sort.cpp) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/merge_sort.java) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/merge_sort.js) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/merge_sort.py)\n- Quick Sort [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/quick_sort.cpp) [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/quick_sort.go) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/quick_sort.py) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/quick_sort.js) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/sorting/quick_sort.java)\n\n# Binary Search\n\nA general method for searching for an element in an array is to use a for loop\nthat iterates through the elements of the array. For example, the following code\nsearches for an element x in an array:\n\n```cpp\nfor (int i = 0; i < n; i++) {\n  if (array[i] == x) {\n    // x found at index i\n  }\n}\n```\n\nThe time complexity of this approach is O(n), because in the worst case, it\nis necessary to check all elements of the array. If the order of the elements is\narbitrary, this is also the best possible approach, because there is no additional\ninformation available where in the array we should search for the element x.\nHowever, if the array is sorted, the situation is different. In this case it is\npossible to perform the search much faster, because the order of the elements in\nthe array guides the search. The following binary search algorithm efficiently\nsearches for an element in a sorted array in O(logn) time.\n\n## Method 1\n\nThe usual way to implement binary search resembles looking for a word in a\ndictionary. The search maintains an active region in the array, which initially\ncontains all array elements. Then, a number of steps is performed, each of which\nhalves the size of the region.\nAt each step, the search checks the middle element of the active region. If\nthe middle element is the target element, the search terminates. Otherwise, the\nsearch recursively continues to the left or right half of the region, depending on\nthe value of the middle element.\nThe above idea can be implemented as follows:\n\n```cpp\nint a = 0, b = n-1;\nwhile (a <= b) {\n  int k = (a+b)/2;\n  if (array[k] == x) {\n    // x found at index k\n  }\n  if (array[k] > x) b = k-1;\n  else a = k+1;\n}\n```\n\n## Example\n\n[Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Binary%20Search/binary_search_iterative.go) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Binary%20Search/binary_search.py) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Binary%20Search/binary_search.cpp) [JS](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Binary%20Search/binary_search.js)\n\n## Method 2\n\nAn alternative method to implement binary search is based on an efficient way to\niterate through the elements of the array. The idea is to make jumps and slow\nthe speed when we get closer to the target element.\nThe search goes through the array from left to right, and the initial jump\nlength is n/2. At each step, the jump length will be halved: first n/4, then n/8,\nn/16, etc., until finally the length is 1. After the jumps, either the target element\nhas been found or we know that it does not appear in the array.\nThe following code implements the above idea:\n\n```cpp\nint k = 0;\nfor (int b = n/2; b >= 1; b /= 2) {\n  while (k+b < n && array[k+b] <= x) k += b;\n}\nif (array[k] == x) {\n  // x found at index k\n}\n```\n\nDuring the search, the variable b contains the current jump length. The\ntime complexity of the algorithm is O(logn), because the code in the while loop is\nperformed at most twice for each jump length.\n\n# Greedy algorithms\n\nA greedy algorithm constructs a solution to the problem by always making a\nchoice that looks the best at the moment. A greedy algorithm never takes back\nits choices, but directly constructs the final solution. For this reason, greedy\nalgorithms are usually very efficient.\nThe difficulty in designing greedy algorithms is to find a greedy strategy that\nalways produces an optimal solution to the problem. The locally optimal choices\nin a greedy algorithm should also be globally optimal. It is often difficult to argue\nthat a greedy algorithm works.\n\n## Coin problem\n\nAs a first example, we consider a problem where we are given a set of coins and\nour task is to form a sum of money n using the coins. The values of the coins are\ncoins = `{c1, c2,..., ck}`, and each coin can be used as many times we want. What\nis the minimum number of coins needed?\nFor example, if the coins are the euro coins (in cents)\n`{1,2,5,10,20,50,100,200}`\nand `n = 520`, we need at least four coins. The optimal solution is to select coins\n`200 + 200 + 100 + 20` whose sum is `520`.\n\nA simple greedy algorithm to the problem always selects the largest possible coin,\nuntil the required sum of money has been constructed. This algorithm works in\nthe example case, because we first select two `200` cent coins, then one `100` cent\ncoin and finally one `20` cent coin. But does this algorithm always work?\nIt turns out that if the coins are the euro coins, the greedy algorithm always\nworks, i.e., it always produces a solution with the fewest possible number of coins.\nThe correctness of the algorithm can be shown as follows:\nFirst, each coin `1, 5, 10, 50 and 100` appears at most once in an optimal\nsolution, because if the solution would contain two such coins, we could replace them by one coin and obtain a better solution. For example, if the solution would\ncontain coins `5 + 5`, we could replace them by coin 10.\nIn the same way, coins 2 and 20 appear at most twice in an optimal solution,\nbecause we could replace coins `2 + 2 + 2` by coins `5 + 1` and coins `20 + 20 + 20` by\ncoins 50 + 10. Moreover, an optimal solution cannot contain coins `2 + 2 + 1` or\n`20 + 20 + 10`, because we could replace them by coins 5 and 50.\nUsing these observations, we can show for each coin x that it is not possible\nto optimally construct a sum x or any larger sum by only using coins that are\nsmaller than x. For example, `if x = 100`, the largest optimal sum using the smaller\ncoins is `50 + 20 + 20 + 5 + 2 + 2 = 99`. Thus, the greedy algorithm that always selects\nthe largest coin produces the optimal solution.\nThis example shows that it can be difficult to argue that a greedy algorithm\nworks, even if the algorithm itself is simple.\n\n## General case\n\nIn the general case, the coin set can contain any coins and the greedy algorithm\ndoes not necessarily produce an optimal solution.\nWe can prove that a greedy algorithm does not work by showing a counterexample\nwhere the algorithm gives a wrong answer. In this problem we can easily\nfind a counterexample: if the coins are `{1,3,4}` and the target sum is `6`, the greedy\nalgorithm produces the solution 4 + 1 + 1 while the optimal solution is `3 + 3`.\nIt is not known if the general coin problem can be solved using any greedy\nalgorithm.\n\n# Dynamic programming\n\nDynamic programming is a technique that combines the correctness of complete\nsearch and the efficiency of greedy algorithms. Dynamic programming can\nbe applied if the problem can be divided into overlapping subproblems that can\nbe solved independently.\n\nThere are two uses for dynamic programming:\n\n- Finding an optimal solution: We want to find a solution that is as large as possible or as small as possible.\n- Counting the number of solutions: We want to calculate the total number of possible solutions.\n\n## Coin problem\n\nWe first focus on a problem that we have already seen in Greedy Algorithm Given a set\nof coin values coins = `{c1, c2,..., ck}` and a target sum of money n, our task is to\nform the sum n using as few coins as possible.\nWe solved the problem using a greedy algorithm that always\nchooses the largest possible coin. The greedy algorithm works, for example, when\nthe coins are the euro coins, but in the general case the greedy algorithm does\nnot necessarily produce an optimal solution.\nNow is time to solve the problem efficiently using dynamic programming, so\nthat the algorithm works for any coin set. The dynamic programming algorithm\nis based on a recursive function that goes through all possibilities how to form\nthe sum, like a brute force algorithm. However, the dynamic programming\nalgorithm is efficient because it uses memoization and calculates the answer to\neach subproblem only once.\n\nThe idea in dynamic programming is to formulate the problem recursively so\nthat the solution to the problem can be calculated from solutions to smaller\nsubproblems. In the coin problem, a natural recursive problem is as follows: what\nis the smallest number of coins required to form a sum x?\nLet solve(x) denote the minimum number of coins required for a sum x.\nThe values of the function depend on the values of the coins. For example, if\n`coins = {1,3,4}`, the first values of the function are as follows:\n\n```solve(0) = 0\nsolve(1) = 1\nsolve(2) = 2\nsolve(3) = 1\nsolve(4) = 1\nsolve(5) = 2\nsolve(6) = 2\nsolve(7) = 2\nsolve(8) = 2\nsolve(9) = 3\nsolve(10) = 3\n```\n\nFor example, `solve(10) = 3`, because at least 3 coins are needed to form the\nsum `10`. The optimal solution is `3 + 3 + 4 = 10`.\nThe essential property of solve is that its values can be recursively calculated\nfrom its smaller values. The idea is to focus on the first coin that we choose for\nthe sum. For example, in the above scenario, the first coin can be either `1, 3\nor 4`. If we first choose coin `1`, the remaining task is to form the sum 9 using\nthe minimum number of coins, which is a subproblem of the original problem.\nOf course, the same applies to coins` 3 and 4`.\n\nThus, we can use the following recursive formula to calculate the minimum number of coins:  \nsolve(x) = min(solve(x - 1) + 1,  \nsolve(x - 3) + 1,  \nsolve(x - 4) + 1).\n\nThe base case of the recursion is solve(0) Æ 0, because no coins are needed to form an empty sum. For example,  \nsolve(10) = solve(7) + 1 = solve(4) + 2 = solve(0) + 3 = 3.\n\nNow we are ready to give a general recursive function that calculates the minimum number of coins needed to form a sum x:\nsolve(x) = Infinity if x < 0  \nsolve(x) = 0 if x == 0  \nsolve(x) = min(c --> coins) ==> solve(x - c) + 1, if x > 0\n\nOnce a recursive function that solves the problem has been found, we can\ndirectly implement a solution, (the constant INF denotes infinity):\n\n```cpp\nint solve(int x) {\n  if (x < 0) return INF;\n  if (x == 0) return 0;\n  int best = INF;\n  for (auto c : coins) {\n    best = min(best, solve(x-c)+1);\n  }\n  return best;\n}\n```\n\nStill, this function is not efficient, because there may be an exponential number of ways to construct the sum. However, next we will see how to make the function efficient using a technique called memoization.\n\n## Using memoization\n\nThe idea of dynamic programming is to use memoization to efficiently calculate values of a recursive function. This means that the values of the function are stored in an array after calculating them. For each parameter, the value of the function is calculated recursively only once, and after this, the value can be\ndirectly retrieved from the array.\n\nIn this problem, we use arrays\n\n```cpp\nbool ready[N];\nint value[N];\n```\n\nwhere `ready[x]` indicates whether the value of `solve(x)` has been calculated,\nand if it is, `value[x]` contains this value. The constant `N` has been chosen so that all required values fit in the arrays.  \nNow the function can be efficiently implemented as follows:\n\n```cpp\nint solve(int x) {\n  if (x < 0) return INF;\n  if (x == 0) return 0;\n  if (ready[x]) return value[x];\n  int best = INF;\n  for (auto c : coins) {\n    best = min(best, solve(x-c)+1);\n  }\n  value[x] = best;\n  ready[x] = true;\n  return best;\n}\n```\n\n# Amortized analysis\n\nThe time complexity of an algorithm is often easy to analyze just by examining the structure of the algorithm: what loops does the algorithm contain and how many times the loops are performed. However, sometimes a straightforward analysis does not give a true picture of the efficiency of the algorithm.\nAmortized analysis can be used to analyze algorithms that contain operations whose time complexity varies. The idea is to estimate the total time used to all such operations during the execution of the algorithm, instead of focusing on individual operations.\n\n# Pattern 1: Two Pointers\n\nAs the name suggests, the two pointers pattern uses two pointers to iterate over an array or list until the conditions of the problem are satisfied. This is useful because it allows us to keep track of the values of two different indexes in a single iteration. Whenever there’s a requirement to find two data elements in an array that satisfy a certain condition, the two pointers pattern should be the first strategy to come to mind.\n\nThe pointers can be used to iterate the data structure in one or both directions, depending on the problem statement. For example, to identify whether a string is a palindrome, we can use one pointer to iterate the string from the beginning and the other to iterate it from the end. At each step, we can compare the values of the two pointers and see if they meet the palindrome properties.\n\n## Practice problems for two pointers\n\n- Two sum [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Hash%20Table/two_sum.go) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Hash%20Table/two_sum.cpp) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Hash%20Table/two_sum.java) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Hash%20Table/two_sum.py) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Hash%20Table/two_sum.js)\n\n- Three Number Sum [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/triplet_sum.go) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/triplet_sum.java) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/triplet_sum.cpp) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/triplet_sum.py) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/triplet_sum.js)\n\n- Valid Pallindrome [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/is_pallindrome.go) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/is_pallindrome.js) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/is_pallindrome.cpp) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/is_pallindrome.py) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/is_pallindrome.java)\n\n- Reverse Word in a String [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/reverse_words_in_a_string.go) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/reverse_words_in_a_string.jd) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/reverse_words_in_a_string.cpp) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/reverse_words_in_a_string.java)\n\n- Valid Pallindrome II [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/valid_pallindrome2.go) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/valid_pallindrome2.cpp) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/valid_pallindrome2.py) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/valid_pallindrome2.js) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Strings/valid_pallindrome2.java)\n\n# Pattern 2: Fast and Slow Pointers\n\nThe fast and slow pointer technique (also known as the tortoise and hare algorithm) uses two pointers to determine traits about directional data structures. This can be an array, singly-linked list, or a graph.\n\nSimilar to the two pointers pattern, the fast and slow pointers pattern uses two pointers to traverse an iterable data structure at different speeds. It’s usually used to identify distinguishable features of directional data structures, such as a linked list or an array.\n\nThe pointers can be used to traverse the array or list in either direction, however, one moves faster than the other. Generally, the slow pointer moves forward by a factor of one, and the fast pointer moves by a factor of two in each step. However, the speed can be adjusted according to the problem statement.\n\nUnlike the two pointers approach, which is concerned with data values, the fast and slow pointers approach is used to determine data structure traits using indices in arrays or node pointers in linked lists. The approach is commonly used to detect cycles in the given data structure, so it’s also known as Floyd’s cycle detection algorithm.\n\nThe key idea is that the pointers start at the same location, but they move forward at different speeds. If there is a cycle, the two are bound to meet at some point in the traversal. To understand the concept, think of two runners on a track. While they start from the same point, they have different running speeds. If the race track is a circle, the faster runner will overtake the slower one after completing a lap. On the other hand, if the track is straight, the faster runner will end the race before the slower one, hence never meeting on the track again. The fast and slow pointers pattern uses the same intuition.\n\n## Practice problems for fast and slow pointers\n\n- Linked List cycle detection [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Fast%20and%20Slow%20Pointers/linked_floyds_cycle_detection.cpp) [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Linked%20List/floyds_cycle_detection.go) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Linked%20List/floyds_cycle_detection.java)\n- Find middle of Linked List [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Fast%20and%20Slow%20Pointers/linked_list_compute_midpoint.cpp) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Fast%20and%20Slow%20Pointers/linked_list_find_middle.py)\n- Happy Number [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Fast%20and%20Slow%20Pointers/happy_number.go)\n- Pallindrome Linked List [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Linked%20List/linked_list_pallindrome.cpp)\n- Remove Kth node from end [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Linked%20List/linked_list_kth_from_end.go) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Linked%20List/linked_list_remove_nth_node_from_end.cpp) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Linked%20List/remove_kth_node_from_end.py)\n- Linked List Sort List [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Linked%20List/liniked_list_sort_list.cpp)\n\n# Pattern 3: Sliding Window\n\nThe Sliding window is a problem-solving technique of data structure and algorithm for problems that apply arrays or lists. These problems are painless to solve using a brute force approach in O(n²) or O(n³). However, the Sliding window technique can reduce the time complexity to O(n).\n\nThe sliding window pattern is a computational method aimed at reducing the use of nested loops in an algorithm. It’s a variation of the two pointers pattern, where the pointers can be used to set window bounds.\n\nA window is a sublist formed over a part of an iterable data structure. It can be used to slide over the data in chunks corresponding to the window size. The sliding window pattern allows us to process the data in segments instead of the entire list. The segment or window size can be set according to the problem’s requirements. For example, if we have to find three consecutive integers with the largest sum in an array, we can set the window size to 3. This will allow us to process the data three elements at a time.\n\nWhy is this method more efficient? It isn’t if, for each window, we iterate over all the elements of the window because that gives us the same O(kn) time complexity.\n\nInstead, what if we focused on the element entering the window and the one leaving it? For example, after calculating the sum of the first three elements, we move the window one step forward, subtract the element that is no longer in the window from the sum, and add the new element that has entered it. Next we check if the new sum is greater than the first. If it is, we update the max sum found so far. Now, each time we move the window forward, we perform at most four operations, reducing the time complexity to O(4n), that is, O(n).\n\n## Practice problems for sliding window\n\n- Find Maximum in Sliding Window [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Sliding%20Window/sliding_window_max.java) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Sliding%20Window/sliding_window_max.js) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Sliding%20Window/sliding_window_max.py)\n- Minimum Window Subsequence\n- Repeated DNA Sequences\n- Minimum Window Substring\n- Longest Substring without Repeating Characters [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Sliding%20Window/longest_substring_without_repeating_characters.go)\n\n# Pattern 4: Merge Interval\n\nThe merge intervals pattern deals with problems involving overlapping intervals. Each interval is represented by a start and an end time. For example, an interval of [10,20] seconds means that the interval starts at 10 seconds and ends at 20seconds, such that both 10 and time 20 are included in the interval.\n\nThe most common problems solved using this pattern are scheduling problems.\n\nThe key to understanding this pattern and exploiting its power lies in understanding how any two intervals may overlap.\n\nMany problems in the real world use the merge intervals pattern. Let’s look at some examples.\n\n- Display busy schedule: Display the busy hours of a user to other users without revealing the individual meeting slots in a calendar.\n\n- Schedule a new meeting: Add a new meeting to the tentative meeting schedule of a user in such a way that no two meetings overlap each other.\n\n- Task scheduling in operating systems (OS): Schedule tasks for the OS based on task priority and the free slots in the machine’s processing schedule.\n\n## Practice problems for merge intervals\n\n- Merge Intervals [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/merge_intervals.go) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/merge_intervals.cpp) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/merge_intervals.java) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/merge_intervals.py) [Javacript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/merge_intervals.js)\n- Insert Interval [Go](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/insert_interval.go) [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/insert_interval.cpp) [Python](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/insert_interval.py) [Java](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/insert_interval.java) [Javascript](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Arrays/insert_interval.js)\n- Interval List Intersections\n- Employee Free Time\n- Meeting Rooms\n\n# Pattern 5: In-place Reversal of a Linked List\n\nThe in-place reversal of a linked list pattern allows us to reverse a linked list without any additional memory, using only the given nodes.\n\nMany problems require a reversal of a set of nodes in a linked list without using additional memory. In such cases, using the in-place reversal pattern is the simplest solution. Instead of making a new linked list with reversed links, we can do it in place, without using additional memory.\n\nHow can we achieve an in-place reversal of nodes? We iterate in a linked list and keep track of the current node, the next node, and the previous node simultaneously. Keeping track of the nodes allows us to easily change the links between them and make them point to a different node than before.\n\nWhen solving such problems, the naive approach of iterating the linked list using nested loops takes O(n²) time. However, using the in-place reversal pattern, the time complexity is O(n)\ntime, since we use a single loop to iterate the linked list.\n\nSimilarly, for space complexity: the naive approach requires the use of additional memory—if a linked list contains thousands of nodes, we’d need to allocate a lot of additional memory resources to solve the problem. However, the in-place reversal of a linked pattern will use only O(1) space.\n\n## Practice problems for in-place reversal of a linked list\n\n- Reverse Linked List [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Linked%20List/linked_list_reverse.cpp)\n- Reverse Nodes in k-group\n- Reorder List\n- Swapping Nodes in a Linked List\n- Swapping Nodes in Pairs [C++](https://github.com/akgmage/data-structures-and-algorithms/blob/main/Linked%20List/linked_list_swap_nodes_in_pair.cpp)\n- Reverse Nodes in Even Length Groups\n\n# Pattern 6: Two Heaps\n\nAs the name suggests, the two heaps pattern uses either two min-heaps, two max-heaps, or a min-heap and a max-heap simultaneously to solve the problem.\n\nGiven that there are n elements in a heap, it takes O(log n) time to insert an element in it, O(log n) time to remove an element from it, and O(1) time to access the element at the root of the heap. The root stores the smallest element in the case of a min-heap and the largest element in a max-heap.\n\nIn some problems, we’re given a set of data such that it can be divided into two parts. We can either use the first part to find the smallest element using the min-heap and the second part to find the largest element using the max-heap, or we can do the reverse and use the first part to find the largest element using the max-heap and the second part to find the smallest element using the min-heap.\n\nThere might be cases where we need to find the two largest numbers from two different data sets. We’ll use two max-heaps to store two different data sets in that case. In other cases, we might need to find the two smallest numbers from two different data sets, and then we would use two min-heaps.\n\nMany problems in the real world use the two heaps pattern. Let’s look at some examples.\n\n- Video streaming: During a user session, there is often a possibility that packet drops and buffering might occur. We want to record the median number of buffering events that might occur in a particular session, which could then be used to improve the user experience.\n\n- Netflix: As part of a demographic study, we’re interested in the median age of our viewers. We want to implement a functionality whereby the median age can be updated efficiently whenever a new user signs up for video streaming.\n\n## Practice problems for two heaps\n\n- Maximize Capital\n- Find Median from a data stream\n- Schedule Tasks on minimum machines\n\n# Pattern 7: K-way Merge\n\nThe k-way merge pattern helps to solve problems involving a list of sorted arrays.\n\nHere is what the pattern looks like:\n\n1. Insert the first element of each array in a min-heap.\n2. Next, remove the smallest element from the heap and add it to the merged array.\n3. Keep track of which array each element comes from.\n4. Then, insert the next element of the same array into the heap.\n5. Repeat steps 2 to 4 to fill the merged array in sorted order.\n\nMany problems in the real world use the k-way merge pattern. Let’s look at some examples.\n\n- Merge tweets in twitter feed: Sometimes we need to implement a module that adds a user’s Tweets into an already populated Twitter feed in chronological order.\n\n- Used in external sorting procedures: When an algorithm is processing huge amounts of data, it needs to repeatedly fetch it from external storage because RAM capacity is fixed. To overcome the speed limitation of external storage, k-way merges are used in external sorting. Let’s consider a case where we need to perform six merges. A binary merge requires three merge passes while a 6-way merge only requires one pass. K-way merge reduces the number of accesses to external storage, which in turn greatly improves performance when dealing with large amounts of data.\n\n## Practice problems for k-way Merge\n\n- Merge Sorted Array\n- Kth smallest number in M sorted list\n- Find K pairs with smallest sums\n- Merge K sorted lists\n- Kth Smallest element in a sorted matrix\n- Median of two sorted arrays\n\n# Pattern 8: Top K Elements\n\nThe top K elements pattern helps find some specific k number of elements from the given data with optimum time complexity. Many problems ask us to find the top, the smallest, or the most/least frequent k elements in an unsorted list of elements. To solve such problems, sorting the list takes O(nlog(n)) time, then finding the k elements takes O(k) time. However, the top k elements pattern can allow us to solve the problem using O(n logk) time without sorting the list first.\n\nWhich data structure can we use to solve such problems? The best data structure to keep track of the smallest or largest k elements is heap. With this pattern, we either use a max-heap or a min-heap to find the smallest or largest k elements, respectively.\n\nFor example, let’s look at how this pattern takes steps to solve the problem of finding the top k largest elements (using min-heap) or top k smallest elements (using max-heap):\nInsert the first k elements from the given set of elements to the min-heap or max-heap.\n\nIterate through the rest of the elements.\n\nFor min-heap, if you find the larger element, remove the top (smallest number) of the min-heap and insert the new larger element.\nFor max-heap, if you find the smaller element, remove the top (largest number) of the max-heap and insert the new smaller element.\nIterating the complete list takes O(n) time, and the heap takes O(logk) time for insertion. However, we get the O(1) access to the k elements using the heap.\n\nMany problems in the real world use the top K elements pattern. Let’s look at some examples.\n\n- Uber: Select at least the n nearest drivers within the user’s vicinity, avoiding the drivers that are too far away.\n\n- Stocks: Given the set of IDs of brokers, determine the top K broker’s performance with the frequently repeated IDs in the given data set.\n\n## Practice problems for Top K Elements\n\n- Kth largest element in a stream\n- Reorganize string\n- K closest point to origin\n- Top K frequent element\n- Kth largest element in an array\n- Kth smallest element in an BST\n"
  },
  {
    "path": "Recursion/calculatextopowern.cpp",
    "content": "// Canculate power of x^n\n// Sample Input : 3 2\n// Output : 9\n\n#include<bits/stdc++.h>\nusing namespace std;\n\n// Method 1 Time complexity O(n)\nint power1(int x, int n){\n\tif(n == 0)\n\t\treturn 1;\n\treturn x * power1(x, n-1);\n}\n\n// Method 2 : Time complexity O(log n)\nint power(int x, int n){\n\tif(n == 0)\n\t\treturn 1;\n\telse if(n % 2 == 0){\n\t\tint y = power(x, n / 2);\n\t\treturn y * y;\t\n\t}\n\treturn x * power(x, n - 1);\n}\n\nint main(){\n\tint x, n;\n\tcout << \"Give me x annd n\";\n\tcin >> x >> n;\n\tint result = power(x,n);\n\tcout << result << endl;\n\treturn 0;\n}\n"
  },
  {
    "path": "Recursion/count_digits.cpp",
    "content": "// Count the number of digits in an integer\r\n// Sample Input: 2003\r\n// Output: 4\r\n\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\nint count_digits(int n){\r\n    if(n == 0)\r\n        return 0;       \r\n    // recursively hit base case and keep adding 1 afterwards    \r\n    int small_no = count_digits(n / 10);\r\n    return small_no + 1;\r\n}\r\nint main(){\r\n    cout << count_digits(2003099910);\r\n    return 0;\r\n}"
  },
  {
    "path": "Recursion/count_digits.go",
    "content": "// Count the number of digits in an integer\n// Sample Input: 2003\n// Output: 4\npackage main\n\nimport \"fmt\"\n\nfunc CountDigits(n int) int {\n\tif n == 0 {\n\t\treturn 0;\n\t}\n\t// recursively hit base case and keep adding 1 afterwards  \n\tsmallNo := CountDigits(n / 10)\n\treturn smallNo + 1\n}\n\nfunc main() {\n\tmsg := CountDigits(2003)\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Recursion/count_zeros.cpp",
    "content": "// Count the number of 0's in an integer\r\n// Sample Input : 10010\r\n// Output: 3\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\nint count_zeros(int n){\r\n    if(n == 0)\r\n        return 0;\r\n    // divide the number recursively and hit the base case    \r\n    int small_no = count_zeros(n / 10);\r\n    int last_digit = n % 10;\r\n    if(last_digit == 0)\r\n        return small_no + 1;\r\n    else \r\n        return small_no;    \r\n}\r\nint main(){\r\n    cout << count_zeros(2003010);\r\n    return 0;\r\n}"
  },
  {
    "path": "Recursion/count_zeros.go",
    "content": "// Count the number of 0's in an integer\n// Sample Input : 10010\n// Output: 3\npackage main\n\nimport \"fmt\"\n\nfunc CountZeroes(n int) int {\n\tif n == 0 {\n\t\treturn 0;\n\t}\n\t// divide the number recursively and hit the base case\n\tsmallNo := CountZeroes(n / 10)\n\tlastDigit := n % 10\n\tif lastDigit == 0 {\n\t\tsmallNo += 1\n\t} else {\n\t\treturn smallNo\n\t}\n\treturn smallNo\n}\n\nfunc main() {\n\tmsg := CountZeroes(1000100100100)\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Recursion/factorial.cpp",
    "content": "// Factorial of an integer\n// Sample Input: 5\n// Output: 120\n#include<iostream>\nusing namespace std;\nint factorial(int n){\n\tcout << \"I am calculating f(\" << n << \")\\n\";\t\n\tif(n == 0)\n\t\treturn 1;\n\tint f =  n * factorial(n - 1);\n\tcout << \"Done! f(\" << n << \") = \" << f << endl; \n\treturn f;\n}\nint main(){\n\tint n;\n\tcout << \"Give me n : \";\n\tcin >> n;\n\tint result = factorial(n);\n\tcout << result << endl;\t\n\treturn 0;\n}\n"
  },
  {
    "path": "Recursion/factorial.go",
    "content": "// Factorial of an integer\n// Sample Input: 5\n// Output: 120\n\npackage main\n\nimport \"fmt\"\n\nfunc Factorial(n int) int {\n\tif n == 0 {\n\t\treturn 1;\n\t}\n\treturn n * Factorial(n - 1)\n}\n\nfunc main() {\n\tmsg := Factorial(5);\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Recursion/factorial.js",
    "content": "// Factorial of an integer\n// Sample Input: 5\n// Output: 120\nfunction recursiveFactorial(number) {\n  //Base case\n  if (number == 1) {\n    return 1;\n  }\n\n  //recursively calling function to get factorial result\n  return number * recursiveFactorial(number - 1);\n}\n\n// Driver code\nconsole.log(recursiveFactorial(2));\nconsole.log(recursiveFactorial(3));\nconsole.log(recursiveFactorial(4));\nconsole.log(recursiveFactorial(5));\n"
  },
  {
    "path": "Recursion/fibonacci.cpp",
    "content": "// Fibonacci numbers, commonly denoted Fn , form a sequence, the Fibonacci sequence,\n// in which each number is the sum of the two preceding ones.\n// The sequence commonly starts from 0 and 1, although some authors start the sequence\n// from 1 and 1 or sometimes (as did Fibonacci) from 1 and 2. Starting from 0 and 1,\n// the first few values in the sequence are:\n// 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144.\n\n// Sample Input: 5\n// Output: 5\n// Sample Input: 7\n// Output: 13\n#include<bits/stdc++.h>\nusing namespace std;\nint fib(int n){\n\tif(n <= 1)\n\t\treturn n;\n\treturn fib(n-1) + fib(n-2);\n}\nint main(){\n\tint n;\n\tcout << \"Give me n : \";\n\tcin >> n;\n\tint result = fib(n);\n\tcout << result << endl;\n}\n"
  },
  {
    "path": "Recursion/fibonacci.go",
    "content": "// Fibonacci numbers, commonly denoted Fn , form a sequence, the Fibonacci sequence,\n// in which each number is the sum of the two preceding ones.\n// The sequence commonly starts from 0 and 1, although some authors start the sequence\n// from 1 and 1 or sometimes (as did Fibonacci) from 1 and 2. Starting from 0 and 1,\n// the first few values in the sequence are:\n// 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144.\n\n// Sample Input: 5\n// Output: 5\n// Sample Input: 7\n// Output: 13\npackage main\n\nimport \"fmt\"\n\nfunc Fibonacci(n int) int {\n\tif n <= 1 {\n\t\treturn n\n\t}\n\treturn Fibonacci(n - 1) + Fibonacci(n - 2)\n}\n\nfunc main() {\n\tmsg := Fibonacci(7)\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Recursion/fibonacci_memoization.cpp",
    "content": "/*\n\tImplelement memoized fibonacci\n\n\tMemoization is an enhancement procedure used to speed up computer programs by keeping the values\n\tof distinct function calls and returning the stored input when the same function is invoked again.\n\n\tSample Input: 6\n\tOutput: 8\n*/\n#include<bits/stdc++.h>\nusing namespace std;\nint F[51];\nint fib(int n){\n\tif(F[n] != -1)\n\t\treturn F[n];\n\tF[n] = fib(n - 1) + fib(n-2);\t\n\treturn F[n];\n}\nint main(){\t\n\tfor(int i = 0; i < 51; i++)\n\t\tF[i] = -1;\n\tF[0] = 0;\n\tF[1] = 1;\t\n\tint n;\n\tcout << \"Give me n : \";\n\tcin >> n;\n\tint result = fib(n);\n\tcout << result;\nreturn 0;\n}\n"
  },
  {
    "path": "Recursion/fibonacci_memoization.go",
    "content": "/*\n\tImplelement memoized fibonacci\n\n\tMemoization is an enhancement procedure used to speed up computer programs by keeping the values\n\tof distinct function calls and returning the stored input when the same function is invoked again.\n\n\tSample Input: 6\n\tOutput: 8\n*/\npackage main\n\nimport \"fmt\"\n\nvar F = make([]int, 51)\n// array based implementation 0th fib = 1\nfunc Fibonacci(n int) int {\t\n\tif F[n] != -1 {\n\t\treturn F[n]\n\t}\n\tF[n] = Fibonacci(n - 1) + Fibonacci(n - 2)\n\treturn F[n]\n}\n// more optimized 1st fibonacci = 0, second = 1\nfunc GetNthFib(n int) int {\n    firstNo := 0\n    secondNo := 1\n    result := 0\n    if n <= 2 {\n        return n - 1\n    } \n    for i := 2; i < n; i++ {\n\t\t// move first and second to to next iteration\n        result = firstNo + secondNo\n        firstNo = secondNo\n        secondNo = result\n    }\n\treturn result\n}\nfunc main() {\n\tfor i := 0; i < 51; i++ {\n\t\tF[i] = -1\n\t}\n\tF[0] = 0\n\tF[1] = 1\n\tmsg := Fibonacci(5)\n\tfmt.Println(msg)\n\tmsg = GetNthFib(5)\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Recursion/geometric_sum.cpp",
    "content": "#include<bits/stdc++.h>\r\nusing namespace std;\r\ndouble g_sum(int m){\r\n    if(m == 0)\r\n        return 1;       \r\n    double small_num = g_sum(m - 1);\r\n    return small_num + 1.0 / pow(2, m);\r\n}    \r\nint main(){\r\n    cout << g_sum(2);\r\n    return 0;\r\n}"
  },
  {
    "path": "Recursion/is_array_sorted.cpp",
    "content": "// Given an array, check whether the array is in sorted order with recursion.\n// Sample Input: [1, 2, 3, 4, 4, 5, 3]\n// Output: 0 meaning false\n// Sample Output: [1, 2, 3, 4, 4, 5, 6]\n// Output: 1 meaning true\n#include<bits/stdc++.h>\nusing namespace std;\nbool is_sorted(int A[], int m){\n    if(m == 0 || m == 1)\n        return true;       \n    if(A[0] > A[1])\n        return false;\n    bool small_array = is_sorted(A + 1, m - 1);\n    return small_array;        \n}\nint main(){\n    int A[7] = {1, 2, 3, 4, 4, 5, 3};\n    cout << is_sorted(A, 7);\n    return 0;\n}"
  },
  {
    "path": "Recursion/is_array_sorted.go",
    "content": "// Given an array, check whether the array is in sorted order with recursion.\n\npackage main\n\nimport \"fmt\"\n\n// Time Complexity: O(n). Space Complexity: O(n) for recursive stack space.\nfunc isSorted(A []int) bool {\n\tn := len(A)\n\t// Base case 1\n\tif n == 1 {\n\t\treturn true\n\t}\n\t// Base case 2\n\tif A[n - 1] < A[n - 2] {\n\t\treturn false\n\t}\n\t// recursive case\n\treturn isSorted(A[:n-1])\n}\n\nfunc main() {\n\tA := []int{10, 20, 23, 23, 45, 78, 88}\n\tfmt.Println(isSorted(A))\n\tA = []int{10, 20, 23, 7, 23, 45, 78, 88}\n\tfmt.Println(isSorted(A))\n}"
  },
  {
    "path": "Recursion/is_element_present.cpp",
    "content": "// Program to check if an element is present in an array\r\n// Sample Input: [1, 2, 3, 4, 4, 5, 3] key: 51\r\n// Output: 0 meaning false\r\n// Sample Input: [1, 2, 3, 4, 4, 5, 3] key: 5\r\n// Output: 1 meaning true\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\nbool is_element_present(int A[], int m, int key){\r\n    if(m == 0)\r\n        return false;\r\n    if(A[0] == key)\r\n        return true;    \r\n    return is_element_present(A + 1, m - 1, key);        \r\n}\r\nbool is_element_present2(int A[], int m, int key, int i){\r\n    if(i == m)\r\n        return false;\r\n    if(A[i] == key)\r\n        return true;    \r\n    return is_element_present2(A, m, key, i + 1);        \r\n}\r\nint main(){\r\n    int A[7] = {1, 2, 3, 4, 4, 5, 3};\r\n    int key = 51;\r\n    cout << is_element_present(A, 7, key) << endl;\r\n    cout << is_element_present2(A, 7, 5, 0) << endl;\r\n    return 0;\r\n}"
  },
  {
    "path": "Recursion/modular_exponentiation.cpp",
    "content": "// Modular exponentiation is exponentiation performed over a modulus. \n// It is useful in computer science, especially in the field of public-key cryptography, \n// where it is used in both Diffie-Hellman Key Exchange and RSA public/private keys.\n\n// Sample Input : 2 3 100\n// Output: 8\n\n#include<bits/stdc++.h>\nusing namespace std;\nint mod(int x, int n, int m){\n\tif(n == 0)\n\t\treturn 1;\n\telse if( n % 2 == 0){\n\t\tint y = mod(x, n/2, m);\n\t\treturn y * y % m;\t\t\n\t}\n\treturn ((x % m) * mod(x, n-1, m)) % m;\n}\nint main(){\n\tint x, n, m;\n\tcout << \"Give me x, n and m : \";\n\tcin >> x >> n >> m;\n\tint result = mod(x, n, m);\n\tcout << result << endl;\n\treturn 0;\n}\n"
  },
  {
    "path": "Recursion/multiplication.cpp",
    "content": "// Multiply number using recursion\r\n// Sample Input: 7, 9\r\n// Output: 63\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\nint multiply(int n, int m){\r\n    if(m == 0)\r\n        return 0;       \r\n    int small_m = multiply(n, m-1);\r\n    return n + small_m;    \r\n}\r\nint main(){\r\n    cout << multiply(7, 9);\r\n    return 0;\r\n}"
  },
  {
    "path": "Recursion/powerset.cpp",
    "content": "/*\n\n\tWrite a function that takes in an array of unique integers and returns its powerset.\n\n\tSample Input : [1, 2, 3]\n\tOutput: [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]\n\n\tExplanation:\n\n\tThe code snippet represents a function `Powerset` that takes an array of integers as input and returns the powerset\n\tof the array. The powerset of a set is the set of all possible subsets of that set, including the empty set and the set itself.\n\n\tThe function `Powerset` calls a helper function `powerset` to perform the actual computation. Here's how the code works:\n\n\t1. The `Powerset` function initializes the computation by calling the `powerset` function with the array and the index\n\t   of the last element in the array (`len(array) - 1`).\n\n\t2. The `powerset` function is a recursive function that calculates the powerset. It takes the array and the current\n\t   index as input.\n\n\t3. At each recursive call, the function checks if the index is less than 0. If so, it means all elements have been\n\t   processed, and it returns a 2D slice containing the empty set as the only subset.\n\n\t4. If the index is not less than 0, the function retrieves the element at the current index from the array.\n\n\t5. The function recursively calls itself with the array and the index decremented by 1 to generate the subsets without\n\t   the current element.\n\n\t6. It then calculates the length of the subsets generated so far.\n\n\t7. Using a loop, the function iterates over the existing subsets and creates new subsets by appending the current element\n\t   to each subset. The new subsets are added to the existing subset slice.\n\n\t8. Finally, the function returns the updated subset slice, which contains all the subsets of the original array.\n\n\tBy recursively generating subsets while building upon the subsets generated at each step, the function constructs the\n\tpowerset of the given array.\n\n\tO(n*2^n) time | O(n*2^n) space - where n is the length of the input array\n*/\n#include <vector>\n\nusing namespace std;\n\nvector<vector<int>> powerset(vector<int>& array, int index) {\n    // Base case: when the index reaches -1, return a vector with an empty subset\n    if (index < 0) {\n        return {{}};\n    }\n\n    int element = array[index];\n    // Recursive call to generate the powerset for the elements up to index - 1\n    vector<vector<int>> subset = powerset(array, index - 1);\n\n    // Length of the current subset vector\n    int length = subset.size();\n\n    // Iterate through each subset and create new subsets by adding the current element\n    for (int i = 0; i < length; i++) {\n        vector<int> currentSubset = subset[i];\n        // Create a new subset by making a copy of the current subset\n        vector<int> newSubset = currentSubset;\n        // Add the current element to the new subset\n        newSubset.push_back(element);\n        // Add the new subset to the existing subset vector\n        subset.push_back(newSubset);\n    }\n\n    // Return the resulting subset vector\n    return subset;\n}\n\nvector<vector<int>> Powerset(vector<int>& array) {\n    // Call the helper function to generate the powerset starting from the last index\n    return powerset(array, array.size() - 1);\n}\n\n// Iterative approach\nvector<vector<int>> powerset(vector<int>& array) {\n    vector<vector<int>> subset;\n    subset.push_back({}); // Initialize the powerset with the empty subset\n\n    // Iterate over each element in the input array\n    for (int ele : array) {\n        int length = subset.size(); // Get the current length of the subset\n\n        // Iterate over each existing subset\n        for (int i = 0; i < length; i++) {\n            vector<int> currentSubset = subset[i]; // Get the current subset\n\n            // Create a new subset by making a copy of the current subset\n            vector<int> newSubset = currentSubset;\n\n            // Add the current element to the new subset\n            newSubset.push_back(ele);\n\n            // Append the new subset to the powerset\n            subset.push_back(newSubset);\n        }\n    }\n\n    // Return the powerset\n    return subset;\n}"
  },
  {
    "path": "Recursion/powerset.go",
    "content": "/*\n\n\tWrite a function that takes in an array of unique integers and returns its powerset.\n\n\tSample Input : [1, 2, 3]\n\tOutput: [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]\n\n\tExplanation:\n\n\tThe code snippet represents a function `Powerset` that takes an array of integers as input and returns the powerset\n\tof the array. The powerset of a set is the set of all possible subsets of that set, including the empty set and the set itself.\n\n\tThe function `Powerset` calls a helper function `powerset` to perform the actual computation. Here's how the code works:\n\n\t1. The `Powerset` function initializes the computation by calling the `powerset` function with the array and the index\n\t   of the last element in the array (`len(array) - 1`).\n\n\t2. The `powerset` function is a recursive function that calculates the powerset. It takes the array and the current\n\t   index as input.\n\n\t3. At each recursive call, the function checks if the index is less than 0. If so, it means all elements have been\n\t   processed, and it returns a 2D slice containing the empty set as the only subset.\n\n\t4. If the index is not less than 0, the function retrieves the element at the current index from the array.\n\n\t5. The function recursively calls itself with the array and the index decremented by 1 to generate the subsets without\n\t   the current element.\n\n\t6. It then calculates the length of the subsets generated so far.\n\n\t7. Using a loop, the function iterates over the existing subsets and creates new subsets by appending the current element\n\t   to each subset. The new subsets are added to the existing subset slice.\n\n\t8. Finally, the function returns the updated subset slice, which contains all the subsets of the original array.\n\n\tBy recursively generating subsets while building upon the subsets generated at each step, the function constructs the\n\tpowerset of the given array.\n\n\tO(n*2^n) time | O(n*2^n) space - where n is the length of the input array\n*/\n\npackage main\n\nfunc Powerset(array []int) [][]int {\n\t// Call the powerset helper function to compute the powerset of the array\n\treturn powerset(array, len(array)-1)\n}\n\nfunc powerset(array []int, index int) [][]int {\n\t// Base case: If the index is less than 0, all elements have been processed, return the empty set\n\tif index < 0 {\n\t\treturn [][]int{{}}\n\t}\n\n\t// Retrieve the element at the current index\n\telement := array[index]\n\n\t// Recursively call the powerset function with the array and the index decremented by 1\n\tsubset := powerset(array, index-1)\n\n\t// Calculate the length of the current subset\n\tlength := len(subset)\n\n\t// Iterate over the existing subsets and create new subsets by appending the current element\n\tfor i := 0; i < length; i++ {\n\t\tcurrentSubset := subset[i]\n\t\tnewSubset := append([]int{}, currentSubset...) // Create a new subset by making a copy of the current subset\n\t\tnewSubset = append(newSubset, element)         // Append the current element to the new subset\n\t\tsubset = append(subset, newSubset)             // Add the new subset to the existing subset slice\n\t}\n\n\t// Return the updated subset slice containing all the subsets of the original array\n\treturn subset\n}\n\n// Iterative approach\n\nfunc PowersetIterative(array []int) [][]int {\n\t// Initialize the powerset with the empty subset\n\tsubset := [][]int{{}}\n\n\t// Iterate over each element in the input array\n\tfor _, ele := range array {\n\t\t// Get the current length of the subset\n\t\tlength := len(subset)\n\n\t\t// Iterate over each existing subset\n\t\tfor i := 0; i < length; i++ {\n\t\t\t// Get the current subset\n\t\t\tcurrentSubset := subset[i]\n\n\t\t\t// Create a new subset by making a copy of the current subset\n\t\t\tnewSubset := append([]int{}, currentSubset...)\n\n\t\t\t// Add the current element to the new subset\n\t\t\tnewSubset = append(newSubset, ele)\n\n\t\t\t// Append the new subset to the powerset\n\t\t\tsubset = append(subset, newSubset)\n\t\t}\n\t}\n\n\t// Return the powerset\n\treturn subset\n}\n"
  },
  {
    "path": "Recursion/powerset.java",
    "content": "/*\n\n\tWrite a function that takes in an array of unique integers and returns its powerset.\n\n\tSample Input : [1, 2, 3]\n\tOutput: [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]\n\n\tExplanation:\n\n\tThe code snippet represents a function `Powerset` that takes an array of integers as input and returns the powerset\n\tof the array. The powerset of a set is the set of all possible subsets of that set, including the empty set and the set itself.\n\n\tThe function `Powerset` calls a helper function `powerset` to perform the actual computation. Here's how the code works:\n\n\t1. The `Powerset` function initializes the computation by calling the `powerset` function with the array and the index\n\t   of the last element in the array (`len(array) - 1`).\n\n\t2. The `powerset` function is a recursive function that calculates the powerset. It takes the array and the current\n\t   index as input.\n\n\t3. At each recursive call, the function checks if the index is less than 0. If so, it means all elements have been\n\t   processed, and it returns a 2D slice containing the empty set as the only subset.\n\n\t4. If the index is not less than 0, the function retrieves the element at the current index from the array.\n\n\t5. The function recursively calls itself with the array and the index decremented by 1 to generate the subsets without\n\t   the current element.\n\n\t6. It then calculates the length of the subsets generated so far.\n\n\t7. Using a loop, the function iterates over the existing subsets and creates new subsets by appending the current element\n\t   to each subset. The new subsets are added to the existing subset slice.\n\n\t8. Finally, the function returns the updated subset slice, which contains all the subsets of the original array.\n\n\tBy recursively generating subsets while building upon the subsets generated at each step, the function constructs the\n\tpowerset of the given array.\n\n\tO(n*2^n) time | O(n*2^n) space - where n is the length of the input array\n*/\nimport java.util.ArrayList;\nimport java.util.List;\n\nclass Main {\n\n    public static List<List<Integer>> powerset(int[] array, int index) {\n        // Base case: when the index reaches -1, return a list with an empty subset\n        if (index < 0) {\n            List<List<Integer>> subsets = new ArrayList<>();\n            subsets.add(new ArrayList<>());\n            return subsets;\n        }\n\n        int element = array[index];\n        // Recursive call to generate the powerset for the elements up to index - 1\n        List<List<Integer>> subsets = powerset(array, index - 1);\n\n        // Length of the current subsets list\n        int length = subsets.size();\n\n        // Iterate through each subset and create new subsets by adding the current element\n        for (int i = 0; i < length; i++) {\n            List<Integer> currentSubset = subsets.get(i);\n            // Create a new subset by making a copy of the current subset\n            List<Integer> newSubset = new ArrayList<>(currentSubset);\n            // Add the current element to the new subset\n            newSubset.add(element);\n            // Add the new subset to the existing subsets list\n            subsets.add(newSubset);\n        }\n\n        // Return the resulting subsets list\n        return subsets;\n    }\n\n    public static List<List<Integer>> powerset(int[] array) {\n        // Call the helper function to generate the powerset starting from the last index\n        return powerset(array, array.length - 1);\n    }\n\n    public static void main(String[] args) {\n        int[] array = {1, 2, 3};\n        List<List<Integer>> subsets = powerset(array);\n        \n        // Print the subsets\n        for (List<Integer> subset : subsets) {\n            System.out.println(subset);\n        }\n    }\n}\n\n\n// Iterative approach\npublic class Powerset {\n    public static List<List<Integer>> powerset(int[] array) {\n        List<List<Integer>> subset = new ArrayList<>();\n        subset.add(new ArrayList<>()); // Initialize the powerset with the empty subset\n\n        // Iterate over each element in the input array\n        for (int ele : array) {\n            int length = subset.size(); // Get the current length of the subset\n\n            // Iterate over each existing subset\n            for (int i = 0; i < length; i++) {\n                List<Integer> currentSubset = new ArrayList<>(subset.get(i)); // Get the current subset\n\n                // Create a new subset by making a copy of the current subset\n                List<Integer> newSubset = new ArrayList<>(currentSubset);\n\n                // Add the current element to the new subset\n                newSubset.add(ele);\n\n                // Append the new subset to the powerset\n                subset.add(newSubset);\n            }\n        }\n\n        // Return the powerset\n        return subset;\n    }\n\n    public static void main(String[] args) {\n        int[] array = {1, 2, 3};\n        List<List<Integer>> result = powerset(array);\n        System.out.println(result);\n    }\n}"
  },
  {
    "path": "Recursion/powerset.js",
    "content": "/*\n\n\tWrite a function that takes in an array of unique integers and returns its powerset.\n\n\tSample Input : [1, 2, 3]\n\tOutput: [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]\n\n\tExplanation:\n\n\tThe code snippet represents a function `Powerset` that takes an array of integers as input and returns the powerset\n\tof the array. The powerset of a set is the set of all possible subsets of that set, including the empty set and the set itself.\n\n\tThe function `Powerset` calls a helper function `powerset` to perform the actual computation. Here's how the code works:\n\n\t1. The `Powerset` function initializes the computation by calling the `powerset` function with the array and the index\n\t   of the last element in the array (`len(array) - 1`).\n\n\t2. The `powerset` function is a recursive function that calculates the powerset. It takes the array and the current\n\t   index as input.\n\n\t3. At each recursive call, the function checks if the index is less than 0. If so, it means all elements have been\n\t   processed, and it returns a 2D slice containing the empty set as the only subset.\n\n\t4. If the index is not less than 0, the function retrieves the element at the current index from the array.\n\n\t5. The function recursively calls itself with the array and the index decremented by 1 to generate the subsets without\n\t   the current element.\n\n\t6. It then calculates the length of the subsets generated so far.\n\n\t7. Using a loop, the function iterates over the existing subsets and creates new subsets by appending the current element\n\t   to each subset. The new subsets are added to the existing subset slice.\n\n\t8. Finally, the function returns the updated subset slice, which contains all the subsets of the original array.\n\n\tBy recursively generating subsets while building upon the subsets generated at each step, the function constructs the\n\tpowerset of the given array.\n\n\tO(n*2^n) time | O(n*2^n) space - where n is the length of the input array\n*/\nfunction powerset(array, index) {\n  // Base case: when the index reaches -1, return a list with an empty subset\n  if (index < 0) {\n    return [[]];\n  }\n\n  const element = array[index];\n  // Recursive call to generate the powerset for the elements up to index - 1\n  const subsets = powerset(array, index - 1);\n\n  // Create new subsets by adding the current element to existing subsets\n  const length = subsets.length;\n  for (let i = 0; i < length; i++) {\n    const currentSubset = subsets[i];\n    // Create a new subset by making a copy of the current subset\n    const newSubset = [...currentSubset];\n    // Add the current element to the new subset\n    newSubset.push(element);\n    // Add the new subset to the existing subsets array\n    subsets.push(newSubset);\n  }\n\n  // Return the resulting subsets array\n  return subsets;\n}\n\nfunction getPowerSet(array) {\n  // Call the helper function to generate the powerset starting from the last index\n  return powerset(array, array.length - 1);\n}\n\n// Example usage\nconst array = [1, 2, 3];\nconst subsets = getPowerSet(array);\n\n// Print the subsets\nsubsets.forEach((subset) => {\n  console.log(subset);\n});\n\n// Iterative approach\nfunction powersetIterative(array) {\n  // Initialize the powerset with the empty subset\n  let subset = [[]];\n\n  // Iterate over each element in the input array\n  for (let ele of array) {\n    // Get the current length of the subset\n    let length = subset.length;\n\n    // Iterate over each existing subset\n    for (let i = 0; i < length; i++) {\n      // Get the current subset\n      let currentSubset = subset[i];\n\n      // Create a new subset by making a copy of the current subset\n      let newSubset = [...currentSubset];\n\n      // Add the current element to the new subset\n      newSubset.push(ele);\n\n      // Append the new subset to the powerset\n      subset.push(newSubset);\n    }\n  }\n\n  // Return the powerset\n  return subset;\n}\n"
  },
  {
    "path": "Recursion/powerset.py",
    "content": "'''\n\n\tWrite a function that takes in an array of unique integers and returns its powerset.\n\n\tSample Input : [1, 2, 3]\n\tOutput: [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]\n\n\tExplanation:\n\n\tThe code snippet represents a function `Powerset` that takes an array of integers as input and returns the powerset\n\tof the array. The powerset of a set is the set of all possible subsets of that set, including the empty set and the set itself.\n\n\tThe function `Powerset` calls a helper function `powerset` to perform the actual computation. Here's how the code works:\n\n\t1. The `Powerset` function initializes the computation by calling the `powerset` function with the array and the index\n\t   of the last element in the array (`len(array) - 1`).\n\n\t2. The `powerset` function is a recursive function that calculates the powerset. It takes the array and the current\n\t   index as input.\n\n\t3. At each recursive call, the function checks if the index is less than 0. If so, it means all elements have been\n\t   processed, and it returns a 2D slice containing the empty set as the only subset.\n\n\t4. If the index is not less than 0, the function retrieves the element at the current index from the array.\n\n\t5. The function recursively calls itself with the array and the index decremented by 1 to generate the subsets without\n\t   the current element.\n\n\t6. It then calculates the length of the subsets generated so far.\n\n\t7. Using a loop, the function iterates over the existing subsets and creates new subsets by appending the current element\n\t   to each subset. The new subsets are added to the existing subset slice.\n\n\t8. Finally, the function returns the updated subset slice, which contains all the subsets of the original array.\n\n\tBy recursively generating subsets while building upon the subsets generated at each step, the function constructs the\n\tpowerset of the given array.\n\n\tO(n*2^n) time | O(n*2^n) space - where n is the length of the input array\n'''\ndef powerset(array):\n    # Base case: when the index reaches -1, return a list with an empty subset\n    if index < 0:\n        return [[]]\n\n    element = array[index]\n    # Recursive call to generate the powerset for the elements up to index - 1\n    subset = powerset(array, index - 1)\n\n    # Length of the current subset list\n    length = len(subset)\n\n    # Iterate through each subset and create new subsets by adding the current element\n    for i in range(length):\n        currentSubset = subset[i]\n        # Create a new subset by making a copy of the current subset\n        newSubset = currentSubset[:]\n        # Add the current element to the new subset\n        newSubset.append(element)\n        # Add the new subset to the existing subset list\n        subset.append(newSubset)\n\n    # Return the resulting subset list\n    return subset\n\ndef Powerset(array):\n    # Call the helper function to generate the powerset starting from the last index\n    return powerset(array, len(array) - 1)\n\n\n# Iterative approach\ndef powersetIterative(array):\n  # Initialize the powerset with the empty subset\n  subset = [[]]\n\n  # Iterate over each element in the input array\n  for ele in array:\n    # Get the current length of the subset\n    length = len(subset)\n\n    # Iterate over each existing subset\n    for i in range(length):\n      # Get the current subset\n      currentSubset = subset[i]\n\n      # Create a new subset by making a copy of the current subset\n      newSubset = list(currentSubset)\n\n      # Add the current element to the new subset\n      newSubset.append(ele)\n\n      # Append the new subset to the powerset\n      subset.append(newSubset)\n\n  # Return the powerset\n  return subset\n"
  },
  {
    "path": "Recursion/print_numbers.cpp",
    "content": "// Print numbers recursively\r\n// Sample Input: 5\r\n// Output: 1 2 3 4 5\r\n#include<bits/stdc++.h>\r\nusing namespace std;\r\nvoid print(int n){\r\n    if(n == 0)\r\n        return;\r\n    print(n - 1);\r\n    cout << n << \" \";    \r\n}\r\nint main(){\r\n    print(5);\r\n    return 0;\r\n}"
  },
  {
    "path": "Recursion/recursive_bubble_sort.cpp",
    "content": "// Implementation of Recursive Bubble sort.\n// Bubble sort, sometimes referred to as sinking sort, is a simple sorting algorithm\n// that repeatedly steps through the input list element by element,\n// comparing the current element with the one after it, swapping their values if needed.\n//  These passes through the list are repeated until no swaps had to be performed during a pass,\n// meaning that the list has become fully sorted. (Source wiki) https://en.wikipedia.org/wiki/Bubble_sort\n\n// Time Complexity worst-case and average complexity O(n^{2})\n// Bubble sort is O(n) on a list that is already sorted i.e. Best case\n\n// Sample Input : [2, 1, 9, 3, 5, 4, 0]\n// Output : [0 1 2 3 4 5 9]\n// Program Author : Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\nvoid bubble_sort(int *A, int len){\n    if(len == 1)\n        return;\n    for(int i = 0; i < len - 1; i++){\n        if(A[i] > A[i+1]){\n            swap(A[i], A[i+1]);\n        }\n    }\n    bubble_sort(A, len-1);\n}\nint main(){\n    int A[] = {5, 4, 3, 2, 1, 7};\n    int len = sizeof(A) / sizeof(int);\n    bubble_sort(A, len);\n    for(int x : A){\n        cout << x << \" \";\n    }\n    return 0;\n}"
  },
  {
    "path": "Recursion/reverse_print.go",
    "content": "package main\n\nimport \"fmt\"\n\n// Starting from n print number till 1\nfunc print(n int) int {\n\tif n == 0 { // base case\n\t\treturn 0\n\t}\n\tfmt.Println(n)\n\treturn print(n - 1)\n}\n\nfunc main() {\n\tprint(10)\n}"
  },
  {
    "path": "Recursion/tower_of_hannoi.cpp",
    "content": "/*\n\tTowers of Hanoi puzzle.\n\tSource(https://en.wikipedia.org/wiki/Tower_of_Hanoi)\n\tObject of the game is to move all the disks over to Tower 3.\n\tBut you cannot place a larger disk onto a smaller disk.\n\n  Approach\n\t1 Move the top 􀝊 − 1 disks from 􀜵􀝋􀝑􀝎􀜿􀝁 to 􀜣􀝑􀝔􀝅􀝈􀝅􀜽􀝎􀝕 tower,\n\t2 Move the 􀝊􀯧􀯛 disk from 􀜵􀝋􀝑􀝎􀜿􀝁 to 􀜦􀝁􀝏􀝐􀝅􀝊􀜽􀝐􀝅􀝋􀝊 tower,\n\t3 Move the 􀝊 − 1disks from 􀜣􀝑􀝔􀝅􀝈􀝅􀜽􀝎􀝕 tower to 􀜦􀝁􀝏􀝐􀝅􀝊􀜽􀝐􀝅􀝋􀝊 tower.\n*/\n#include <iostream>\n\nvoid towerOfHanoi(int numDisks, char fromPeg, char toPeg, char auxPeg) {\n  if (numDisks == 1) {\n    std::cout << \"Move disk 1 from peg \" << fromPeg << \" to peg \" << toPeg << std::endl;\n  } else {\n    towerOfHanoi(numDisks - 1, fromPeg, auxPeg, toPeg);\n    std::cout << \"Move disk \" << numDisks << \" from peg \" << fromPeg << \" to peg \" << toPeg << std::endl;\n    towerOfHanoi(numDisks - 1, auxPeg, toPeg, fromPeg);\n  }\n}\n\nint main() {\n  towerOfHanoi(3, 'A', 'C', 'B');\n  return 0;\n}\n\n// This implementation uses recursion to solve the problem. The towerOfHanoi function takes four arguments: numDisks (the number of disks to move), fromPeg (the peg the disks start on), toPeg (the peg the disks should end up on), and auxPeg (the auxiliary peg used for moving the disks).\n// If numDisks is 1, the function simply moves the single disk from fromPeg to toPeg. Otherwise, it first moves numDisks - 1 disks from fromPeg to auxPeg using toPeg as the auxiliary peg. Then it moves the largest remaining disk from fromPeg to toPeg. Finally, it moves the numDisks - 1 disks from auxPeg to toPeg using fromPeg as the auxiliary peg.\n// The main function simply calls towerOfHanoi with the appropriate arguments (in this case, numDisks is 3 and the pegs are labeled A, B, and C).\n\n// When run, the program outputs the following to the console:\n\n// Move disk 1 from peg A to peg C\n// Move disk 2 from peg A to peg B\n// Move disk 1 from peg C to peg B\n// Move disk 3 from peg A to peg C\n// Move disk 1 from peg B to peg A\n// Move disk 2 from peg B to peg C\n// Move disk 1 from peg A to peg C\n\n\n// This output shows the sequence of moves that solve the Tower of Hanoi problem for 3 disks.\n\n\n"
  },
  {
    "path": "Recursion/tower_of_hannoi.java",
    "content": "/*\n    The Tower of Hanoi problem is a classic problem in computer science and mathematics that involves moving a stack of disks from one peg to another peg. The problem consists of three pegs and a set of disks of different sizes that can slide onto any peg. The objective of the puzzle is to move the entire stack to another peg, obeying the following simple rules:\n\n    Only one disk can be moved at a time.\n    Each move consists of taking the upper disk from one of the stacks and placing it on top of another stack or an empty peg.\n    No disk may be placed on top of a smaller disk.\n    The Tower of Hanoi problem is often used as an example of recursive problem-solving. The solution to the problem can be divided into three parts:\n\n    Move n-1 disks from the starting peg to the auxiliary peg.\n    Move the largest disk from the starting peg to the destination peg.\n    Move the n-1 disks from the auxiliary peg to the destination peg.\n    This process is repeated recursively until all the disks have been moved from the starting peg to the destination peg. The number of moves required to solve the puzzle for n disks can be calculated using the formula 2^n - 1.\n\n    Here's an implementation of the Tower of Hanoi problem in Java using recursion:\n\n*/\npublic class TowerOfHanoi {\n    public static void main(String[] args) {\n        int n = 3; // number of disks\n        char fromRod = 'A';\n        char toRod = 'C';\n        char auxRod = 'B';\n\n        System.out.println(\"Moves to solve Tower of Hanoi problem with \" + n + \" disks:\");\n        solveHanoi(n, fromRod, toRod, auxRod);\n    }\n\n    public static void solveHanoi(int n, char fromRod, char toRod, char auxRod) {\n        if (n == 1) {\n            System.out.println(\"Move disk 1 from rod \" + fromRod + \" to rod \" + toRod);\n            return;\n        }\n        solveHanoi(n - 1, fromRod, auxRod, toRod);\n        System.out.println(\"Move disk \" + n + \" from rod \" + fromRod + \" to rod \" + toRod);\n        solveHanoi(n - 1, auxRod, toRod, fromRod);\n    }\n}\n\n\n// -----------------------Explanation------------------------------\n\n// In this implementation, the solveHanoi method is called recursively to move the disks from one rod to another. The method takes in four parameters:\n\n// n: the number of disks\n// fromRod: the rod from which the disks are to be moved\n// toRod: the rod to which the disks are to be moved\n// auxRod: the auxiliary rod which can be used to move the disks\n// When the number of disks is 1, the method simply prints the move to be made. Otherwise, the method makes the following three recursive calls:\n\n// Move n-1 disks from fromRod to auxRod using toRod as the auxiliary rod.\n// Move the nth disk from fromRod to toRod.\n// Move the n-1 disks from auxRod to toRod using fromRod as the auxiliary rod.\n// This process is repeated recursively until all the disks have been moved from the starting rod to the destination rod."
  },
  {
    "path": "Recursion/tower_of_hannoi.js",
    "content": "/*\n\tTowers of Hanoi puzzle.\n\tSource(https://en.wikipedia.org/wiki/Tower_of_Hanoi)\n\tObject of the game is to move all the disks over to Tower 3.\n\tBut you cannot place a larger disk onto a smaller disk.\n\n  Approach\n\t1 Move the top 􀝊 − 1 disks from 􀜵􀝋􀝑􀝎􀜿􀝁 to 􀜣􀝑􀝔􀝅􀝈􀝅􀜽􀝎􀝕 tower,\n\t2 Move the 􀝊􀯧􀯛 disk from 􀜵􀝋􀝑􀝎􀜿􀝁 to 􀜦􀝁􀝏􀝐􀝅􀝊􀜽􀝐􀝅􀝋􀝊 tower,\n\t3 Move the 􀝊 − 1disks from 􀜣􀝑􀝔􀝅􀝈􀝅􀜽􀝎􀝕 tower to 􀜦􀝁􀝏􀝐􀝅􀝊􀜽􀝐􀝅􀝋􀝊 tower.\n*/\nfunction towerOfHanoi(numDisks, fromPeg, toPeg, auxPeg) {\n  if (numDisks === 1) {\n    console.log(`Move disk 1 from peg ${fromPeg} to peg ${toPeg}`);\n  } else {\n    towerOfHanoi(numDisks - 1, fromPeg, auxPeg, toPeg);\n    console.log(`Move disk ${numDisks} from peg ${fromPeg} to peg ${toPeg}`);\n    towerOfHanoi(numDisks - 1, auxPeg, toPeg, fromPeg);\n  }\n}\n\n// Example usage:\ntowerOfHanoi(3, \"A\", \"C\", \"B\"); // Move disk 1 from peg A to peg C, Move disk 2 from peg A to peg B, Move disk 1 from peg C to peg B, Move disk 3 from peg A to peg C, Move disk 1 from peg B to peg A, Move disk 2 from peg B to peg C, Move disk 1 from peg A to peg C\n\n// This implementation uses recursion to solve the problem. The towerOfHanoi function takes four arguments: numDisks (the number of disks to move), fromPeg (the peg the disks start on), toPeg (the peg the disks should end up on), and auxPeg (the auxiliary peg used for moving the disks).\n// If numDisks is 1, the function simply moves the single disk from fromPeg to toPeg. Otherwise, it first moves numDisks - 1 disks from fromPeg to auxPeg using toPeg as the auxiliary peg. Then it moves the largest remaining disk from fromPeg to toPeg. Finally, it moves the numDisks - 1 disks from auxPeg to toPeg using fromPeg as the auxiliary peg.\n// The function prints out the moves it makes to the console, so running towerOfHanoi(3, \"A\", \"C\", \"B\") would output:\n\n// Move disk 1 from peg A to peg C\n// Move disk 2 from peg A to peg B\n// Move disk 1 from peg C to peg B\n// Move disk 3 from peg A to peg C\n// Move disk 1 from peg B to peg A\n// Move disk 2 from peg B to peg C\n// Move disk 1 from peg A to peg C\n"
  },
  {
    "path": "Recursion/tower_of_hannoi.py",
    "content": "\n'''\n\tTowers of Hanoi puzzle.\n\tSource(https://en.wikipedia.org/wiki/Tower_of_Hanoi)\n\tObject of the game is to move all the disks over to Tower 3.\n\tBut you cannot place a larger disk onto a smaller disk.\n\n    Approach\n\t1 Move the top 􀝊 − 1 disks from 􀜵􀝋􀝑􀝎􀜿􀝁 to 􀜣􀝑􀝔􀝅􀝈􀝅􀜽􀝎􀝕 tower,\n\t2 Move the 􀝊􀯧􀯛 disk from 􀜵􀝋􀝑􀝎􀜿􀝁 to 􀜦􀝁􀝏􀝐􀝅􀝊􀜽􀝐􀝅􀝋􀝊 tower,\n\t3 Move the 􀝊 − 1disks from 􀜣􀝑􀝔􀝅􀝈􀝅􀜽􀝎􀝕 tower to 􀜦􀝁􀝏􀝐􀝅􀝊􀜽􀝐􀝅􀝋􀝊 tower.\n'''\n#Tower of Hanoi explanation - https://youtu.be/YstLjLCGmgg\ndef TowerOfHanoi(n, A,B,C):\n    if n == 0:\n        return\n    TowerOfHanoi(n-1, A,C,B)\n    print(\"Move disk\", n, \"from\", A, \"to rod\", B)\n    TowerOfHanoi(n-1, C, B, A)"
  },
  {
    "path": "Recursion/tower_of_hanoi.go",
    "content": "/*\n\tTowers of Hanoi puzzle.\n\tSource(https://en.wikipedia.org/wiki/Tower_of_Hanoi)\n\tObject of the game is to move all the disks over to Tower 3.\n\tBut you cannot place a larger disk onto a smaller disk.\n*/\n/*\nApproach\n\t1 Move the top 􀝊 − 1 disks from 􀜵􀝋􀝑􀝎􀜿􀝁 to 􀜣􀝑􀝔􀝅􀝈􀝅􀜽􀝎􀝕 tower,\n\t2 Move the 􀝊􀯧􀯛 disk from 􀜵􀝋􀝑􀝎􀜿􀝁 to 􀜦􀝁􀝏􀝐􀝅􀝊􀜽􀝐􀝅􀝋􀝊 tower,\n\t3 Move the 􀝊 − 1disks from 􀜣􀝑􀝔􀝅􀝈􀝅􀜽􀝎􀝕 tower to 􀜦􀝁􀝏􀝐􀝅􀝊􀜽􀝐􀝅􀝋􀝊 tower.\n*/\npackage main\n\nimport \"fmt\"\nfunc TowerOfHanoiHelper(n int, from, to, temp string) {\n\t// Base case\n\t// If only 1 disk, make the move and return \n\tif n == 1 {\n\t\tfmt.Println(\"Move disk \", n, \" from peg \", from, \" to peg \", to)\n\t\treturn\n\t}\n\n\t// Move top n-1 disks from A to B, using C as auxiliary \n\tTowerOfHanoiHelper(n-1, from, temp, to)\n\n\t// Move remaining disks from A to C \n\tfmt.Println(\"Move disk \", n, \" from peg \", from, \" to peg \", to)\n\t\n\t// Move n-1 disks from B to C using A as auxiliary\n\tTowerOfHanoiHelper(n-1, temp, to, from)\n}\n\nfunc TowersOfHanoi(n int) {\n\tTowerOfHanoiHelper(n, \"A\", \"C\", \"B\")\n}\nfunc main() {\n\tTowersOfHanoi(3)\n}"
  },
  {
    "path": "Recursion/valid_palindrome_2.py",
    "content": "'''\n    Write a function that takes a string as input and checks whether it can be a valid palindrome by removing at most one character from it.\n\n    Constraints: string.length The string only consists of English letters\n\n    Sample Input : \"madame\"\n    Output : True\n\n    Sample Input : \"masdasd\"\n    Output : False\t\n    \n'''\nclass Solution:\n    def subPalindrome(self,s,low,high,count):\n        if(low>high):\n            return True\n        if(count>1):\n            return False\n        if(s[low]!=s[high]):\n            return Solution.subPalindrome(self,s,low+1,high,count+1) or Solution.subPalindrome(self,s,low,high-1,count+1)\n        else:\n            return Solution.subPalindrome(self,s,low+1,high-1,count)\n\n    def validPalindrome(self, s: str) -> bool:\n        if(s==s[::-1]):\n            return True\n        return Solution.subPalindrome(self,s,0,len(s)-1,0)\n\nprint(Solution().validPalindrome(\"ebcbbececabbacecbbcbe\"))\nprint(Solution().validPalindrome(\"cdbeeeabddddbaeedebdc\"))\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n"
  },
  {
    "path": "Scheduling/fcfs.c",
    "content": "/*\n\nThe First-Come, First-Served (FCFS) scheduling algorithm is one of the simplest process scheduling algorithms used in operating systems. It follows the principle of serving processes in the order they arrive in the ready queue. In FCFS, the process that arrives first will be the first one to be executed, and it continues until the process completes its execution or enters a waiting state.\n\nAlgorithm Description:\n\nWhen a process enters the ready queue, it is added to the end of the queue (at the \"tail\" of the queue).\n\nThe CPU scheduler selects the process at the front of the queue (the \"head\" of the queue) for execution.\n\nThe selected process runs on the CPU until it completes its execution, enters a waiting state (e.g., I/O operation), or its time quantum (if there is a time-sharing system) expires.\n\nOnce the currently running process finishes, the CPU scheduler selects the process at the front of the queue as the next process to run. This process will continue until it completes or enters a waiting state, and so on.\n\nThis process of selecting and executing processes continues until all processes in the queue have executed.\n\nExample:\nLet's illustrate the FCFS algorithm with a simple example. Consider three processes, P1, P2, and P3, with their respective burst times (the time they need to complete execution):\n\nProcess P1: Burst time = 2 ms\nProcess P2: Burst time = 7 ms\nProcess P3: Burst time = 4 ms\nHere's how FCFS will schedule and execute these processes:\n\nInitially, the ready queue is empty.\n\nProcess P1 arrives first, so it is added to the ready queue:\n\nReady Queue: [P1]\nExecution: P1 (2 ms)\nProcess P1 completes its execution. Now, process P2 is selected because it's at the front of the queue:\n\nReady Queue: [P2]\nExecution: P2 (7 ms)\nProcess P2 completes its execution. Finally, process P3 is selected:\n\nReady Queue: [P3]\nExecution: P3 (4 ms)\nProcess P3 completes its execution.\n\nThe order of execution in FCFS is P1 -> P2 -> P3. FCFS is non-preemptive, meaning once a process starts execution, it continues until it finishes or enters a waiting state. It can suffer from the \"convoy effect,\" where a long process at the head of the queue can block shorter processes behind it.\n\n*/\n\n#include <stdio.h>\n#include <stdlib.h>\n\n// Struct for the info of each process\ntypedef struct \n{\n\n  int process_id;\n  int arrival_time;\n  int burst_time;\n\n} process;\n\n\nint main() {\n\n  // Number of processes\n  int number=3;\n\n  // Size of the array which will show the order of execution of the processes\n  process *arr;\n  arr = malloc(number * sizeof(process));\n\n  // Initialize for our example \n  arr[0].process_id = 1;\n  arr[0].arrival_time = 0;\n  arr[0].burst_time = 2;\n\n  arr[1].process_id = 2;\n  arr[1].arrival_time = 1;\n  arr[1].burst_time = 7;\n  \n  arr[2].process_id = 3;\n  arr[2].arrival_time = 3;\n  arr[2].burst_time = 4;\n\n  //Sorting the struct by arrival time\n  process temp;\n  for(int i=0; i<number; i++)\n  {\n    for(int j=0; j<number; j++)\n\t  {\n      //if shorter swap\n\t\t  if(arr[i].arrival_time < arr[j].arrival_time)\n\t\t  {\n\t\t\t  temp = arr[j];\n\t\t\t  arr[j] = arr[i];\n\t\t\t  arr[i] = temp;\n\t    }\n      \n    }\n  }\n\n  //Variable for the sum of burst time \n  int sum_of_burst_time=0;\n\n  //Calculate sum of burst time for helping us know the size of A\n  for (int i=0; i<number; i++)\n  {\n    sum_of_burst_time = sum_of_burst_time+arr[i].burst_time;\n  }\n\n  //Create an array to save the processes for gnatt chart\n  int *A = malloc( sum_of_burst_time * sizeof(int) );\n\n  //index for array A\n  int count=0;\n\n  //Save the id in cells of A\n  for (int i=0; i<number; i++)\n  {\n    //Put process id in arr[i].burst_time cells of A\n    for (int j=0; j<arr[i].burst_time; j++)\n    {\n      A[count]=arr[i].process_id; //save id\n      count++; //increase index\n    }\n    \n  }\n\n  //Print A (Gnatt chart)\n  for (int i=0; i<sum_of_burst_time; i++)\n  {\n    printf(\"%d\\n\",A[i]);\n  }\n\n  return 0; \n}"
  },
  {
    "path": "Scheduling/sjf.c",
    "content": "/*\nThe Shortest Job First (SJF) scheduling algorithm is a non-preemptive scheduling algorithm that selects the process with the shortest burst time for execution. In this algorithm, the process that requires the least amount of time to complete its execution is given the CPU first.\n\nAlgorithm Description:\n\nWhen a process enters the ready queue, the scheduler compares its burst time with the burst times of all other processes in the queue.\n\nThe process with the shortest burst time is selected to run next. If two processes have the same shortest burst time, the one that arrived first is chosen.\n\nThe selected process runs on the CPU until it completes its execution, enters a waiting state (e.g., I/O operation), or its time quantum (if there is a time-sharing system) expires.\n\nOnce the currently running process finishes, the CPU scheduler again selects the process with the shortest remaining burst time for execution.\n\nThis process of selecting and executing processes continues until all processes have completed.\n\nExample:\nLet's use your example with three processes: P1, P2, and P3, with arrival times and burst times as follows:\n\nProcess P1: Arrival time = 0 ms, Burst time = 7 ms\nProcess P2: Arrival time = 2 ms, Burst time = 3 ms\nProcess P3: Arrival time = 4 ms, Burst time = 8 ms\nHere's how SJF will schedule and execute these processes:\n\nInitially, the ready queue is empty.\n\nProcess P1 arrives first, so it is added to the ready queue:\n\nReady Queue: [P1]\nP1 has the shortest burst time (7 ms), so it is selected to run:\n\nExecution: P1 (7 ms)\nReady Queue: []\nProcess P2 arrives next, with a shorter burst time than P3, so it is added to the ready queue:\n\nReady Queue: [P2]\nP2 has the shortest burst time (3 ms), so it is selected to run:\n\nExecution: P2 (3 ms)\nReady Queue: []\nFinally, process P3 arrives and is added to the ready queue:\n\nReady Queue: [P3]\nP3 has the shortest burst time (8 ms), so it is selected to run:\n\nExecution: P3 (8 ms)\nReady Queue: []\nThe order of execution in SJF is P1 -> P2 -> P3. SJF aims to minimize the average waiting time for processes, making it an effective algorithm when you have information about the burst times of processes. However, it can suffer from starvation if a long job continually arrives after shorter jobs.\n*/\n\n#include <stdio.h>\n#include <stdlib.h>\n\n// Struct for the info of each process\ntypedef struct \n{\n\n  int process_id;\n  int arrival_time;\n  int burst_time;\n\n} process;\n\n\nint main() {\n\n  // Number of processes\n  int number=3;\n\n  // Size of the array which will show the order of execution of the processes\n  process *arr;\n  arr = malloc(number * sizeof(process));\n\n  // Initialize for our example \n  arr[0].process_id = 1;\n  arr[0].arrival_time = 0;\n  arr[0].burst_time = 7;\n  \n  arr[1].process_id = 2;\n  arr[1].arrival_time = 2;\n  arr[1].burst_time = 3;\n  \n  arr[2].process_id = 3;\n  arr[2].arrival_time = 4;\n  arr[2].burst_time = 8;\n\n  //Sorting the struct by arrival time\n  process temp;\n  for(int i=0; i<number; i++)\n  {\n\t  for(int j=0; j<number; j++)\n\t  {\n      //if shorter swap\n\t    if(arr[i].arrival_time < arr[j].arrival_time)\n\t\t  {\n\t\t\t  temp = arr[j];\n\t\t\t  arr[j] = arr[i];\n\t\t\t  arr[i] = temp;\n\t    }\n    }\n  }\n\n  //Variables for index,time and minimum burst time\n  int k=1,time=0,min;\n\n  //Sorting to create a correct priority\n  for (int i=0; i<number; i++)\n  {\n    \n    time = time + arr[i].burst_time; //Add arrival time to time\n    min = arr[k].burst_time; //Set minimum burst time\n    \n    for (int j=k; j<number; j++)\n    {\n      //If time more than or equal to arrival time \n      //And burst time less than or equal to minimum\n      //Then swap\n      if (time >= arr[j].arrival_time && arr[j].burst_time <= min)\n      {\n        temp = arr[k];\n        arr[k] = arr[j];\n        arr[j] = temp;\n      }\n    }\n    k++; //increase index\n  }\n\n  //Variable for the sum of burst time \n  int sum_of_burst_time=0;\n\n  //Calculate sum of burst time\n  for (int i=0; i<number; i++)\n  {\n    sum_of_burst_time = sum_of_burst_time + arr[i].burst_time;\n  }\n\n  //Create an array to save the processesfor gnatt chart\n  int *A = malloc( sum_of_burst_time * sizeof(int) );\n\n  //index for array A\n  int count=0;\n  \n  //Save the id in cells of A\n  for (int i=0; i<number; i++)\n  {\n    //Put process id in arr[i].burst_time cells of A\n    for (int j=0; j<arr[i].burst_time; j++)\n    {\n      A[count]=arr[i].process_id;//save id\n      count++; //increase index\n    }\n    \n  }\n\n  //Print A (Gnatt chart)\n  for (int i=0; i<sum_of_burst_time; i++)\n  {\n    printf(\"%d\\n\",A[i]);\n  }\n\n  return 0; \n  \n}"
  },
  {
    "path": "Scheduling/srtf.c",
    "content": "/*\nThe Shortest Remaining Time First (SRTF) scheduling algorithm is a preemptive scheduling algorithm that is an extension of the Shortest Job First (SJF) algorithm. SRTF selects the process with the shortest remaining burst time for execution. If a new process arrives with a shorter burst time than the currently executing process, the CPU is preempted, and the new process is executed. SRTF aims to minimize the waiting time for processes.\n\nAlgorithm Description:\n\nWhen a process enters the ready queue, the scheduler compares its burst time with the remaining burst times of all other processes in the queue.\n\nThe process with the shortest remaining burst time is selected to run. If two processes have the same shortest remaining time, the one that arrived first is chosen.\n\nThe selected process runs on the CPU for a time quantum or until it completes its execution, enters a waiting state (e.g., I/O operation), or a process with a shorter remaining time arrives.\n\nIf a new process with a shorter remaining time arrives while another process is executing, the CPU scheduler preempts the currently executing process and allows the new process to run.\n\nThis process of selecting and executing processes continues until all processes have completed.\n\nExample:\nLet's use your example with three processes: P1, P2, and P3, with arrival times and burst times as follows:\n\nProcess P1: Arrival time = 0 ms, Burst time = 7 ms\nProcess P2: Arrival time = 2 ms, Burst time = 3 ms\nProcess P3: Arrival time = 4 ms, Burst time = 8 ms\nHere's how SRTF will schedule and execute these processes:\n\nInitially, the ready queue is empty.\n\nProcess P1 arrives first, so it is added to the ready queue:\n\nReady Queue: [P1]\nP1 has the shortest remaining burst time (7 ms), so it is selected to run:\n\nExecution: P1 (7 ms)\nReady Queue: []\nProcess P2 arrives next, with a shorter burst time than P1, so it preempts the execution of P1:\n\nReady Queue: [P1]\nExecution: P2 (3 ms)\nReady Queue: [P1]\nP2 completes its execution, and P1 resumes because it has the shortest remaining burst time:\n\nExecution: P1 (4 ms)\nReady Queue: []\nFinally, process P3 arrives and is added to the ready queue:\n\nReady Queue: [P3]\nP1 has the shortest remaining burst time (4 ms), so it continues to run:\n\nExecution: P1 (4 ms)\nReady Queue: [P3]\n\nProcess P1 has a shorter remaining burst time (4 ms vs. 8 ms), so it preempts the execution of P3:\n\nReady Queue: [P3]\nExecution: P1 (4 ms)\nReady Queue: [P3]\nP1 completes its execution, and P3 resumes because it has the shortest remaining burst time:\n\nExecution: P3 (8 ms)\nReady Queue: []\n\nThe order of execution in SRTF is P1 -> P2 -> P1 -> P3. SRTF provides optimal turnaround times but may suffer from frequent context switches due to its preemptive nature.\n*/\n\n#include <stdio.h>\n#include <stdlib.h>\n\n// Struct for the info of each process\ntypedef struct \n{\n\n  int process_id;\n  int arrival_time;\n  int burst_time;\n\n} process;\n\n\nint main() {\n\n  // Number of processes\n  int number=3;\n  \n   // Size of the array which will show the order of execution of the processes\n  process *arr;\n  arr = malloc(number * sizeof(process));\n  \n  // Initialize for our example \n  arr[0].process_id = 1;\n  arr[0].arrival_time = 0;\n  arr[0].burst_time = 7;\n  \n  arr[1].process_id = 2;\n  arr[1].arrival_time = 2;\n  arr[1].burst_time = 3;\n  \n  arr[2].process_id = 3;\n  arr[2].arrival_time = 4;\n  arr[2].burst_time = 8;\n  \n  //Sorting the struct by arrival time\n  process temp;\n  for (int i=0; i<number; i++)\n  {\n    for (int j=0; j<number; j++)\n    {\n      //if shorter swap\n      if (arr[i].arrival_time < arr[j].arrival_time)\n      {\n        temp = arr[j];\n        arr[j] = arr[i];\n        arr[i] = temp;\n      }\n    }\n  }\n\n  //Variable for the sum of burst time \n  int sum_of_burst_time=0;\n\n  //Calculate sum of burst time\n  for (int i=0; i<number; i++)\n  {\n    sum_of_burst_time=sum_of_burst_time+arr[i].burst_time;\n  }\n\n  //Create an array to save the processesfor gnatt chart\n  int *A = malloc( sum_of_burst_time * sizeof(int) );\n\n  //Variables for minimum position,time and \"completed\" which check if processes are completed\n  int min_position;\n  int time=0;\n  int completed=0;\n\n  //Dont stop until completed=n\n  while (completed!=number)\n  {\n    int min=1000; //Set minimum a high number \n    \n    //Find minimum and minimum position\n    for (int i=0; i<number; i++)\n    {\n      \n      if (arr[i].burst_time<min && arr[i].burst_time!=0 && arr[i].arrival_time<=time)\n      {\n        \n        min = arr[i].burst_time;\n        min_position=i;\n        \n      }\n      \n    }\n\n    //Save the id in a cell of A\n    A[time]=arr[min_position].process_id;\n\n    //Decrease burst time of minimum \n    arr[min_position].burst_time--;\n\n    //If a process is finished increase \"completed\"\n    if (arr[min_position].burst_time==0)\n    {\n      completed++;\n    }\n\n    //Increase time\n    time++;\n    \n  }\n\n  //Print A (Gnatt chart)\n  for (int i=0; i<sum_of_burst_time; i++)\n  {\n    printf(\"%d\\n\",A[i]);\n  }\n\n\n    return 0; \n}"
  },
  {
    "path": "Scheduling Algortihms/fcfs.c",
    "content": "/*\n\nThe First-Come, First-Served (FCFS) scheduling algorithm is one of the simplest process scheduling algorithms used in operating systems. It follows the principle of serving processes in the order they arrive in the ready queue. In FCFS, the process that arrives first will be the first one to be executed, and it continues until the process completes its execution or enters a waiting state.\n\nAlgorithm Description:\n\nWhen a process enters the ready queue, it is added to the end of the queue (at the \"tail\" of the queue).\n\nThe CPU scheduler selects the process at the front of the queue (the \"head\" of the queue) for execution.\n\nThe selected process runs on the CPU until it completes its execution, enters a waiting state (e.g., I/O operation), or its time quantum (if there is a time-sharing system) expires.\n\nOnce the currently running process finishes, the CPU scheduler selects the process at the front of the queue as the next process to run. This process will continue until it completes or enters a waiting state, and so on.\n\nThis process of selecting and executing processes continues until all processes in the queue have executed.\n\nExample:\nLet's illustrate the FCFS algorithm with a simple example. Consider three processes, P1, P2, and P3, with their respective burst times (the time they need to complete execution):\n\nProcess P1: Burst time = 2 ms\nProcess P2: Burst time = 7 ms\nProcess P3: Burst time = 4 ms\nHere's how FCFS will schedule and execute these processes:\n\nInitially, the ready queue is empty.\n\nProcess P1 arrives first, so it is added to the ready queue:\n\nReady Queue: [P1]\nExecution: P1 (2 ms)\nProcess P1 completes its execution. Now, process P2 is selected because it's at the front of the queue:\n\nReady Queue: [P2]\nExecution: P2 (7 ms)\nProcess P2 completes its execution. Finally, process P3 is selected:\n\nReady Queue: [P3]\nExecution: P3 (4 ms)\nProcess P3 completes its execution.\n\nThe order of execution in FCFS is P1 -> P2 -> P3. FCFS is non-preemptive, meaning once a process starts execution, it continues until it finishes or enters a waiting state. It can suffer from the \"convoy effect,\" where a long process at the head of the queue can block shorter processes behind it.\n\n*/\n\n#include <stdio.h>\n#include <stdlib.h>\n\n// Struct for the info of each process\ntypedef struct \n{\n\n  int process_id;\n  int arrival_time;\n  int burst_time;\n\n} process;\n\n\nint main() {\n\n  // Number of processes\n  int number=3;\n\n  // Size of the array which will show the order of execution of the processes\n  process *arr;\n  arr = malloc(number * sizeof(process));\n\n  // Initialize for our example \n  arr[0].process_id = 1;\n  arr[0].arrival_time = 0;\n  arr[0].burst_time = 2;\n\n  arr[1].process_id = 2;\n  arr[1].arrival_time = 1;\n  arr[1].burst_time = 7;\n  \n  arr[2].process_id = 3;\n  arr[2].arrival_time = 3;\n  arr[2].burst_time = 4;\n\n  //Sorting the struct by arrival time\n  process temp;\n  for(int i=0; i<number; i++)\n  {\n    for(int j=0; j<number; j++)\n\t  {\n      //if shorter swap\n\t\t  if(arr[i].arrival_time < arr[j].arrival_time)\n\t\t  {\n\t\t\t  temp = arr[j];\n\t\t\t  arr[j] = arr[i];\n\t\t\t  arr[i] = temp;\n\t    }\n      \n    }\n  }\n\n  //Variable for the sum of burst time \n  int sum_of_burst_time=0;\n\n  //Calculate sum of burst time for helping us know the size of A\n  for (int i=0; i<number; i++)\n  {\n    sum_of_burst_time = sum_of_burst_time+arr[i].burst_time;\n  }\n\n  //Create an array to save the processes for gnatt chart\n  int *A = malloc( sum_of_burst_time * sizeof(int) );\n\n  //index for array A\n  int count=0;\n\n  //Save the id in cells of A\n  for (int i=0; i<number; i++)\n  {\n    //Put process id in arr[i].burst_time cells of A\n    for (int j=0; j<arr[i].burst_time; j++)\n    {\n      A[count]=arr[i].process_id; //save id\n      count++; //increase index\n    }\n    \n  }\n\n  //Print A (Gnatt chart)\n  for (int i=0; i<sum_of_burst_time; i++)\n  {\n    printf(\"%d\\n\",A[i]);\n  }\n\n  return 0; \n}"
  },
  {
    "path": "Scheduling Algortihms/sjf.c",
    "content": "/*\nThe Shortest Job First (SJF) scheduling algorithm is a non-preemptive scheduling algorithm that selects the process with the shortest burst time for execution. In this algorithm, the process that requires the least amount of time to complete its execution is given the CPU first.\n\nAlgorithm Description:\n\nWhen a process enters the ready queue, the scheduler compares its burst time with the burst times of all other processes in the queue.\n\nThe process with the shortest burst time is selected to run next. If two processes have the same shortest burst time, the one that arrived first is chosen.\n\nThe selected process runs on the CPU until it completes its execution, enters a waiting state (e.g., I/O operation), or its time quantum (if there is a time-sharing system) expires.\n\nOnce the currently running process finishes, the CPU scheduler again selects the process with the shortest remaining burst time for execution.\n\nThis process of selecting and executing processes continues until all processes have completed.\n\nExample:\nLet's use your example with three processes: P1, P2, and P3, with arrival times and burst times as follows:\n\nProcess P1: Arrival time = 0 ms, Burst time = 7 ms\nProcess P2: Arrival time = 2 ms, Burst time = 3 ms\nProcess P3: Arrival time = 4 ms, Burst time = 8 ms\nHere's how SJF will schedule and execute these processes:\n\nInitially, the ready queue is empty.\n\nProcess P1 arrives first, so it is added to the ready queue:\n\nReady Queue: [P1]\nP1 has the shortest burst time (7 ms), so it is selected to run:\n\nExecution: P1 (7 ms)\nReady Queue: []\nProcess P2 arrives next, with a shorter burst time than P3, so it is added to the ready queue:\n\nReady Queue: [P2]\nP2 has the shortest burst time (3 ms), so it is selected to run:\n\nExecution: P2 (3 ms)\nReady Queue: []\nFinally, process P3 arrives and is added to the ready queue:\n\nReady Queue: [P3]\nP3 has the shortest burst time (8 ms), so it is selected to run:\n\nExecution: P3 (8 ms)\nReady Queue: []\nThe order of execution in SJF is P1 -> P2 -> P3. SJF aims to minimize the average waiting time for processes, making it an effective algorithm when you have information about the burst times of processes. However, it can suffer from starvation if a long job continually arrives after shorter jobs.\n*/\n\n#include <stdio.h>\n#include <stdlib.h>\n\n// Struct for the info of each process\ntypedef struct \n{\n\n  int process_id;\n  int arrival_time;\n  int burst_time;\n\n} process;\n\n\nint main() {\n\n  // Number of processes\n  int number=3;\n\n  // Size of the array which will show the order of execution of the processes\n  process *arr;\n  arr = malloc(number * sizeof(process));\n\n  // Initialize for our example \n  arr[0].process_id = 1;\n  arr[0].arrival_time = 0;\n  arr[0].burst_time = 7;\n  \n  arr[1].process_id = 2;\n  arr[1].arrival_time = 2;\n  arr[1].burst_time = 3;\n  \n  arr[2].process_id = 3;\n  arr[2].arrival_time = 4;\n  arr[2].burst_time = 8;\n\n  //Sorting the struct by arrival time\n  process temp;\n  for(int i=0; i<number; i++)\n  {\n\t  for(int j=0; j<number; j++)\n\t  {\n      //if shorter swap\n\t    if(arr[i].arrival_time < arr[j].arrival_time)\n\t\t  {\n\t\t\t  temp = arr[j];\n\t\t\t  arr[j] = arr[i];\n\t\t\t  arr[i] = temp;\n\t    }\n    }\n  }\n\n  //Variables for index,time and minimum burst time\n  int k=1,time=0,min;\n\n  //Sorting to create a correct priority\n  for (int i=0; i<number; i++)\n  {\n    \n    time = time + arr[i].burst_time; //Add arrival time to time\n    min = arr[k].burst_time; //Set minimum burst time\n    \n    for (int j=k; j<number; j++)\n    {\n      //If time more than or equal to arrival time \n      //And burst time less than or equal to minimum\n      //Then swap\n      if (time >= arr[j].arrival_time && arr[j].burst_time <= min)\n      {\n        temp = arr[k];\n        arr[k] = arr[j];\n        arr[j] = temp;\n      }\n    }\n    k++; //increase index\n  }\n\n  //Variable for the sum of burst time \n  int sum_of_burst_time=0;\n\n  //Calculate sum of burst time\n  for (int i=0; i<number; i++)\n  {\n    sum_of_burst_time = sum_of_burst_time + arr[i].burst_time;\n  }\n\n  //Create an array to save the processesfor gnatt chart\n  int *A = malloc( sum_of_burst_time * sizeof(int) );\n\n  //index for array A\n  int count=0;\n  \n  //Save the id in cells of A\n  for (int i=0; i<number; i++)\n  {\n    //Put process id in arr[i].burst_time cells of A\n    for (int j=0; j<arr[i].burst_time; j++)\n    {\n      A[count]=arr[i].process_id;//save id\n      count++; //increase index\n    }\n    \n  }\n\n  //Print A (Gnatt chart)\n  for (int i=0; i<sum_of_burst_time; i++)\n  {\n    printf(\"%d\\n\",A[i]);\n  }\n\n  return 0; \n  \n}"
  },
  {
    "path": "Scheduling Algortihms/srtf.c",
    "content": "/*\nThe Shortest Remaining Time First (SRTF) scheduling algorithm is a preemptive scheduling algorithm that is an extension of the Shortest Job First (SJF) algorithm. SRTF selects the process with the shortest remaining burst time for execution. If a new process arrives with a shorter burst time than the currently executing process, the CPU is preempted, and the new process is executed. SRTF aims to minimize the waiting time for processes.\n\nAlgorithm Description:\n\nWhen a process enters the ready queue, the scheduler compares its burst time with the remaining burst times of all other processes in the queue.\n\nThe process with the shortest remaining burst time is selected to run. If two processes have the same shortest remaining time, the one that arrived first is chosen.\n\nThe selected process runs on the CPU for a time quantum or until it completes its execution, enters a waiting state (e.g., I/O operation), or a process with a shorter remaining time arrives.\n\nIf a new process with a shorter remaining time arrives while another process is executing, the CPU scheduler preempts the currently executing process and allows the new process to run.\n\nThis process of selecting and executing processes continues until all processes have completed.\n\nExample:\nLet's use your example with three processes: P1, P2, and P3, with arrival times and burst times as follows:\n\nProcess P1: Arrival time = 0 ms, Burst time = 7 ms\nProcess P2: Arrival time = 2 ms, Burst time = 3 ms\nProcess P3: Arrival time = 4 ms, Burst time = 8 ms\nHere's how SRTF will schedule and execute these processes:\n\nInitially, the ready queue is empty.\n\nProcess P1 arrives first, so it is added to the ready queue:\n\nReady Queue: [P1]\nP1 has the shortest remaining burst time (7 ms), so it is selected to run:\n\nExecution: P1 (7 ms)\nReady Queue: []\nProcess P2 arrives next, with a shorter burst time than P1, so it preempts the execution of P1:\n\nReady Queue: [P1]\nExecution: P2 (3 ms)\nReady Queue: [P1]\nP2 completes its execution, and P1 resumes because it has the shortest remaining burst time:\n\nExecution: P1 (4 ms)\nReady Queue: []\nFinally, process P3 arrives and is added to the ready queue:\n\nReady Queue: [P3]\nP1 has the shortest remaining burst time (4 ms), so it continues to run:\n\nExecution: P1 (4 ms)\nReady Queue: [P3]\n\nProcess P1 has a shorter remaining burst time (4 ms vs. 8 ms), so it preempts the execution of P3:\n\nReady Queue: [P3]\nExecution: P1 (4 ms)\nReady Queue: [P3]\nP1 completes its execution, and P3 resumes because it has the shortest remaining burst time:\n\nExecution: P3 (8 ms)\nReady Queue: []\n\nThe order of execution in SRTF is P1 -> P2 -> P1 -> P3. SRTF provides optimal turnaround times but may suffer from frequent context switches due to its preemptive nature.\n*/\n\n#include <stdio.h>\n#include <stdlib.h>\n\n// Struct for the info of each process\ntypedef struct \n{\n\n  int process_id;\n  int arrival_time;\n  int burst_time;\n\n} process;\n\n\nint main() {\n\n  // Number of processes\n  int number=3;\n  \n   // Size of the array which will show the order of execution of the processes\n  process *arr;\n  arr = malloc(number * sizeof(process));\n  \n  // Initialize for our example \n  arr[0].process_id = 1;\n  arr[0].arrival_time = 0;\n  arr[0].burst_time = 7;\n  \n  arr[1].process_id = 2;\n  arr[1].arrival_time = 2;\n  arr[1].burst_time = 3;\n  \n  arr[2].process_id = 3;\n  arr[2].arrival_time = 4;\n  arr[2].burst_time = 8;\n  \n  //Sorting the struct by arrival time\n  process temp;\n  for (int i=0; i<number; i++)\n  {\n    for (int j=0; j<number; j++)\n    {\n      //if shorter swap\n      if (arr[i].arrival_time < arr[j].arrival_time)\n      {\n        temp = arr[j];\n        arr[j] = arr[i];\n        arr[i] = temp;\n      }\n    }\n  }\n\n  //Variable for the sum of burst time \n  int sum_of_burst_time=0;\n\n  //Calculate sum of burst time\n  for (int i=0; i<number; i++)\n  {\n    sum_of_burst_time=sum_of_burst_time+arr[i].burst_time;\n  }\n\n  //Create an array to save the processesfor gnatt chart\n  int *A = malloc( sum_of_burst_time * sizeof(int) );\n\n  //Variables for minimum position,time and \"completed\" which check if processes are completed\n  int min_position;\n  int time=0;\n  int completed=0;\n\n  //Dont stop until completed=n\n  while (completed!=number)\n  {\n    int min=1000; //Set minimum a high number \n    \n    //Find minimum and minimum position\n    for (int i=0; i<number; i++)\n    {\n      \n      if (arr[i].burst_time<min && arr[i].burst_time!=0 && arr[i].arrival_time<=time)\n      {\n        \n        min = arr[i].burst_time;\n        min_position=i;\n        \n      }\n      \n    }\n\n    //Save the id in a cell of A\n    A[time]=arr[min_position].process_id;\n\n    //Decrease burst time of minimum \n    arr[min_position].burst_time--;\n\n    //If a process is finished increase \"completed\"\n    if (arr[min_position].burst_time==0)\n    {\n      completed++;\n    }\n\n    //Increase time\n    time++;\n    \n  }\n\n  //Print A (Gnatt chart)\n  for (int i=0; i<sum_of_burst_time; i++)\n  {\n    printf(\"%d\\n\",A[i]);\n  }\n\n\n    return 0; \n}"
  },
  {
    "path": "Searching/first_duplicate_value.js",
    "content": "/*  PROBLEM STATEMENT  */\n\n/*  Given an array of integers between 1 and n, inclusive, where n is the length of the array, \n    write a function that returns the first integer that appears more than once (when the array\n    is read from left to right). \n*/\n\n\n\n/*  The difference between the two solutions provided is that the first solution has a space complexity\n    of 0(1), meaning constant space complexity, while the second solution has a space complexity of 0(n),\n    meaning linear space complexity. finally both solutions has a time complexity of 0(n), meaning linear\n    time complexity.\n*/\n\n\n\n//  Big-O = O(n) time complexity\n//  Big-O = O(1) space complexity\nconst firstDuplicate1 = arr => {\n    \n    // firstly iterate/loop through the given array\n    for(let i = 0; i < arr.length; i++){\n        // then use the Array.prototype.lastIndexOf() method to check for duplicates.\n        // finally return the first number that appers more than once.\n        if(arr.lastIndexOf(arr[i]) !== i) return arr[i];\n    };\n\n    // return the message No duplicate found, if no dupliacte is found after the iteration process.\n    return \"No duplicate found!\";\n}\n\nconsole.log(firstDuplicate1([2, 1, 5, 2, 3, 3, 4]));\n\n\n\n\n// Big-O = O(n) time complexity\n// Big-O = O(n) space complexity\nconst firstDuplicate2 = arr => {\n\n    // first off, let's create our Set object\n    // this Set object will allow us to store each element from the given array as a unique value\n    let elementSet = new Set();\n    \n    // then iterate/loop through the given array\n    for (let i = 0; i < arr.length; i++) {\n        // we'll check to see if the Set already contains the element that we're currently on in our loop\n        // if it exists, then we've found our first duplicate! We'll return that value and be done\n        if (elementSet.has(arr[i])) return arr[i];\n        // if the element isn't in our Set yet, then we add it to the Set and move on to the next element in the array.\n        elementSet.add(arr[i]);\n    }\n\n    // return the message No duplicate found, if no dupliacte is found after the iteration process.\n    return \"No duplicates found!\";\n}\n\nconsole.log(firstDuplicate2([2, 1, 5, 2, 3, 3, 4]));\n\n"
  },
  {
    "path": "Searching/linear_search_string.cpp",
    "content": "// Linear search in an array of strings\n#include<bits/stdc++.h>\nusing namespace std;\nint main(){\n    char a[10][100];\n    int n;\n    cin >> n;\n    cin.ignore();\n    for(int i = 0 ; i < n; i++){\n        cin.getline(a[i], 100);\n    }\n    char key[100];\n    cout << \"Enter string to search : \";\n    cin.getline(key, 100);\n    int i = 0; \n    for(i = 0; i < n; i++){\n        if(strcmp(key, a[i]) == 0){\n            cout << \"Found at index : \" << i;\n            break;\n        }    \n    }\n    if(i == n)\n        cout << \"Not Found\" <<endl;\n    return 0;\n}"
  },
  {
    "path": "Searching/semordnilap.go",
    "content": "/*\n\tWrite a function that takes in a list of unique strings and returns a list of\n\tsemordnilap pairs.\n\n\tA semordnilap pair is defined as a set of different strings where the reverse\n\tof one word is the same as the forward version of the other. For example the\n\twords \"diaper\" and \"repaid\" are a semordnilap pair, as are the words\n\t\"palindromes\" and \"semordnilap\".\n*/\n\n// Sample Input :  = [\"diaper\", \"abc\", \"test\", \"cba\", \"repaid\"]\n// Output : [[\"diaper\", \"repaid\"], [\"abc\", \"cba\"]]\n// Time and Space complexity : O(n * m) time | O(n * m) space - where n is the number of words and m is the length of the longest word\npackage main\n\nfunc Semordnilap(words []string) [][]string {\n\tresult := [][]string{}\n\t// crete word set\n    wordSet := make(map[string]bool)\n    for _, word := range words {\n        wordSet[word] = true\n    }\n\t\n\t// After creating the set of words, try iterating through the original array. For\n\t// each word, can you check if its semordnilap pair is in the word list\n    for _, word := range words {\n        reverse := reverse(word)\n        if _, wordInSet := wordSet[reverse]; wordInSet && word != reverse {\n            result = append(result, []string{word, reverse})\n            delete(wordSet, word)\n            delete(wordSet, reverse)\n        } \n    }\n\treturn result\n}\n\nfunc reverse(s string) string {\n    x := []byte{}\n    for i := len(s) - 1; i >= 0; i-- {\n        x = append(x, s[i])\n    }\n    return string(x)\n}\n"
  },
  {
    "path": "Searching/separate_0s_and_1s.go",
    "content": "// Program to separate Zeros and Ones\n// Sample input: [0, 1, 0, 1, 0, 0, 1]\n// Output : [0, 0, 0, 0, 1, 1, 1]\n\npackage main\n\nimport \"fmt\"\n\nfunc SeparateZerosAndOnes(Arr []int) []int {\n\tstart, end := 0, len(Arr) - 1\n\n\tfor start < end {\n\t\tfor Arr[start] == 0 && start < end {\n\t\t\tstart++ // element in correct place so just increment the counter\n\t\t}\n\t\tfor Arr[end]  == 1 && start < end {\n\t\t\tend-- // element in correct place so just decrement the counter\n\t\t}\n\t\t// two pointers start and end which are not in correct place so need to be swapped\n\t\tif start < end {\n\t\t\tArr[start], Arr[end] = Arr[end], Arr[start]\n\t\t\tstart++ \n\t\t\tend--\n\t\t}\n\t}\n\treturn Arr\n}\n\nfunc main() {\n\tArr := []int{0, 1, 1, 0, 1, 0, 0, 1}\n\tfmt.Println(SeparateZerosAndOnes(Arr))\n}"
  },
  {
    "path": "Searching/separate_even_odd.go",
    "content": "// Program to separate Even and Odd numbers\n// Sample input: [1, 2, 3, 4, 5, 6]\n// Output : [6 2 4 3 5 1]\n\npackage main\n\nimport \"fmt\"\n\nfunc SeparateEvenAndOdd(Arr []int) []int {\n\tstart, end := 0, len(Arr) - 1\n\n\tfor start < end {\n\t\tfor Arr[start] % 2 == 0 && start < end {\n\t\t\tstart++ // element in correct place so just increment the counter\n\t\t}\n\t\tfor Arr[end] % 2 == 1 && start < end {\n\t\t\tend-- // element in correct place so just decrement the counter\n\t\t}\n\t\t// two pointers start and end which are not in correct place so need to be swapped\n\t\tif start < end {\n\t\t\tArr[start], Arr[end] = Arr[end], Arr[start]\n\t\t\tstart++ \n\t\t\tend--\n\t\t}\n\t}\n\treturn Arr\n}\n\nfunc main() {\n\tArr := []int{1, 2, 3, 4, 5, 6}\n\tfmt.Println(SeparateEvenAndOdd(Arr))\n}"
  },
  {
    "path": "Sliding Window/find_max.go",
    "content": "// Statement:\n\n//// Given an array and an integer K, find the maximum for each and every contiguous subarray of size K.\n\n// Example:\n\n//// Input: N = 5 arr[] = {5, 4, 1, 7, 3}, K = 2\n//// Output: 5 4 7 7\n//// Explanation: \tMaximum of 5, 4 is 5\n////           \tMaximum of 4, 1 is 4\n////           \tMaximum of 1, 7 is 7\n////           \tMaximum of 7, 3 is 7\n\n// Approach:\n\n//// We will travel from 0 to (N-K)th element of the given array. \n//// At each index, we will find the maximum of K indexes including the current index and print.\n//// Suppose we are at ith index then we will find maximum of i, i+1, i+2, .. i+k-1 elements and print it.    \n\n// Complexity:\n\n//// Time  Complexity: O(N*K)\n//// Space Complexity: O(1)\n\n// Code: \n\npackage main\nimport \"fmt\"\n\nfunc printKMax(arr []int, N int, K int) {\n    \n\tvar j, max int\n\n\t// Finding the maximum elemnt in each window\n\tfor i := 0; i <= N-K; i++ {\n\t\tmax = arr[i]\n\n\t\tfor j = 1; j < K; j++ {\t\t\n\t\t\tif arr[i+j] > max {\n\t\t\t\tmax = arr[i+j]\n\t\t\t}\n\t\t}\n\t\tfmt.Printf(\"%d \", max)\n\t}\n}\n\nfunc main() {\n\n\tvar N, K int  \t\t\t\t\t// Variable declaration \n\tfmt.Scan(&N) \t\t\t\t\t// Initialise length of array \n\t\n\tarr := make([]int, N)\t\t\t// Array Declaration\n\tfor i := 0; i < N; i++ {\t\t\t// Array Initialisation\n\t    fmt.Scan(&arr[i])\n\t}\n\t\n\tfmt.Scan(&K)\t\t\t\t\t// Window length initialisation\n\t\n\tprintKMax(arr, N, K)\t\t\t// Function call to print maximum element in the window\n}\n"
  },
  {
    "path": "Sliding Window/fruits_into_basket.cpp",
    "content": "/*\n    Fruits into basket\n    Summary:\n    The given code defines a Java class `Solution` with a method `totalFruit` that solves a problem related to collecting fruits \n    from fruit trees while adhering to a constraint of collecting fruits from at most two different types of fruit trees. \n    The code uses a sliding window approach to find the maximum number of fruits that can be collected from the trees under \n    this constraint.\n\n    - The `fruits` array represents the types of fruit trees, where each element represents a type of fruit.\n\n    - The code initializes variables `longest` and `max` to keep track of the length of the longest subarray with at \n    most two distinct elements and the maximum number of fruits collected, respectively.\n\n    - The `startWindow` variable represents the left boundary of the sliding window.\n\n    - A `HashMap` called `basket` is used to keep track of the count of each type of fruit in the current window.\n\n    - The code iterates through the `fruits` array using two pointers, `startWindow` and `endWindow`, to traverse \n    the array from left to right.\n\n    - Within the loop, the code updates the `basket` map with the count of fruit types in the current window, and it \n    ensures that there are at most two different types of fruits in the window by adjusting the window as needed.\n\n    - The `max` variable is updated with the maximum window size seen so far.\n\n    - Finally, the method returns `max`, which represents the maximum number of fruits that can be collected under \n    the given constraint.\n\n    Space Complexity:\n    - The space complexity of this code is O(1) in addition to the input `fruits` array. This is because the space used \n    for variables such as `longest`, `max`, `startWindow`, and `basket` remains constant and does not depend on the size \n    of the `fruits` array.\n\n    Time Complexity:\n    - The time complexity of this code is O(n), where 'n' is the length of the `fruits` array. The code iterates through the \n    `fruits` array once with two pointers, and the work done within each iteration is constant time. Therefore, the overall \n    time complexity is linear in the size of the input array.\n*/\n#include <iostream>\n#include <vector>\n#include <unordered_map>\n\nusing namespace std;\n\nint totalFruit(vector<int>& fruits) {\n    int longest = 0; // Initialize a variable to track the longest subarray length\n    int maxFruits = 0; // Initialize a variable to store the maximum number of fruits\n    int startWindow = 0; // Initialize the left boundary of the window\n    unordered_map<int, int> basket; // Create an unordered_map to track fruit counts\n\n    for (int endWindow = 0; endWindow < fruits.size(); endWindow++) {\n        basket[fruits[endWindow]]++;\n        // Add the current fruit to the basket and increment its count\n\n        while (basket.size() > 2) {\n            basket[fruits[startWindow]]--;\n            if (basket[fruits[startWindow]] == 0) {\n                basket.erase(fruits[startWindow]);\n            }\n            // Adjust the window to maintain at most two fruit types\n            startWindow++; // Move the left boundary of the window to the right\n        }\n\n        maxFruits = max(maxFruits, endWindow - startWindow + 1);\n        // Update maxFruits with the maximum window size seen so far\n    }\n\n    return maxFruits; // Return the maximum number of fruits that can be collected\n}\n\nint main() {\n    vector<int> fruits = {1, 2, 1, 2, 3};\n\n    int result = totalFruit(fruits);\n\n    cout << result << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Sliding Window/fruits_into_basket.go",
    "content": "/*\n    Fruits into basket\n    Summary:\n    The given code defines a Java class `Solution` with a method `totalFruit` that solves a problem related to collecting fruits \n    from fruit trees while adhering to a constraint of collecting fruits from at most two different types of fruit trees. \n    The code uses a sliding window approach to find the maximum number of fruits that can be collected from the trees under \n    this constraint.\n\n    - The `fruits` array represents the types of fruit trees, where each element represents a type of fruit.\n\n    - The code initializes variables `longest` and `max` to keep track of the length of the longest subarray with at \n    most two distinct elements and the maximum number of fruits collected, respectively.\n\n    - The `startWindow` variable represents the left boundary of the sliding window.\n\n    - A `HashMap` called `basket` is used to keep track of the count of each type of fruit in the current window.\n\n    - The code iterates through the `fruits` array using two pointers, `startWindow` and `endWindow`, to traverse \n    the array from left to right.\n\n    - Within the loop, the code updates the `basket` map with the count of fruit types in the current window, and it \n    ensures that there are at most two different types of fruits in the window by adjusting the window as needed.\n\n    - The `max` variable is updated with the maximum window size seen so far.\n\n    - Finally, the method returns `max`, which represents the maximum number of fruits that can be collected under \n    the given constraint.\n\n    Space Complexity:\n    - The space complexity of this code is O(1) in addition to the input `fruits` array. This is because the space used \n    for variables such as `longest`, `max`, `startWindow`, and `basket` remains constant and does not depend on the size \n    of the `fruits` array.\n\n    Time Complexity:\n    - The time complexity of this code is O(n), where 'n' is the length of the `fruits` array. The code iterates through the \n    `fruits` array once with two pointers, and the work done within each iteration is constant time. Therefore, the overall \n    time complexity is linear in the size of the input array.\n*/\npackage main\n\nimport \"fmt\"\n\nfunc totalFruit(fruits []int) int {\n    longest := 0 // Initialize a variable to track the longest subarray length\n    maxFruits := 0 // Initialize a variable to store the maximum number of fruits\n    startWindow := 0 // Initialize the left boundary of the window\n    basket := make(map[int]int) // Create a map to track fruit counts\n\n    for endWindow := 0; endWindow < len(fruits); endWindow++ {\n        basket[fruits[endWindow]]++\n        // Add the current fruit to the basket and increment its count\n\n        for len(basket) > 2 {\n            basket[fruits[startWindow]]--\n            if basket[fruits[startWindow]] == 0 {\n                delete(basket, fruits[startWindow])\n            }\n            // Adjust the window to maintain at most two fruit types\n            startWindow++ // Move the left boundary of the window to the right\n        }\n\n        if endWindow-startWindow+1 > maxFruits {\n            maxFruits = endWindow - startWindow + 1\n        }\n        // Update maxFruits with the maximum window size seen so far\n    }\n\n    return maxFruits // Return the maximum number of fruits that can be collected\n}\n\nfunc main() {\n    fruits := []int{1, 2, 1, 2, 3}\n\n    result := totalFruit(fruits)\n\n    fmt.Println(result)\n}\n"
  },
  {
    "path": "Sliding Window/fruits_into_basket.java",
    "content": "/*\n    Fruits into basket\n    Summary:\n    The given code defines a Java class `Solution` with a method `totalFruit` that solves a problem related to collecting fruits \n    from fruit trees while adhering to a constraint of collecting fruits from at most two different types of fruit trees. \n    The code uses a sliding window approach to find the maximum number of fruits that can be collected from the trees under \n    this constraint.\n\n    - The `fruits` array represents the types of fruit trees, where each element represents a type of fruit.\n\n    - The code initializes variables `longest` and `max` to keep track of the length of the longest subarray with at \n    most two distinct elements and the maximum number of fruits collected, respectively.\n\n    - The `startWindow` variable represents the left boundary of the sliding window.\n\n    - A `HashMap` called `basket` is used to keep track of the count of each type of fruit in the current window.\n\n    - The code iterates through the `fruits` array using two pointers, `startWindow` and `endWindow`, to traverse \n    the array from left to right.\n\n    - Within the loop, the code updates the `basket` map with the count of fruit types in the current window, and it \n    ensures that there are at most two different types of fruits in the window by adjusting the window as needed.\n\n    - The `max` variable is updated with the maximum window size seen so far.\n\n    - Finally, the method returns `max`, which represents the maximum number of fruits that can be collected under \n    the given constraint.\n\n    Space Complexity:\n    - The space complexity of this code is O(1) in addition to the input `fruits` array. This is because the space used \n    for variables such as `longest`, `max`, `startWindow`, and `basket` remains constant and does not depend on the size \n    of the `fruits` array.\n\n    Time Complexity:\n    - The time complexity of this code is O(n), where 'n' is the length of the `fruits` array. The code iterates through the \n    `fruits` array once with two pointers, and the work done within each iteration is constant time. Therefore, the overall \n    time complexity is linear in the size of the input array.\n*/\nclass Solution {\n    public int totalFruit(int[] fruits) {\n        int longest = 0;           // Initialize a variable to track the longest subarray length\n        int max = 0;               // Initialize a variable to store the maximum number of fruits\n        int startWindow = 0;       // Initialize the left boundary of the window\n        HashMap<Integer, Integer> basket = new HashMap<>(); // Create a HashMap to track fruit counts\n        \n        for(int endWindow = 0; endWindow < fruits.length; endWindow++) {\n            basket.put(fruits[endWindow], basket.getOrDefault(fruits[endWindow], 0) + 1);\n            // Add the current fruit to the basket and increment its count\n            \n            while(basket.size() > 2) {\n                basket.put(fruits[startWindow], basket.get(fruits[startWindow]) - 1);\n                basket.remove(fruits[startWindow], 0);\n                // Adjust the window to maintain at most two fruit types\n                startWindow++; // Move the left boundary of the window to the right\n            }\n            \n            max = Math.max(max, (endWindow - startWindow) + 1);\n            // Update max with the maximum window size seen so far\n        }\n        \n        return max; // Return the maximum number of fruits that can be collected\n    }\n}\n"
  },
  {
    "path": "Sliding Window/fruits_into_basket.js",
    "content": "/*\n    Fruits into basket\n    Summary:\n    The given code defines a Java class `Solution` with a method `totalFruit` that solves a problem related to collecting fruits \n    from fruit trees while adhering to a constraint of collecting fruits from at most two different types of fruit trees. \n    The code uses a sliding window approach to find the maximum number of fruits that can be collected from the trees under \n    this constraint.\n\n    - The `fruits` array represents the types of fruit trees, where each element represents a type of fruit.\n\n    - The code initializes variables `longest` and `max` to keep track of the length of the longest subarray with at \n    most two distinct elements and the maximum number of fruits collected, respectively.\n\n    - The `startWindow` variable represents the left boundary of the sliding window.\n\n    - A `HashMap` called `basket` is used to keep track of the count of each type of fruit in the current window.\n\n    - The code iterates through the `fruits` array using two pointers, `startWindow` and `endWindow`, to traverse \n    the array from left to right.\n\n    - Within the loop, the code updates the `basket` map with the count of fruit types in the current window, and it \n    ensures that there are at most two different types of fruits in the window by adjusting the window as needed.\n\n    - The `max` variable is updated with the maximum window size seen so far.\n\n    - Finally, the method returns `max`, which represents the maximum number of fruits that can be collected under \n    the given constraint.\n\n    Space Complexity:\n    - The space complexity of this code is O(1) in addition to the input `fruits` array. This is because the space used \n    for variables such as `longest`, `max`, `startWindow`, and `basket` remains constant and does not depend on the size \n    of the `fruits` array.\n\n    Time Complexity:\n    - The time complexity of this code is O(n), where 'n' is the length of the `fruits` array. The code iterates through the \n    `fruits` array once with two pointers, and the work done within each iteration is constant time. Therefore, the overall \n    time complexity is linear in the size of the input array.\n */\nvar totalFruit = function (fruits) {\n  let longest = 0; // Initialize a variable to track the longest subarray length\n  let maxFruits = 0; // Initialize a variable to store the maximum number of fruits\n  let startWindow = 0; // Initialize the left boundary of the window\n  const basket = new Map(); // Create a Map to track fruit counts\n\n  for (let endWindow = 0; endWindow < fruits.length; endWindow++) {\n    basket.set(fruits[endWindow], (basket.get(fruits[endWindow]) || 0) + 1);\n    // Add the current fruit to the basket and increment its count\n\n    while (basket.size > 2) {\n      basket.set(fruits[startWindow], basket.get(fruits[startWindow]) - 1);\n      if (basket.get(fruits[startWindow]) === 0) {\n        basket.delete(fruits[startWindow]);\n      }\n      // Adjust the window to maintain at most two fruit types\n      startWindow++; // Move the left boundary of the window to the right\n    }\n\n    maxFruits = Math.max(maxFruits, endWindow - startWindow + 1);\n    // Update maxFruits with the maximum window size seen so far\n  }\n\n  return maxFruits; // Return the maximum number of fruits that can be collected\n};\n"
  },
  {
    "path": "Sliding Window/fruits_into_basket.py",
    "content": "'''\n    Fruits into basket\n    Summary:\n    The given code defines a Java class `Solution` with a method `totalFruit` that solves a problem related to collecting fruits \n    from fruit trees while adhering to a constraint of collecting fruits from at most two different types of fruit trees. \n    The code uses a sliding window approach to find the maximum number of fruits that can be collected from the trees under \n    this constraint.\n\n    - The `fruits` array represents the types of fruit trees, where each element represents a type of fruit.\n\n    - The code initializes variables `longest` and `max` to keep track of the length of the longest subarray with at \n    most two distinct elements and the maximum number of fruits collected, respectively.\n\n    - The `startWindow` variable represents the left boundary of the sliding window.\n\n    - A `HashMap` called `basket` is used to keep track of the count of each type of fruit in the current window.\n\n    - The code iterates through the `fruits` array using two pointers, `startWindow` and `endWindow`, to traverse \n    the array from left to right.\n\n    - Within the loop, the code updates the `basket` map with the count of fruit types in the current window, and it \n    ensures that there are at most two different types of fruits in the window by adjusting the window as needed.\n\n    - The `max` variable is updated with the maximum window size seen so far.\n\n    - Finally, the method returns `max`, which represents the maximum number of fruits that can be collected under \n    the given constraint.\n\n    Space Complexity:\n    - The space complexity of this code is O(1) in addition to the input `fruits` array. This is because the space used \n    for variables such as `longest`, `max`, `startWindow`, and `basket` remains constant and does not depend on the size \n    of the `fruits` array.\n\n    Time Complexity:\n    - The time complexity of this code is O(n), where 'n' is the length of the `fruits` array. The code iterates through the \n    `fruits` array once with two pointers, and the work done within each iteration is constant time. Therefore, the overall \n    time complexity is linear in the size of the input array.\n'''\nclass Solution:\n    def totalFruit(self, fruits):\n        longest = 0            # Initialize a variable to track the longest subarray length\n        max_fruits = 0          # Initialize a variable to store the maximum number of fruits\n        start_window = 0       # Initialize the left boundary of the window\n        basket = {}            # Create a dictionary to track fruit counts\n\n        for end_window in range(len(fruits)):\n            basket[fruits[end_window]] = basket.get(fruits[end_window], 0) + 1\n            # Add the current fruit to the basket and increment its count\n\n            while len(basket) > 2:\n                basket[fruits[start_window]] -= 1\n                if basket[fruits[start_window]] == 0:\n                    del basket[fruits[start_window]]\n                # Adjust the window to maintain at most two fruit types\n                start_window += 1  # Move the left boundary of the window to the right\n\n            max_fruits = max(max_fruits, (end_window - start_window) + 1)\n            # Update max_fruits with the maximum window size seen so far\n\n        return max_fruits  # Return the maximum number of fruits that can be collected\n"
  },
  {
    "path": "Sliding Window/longest_repeated_character_replacement.cpp",
    "content": "/*\n     You are given a string s and an integer k. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k times.\n\n    Return the length of the longest substring containing the same letter you can get after performing the above operations.\n\n    Example 1:\n\n    Input: s = \"ABAB\", k = 2\n    Output: 4\n    Explanation: Replace the two 'A's with two 'B's or vice versa.\n\n    Summary:\n    The provided code defines a Java class `Solution` with a method `characterReplacement` that aims to find the \n    longest substring within the input string `s` such that it can be created by replacing at most `k` characters \n    with any other character. It uses a sliding window approach to efficiently compute the maximum length of such a \n    substring.\n\n    Time Complexity:\n    - The code iterates through the input string `s` using a sliding window with two pointers \n    (startWindow and endWindow). During each iteration, it updates character counts and evaluates the \n    maximum length of a valid substring. Since each character is processed exactly once, the time complexity \n    is O(N), where N is the length of the input string `s`.\n\n    Space Complexity:\n    - The code uses additional space to store integer variables (`count`, `startWindow`, `maxCount`, and `max`). \n    The `count` array has a fixed size of 26 (for 26 English alphabet letters). Therefore, the space complexity is\n     O(1), as the space used is constant and does not depend on the input size.\n\n    In summary, the algorithm has a time complexity of O(N) and a space complexity of O(1), making it efficient \n    for finding the longest substring with at most 'k' replacements in a given string.\n */\n#include <vector>\n#include <string>\n#include <algorithm>\n\nclass Solution {\npublic:\n    int characterReplacement(std::string s, int k) {\n        std::vector<int> count(26, 0); // Initialize an array to count the occurrences of characters (26 letters in the English alphabet)\n        int startWindow = 0;            // The left end of the sliding window\n        int maxCount = 0;               // The maximum count of any character within the window\n        int max = 0;                    // The maximum length of a substring that can be formed\n\n        // Iterate through the string using a sliding window approach\n        for (int endWindow = 0; endWindow < s.length(); endWindow++) {\n            int val = s[endWindow] - 'A'; // Convert the character to an index (0-25)\n            count[val]++;                 // Increment the count for the current character\n            maxCount = std::max(maxCount, count[val]); // Update the maximum character count\n\n            // While the length of the current window minus the maximum character count exceeds 'k', shrink the window\n            while (endWindow - startWindow + 1 - maxCount > k) {\n                val = s[startWindow] - 'A'; // Get the character at the start of the window\n                count[val]--;               // Decrement the count for the character at the start of the window\n                startWindow++;             // Move the start of the window to the right\n            }\n\n            // Update the maximum length of a substring that can be formed\n            max = std::max(max, endWindow - startWindow + 1);\n        }\n\n        // Return the maximum length, which represents the longest substring with at most 'k' replacements\n        return max;\n    }\n};\n"
  },
  {
    "path": "Sliding Window/longest_repeated_character_replacement.go",
    "content": "/*\n     You are given a string s and an integer k. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k times.\n\n    Return the length of the longest substring containing the same letter you can get after performing the above operations.\n\n    Example 1:\n\n    Input: s = \"ABAB\", k = 2\n    Output: 4\n    Explanation: Replace the two 'A's with two 'B's or vice versa.\n\n    Summary:\n    The provided code defines a Java class `Solution` with a method `characterReplacement` that aims to find the \n    longest substring within the input string `s` such that it can be created by replacing at most `k` characters \n    with any other character. It uses a sliding window approach to efficiently compute the maximum length of such a \n    substring.\n\n    Time Complexity:\n    - The code iterates through the input string `s` using a sliding window with two pointers \n    (startWindow and endWindow). During each iteration, it updates character counts and evaluates the \n    maximum length of a valid substring. Since each character is processed exactly once, the time complexity \n    is O(N), where N is the length of the input string `s`.\n\n    Space Complexity:\n    - The code uses additional space to store integer variables (`count`, `startWindow`, `maxCount`, and `max`). \n    The `count` array has a fixed size of 26 (for 26 English alphabet letters). Therefore, the space complexity is\n     O(1), as the space used is constant and does not depend on the input size.\n\n    In summary, the algorithm has a time complexity of O(N) and a space complexity of O(1), making it efficient \n    for finding the longest substring with at most 'k' replacements in a given string.\n */\n func characterReplacement(s string, k int) int {\n    count := make([]int, 26) // Initialize an array to count the occurrences of characters (26 letters in the English alphabet)\n    startWindow := 0         // The left end of the sliding window\n    maxCount := 0            // The maximum count of any character within the window\n    max := 0                 // The maximum length of a substring that can be formed\n\n    // Iterate through the string using a sliding window approach\n    for endWindow := 0; endWindow < len(s); endWindow++ {\n        val := int(s[endWindow] - 'A') // Convert the character to an index (0-25)\n        count[val]++                   // Increment the count for the current character\n        maxCount = maxInt(maxCount, count[val]) // Update the maximum character count\n\n        // While the length of the current window minus the maximum character count exceeds 'k', shrink the window\n        for endWindow - startWindow + 1 - maxCount > k {\n            val = int(s[startWindow] - 'A') // Get the character at the start of the window\n            count[val]-- // Decrement the count for the character at the start of the window\n            startWindow++ // Move the start of the window to the right\n        }\n\n        // Update the maximum length of a substring that can be formed\n        max = maxInt(max, endWindow - startWindow + 1)\n    }\n\n    // Return the maximum length, which represents the longest substring with at most 'k' replacements\n    return max\n}\n\nfunc maxInt(a, b int) int {\n    if a > b {\n        return a\n    }\n    return b\n}\n"
  },
  {
    "path": "Sliding Window/longest_repeated_character_replacement.java",
    "content": "/*\n     You are given a string s and an integer k. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k times.\n\n    Return the length of the longest substring containing the same letter you can get after performing the above operations.\n\n    Example 1:\n\n    Input: s = \"ABAB\", k = 2\n    Output: 4\n    Explanation: Replace the two 'A's with two 'B's or vice versa.\n\n    Summary:\n    The provided code defines a Java class `Solution` with a method `characterReplacement` that aims to find the \n    longest substring within the input string `s` such that it can be created by replacing at most `k` characters \n    with any other character. It uses a sliding window approach to efficiently compute the maximum length of such a \n    substring.\n\n    Time Complexity:\n    - The code iterates through the input string `s` using a sliding window with two pointers \n    (startWindow and endWindow). During each iteration, it updates character counts and evaluates the \n    maximum length of a valid substring. Since each character is processed exactly once, the time complexity \n    is O(N), where N is the length of the input string `s`.\n\n    Space Complexity:\n    - The code uses additional space to store integer variables (`count`, `startWindow`, `maxCount`, and `max`). \n    The `count` array has a fixed size of 26 (for 26 English alphabet letters). Therefore, the space complexity is\n     O(1), as the space used is constant and does not depend on the input size.\n\n    In summary, the algorithm has a time complexity of O(N) and a space complexity of O(1), making it efficient \n    for finding the longest substring with at most 'k' replacements in a given string.\n */\nclass Solution {\n    public int characterReplacement(String s, int k) {\n        // Initialize an array to count the occurrences of characters (26 letters in the English alphabet)\n        int[] count = new int[26];\n        int startWindow = 0;   // The left end of the sliding window\n        int maxCount = 0;      // The maximum count of any character within the window\n        int max = 0;           // The maximum length of a substring that can be formed\n\n        // Iterate through the string using a sliding window approach\n        for (int endWindow = 0; endWindow < s.length(); endWindow++) {\n            int val = s.charAt(endWindow) - 'A'; // Convert the character to an index (0-25)\n            count[val]++; // Increment the count for the current character\n            maxCount = Math.max(maxCount, count[val]); // Update the maximum character count\n\n            // While the length of the current window minus the maximum character count exceeds 'k', shrink the window\n            while (endWindow - startWindow + 1 - maxCount > k) {\n                val = s.charAt(startWindow) - 'A'; // Get the character at the start of the window\n                count[val]--; // Decrement the count for the character at the start of the window\n                startWindow++; // Move the start of the window to the right\n            }\n\n            // Update the maximum length of a substring that can be formed\n            max = Math.max(max, endWindow - startWindow + 1);\n        }\n\n        // Return the maximum length, which represents the longest substring with at most 'k' replacements\n        return max;\n    }\n}\n"
  },
  {
    "path": "Sliding Window/longest_repeated_character_replacement.js",
    "content": "/*\n     You are given a string s and an integer k. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k times.\n\n    Return the length of the longest substring containing the same letter you can get after performing the above operations.\n\n    Example 1:\n\n    Input: s = \"ABAB\", k = 2\n    Output: 4\n    Explanation: Replace the two 'A's with two 'B's or vice versa.\n\n    Summary:\n    The provided code defines a Java class `Solution` with a method `characterReplacement` that aims to find the \n    longest substring within the input string `s` such that it can be created by replacing at most `k` characters \n    with any other character. It uses a sliding window approach to efficiently compute the maximum length of such a \n    substring.\n\n    Time Complexity:\n    - The code iterates through the input string `s` using a sliding window with two pointers \n    (startWindow and endWindow). During each iteration, it updates character counts and evaluates the \n    maximum length of a valid substring. Since each character is processed exactly once, the time complexity \n    is O(N), where N is the length of the input string `s`.\n\n    Space Complexity:\n    - The code uses additional space to store integer variables (`count`, `startWindow`, `maxCount`, and `max`). \n    The `count` array has a fixed size of 26 (for 26 English alphabet letters). Therefore, the space complexity is\n     O(1), as the space used is constant and does not depend on the input size.\n\n    In summary, the algorithm has a time complexity of O(N) and a space complexity of O(1), making it efficient \n    for finding the longest substring with at most 'k' replacements in a given string.\n*/\nclass Solution {\n  characterReplacement(s, k) {\n    const count = Array(26).fill(0); // Initialize an array to count the occurrences of characters (26 letters in the English alphabet)\n    let startWindow = 0; // The left end of the sliding window\n    let maxCount = 0; // The maximum count of any character within the window\n    let max_length = 0; // The maximum length of a substring that can be formed\n\n    // Iterate through the string using a sliding window approach\n    for (let endWindow = 0; endWindow < s.length; endWindow++) {\n      const val = s.charCodeAt(endWindow) - \"A\".charCodeAt(0); // Convert the character to an index (0-25)\n      count[val]++; // Increment the count for the current character\n      maxCount = Math.max(maxCount, count[val]); // Update the maximum character count\n\n      // While the length of the current window minus the maximum character count exceeds 'k', shrink the window\n      while (endWindow - startWindow + 1 - maxCount > k) {\n        const val = s.charCodeAt(startWindow) - \"A\".charCodeAt(0); // Get the character at the start of the window\n        count[val]--; // Decrement the count for the character at the start of the window\n        startWindow++; // Move the start of the window to the right\n      }\n\n      // Update the maximum length of a substring that can be formed\n      max_length = Math.max(max_length, endWindow - startWindow + 1);\n    }\n\n    // Return the maximum length, which represents the longest substring with at most 'k' replacements\n    return max_length;\n  }\n}\n\n// Example usage\nconst solution = new Solution();\nconst result = solution.characterReplacement(\"ABAB\", 2);\nconsole.log(result); // Output: 4\n"
  },
  {
    "path": "Sliding Window/longest_repeated_character_replacement.py",
    "content": "'''\n     You are given a string s and an integer k. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k times.\n\n    Return the length of the longest substring containing the same letter you can get after performing the above operations.\n\n    Example 1:\n\n    Input: s = \"ABAB\", k = 2\n    Output: 4\n    Explanation: Replace the two 'A's with two 'B's or vice versa.\n\n    Summary:\n    The provided code defines a Java class `Solution` with a method `characterReplacement` that aims to find the \n    longest substring within the input string `s` such that it can be created by replacing at most `k` characters \n    with any other character. It uses a sliding window approach to efficiently compute the maximum length of such a \n    substring.\n\n    Time Complexity:\n    - The code iterates through the input string `s` using a sliding window with two pointers \n    (startWindow and endWindow). During each iteration, it updates character counts and evaluates the \n    maximum length of a valid substring. Since each character is processed exactly once, the time complexity \n    is O(N), where N is the length of the input string `s`.\n\n    Space Complexity:\n    - The code uses additional space to store integer variables (`count`, `startWindow`, `maxCount`, and `max`). \n    The `count` array has a fixed size of 26 (for 26 English alphabet letters). Therefore, the space complexity is\n     O(1), as the space used is constant and does not depend on the input size.\n\n    In summary, the algorithm has a time complexity of O(N) and a space complexity of O(1), making it efficient \n    for finding the longest substring with at most 'k' replacements in a given string.\n'''\nclass Solution:\n    def characterReplacement(self, s: str, k: int) -> int:\n        count = [0] * 26  # Initialize a list to count the occurrences of characters (26 letters in the English alphabet)\n        startWindow = 0  # The left end of the sliding window\n        maxCount = 0     # The maximum count of any character within the window\n        max_length = 0   # The maximum length of a substring that can be formed\n\n        # Iterate through the string using a sliding window approach\n        for endWindow in range(len(s)):\n            val = ord(s[endWindow]) - ord('A')  # Convert the character to an index (0-25)\n            count[val] += 1  # Increment the count for the current character\n            maxCount = max(maxCount, count[val])  # Update the maximum character count\n\n            # While the length of the current window minus the maximum character count exceeds 'k', shrink the window\n            while endWindow - startWindow + 1 - maxCount > k:\n                val = ord(s[startWindow]) - ord('A')  # Get the character at the start of the window\n                count[val] -= 1  # Decrement the count for the character at the start of the window\n                startWindow += 1  # Move the start of the window to the right\n\n            # Update the maximum length of a substring that can be formed\n            max_length = max(max_length, endWindow - startWindow + 1)\n\n        # Return the maximum length, which represents the longest substring with at most 'k' replacements\n        return max_length\n"
  },
  {
    "path": "Sliding Window/longest_substring_with_k_distinct_chars.go",
    "content": "/*\n * Given a string, find the length of the longest substring in it with no more than K distinct characters.\n\n */\npackage main\n\nimport (\n\t\"fmt\"\n)\n\nfunc longestSubstringWithKDistinctChars(s string, k int) int {\n\t// Check for edge cases where s is empty, or k is 0.\n\tif len(s) == 0 || k == 0 {\n\t\treturn 0\n\t}\n\n\tstartWindow := 0      // Initialize the start of the sliding window.\n\tmaxLen := 0           // Initialize the maximum length of the substring.\n\tcharCount := make(map[byte]int) // Create a map to store character frequencies.\n\n\tfor endWindow := 0; endWindow < len(s); endWindow++ {\n\t\tright := s[endWindow] // Get the character at the end of the window.\n\t\tcharCount[right]++   // Update the character count in the map.\n\n\t\t// While there are more than k distinct characters in the window.\n\t\tfor len(charCount) > k {\n\t\t\tleft := s[startWindow] // Get the character at the start of the window.\n\t\t\tcharCount[left]--     // Decrease the count of the character.\n\t\t\tif charCount[left] == 0 {\n\t\t\t\tdelete(charCount, left) // If the count becomes 0, remove the character from the map.\n\t\t\t}\n\t\t\tstartWindow++ // Move the start of the window to the right.\n\t\t}\n\n\t\tmaxLen = max(maxLen, endWindow-startWindow+1) // Update the maximum length.\n\t}\n\treturn maxLen\n}\n\nfunc max(a, b int) int {\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n\nfunc main() {\n\tfmt.Println(longestSubstringWithKDistinctChars(\"araaci\", 2))\n\tfmt.Println(longestSubstringWithKDistinctChars(\"araaci\", 1))\n\tfmt.Println(longestSubstringWithKDistinctChars(\"cbbebi\", 3))\n}\n"
  },
  {
    "path": "Sliding Window/longest_substring_with_k_distinct_chars.java",
    "content": "\n/*\n * Given a string, find the length of the longest substring in it with no more than K distinct characters.\n\n */\npublic class LongestSubstringWithKDistinctChars {\n    public int longestSubstringWithKDistinctChars(String s, int k) {\n        // Check for edge cases where s is empty, null, or k is 0.\n        if (s.length() == 0 || s == null || k == 0) {\n            return 0;\n        }\n        \n        int startWindow = 0; // Initialize the start of the sliding window.\n        int maxlen = 0; // Initialize the maximum length of the substring.\n        HashMap<Character, Integer> mp = new HashMap(); // Create a HashMap to store character frequencies.\n\n        for (int endWindow = 0; endWindow < s.length(); endWindow++) {\n            char right = s.charAt(endWindow); // Get the character at the end of the window.\n            mp.put(right, mp.getOrDefault(right, 0) + 1); // Update the character count in the HashMap.\n\n            // While there are more than k distinct characters in the window.\n            while (mp.size() > k) {\n                char left = s.charAt(startWindow); // Get the character at the start of the window.\n                mp.put(left, mp.get(left) - 1); // Decrease the count of the character.\n                startWindow++; // Move the start of the window to the right.\n\n                if (mp.get(left) == 0) {\n                    mp.remove(left); // If the count becomes 0, remove the character from the HashMap.\n                }\n            }\n\n            maxlen = Math.max(maxlen, endWindow - startWindow + 1); // Update the maximum length.\n        }\n        return maxlen;\n    }\n\n    public static void main(String[] args) {\n        LongestSubstringWithKDistinctChars l = new LongestSubstringWithKDistinctChars();\n        System.out.println(l.longestSubstringWithKDistinctChars(\"araaci\", 2));\n        System.out.println(l.longestSubstringWithKDistinctChars(\"araaci\", 1));\n        System.out.println(l.longestSubstringWithKDistinctChars(\"cbbebi\", 3));\n    }\n}\n"
  },
  {
    "path": "Sliding Window/longest_substring_with_k_distinct_chars.js",
    "content": "/*\n * Given a string, find the length of the longest substring in it with no more than K distinct characters.\n\n */\nfunction longestSubstringWithKDistinctChars(s, k) {\n  // Check for edge cases where s is empty, or k is 0.\n  if (!s || k === 0) {\n    return 0;\n  }\n\n  let startWindow = 0; // Initialize the start of the sliding window.\n  let maxLen = 0; // Initialize the maximum length of the substring.\n  const charCount = {}; // Create an object to store character frequencies.\n\n  for (let endWindow = 0; endWindow < s.length; endWindow++) {\n    const right = s[endWindow]; // Get the character at the end of the window.\n    charCount[right] = (charCount[right] || 0) + 1; // Update the character count in the object.\n\n    // While there are more than k distinct characters in the window.\n    while (Object.keys(charCount).length > k) {\n      const left = s[startWindow]; // Get the character at the start of the window.\n      charCount[left]--; // Decrease the count of the character.\n      if (charCount[left] === 0) {\n        delete charCount[left]; // If the count becomes 0, remove the character from the object.\n      }\n      startWindow++; // Move the start of the window to the right.\n    }\n\n    maxLen = Math.max(maxLen, endWindow - startWindow + 1); // Update the maximum length.\n  }\n\n  return maxLen;\n}\n\nfunction max(a, b) {\n  return a > b ? a : b;\n}\n\nconsole.log(longestSubstringWithKDistinctChars(\"araaci\", 2));\nconsole.log(longestSubstringWithKDistinctChars(\"araaci\", 1));\nconsole.log(longestSubstringWithKDistinctChars(\"cbbebi\", 3));\n"
  },
  {
    "path": "Sliding Window/longest_substring_with_k_distinct_chars.py",
    "content": "'''\nGiven a string, find the length of the longest substring in it with no more than K distinct characters.\n\n'''\ndef longestSubstringWithKDistinctChars(s, k):\n    # Check for edge cases where s is empty, or k is 0.\n    if not s or k == 0:\n        return 0\n\n    start_window = 0           # Initialize the start of the sliding window.\n    max_len = 0                # Initialize the maximum length of the substring.\n    char_count = {}            # Create a dictionary to store character frequencies.\n\n    for end_window in range(len(s)):\n        right = s[end_window]    # Get the character at the end of the window.\n        char_count[right] = char_count.get(right, 0) + 1  # Update the character count in the dictionary.\n\n        # While there are more than k distinct characters in the window.\n        while len(char_count) > k:\n            left = s[start_window]   # Get the character at the start of the window.\n            char_count[left] -= 1    # Decrease the count of the character.\n            if char_count[left] == 0:\n                del char_count[left]  # If the count becomes 0, remove the character from the dictionary.\n            start_window += 1        # Move the start of the window to the right.\n\n        max_len = max(max_len, end_window - start_window + 1)  # Update the maximum length.\n\n    return max_len\n\ndef max(a, b):\n    if a > b:\n        return a\n    return b\n\nif __name__ == \"__main__\":\n    print(longestSubstringWithKDistinctChars(\"araaci\", 2))\n    print(longestSubstringWithKDistinctChars(\"araaci\", 1))\n    print(longestSubstringWithKDistinctChars(\"cbbebi\", 3))\n"
  },
  {
    "path": "Sliding Window/longest_substring_without_repeating_characters.go",
    "content": "package main\n\n/*\nGiven a string s, find the length of the longest substring without repeating characters.\n\n\n\nExample 1:\n\nInput: s = \"abcabcbb\"\nOutput: 3\nExplanation: The answer is \"abc\", with the length of 3.\nExample 2:\n\nInput: s = \"bbbbb\"\nOutput: 1\nExplanation: The answer is \"b\", with the length of 1.\nExample 3:\n\nInput: s = \"pwwkew\"\nOutput: 3\nExplanation: The answer is \"wke\", with the length of 3.\nNotice that the answer must be a substring, \"pwke\" is a subsequence and not a substring.\n\n\nConstraints:\n\n0 <= s.length <= 5 * 104\ns consists of English letters, digits, symbols and spaces.\n*/\n// Approach 1 Brute force\n// Intuition\n// Check all the substring one by one to see if it has no duplicate character.\n// Time complexity O(n³ ) Space complexity O(m) where m is size of hMap\nfunc LengthOfLongestSubstring1(s string) int {\n    n := len(s)\n    res := 0\n    for i := 0; i < n; i++ {\n        for j := i; j < n; j++ {\n            if check(s, i, j) {\n                res = max(res, j - i + 1)\n            }\n        }\n    }\n    return res\n}\nfunc max(a, b int) int {\n    if a >= b {\n        return a\n    } else {\n        return b\n    }\n}\nfunc check(s string, start int, end int) bool {\n    hMap := [128]int{}\n    for i := start; i <= end; i++ {\n        hMap[s[i]]++\n        if hMap[s[i]] > 1 {\n            return false\n        }\n    }\n    return true\n}\n\n// Approach 2:  Sliding window\n// Time complexity O(n) Space complexity O(m) where m is size of char \nfunc LengthOfLongestSubstring2(s string) int {\n    result := 0\n    for i := 0; i < len(s); i++ {\n        char := make(map[byte]bool)\n        char[s[i]] = true\n        for j := i + 1; j < len(s); j++ {\n            if _, ok := char[s[j]]; ok {\n                break\n            }\n            char[s[j]] = true\n        }\n        if len(char) > result {\n            result = len(char)\n        }\n    }\n    return result\n}"
  },
  {
    "path": "Sliding Window/max_eraser_value.go",
    "content": "/*\n    You are given an array of positive integers nums and want to erase a subarray containing unique elements. The score you get by erasing the subarray is equal to the sum of its elements.\n\n    Return the maximum score you can get by erasing exactly one subarray.\n\n    An array b is called to be a subarray of a if it forms a contiguous subsequence of a, that is, if it is equal to a[l],a[l+1],...,a[r] for some (l,r).\n\n    \n\n    Example 1:\n\n    Input: nums = [4,2,4,5,6]\n    Output: 17\n    Explanation: The optimal subarray here is [2,4,5,6].\n    Example 2:\n\n    Input: nums = [5,2,1,2,5,2,1,2,5]\n    Output: 8\n    Explanation: The optimal subarray here is [5,2,1] or [1,2,5].\n\n    Explanation:\n\n    startWindow: The left end of the sliding window.\n    windowSum: Sum of elements within the current window.\n    res: Result, initialized to 0, representing the maximum unique subarray sum.\n    mp: HashMap to store the last index where each element was seen.\n    Sliding Window:\n\n    Use a for loop to iterate through the array with the endWindow as the right end of the window.\n    Check if the current element is already in the window using a while loop.\n    If yes, remove the element at the start of the window from the HashMap and update windowSum and startWindow.\n    Update HashMap and windowSum:\n\n    Add the current element to the HashMap and update windowSum.\n    Update Result:\n\n    Update the result (res) with the maximum unique subarray sum.\n    Return Result:\n\n    Return the final result, which represents the maximum unique subarray sum.\n    This code efficiently finds the maximum sum of a subarray where all elements are unique using a sliding window and a HashMap to keep track of the last index of each element encountered.\n\n*/\npackage main\n\nimport \"fmt\"\n\nfunc maximumUniqueSubarray(nums []int) int {\n    startWindow := 0          // The left end of the sliding window\n    windowSum := 0            // Sum of elements within the current window\n    res := 0                  // Result, which represents the maximum unique subarray sum\n    mp := make(map[int]int)   // Map to store the last index where each element was seen\n\n    // Iterate through the array using a sliding window approach\n    for endWindow := 0; endWindow < len(nums); endWindow++ {\n        // Check if the current element is already in the window\n        for mp[nums[endWindow]] > 0 {\n            // Remove the element at the start of the window from the map and update windowSum\n            mp[nums[startWindow]]--\n            windowSum -= nums[startWindow]\n            startWindow++\n        }\n\n        // Add the current element to the map and update windowSum\n        mp[nums[endWindow]]++\n        windowSum += nums[endWindow]\n\n        // Update the result with the maximum unique subarray sum\n        if windowSum > res {\n            res = windowSum\n        }\n    }\n\n    // Return the result, which represents the maximum unique subarray sum\n    return res\n}\n\nfunc main() {\n    nums := []int{4, 2, 4, 5, 6}\n    result := maximumUniqueSubarray(nums)\n    fmt.Println(result) // Output: 17\n}\n"
  },
  {
    "path": "Sliding Window/max_eraser_value.java",
    "content": "/*\n    You are given an array of positive integers nums and want to erase a subarray containing unique elements. The score you get by erasing the subarray is equal to the sum of its elements.\n\n    Return the maximum score you can get by erasing exactly one subarray.\n\n    An array b is called to be a subarray of a if it forms a contiguous subsequence of a, that is, if it is equal to a[l],a[l+1],...,a[r] for some (l,r).\n\n    \n\n    Example 1:\n\n    Input: nums = [4,2,4,5,6]\n    Output: 17\n    Explanation: The optimal subarray here is [2,4,5,6].\n    Example 2:\n\n    Input: nums = [5,2,1,2,5,2,1,2,5]\n    Output: 8\n    Explanation: The optimal subarray here is [5,2,1] or [1,2,5].\n\n    Explanation:\n\n    startWindow: The left end of the sliding window.\n    windowSum: Sum of elements within the current window.\n    res: Result, initialized to 0, representing the maximum unique subarray sum.\n    mp: HashMap to store the last index where each element was seen.\n    Sliding Window:\n\n    Use a for loop to iterate through the array with the endWindow as the right end of the window.\n    Check if the current element is already in the window using a while loop.\n    If yes, remove the element at the start of the window from the HashMap and update windowSum and startWindow.\n    Update HashMap and windowSum:\n\n    Add the current element to the HashMap and update windowSum.\n    Update Result:\n\n    Update the result (res) with the maximum unique subarray sum.\n    Return Result:\n\n    Return the final result, which represents the maximum unique subarray sum.\n    This code efficiently finds the maximum sum of a subarray where all elements are unique using a sliding window and a HashMap to keep track of the last index of each element encountered.\n\n*/\nclass Solution {\n    public int maximumUniqueSubarray(int[] nums) {\n        // Initialize pointers, windowSum, and result\n        int startWindow = 0; // The left end of the sliding window\n        int windowSum = 0;   // Sum of elements within the current window\n        int res = 0;         // Result, which represents the maximum unique subarray sum\n\n        // HashMap to store the last index where each element was seen\n        HashMap<Integer, Integer> mp = new HashMap<>();\n\n        // Iterate through the array using a sliding window approach\n        for (int endWindow = 0; endWindow < nums.length; endWindow++) {\n            // Check if the current element is already in the window\n            while (mp.containsKey(nums[endWindow])) {\n                // Remove the element at the start of the window from the HashMap and update windowSum\n                mp.remove(nums[startWindow]);\n                windowSum -= nums[startWindow];\n                startWindow++;\n            }\n\n            // Add the current element to the HashMap and update windowSum\n            mp.put(nums[endWindow], 1);\n            windowSum += nums[endWindow];\n\n            // Update the result with the maximum unique subarray sum\n            res = Math.max(res, windowSum);\n        }\n\n        // Return the result, which represents the maximum unique subarray sum\n        return res;\n    }\n}\n"
  },
  {
    "path": "Sliding Window/sliding_window_max.java",
    "content": "/*\n    Given an integer array and a window of size windowSize, find the current maximum value in the window as it slides through the entire array\n*/\nimport java.util.*;\n\npublic class SlidingWindowMax {\n    public static int[] findMaxSlidingWindow(int[] nums, int windowSize) {\n        if (nums == null || windowSize <= 0 || nums.length < windowSize) {\n            return new int[0];\n        }\n\n        int n = nums.length;\n        int[] result = new int[n - windowSize + 1];\n        Deque<Integer> deque = new ArrayDeque<>(); // deque stores the indices of elements in the window\n\n        // process the first window separately\n        for (int i = 0; i < windowSize; i++) {\n            while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {\n                deque.removeLast();\n            }\n            deque.addLast(i);\n        }\n        result[0] = nums[deque.peekFirst()];\n\n        // process the remaining windows\n        for (int i = windowSize; i < n; i++) {\n            while (!deque.isEmpty() && deque.peekFirst() <= i - windowSize) {\n                deque.removeFirst(); // remove elements outside the window\n            }\n            while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {\n                deque.removeLast(); // remove elements smaller than nums[i]\n            }\n            deque.addLast(i);\n            result[i - windowSize + 1] = nums[deque.peekFirst()];\n        }\n\n        return result;\n    }\n\n    public static void main(String[] args) {\n        int[] nums = {1, 3, -1, -3, 5, 3, 6, 7};\n        int windowSize = 3;\n\n        int[] maxInWindow = findMaxSlidingWindow(nums, windowSize);\n\n        System.out.println(\"Max values in sliding window of size \" + windowSize + \": \");\n        for (int i = 0; i < maxInWindow.length; i++) {\n            System.out.print(maxInWindow[i] + \" \");\n        }\n    }\n}\n\n---------------Explanation---------------------\n\nThis program defines a findMaxSlidingWindow method that takes an array nums and a window size windowSize as input and returns an array containing the maximum value in each sliding window. The method first checks if the input is valid and creates a deque to store the indices of elements in the window.\n\nThe method then processes the first window separately by adding the indices of its elements to the deque in decreasing order of their values. This way, the first element in the deque will always be the maximum value in the window. The method stores this maximum value in the first element of the result array.\n\nThe method then processes the remaining windows by first removing any elements in the deque that are outside the current window. The method then adds the index of the current element to the deque and removes any elements in the deque that are smaller than the current element. The method stores the maximum value in the window in the corresponding element of the result array.\n\nFinally, the method returns the result array."
  },
  {
    "path": "Sliding Window/sliding_window_max.js",
    "content": "/*\n    Given an integer array and a window of size windowSize, find the current maximum value in the window as it slides through the entire array\n*/\nfunction findMaxSlidingWindow(nums, windowSize) {\n    if (!nums || windowSize <= 0 || nums.length < windowSize) {\n        return [];\n    }\n\n    const n = nums.length;\n    const result = new Array(n - windowSize + 1).fill(0);\n    const deque = []; // deque stores the indices of elements in the window\n\n    // process the first window separately\n    for (let i = 0; i < windowSize; i++) {\n        while (deque.length > 0 && nums[i] >= nums[deque[deque.length - 1]]) {\n            deque.pop();\n        }\n        deque.push(i);\n    }\n    result[0] = nums[deque[0]];\n\n    // process the remaining windows\n    for (let i = windowSize; i < n; i++) {\n        while (deque.length > 0 && deque[0] <= i - windowSize) {\n            deque.shift(); // remove elements outside the window\n        }\n        while (deque.length > 0 && nums[i] >= nums[deque[deque.length - 1]]) {\n            deque.pop(); // remove elements smaller than nums[i]\n        }\n        deque.push(i);\n        result[i - windowSize + 1] = nums[deque[0]];\n    }\n\n    return result;\n}\n\nconst nums = [1, 3, -1, -3, 5, 3, 6, 7];\nconst windowSize = 3;\n\nconst maxInWindow = findMaxSlidingWindow(nums, windowSize);\n\nconsole.log(`Max values in sliding window of size ${windowSize}:`);\nconsole.log(maxInWindow.join(' '));\n\n-------------Explanation---------------------\n\nThis code defines a findMaxSlidingWindow function that takes an array nums and a window size windowSize as input and returns an array containing the maximum value in each sliding window. The function first checks if the input is valid and creates an empty array result and a deque to store the indices of elements in the window.\n\nThe function then processes the first window separately by adding the indices of its elements to the deque in decreasing order of their values. This way, the first element in the deque will always be the maximum value in the window. The function stores this maximum value in the first element of the result array.\n\nThe function then processes the remaining windows by first removing any elements in the deque that are outside the current window. The function then adds the index of the current element to the deque and removes any elements in the deque that are smaller than the current element. The function stores the maximum value in the window in the corresponding element of the result array.\n\nFinally, the function returns the result array.\n\nThe code also includes an example usage of the findMaxSlidingWindow function on an example array and window size. When the code is executed, it prints the maximum values in each sliding window to the console."
  },
  {
    "path": "Sliding Window/sliding_window_max.py",
    "content": "# Given an integer array and a window of size windowSize, find the current maximum value in the window as it slides through the entire array\n\nfrom collections import deque\n\ndef slidingWindowMax(arr,windowSize) -> list[int]:\n    dq = deque()\n    max_elements = []\n    for i in range(len(arr)):\n        if(len(dq) != 0 and dq[0]== i - windowSize):\n            dq.popleft()\n        while(len(dq) !=0 and arr[dq[-1]] < arr[i]):\n            dq.pop()\n        dq.append(i)\n        if(i >= windowSize - 1):\n            max_elements.append(arr[dq[0]])\n    return max_elements\n\narr = list(map(int, input().split()))\nwindowSize = int(input())\nprint(slidingWindowMax(arr, windowSize))\n"
  },
  {
    "path": "Sliding Window/subaray_sum_equals_k.cpp",
    "content": "/*\n    Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.\n\n    A subarray is a contiguous non-empty sequence of elements within an array.\n\n    \n\n    Example 1:\n\n    Input: nums = [1,1,1], k = 2\n    Output: 2\n    Example 2:\n\n    Input: nums = [1,2,3], k = 3\n    Output: 2\n\n\n    ### Explanation:\n\n    The code is designed to count the number of subarrays within the 'nums' array whose elements sum to a given target integer 'k'. \n    It uses a hashmap to efficiently keep track of cumulative sums and their counts.\n\n    Here's the code's key logic:\n\n    1. It initializes a hashmap `sumIndex` to store cumulative sums as keys and their counts as values.\n\n    2. It initializes variables `result` and `currentSum`.\n\n    3. It adds a key-value pair of `(0, 1)` to the `sumIndex` hashmap to represent the sum of an empty subarray (0) and its count (1).\n\n    4. It iterates through the elements of the 'nums' array.\n\n    5. For each element, it adds the element's value to `currentSum`.\n\n    6. It calculates the value to find in the hashmap by subtracting 'k' from the current cumulative sum, which is stored in the `toFind` variable.\n\n    7. It checks if the hashmap contains the value 'toFind' and, if found, adds the count of subarrays that sum to 'toFind' to the 'result'.\n\n    8. It updates the hashmap with the current cumulative sum. If the sum is already in the hashmap, it increments its count by 1. If it's not in the hashmap, \n    it adds it with a count of 1.\n\n    9. Finally, it returns the 'result,' which represents the total number of subarrays with a sum of 'k'.\n\n    ### Time Complexity:\n\n    The time complexity of this code is O(n), where 'n' is the length of the 'nums' array. This is because the code iterates through the 'nums' \n    array once, and each iteration consists of constant-time operations (e.g., hashmap lookups and additions).\n\n    ### Space Complexity:\n\n    The space complexity of this code is O(n), where 'n' is the length of the 'nums' array. The space is primarily used for the hashmap `sumIndex`, \n    which can have up to 'n' distinct cumulative sums. In the worst case, all elements are unique, resulting in 'n' distinct cumulative sums, \n    each with a count of 1.\n\n    In summary, this code efficiently counts subarrays with a sum of 'k' in O(n) time and uses O(n) space to store cumulative sums and their counts.\n */\n#include <iostream>\n#include <unordered_map>\n#include <vector>\n\nint subarraySum(std::vector<int>& nums, int k) {\n  // Create an unordered_map to store cumulative sums as keys and their counts as values.\n  std::unordered_map<int, int> sumIndex;\n  // Initialize the result to 0.\n  int result = 0;\n  // Initialize a variable to track the current cumulative sum.\n  int currentSum = 0;\n  // Initialize the unordered_map with a key-value pair representing the sum of an empty subarray (0) and its count (1).\n  sumIndex[0] = 1;\n\n  // Iterate through the elements of the 'nums' vector.\n  for (int i = 0; i < nums.size(); i++) {\n    // Add the current element to the cumulative sum.\n    currentSum += nums[i];\n    // Calculate the value to find in the unordered_map by subtracting 'k' from the current cumulative sum.\n    int toFind = currentSum - k;\n\n    // Check if the unordered_map contains the value 'toFind'.\n    if (sumIndex.find(toFind) != sumIndex.end()) {\n      // If found, add the count of subarrays that sum to 'toFind' to the 'result'.\n      result += sumIndex[toFind];\n    }\n\n    // Update the unordered_map with the current cumulative sum.\n    // If it's already in the unordered_map, increment its count by 1.\n    // If it's not in the unordered_map, add it with a count of 1.\n    sumIndex[currentSum]++;\n\n  }\n\n  // Return the final result, which represents the total number of subarrays with a sum of 'k'.\n  return result;\n}\n\nint main() {\n  std::vector<int> nums = {1, 1, 1};\n  int k = 2;\n  int result = subarraySum(nums, k);\n  std::cout << \"Number of subarrays with sum \" << k << \" is: \" << result << std::endl;\n  return 0;\n}\n"
  },
  {
    "path": "Sliding Window/subaray_sum_equals_k.go",
    "content": "/*\n    Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.\n\n    A subarray is a contiguous non-empty sequence of elements within an array.\n\n    \n\n    Example 1:\n\n    Input: nums = [1,1,1], k = 2\n    Output: 2\n    Example 2:\n\n    Input: nums = [1,2,3], k = 3\n    Output: 2\n\n\n    ### Explanation:\n\n    The code is designed to count the number of subarrays within the 'nums' array whose elements sum to a given target integer 'k'. \n    It uses a hashmap to efficiently keep track of cumulative sums and their counts.\n\n    Here's the code's key logic:\n\n    1. It initializes a hashmap `sumIndex` to store cumulative sums as keys and their counts as values.\n\n    2. It initializes variables `result` and `currentSum`.\n\n    3. It adds a key-value pair of `(0, 1)` to the `sumIndex` hashmap to represent the sum of an empty subarray (0) and its count (1).\n\n    4. It iterates through the elements of the 'nums' array.\n\n    5. For each element, it adds the element's value to `currentSum`.\n\n    6. It calculates the value to find in the hashmap by subtracting 'k' from the current cumulative sum, which is stored in the `toFind` variable.\n\n    7. It checks if the hashmap contains the value 'toFind' and, if found, adds the count of subarrays that sum to 'toFind' to the 'result'.\n\n    8. It updates the hashmap with the current cumulative sum. If the sum is already in the hashmap, it increments its count by 1. If it's not in the hashmap, \n    it adds it with a count of 1.\n\n    9. Finally, it returns the 'result,' which represents the total number of subarrays with a sum of 'k'.\n\n    ### Time Complexity:\n\n    The time complexity of this code is O(n), where 'n' is the length of the 'nums' array. This is because the code iterates through the 'nums' \n    array once, and each iteration consists of constant-time operations (e.g., hashmap lookups and additions).\n\n    ### Space Complexity:\n\n    The space complexity of this code is O(n), where 'n' is the length of the 'nums' array. The space is primarily used for the hashmap `sumIndex`, \n    which can have up to 'n' distinct cumulative sums. In the worst case, all elements are unique, resulting in 'n' distinct cumulative sums, \n    each with a count of 1.\n\n    In summary, this code efficiently counts subarrays with a sum of 'k' in O(n) time and uses O(n) space to store cumulative sums and their counts.\n */\n func subarraySum(nums []int, k int) int {\n    // Create a map to store cumulative sums as keys and their counts as values.\n    sumIndex := make(map[int]int)\n    // Initialize the result to 0.\n    result := 0\n    // Initialize a variable to track the current cumulative sum.\n    currentSum := 0\n    // Initialize the map with a key-value pair representing the sum of an empty subarray (0) and its count (1).\n    sumIndex[0] = 1\n\n    // Iterate through the elements of the 'nums' slice.\n    for _, num := range nums {\n        // Add the current element to the cumulative sum.\n        currentSum += num\n        // Calculate the value to find in the map by subtracting 'k' from the current cumulative sum.\n        toFind := currentSum - k\n\n        // Check if the map contains the value 'toFind'.\n        if count, ok := sumIndex[toFind]; ok {\n            // If found, add the count of subarrays that sum to 'toFind' to the 'result'.\n            result += count\n        }\n\n        // Update the map with the current cumulative sum.\n        // If it's already in the map, increment its count by 1.\n        // If it's not in the map, add it with a count of 1.\n        sumIndex[currentSum]++\n    }\n\n    // Return the final result, which represents the total number of subarrays with a sum of 'k'.\n    return result\n}\n"
  },
  {
    "path": "Sliding Window/subaray_sum_equals_k.java",
    "content": "/*\n    Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.\n\n    A subarray is a contiguous non-empty sequence of elements within an array.\n\n    \n\n    Example 1:\n\n    Input: nums = [1,1,1], k = 2\n    Output: 2\n    Example 2:\n\n    Input: nums = [1,2,3], k = 3\n    Output: 2\n\n\n    ### Explanation:\n\n    The code is designed to count the number of subarrays within the 'nums' array whose elements sum to a given target integer 'k'. \n    It uses a hashmap to efficiently keep track of cumulative sums and their counts.\n\n    Here's the code's key logic:\n\n    1. It initializes a hashmap `sumIndex` to store cumulative sums as keys and their counts as values.\n\n    2. It initializes variables `result` and `currentSum`.\n\n    3. It adds a key-value pair of `(0, 1)` to the `sumIndex` hashmap to represent the sum of an empty subarray (0) and its count (1).\n\n    4. It iterates through the elements of the 'nums' array.\n\n    5. For each element, it adds the element's value to `currentSum`.\n\n    6. It calculates the value to find in the hashmap by subtracting 'k' from the current cumulative sum, which is stored in the `toFind` variable.\n\n    7. It checks if the hashmap contains the value 'toFind' and, if found, adds the count of subarrays that sum to 'toFind' to the 'result'.\n\n    8. It updates the hashmap with the current cumulative sum. If the sum is already in the hashmap, it increments its count by 1. If it's not in the hashmap, \n    it adds it with a count of 1.\n\n    9. Finally, it returns the 'result,' which represents the total number of subarrays with a sum of 'k'.\n\n    ### Time Complexity:\n\n    The time complexity of this code is O(n), where 'n' is the length of the 'nums' array. This is because the code iterates through the 'nums' \n    array once, and each iteration consists of constant-time operations (e.g., hashmap lookups and additions).\n\n    ### Space Complexity:\n\n    The space complexity of this code is O(n), where 'n' is the length of the 'nums' array. The space is primarily used for the hashmap `sumIndex`, \n    which can have up to 'n' distinct cumulative sums. In the worst case, all elements are unique, resulting in 'n' distinct cumulative sums, \n    each with a count of 1.\n\n    In summary, this code efficiently counts subarrays with a sum of 'k' in O(n) time and uses O(n) space to store cumulative sums and their counts.\n */\npublic int subarraySum(int[] nums, int k) {\n    // Create a hashmap to store cumulative sums as keys and their counts as values.\n    HashMap<Integer, Integer> sumIndex = new HashMap<>();\n    // Initialize the result to 0.\n    int result = 0;\n    // Initialize a variable to track the current cumulative sum.\n    int currentSum = 0;\n    // Initialize the hashmap with a key-value pair representing the sum of an empty subarray (0) and its count (1).\n    sumIndex.put(0, 1);\n\n    // Iterate through the elements of the 'nums' array.\n    for (int i = 0; i < nums.length; i++) {\n        // Add the current element to the cumulative sum.\n        currentSum += nums[i];\n        // Calculate the value to find in the hashmap by subtracting 'k' from the current cumulative sum.\n        int toFind = currentSum - k;\n        \n        // Check if the hashmap contains the value 'toFind'.\n        if (sumIndex.containsKey(toFind)) {\n            // If found, add the count of subarrays that sum to 'toFind' to the 'result'.\n            result += sumIndex.get(toFind);\n        }\n        \n        // Update the hashmap with the current cumulative sum.\n        // If it's already in the hashmap, increment its count by 1.\n        // If it's not in the hashmap, add it with a count of 1.\n        sumIndex.put(currentSum, sumIndex.getOrDefault(currentSum, 0) + 1);\n    }\n    \n    // Return the final result, which represents the total number of subarrays with a sum of 'k'.\n    return result;\n}\n"
  },
  {
    "path": "Sliding Window/subaray_sum_equals_k.js",
    "content": "/*\n    Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.\n\n    A subarray is a contiguous non-empty sequence of elements within an array.\n\n    \n\n    Example 1:\n\n    Input: nums = [1,1,1], k = 2\n    Output: 2\n    Example 2:\n\n    Input: nums = [1,2,3], k = 3\n    Output: 2\n\n\n    ### Explanation:\n\n    The code is designed to count the number of subarrays within the 'nums' array whose elements sum to a given target integer 'k'. \n    It uses a hashmap to efficiently keep track of cumulative sums and their counts.\n\n    Here's the code's key logic:\n\n    1. It initializes a hashmap `sumIndex` to store cumulative sums as keys and their counts as values.\n\n    2. It initializes variables `result` and `currentSum`.\n\n    3. It adds a key-value pair of `(0, 1)` to the `sumIndex` hashmap to represent the sum of an empty subarray (0) and its count (1).\n\n    4. It iterates through the elements of the 'nums' array.\n\n    5. For each element, it adds the element's value to `currentSum`.\n\n    6. It calculates the value to find in the hashmap by subtracting 'k' from the current cumulative sum, which is stored in the `toFind` variable.\n\n    7. It checks if the hashmap contains the value 'toFind' and, if found, adds the count of subarrays that sum to 'toFind' to the 'result'.\n\n    8. It updates the hashmap with the current cumulative sum. If the sum is already in the hashmap, it increments its count by 1. If it's not in the hashmap, \n    it adds it with a count of 1.\n\n    9. Finally, it returns the 'result,' which represents the total number of subarrays with a sum of 'k'.\n\n    ### Time Complexity:\n\n    The time complexity of this code is O(n), where 'n' is the length of the 'nums' array. This is because the code iterates through the 'nums' \n    array once, and each iteration consists of constant-time operations (e.g., hashmap lookups and additions).\n\n    ### Space Complexity:\n\n    The space complexity of this code is O(n), where 'n' is the length of the 'nums' array. The space is primarily used for the hashmap `sumIndex`, \n    which can have up to 'n' distinct cumulative sums. In the worst case, all elements are unique, resulting in 'n' distinct cumulative sums, \n    each with a count of 1.\n\n    In summary, this code efficiently counts subarrays with a sum of 'k' in O(n) time and uses O(n) space to store cumulative sums and their counts.\n */\nfunction subarraySum(nums, k) {\n  // Create a map to store cumulative sums as keys and their counts as values.\n  const sumIndex = new Map();\n  // Initialize the result to 0.\n  let result = 0;\n  // Initialize a variable to track the current cumulative sum.\n  let currentSum = 0;\n  // Initialize the map with a key-value pair representing the sum of an empty subarray (0) and its count (1).\n  sumIndex.set(0, 1);\n\n  // Iterate through the elements of the 'nums' array.\n  for (let i = 0; i < nums.length; i++) {\n    // Add the current element to the cumulative sum.\n    currentSum += nums[i];\n    // Calculate the value to find in the map by subtracting 'k' from the current cumulative sum.\n    const toFind = currentSum - k;\n\n    // Check if the map contains the value 'toFind'.\n    if (sumIndex.has(toFind)) {\n      // If found, add the count of subarrays that sum to 'toFind' to the 'result'.\n      result += sumIndex.get(toFind);\n    }\n\n    // Update the map with the current cumulative sum.\n    // If it's already in the map, increment its count by 1.\n    // If it's not in the map, add it with a count of 1.\n    sumIndex.set(currentSum, (sumIndex.get(currentSum) || 0) + 1);\n  }\n\n  // Return the final result, which represents the total number of subarrays with a sum of 'k'.\n  return result;\n}\n"
  },
  {
    "path": "Sliding Window/subaray_sum_equals_k.py",
    "content": "'''\nGiven an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.\n\n    A subarray is a contiguous non-empty sequence of elements within an array.\n\n\n\n    Example 1:\n\n    Input: nums = [1,1,1], k = 2\n    Output: 2\n    Example 2:\n\n    Input: nums = [1,2,3], k = 3\n    Output: 2\n\n\n    ### Explanation:\n\n    The code is designed to count the number of subarrays within the 'nums' array whose elements sum to a given target integer 'k'.\n    It uses a hashmap to efficiently keep track of cumulative sums and their counts.\n\n    Here's the code's key logic:\n\n    1. It initializes a hashmap `sumIndex` to store cumulative sums as keys and their counts as values.\n\n    2. It initializes variables `result` and `currentSum`.\n\n    3. It adds a key-value pair of `(0, 1)` to the `sumIndex` hashmap to represent the sum of an empty subarray (0) and its count (1).\n\n    4. It iterates through the elements of the 'nums' array.\n\n    5. For each element, it adds the element's value to `currentSum`.\n\n    6. It calculates the value to find in the hashmap by subtracting 'k' from the current cumulative sum, which is stored in the `toFind` variable.\n\n    7. It checks if the hashmap contains the value 'toFind' and, if found, adds the count of subarrays that sum to 'toFind' to the 'result'.\n\n    8. It updates the hashmap with the current cumulative sum. If the sum is already in the hashmap, it increments its count by 1. If it's not in the hashmap,\n    it adds it with a count of 1.\n\n    9. Finally, it returns the 'result,' which represents the total number of subarrays with a sum of 'k'.\n\n    ### Time Complexity:\n\n    The time complexity of this code is O(n), where 'n' is the length of the 'nums' array. This is because the code iterates through the 'nums'\n    array once, and each iteration consists of constant-time operations (e.g., hashmap lookups and additions).\n\n    ### Space Complexity:\n\n    The space complexity of this code is O(n), where 'n' is the length of the 'nums' array. The space is primarily used for the hashmap `sumIndex`,\n    which can have up to 'n' distinct cumulative sums. In the worst case, all elements are unique, resulting in 'n' distinct cumulative sums,\n    each with a count of 1.\n\n    In summary, this code efficiently counts subarrays with a sum of 'k' in O(n) time and uses O(n) space to store cumulative sums and their counts.\n\n'''\ndef subarraySum(nums, k):\n    # Create a dictionary to store cumulative sums as keys and their counts as values.\n    sum_index = {0: 1}\n    # Initialize the result to 0.\n    result = 0\n    # Initialize a variable to track the current cumulative sum.\n    current_sum = 0\n\n    # Iterate through the elements of the 'nums' list.\n    for num in nums:\n        # Add the current element to the cumulative sum.\n        current_sum += num\n        # Calculate the value to find in the dictionary by subtracting 'k' from the current cumulative sum.\n        to_find = current_sum - k\n\n        # Check if the dictionary contains the value 'to_find'.\n        if to_find in sum_index:\n            # If found, add the count of subarrays that sum to 'to_find' to the 'result'.\n            result += sum_index[to_find]\n\n        # Update the dictionary with the current cumulative sum.\n        # If it's already in the dictionary, increment its count by 1.\n        # If it's not in the dictionary, add it with a count of 1.\n        sum_index[current_sum] = sum_index.get(current_sum, 0) + 1\n\n    # Return the final result, which represents the total number of subarrays with a sum of 'k'.\n    return result\n\n"
  },
  {
    "path": "Sliding Window/subarray_product_less_than_k,js",
    "content": "/**\n     Given an array of integers nums and an integer k, \n    return the number of contiguous subarrays where the product of all the elements in the subarray is \n    strictly less than k.\n\n    The provided code defines a Java class Solution with a method numSubarrayProductLessThanK that counts the number \n    of subarrays in an input array nums whose product is less than a given threshold k. It uses a sliding window \n    approach to efficiently compute this count.\n\n    Time Complexity:\n\n    The code iterates through the nums array once, using two pointers (startWindow and endWindow) to define the \n    sliding window. This results in a time complexity of O(N), where N is the length of the input array nums.\n    Space Complexity:\n\n    The code uses a constant amount of additional space to store integer variables (startWindow, product, and count). \n    Therefore, the space complexity is O(1), which means it is independent of the size of the input array.\n */\nclass Solution {\n  numSubarrayProductLessThanK(nums, k) {\n    let startWindow = 0; // The left end of the sliding window\n    let product = 1; // Initialize product to 1 to accumulate the product\n    let count = 0; // Count of subarrays with a product less than k\n\n    // Iterate through the array using a sliding window approach\n    for (let endWindow = 0; endWindow < nums.length; endWindow++) {\n      // Multiply the current element to the product\n      product *= nums[endWindow];\n\n      // Shrink the window by moving the start pointer as long as the product is greater than or equal to k\n      while (startWindow <= endWindow && product >= k) {\n        // Divide the product by the element at the start of the window\n        product /= nums[startWindow];\n        // Move the start of the window to the right\n        startWindow++;\n      }\n\n      // Update the count with the number of valid subarrays within the current window\n      count += endWindow - startWindow + 1;\n    }\n\n    // Return the count, which represents the number of subarrays with a product less than k\n    return count;\n  }\n}\n\n// Example usage\nconst solution = new Solution();\nconst result = solution.numSubarrayProductLessThanK([10, 5, 2, 6], 100);\nconsole.log(result); // Output: 8\n"
  },
  {
    "path": "Sliding Window/subarray_product_less_than_k.cpp",
    "content": "/**\n     Given an array of integers nums and an integer k, \n    return the number of contiguous subarrays where the product of all the elements in the subarray is \n    strictly less than k.\n\n    The provided code defines a Java class Solution with a method numSubarrayProductLessThanK that counts the number \n    of subarrays in an input array nums whose product is less than a given threshold k. It uses a sliding window \n    approach to efficiently compute this count.\n\n    Time Complexity:\n\n    The code iterates through the nums array once, using two pointers (startWindow and endWindow) to define the \n    sliding window. This results in a time complexity of O(N), where N is the length of the input array nums.\n    Space Complexity:\n\n    The code uses a constant amount of additional space to store integer variables (startWindow, product, and count). \n    Therefore, the space complexity is O(1), which means it is independent of the size of the input array.\n */\n\n#include <vector>\n\nclass Solution {\npublic:\n    int numSubarrayProductLessThanK(std::vector<int>& nums, int k) {\n        int startWindow = 0; // The left end of the sliding window\n        int product = 1;    // Initialize product to 1 to accumulate the product\n        int count = 0;      // Count of subarrays with a product less than k\n\n        // Iterate through the array using a sliding window approach\n        for (int endWindow = 0; endWindow < nums.size(); endWindow++) {\n            // Multiply the current element to the product\n            product *= nums[endWindow];\n\n            // Shrink the window by moving the start pointer as long as the product is greater than or equal to k\n            while (startWindow <= endWindow && product >= k) {\n                // Divide the product by the element at the start of the window\n                product /= nums[startWindow];\n                // Move the start of the window to the right\n                startWindow++;\n            }\n\n            // Update the count with the number of valid subarrays within the current window\n            count += endWindow - startWindow + 1;\n        }\n\n        // Return the count, which represents the number of subarrays with a product less than k\n        return count;\n    }\n};\n"
  },
  {
    "path": "Sliding Window/subarray_product_less_than_k.go",
    "content": "/**\n   Given an array of integers nums and an integer k,\n  return the number of contiguous subarrays where the product of all the elements in the subarray is\n  strictly less than k.\n\n  The provided code defines a Java class Solution with a method numSubarrayProductLessThanK that counts the number\n  of subarrays in an input array nums whose product is less than a given threshold k. It uses a sliding window\n  approach to efficiently compute this count.\n\n  Time Complexity:\n\n  The code iterates through the nums array once, using two pointers (startWindow and endWindow) to define the\n  sliding window. This results in a time complexity of O(N), where N is the length of the input array nums.\n  Space Complexity:\n\n  The code uses a constant amount of additional space to store integer variables (startWindow, product, and count).\n  Therefore, the space complexity is O(1), which means it is independent of the size of the input array.\n*/\n \n func numSubarrayProductLessThanK(nums []int, k int) int {\n    startWindow := 0 // The left end of the sliding window\n    product := 1    // Initialize product to 1 to accumulate the product\n    count := 0      // Count of subarrays with a product less than k\n\n    // Iterate through the array using a sliding window approach\n    for endWindow := 0; endWindow < len(nums); endWindow++ {\n        // Multiply the current element to the product\n        product *= nums[endWindow]\n\n        // Shrink the window by moving the start pointer as long as the product is greater than or equal to k\n        for startWindow <= endWindow && product >= k {\n            // Divide the product by the element at the start of the window\n            product /= nums[startWindow]\n            // Move the start of the window to the right\n            startWindow++\n        }\n\n        // Update the count with the number of valid subarrays within the current window\n        count += endWindow - startWindow + 1\n    }\n\n    // Return the count, which represents the number of subarrays with a product less than k\n    return count\n}\n"
  },
  {
    "path": "Sliding Window/subarray_product_less_than_k.java",
    "content": "/**\n     Given an array of integers nums and an integer k, \n    return the number of contiguous subarrays where the product of all the elements in the subarray is \n    strictly less than k.\n\n    The provided code defines a Java class Solution with a method numSubarrayProductLessThanK that counts the number \n    of subarrays in an input array nums whose product is less than a given threshold k. It uses a sliding window \n    approach to efficiently compute this count.\n\n    Time Complexity:\n\n    The code iterates through the nums array once, using two pointers (startWindow and endWindow) to define the \n    sliding window. This results in a time complexity of O(N), where N is the length of the input array nums.\n    Space Complexity:\n\n    The code uses a constant amount of additional space to store integer variables (startWindow, product, and count). \n    Therefore, the space complexity is O(1), which means it is independent of the size of the input array.\n */\nclass Solution {\n    public int numSubarrayProductLessThanK(int[] nums, int k) {\n        // Initialize pointers and a count variable\n        int startWindow = 0; // The left end of the sliding window\n        int product = 1;    // Initialize product to 1 to accumulate the product\n        int count = 0;      // Count of subarrays with a product less than k\n\n        // Iterate through the array using a sliding window approach\n        for (int endWindow = 0; endWindow < nums.length; endWindow++) {\n            // Multiply the current element to the product\n            product *= nums[endWindow];\n\n            // Shrink the window by moving the start pointer as long as the product is greater than or equal to k\n            while (startWindow <= endWindow && product >= k) {\n                // Divide the product by the element at the start of the window\n                product /= nums[startWindow];\n                // Move the start of the window to the right\n                startWindow++;\n            }\n\n            // Update the count with the number of valid subarrays within the current window\n            count += endWindow - startWindow + 1;\n        }\n\n        // Return the count, which represents the number of subarrays with a product less than k\n        return count;\n    }\n}\n"
  },
  {
    "path": "Sliding Window/subarray_product_less_than_k.py",
    "content": "'''\n   Given an array of integers nums and an integer k,\n  return the number of contiguous subarrays where the product of all the elements in the subarray is\n  strictly less than k.\n\n  The provided code defines a Java class Solution with a method numSubarrayProductLessThanK that counts the number\n  of subarrays in an input array nums whose product is less than a given threshold k. It uses a sliding window\n  approach to efficiently compute this count.\n\n  Time Complexity:\n\n  The code iterates through the nums array once, using two pointers (startWindow and endWindow) to define the\n  sliding window. This results in a time complexity of O(N), where N is the length of the input array nums.\n  Space Complexity:\n\n  The code uses a constant amount of additional space to store integer variables (startWindow, product, and count).\n  Therefore, the space complexity is O(1), which means it is independent of the size of the input array.\n'''\nfrom typing import List\n\nclass Solution:\n    def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:\n        startWindow = 0  # The left end of the sliding window\n        product = 1     # Initialize product to 1 to accumulate the product\n        count = 0       # Count of subarrays with a product less than k\n\n        # Iterate through the list using a sliding window approach\n        for endWindow in range(len(nums)):\n            # Multiply the current element to the product\n            product *= nums[endWindow]\n\n            # Shrink the window by moving the start pointer as long as the product is greater than or equal to k\n            while startWindow <= endWindow and product >= k:\n                # Divide the product by the element at the start of the window\n                product /= nums[startWindow]\n                # Move the start of the window to the right\n                startWindow += 1\n\n            # Update the count with the number of valid subarrays within the current window\n            count += endWindow - startWindow + 1\n\n        # Return the count, which represents the number of subarrays with a product less than k\n        return count\n"
  },
  {
    "path": "Stacks/Stack_with_max_API.cpp",
    "content": "/*\nTime Complexity of all Operations is O(1)\nSpace Complexity is O(n)\nIn this implementation, we use two stacks: s is the main stack that holds the elements of the stack, and max_s is a secondary stack that holds the maximum values in s. When a new value is pushed onto the stack, we compare it with the current maximum value in max_s and add it to max_s if it's greater than or equal to the current maximum.\n*/\n#include <stack>\nusing namespace std;\n\nclass MaxStack {\nprivate:\n    stack<int> s;       // Main stack that holds the elements of the stack\n    stack<int> max_s;   // Secondary stack that holds the maximum values in s\n\npublic:\n    void push(int val) {\n        s.push(val);    // Push the value onto the main stack\n        if (max_s.empty() || val >= max_s.top()) {\n            // If max_s is empty or the new value is greater than or equal to the current maximum,\n            // push the value onto max_s\n            max_s.push(val);\n        }\n    }\n\n    void pop() {\n        if (s.top() == max_s.top()) {\n            // If the top value of s is equal to the top value of max_s, it means that the top value\n            // of s is the current maximum, so we need to pop it from max_s as well\n            max_s.pop();\n        }\n        s.pop();    // Pop the value from the main stack\n    }\n\n    int top() {\n        return s.top(); // Return the top value of the main stack\n    }\n\n    int max() {\n        return max_s.top(); // Return the top value of max_s, which is the maximum value in the stack\n    }\n\n    bool empty() {\n        return s.empty();   // Check if the main stack is empty\n    }\n};\n"
  },
  {
    "path": "Stacks/Stacks_using_queues.py",
    "content": "''' Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem : Implement Stack using Queues in Python\nIssue Number : #261\nProblem statement :\n\nExplanation of the below python code :\n\n__init__(self) initializes the two queues (q1 and q2) in the constructor.\n\npush(self, x: int) adds a new element x to the top of the stack. It first adds the element to q2, and then moves all the elements from q1 to q2 using a while loop. Finally, it swaps q1 and q2 so that q1 always contains the elements in the stack.\n\npop(self) -> int removes and returns the element at the top of the stack, which is the first element in q1.\n\ntop(self) -> int returns the element at the top of the stack, which is also the first element in q1.\n\nempty(self) -> bool returns True if the stack is empty (i.e., q1 is empty), and False otherwise.\n\nThe deque data structure from the collections module is used to implement the two queues, since it provides efficient O(1) operations for adding and removing elements from both ends of the queue.\n\nOverall, this implementation is quite simple and efficient, since the push and pop operations take O(1) time complexity on average, while the top and empty operations take constant time.\n\n-------------------------------------------------------------------------//Python code begins here----------------------------------------------------------------------------\n'''\n\nfrom collections import deque\n\nclass Stack:\n    def __init__(self):             #The Stack class is defined with a constructor that initializes a deque object as the Stack's underlying data structure.\n        self.queue = deque()\n\n    def push(self, x: int) -> None:\n        self.queue.append(x)\n        # Move all existing elements to the end of the queue      #The push method takes an integer value as input and appends it to the end of the deque. It then moves all the existing elements in the deque to the end, effectively simulating the addition of the new element to the top of the Stack.\n        for _ in range(len(self.queue) - 1):\n            self.queue.append(self.queue.popleft())\n\n    def pop(self) -> int:\n        return self.queue.popleft()     #The pop method removes and returns the element at the top of the Stack, which is the first element in the deque.\n\n    def top(self) -> int:             #The top method returns the element at the top of the Stack without removing it, which is the first element in the deque.\n        return self.queue[0]\n\n    def empty(self) -> bool:           #The empty method returns True if the Stack is empty (i.e., the deque has length 0), and False otherwise.\n        return len(self.queue) == 0\n\n\nstack = Stack()\nwhile True:\n    print(\"1. Push\")\n    print(\"2. Pop\")\n    print(\"3. Top\")\n    print(\"4. Empty\")\n    print(\"5. Quit\")\n    choice = int(input(\"Enter your choice: \"))\n    if choice == 1:\n        x = int(input(\"Enter the element to push: \"))\n        stack.push(x)\n        print(\"Element pushed to stack\")\n    elif choice == 2:\n        if stack.empty():                                 '''The code above shows an example usage of the Stack class, where the user can interact with the Stack through a command-line interface.The user is prompted with a menu of options to choose from, and their choice is read in as an integer value using the input() functiom'''                                            Depending on the user's choice, the appropriate method is called on the stack object and the results are printed to the console.\n            print(\"Stack is empty\")\n        else:\n            x = stack.pop()\n            print(\"Popped element:\", x)\n    elif choice == 3:\n        if stack.empty():\n            print(\"Stack is empty\")\n        else:\n            x = stack.top()\n            print(\"Top element:\", x)\n    elif choice == 4:\n        if stack.empty():\n            print(\"Stack is empty\")\n        else:\n            print(\"Stack is not empty\")\n    elif choice == 5:\n        break\n    else:\n        print(\"Invalid choice\")\n"
  },
  {
    "path": "Stacks/balanced_parenthesis.go",
    "content": "// Checking balancing of symbols/parentheses.\n\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\ntype Stack struct {\n\ttop      int\n\tcapacity uint\n\tarray    []interface{}\n}\n\n// Init: Returns an Initialized Stack\nfunc (stack *Stack) Init(capacity uint) *Stack {\n\tstack.top = -1\n\tstack.capacity = capacity\n\tstack.array = make([]interface{}, capacity)\n\treturn stack\n}\n\n// NewStack: Returns a new Stack\nfunc NewStack(capacity uint) *Stack {\n\treturn new(Stack).Init(capacity)\n}\n\n// Size: Returns the size of Stack\n// Time complexity O(1)\nfunc (stack *Stack) Size() uint {\n\treturn uint(stack.top + 1)\n}\n\n// IsFull: Returns true if Stack is full or else false\n// Time complexity O(1)\nfunc (stack *Stack) IsFull() bool {\n\t// Stack is full when top is equal to the last index\n\treturn stack.top == int(stack.capacity) - 1\n}\n\n// IsEmpty: Returns true if Stack is empty or else false\n// Time complexity O(1)\nfunc (stack *Stack) IsEmpty() bool {\n\t// Stack is empty when top is equal to -1\n\treturn stack.top == -1\n}\n\n// Resize: If the array is full, creates a new array of\n// twice the size, and copy the items\nfunc (stack *Stack) Resize() {\n\tfmt.Println(\"Resizing\")\n\tif stack.IsFull() {\n\t\tstack.capacity *= 2\n\t} else {\n\t\tstack.capacity /= 2\n\t}\n\ttarget := make([]interface{}, stack.capacity)\n\tcopy(target, stack.array[:stack.top+1])\n\tstack.array = target\n}\n\n// Push: Pushes new [data] into Stack, resizes to double if stack is full\n// Time complexity O(1)\n// Space complexity for n push operations O(n)\nfunc (stack *Stack) Push(data interface{}) error {\n\tif stack.IsFull() {\n\t\tstack.Resize()\n\t}\n\tstack.top++\n\tstack.array[stack.top] = data\n\tfmt.Printf(\"\\n%v Pushed to stack\", data)\n\treturn nil\n}\n\n// Pop: Pops top most data from Stack, resizes to hald if sizeof stack is less than half the capacity\n// Time complexity O(1)\nfunc (stack *Stack) Pop() (interface{}, error) {\n\tif stack.IsEmpty() {\n\t\treturn nil, errors.New(\"Stack is empty\")\n\t}\n\ttemp := stack.array[stack.top]\n\tfmt.Printf(\"\\n%v Popped from stack\", temp)\n\tstack.top--\n\tif stack.Size() < stack.capacity / 2 {\n\t\tstack.Resize()\n\t}\n\treturn temp, nil\n}\n\n// Peek: Returns top most element from Stack\n// Time complexity O(1)\nfunc (stack *Stack) Peek() (interface{}, error) {\n\tif stack.IsEmpty() {\n\t\treturn nil, errors.New(\"Stack is empty\")\n\t}\n\ttemp := stack.array[stack.top]\n\tfmt.Printf(\"\\n%v is the topmost element in stack\", temp)\n\treturn temp, nil\n}\n\n// Drain: Removes all elements that are currently in Stack\n// Time complexity O(1)\nfunc (stack *Stack) Drain() {\n\tstack.array = nil\n\tstack.top = -1\n}\n\ntype Pair struct {\n\topen rune\n\tclose rune\n}\n\nvar pairs = []Pair {\n\t{'(', ')'},\n\t{'[', ']'},\n\t{'{', '}'},\n}\n// IsValid: returns true if string has balanced parenthesis\n// Approach : If the character read is not a symbol to be balanced, ignore it.\n// If the character is an opening symbol like (, [, {, push it onto the stack.\n// If it is a closing symbol like ),],}, then if the stack is empty report an error. Otherwise pop the stack.\n// If the symbol popped is not the corresponding opening symbol, report an error.\n// At end of input, if the stack is not empty report an error\n// Time Complexity: O(n). Since we are scanning the input only once. Space Complexity: O(n) [for stack].\nfunc IsValid(s string) bool {\n\tstack := NewStack(1)\n\tfor _, r := range s {\n\t\tfor _, p := range pairs {\n\t\t\ttemp, _ := stack.Peek()\n\t\t\tif r == p.open {\n\t\t\t\tstack.Push(r)\n\t\t\t} else if r == p.close && stack.IsEmpty() {\n\t\t\t\treturn false\n\t\t\t} else if r == p.close && temp == p.open {\n\t\t\t\tstack.Pop()\n\t\t\t\tbreak\n\t\t\t} else if r == p.close && temp != p.open {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t}\n\treturn stack.IsEmpty()\n}\n\nfunc main() {\n\tfmt.Println(IsValid(\"()(1[23){}{}\"))\n}"
  },
  {
    "path": "Stacks/is_palindrome.go",
    "content": "package main\n\n// IsPalindrome: returns true if supplied string is a palindrome\n// Time Complexity: O(n). Space Complexity: O(n/2) ≈ O(n).\nfunc IsPalindrome(s string) bool {\n\tstack := NewStack(1)\n\ti, n := 0, len(s)\n\t// push hald element into stack\n\tfor i < n/2 {\n\t\tstack.Push(s[i])\n\t\ti++\n\t}\n\t// escape mid character\n\tif n%2 == 1 {\n\t\ti++\n\t}\n\t// compare other half of string with stack\n\tfor i < len(s) {\n\t\t// if element doesn't match, or stack is empty then return false\n\t\tif stack.IsEmpty() || s[i] != stack.Pop() {\n\t\t\treturn false\n\t\t}\n\t\ti++\n\t}\n\treturn true\n}"
  },
  {
    "path": "Stacks/next_greater_element.c++",
    "content": "/*\n\n  \tWrite a function that takes in an array of integers and returns a new array containing, at each index, the next\n\telement in the input array that's greater than the element at that index in the input array.\n\n\tSample Input:[2, 5, -3, -4, 6, 7, 2]\n\tOutput: [5, 6, 6, 6, 7, -1, 5]\n\tExplanation:\n\n\tThe given code snippet implements the Next Greater Element algorithm. Here's how it works:\n\n\t1. The function `NextGreaterElement` takes an input array of integers and returns an array of the same length\n\t   where each element represents the next greater element in the input array. If there is no greater element, the corresponding output element is set to -1.\n\n\t2. The `result` slice is initialized with -1 values, indicating that there are no greater elements initially.\n\n\t3. The `stack` is used to keep track of indices of elements from the input array. It will store indices in a\n\t   way that maintains a decreasing order of values from the input array.\n\n\t4. The algorithm performs two passes over the input array. In each pass, it considers the array elements in a\n\t   circular manner by using the modulo operator `%` on the index.\n\n\t5. In the inner loop, the algorithm checks if the current element is greater than the element at the top of the stack.\n\t   If it is, it means the current element is the next greater element for the element at the top of the stack.\n\n\t6. If a greater element is found, the top index is retrieved from the stack, and the corresponding element in the\n\t   `result` slice is updated with the current element from the input array.\n\n\t7. After updating the `result` slice, the top index is removed from the stack.\n\n\t8. The current circular index is then pushed onto the stack to potentially find the next greater element for it in\n\t   the future.\n\n\t9. Once the algorithm completes the two passes over the input array, the `result` slice contains the next greater\n\t   elements for each element in the input array, or -1 if there is no greater element.\n\n\t10. The `result` slice is returned as the output.\n\n\tThe algorithm utilizes a stack to efficiently find the next greater element for each element in the input array.\n\tBy iterating over the array twice in a circular manner, it ensures that all elements have been considered for finding the next greater elements.\n\n\tNote that this implementation assumes the availability of the built-in append function to modify slices in Go.\n\n\tThe time complexity of the `NextGreaterElement` function is O(n), where n is the length of the input array.\n\tThis is because the function performs two passes over the input array, and in each pass, it processes each element once. The operations performed within each iteration, such as stack operations, have constant time complexity.\n\n    The space complexity of the function is O(n) as well. This is because the function creates two additional\n\tslices: `result` and `stack`, each with a maximum size of n. Therefore, the space required by the function grows linearly with the size of the input array.\n*/\n\n#include <vector>\n#include <stack>\n\nstd::vector<int> nextGreaterElement(std::vector<int>& array) {\n    std::vector<int> result(array.size(), -1); // Initialize result vector with -1 for all elements\n    std::stack<int> stack; // Stack to store indices of elements\n    \n    for (int idx = 0; idx < array.size() * 2; idx++) {\n        int circularIdx = idx % array.size(); // Obtain the circular index of the current element\n        \n        while (!stack.empty() && array[circularIdx] > array[stack.top()]) {\n            // While the stack is not empty and the current element is greater than the element at the top of the stack\n            int top = stack.top(); // Get the index from the top of the stack\n            stack.pop(); // Pop the index from the stack\n            result[top] = array[circularIdx]; // Update the result for the popped index\n        }\n        \n        stack.push(circularIdx); // Push the current index to the stack\n    }\n    \n    return result;\n}\n"
  },
  {
    "path": "Stacks/next_greater_element.go",
    "content": "/*\n\n  \tWrite a function that takes in an array of integers and returns a new array containing, at each index, the next\n\telement in the input array that's greater than the element at that index in the input array.\n\n\tSample Input:[2, 5, -3, -4, 6, 7, 2]\n\tOutput: [5, 6, 6, 6, 7, -1, 5]\n\tExplanation:\n\n\tThe given code snippet implements the Next Greater Element algorithm. Here's how it works:\n\n\t1. The function `NextGreaterElement` takes an input array of integers and returns an array of the same length\n\t   where each element represents the next greater element in the input array. If there is no greater element, the corresponding output element is set to -1.\n\n\t2. The `result` slice is initialized with -1 values, indicating that there are no greater elements initially.\n\n\t3. The `stack` is used to keep track of indices of elements from the input array. It will store indices in a\n\t   way that maintains a decreasing order of values from the input array.\n\n\t4. The algorithm performs two passes over the input array. In each pass, it considers the array elements in a\n\t   circular manner by using the modulo operator `%` on the index.\n\n\t5. In the inner loop, the algorithm checks if the current element is greater than the element at the top of the stack.\n\t   If it is, it means the current element is the next greater element for the element at the top of the stack.\n\n\t6. If a greater element is found, the top index is retrieved from the stack, and the corresponding element in the\n\t   `result` slice is updated with the current element from the input array.\n\n\t7. After updating the `result` slice, the top index is removed from the stack.\n\n\t8. The current circular index is then pushed onto the stack to potentially find the next greater element for it in\n\t   the future.\n\n\t9. Once the algorithm completes the two passes over the input array, the `result` slice contains the next greater\n\t   elements for each element in the input array, or -1 if there is no greater element.\n\n\t10. The `result` slice is returned as the output.\n\n\tThe algorithm utilizes a stack to efficiently find the next greater element for each element in the input array.\n\tBy iterating over the array twice in a circular manner, it ensures that all elements have been considered for finding the next greater elements.\n\n\tNote that this implementation assumes the availability of the built-in append function to modify slices in Go.\n\n\tThe time complexity of the `NextGreaterElement` function is O(n), where n is the length of the input array.\n\tThis is because the function performs two passes over the input array, and in each pass, it processes each element once. The operations performed within each iteration, such as stack operations, have constant time complexity.\n\n    The space complexity of the function is O(n) as well. This is because the function creates two additional\n\tslices: `result` and `stack`, each with a maximum size of n. Therefore, the space required by the function grows linearly with the size of the input array.\n*/\npackage main\n\n// NextGreaterElement finds the next greater element for each element in the input array.\nfunc NextGreaterElement(array []int) []int {\n\t// Create a result slice to store the next greater elements.\n\tresult := make([]int, 0)\n\t// Initialize the result slice with -1 values indicating no greater elements initially.\n\tfor range array {\n\t\tresult = append(result, -1)\n\t}\n\n\t// Create a stack to keep track of indices of elements from the input array.\n\tstack := make([]int, 0)\n\n\t// Perform two passes over the input array, considering elements in a circular manner.\n\tfor idx := 0; idx < 2*len(array); idx++ {\n\t\t// Calculate the circular index by using the modulo operator.\n\t\tcircularIdx := idx % len(array)\n\n\t\t// Check if the current element is greater than the element at the top of the stack.\n\t\tfor len(stack) > 0 && array[circularIdx] > array[stack[len(stack)-1]] {\n\t\t\t// Retrieve the top index from the stack.\n\t\t\ttop := stack[len(stack)-1]\n\t\t\t// Update the corresponding element in the result slice with the current element.\n\t\t\tresult[top] = array[circularIdx]\n\t\t\t// Remove the top index from the stack.\n\t\t\tstack = stack[:len(stack)-1]\n\t\t}\n\n\t\t// Push the current circular index onto the stack.\n\t\tstack = append(stack, circularIdx)\n\t}\n\n\t// Return the result slice containing the next greater elements.\n\treturn result\n}\n"
  },
  {
    "path": "Stacks/next_greater_element.java",
    "content": "/*\n\n  \tWrite a function that takes in an array of integers and returns a new array containing, at each index, the next\n\telement in the input array that's greater than the element at that index in the input array.\n\n\tSample Input:[2, 5, -3, -4, 6, 7, 2]\n\tOutput: [5, 6, 6, 6, 7, -1, 5]\n\tExplanation:\n\n\tThe given code snippet implements the Next Greater Element algorithm. Here's how it works:\n\n\t1. The function `NextGreaterElement` takes an input array of integers and returns an array of the same length\n\t   where each element represents the next greater element in the input array. If there is no greater element, the corresponding output element is set to -1.\n\n\t2. The `result` slice is initialized with -1 values, indicating that there are no greater elements initially.\n\n\t3. The `stack` is used to keep track of indices of elements from the input array. It will store indices in a\n\t   way that maintains a decreasing order of values from the input array.\n\n\t4. The algorithm performs two passes over the input array. In each pass, it considers the array elements in a\n\t   circular manner by using the modulo operator `%` on the index.\n\n\t5. In the inner loop, the algorithm checks if the current element is greater than the element at the top of the stack.\n\t   If it is, it means the current element is the next greater element for the element at the top of the stack.\n\n\t6. If a greater element is found, the top index is retrieved from the stack, and the corresponding element in the\n\t   `result` slice is updated with the current element from the input array.\n\n\t7. After updating the `result` slice, the top index is removed from the stack.\n\n\t8. The current circular index is then pushed onto the stack to potentially find the next greater element for it in\n\t   the future.\n\n\t9. Once the algorithm completes the two passes over the input array, the `result` slice contains the next greater\n\t   elements for each element in the input array, or -1 if there is no greater element.\n\n\t10. The `result` slice is returned as the output.\n\n\tThe algorithm utilizes a stack to efficiently find the next greater element for each element in the input array.\n\tBy iterating over the array twice in a circular manner, it ensures that all elements have been considered for finding the next greater elements.\n\n\tThe time complexity of the `NextGreaterElement` function is O(n), where n is the length of the input array.\n\tThis is because the function performs two passes over the input array, and in each pass, it processes each element once. The operations performed within each iteration, such as stack operations, have constant time complexity.\n\n    The space complexity of the function is O(n) as well. This is because the function creates two additional\n\tslices: `result` and `stack`, each with a maximum size of n. Therefore, the space required by the function grows linearly with the size of the input array.\n*/\n\nimport java.util.*;\n\npublic class NextGreaterElement {\n    public int[] nextGreaterElement(int[] array) {\n        int[] result = new int[array.length];\n        Arrays.fill(result, -1); // Initialize result array with -1 for all elements\n        Stack<Integer> stack = new Stack<>(); // Stack to store indices of elements\n        \n        for (int idx = 0; idx < array.length * 2; idx++) {\n            int circularIdx = idx % array.length; // Obtain the circular index of the current element\n            \n            while (!stack.isEmpty() && array[circularIdx] > array[stack.peek()]) {\n                // While the stack is not empty and the current element is greater than the element at the top of the stack\n                int top = stack.pop(); // Pop the index from the stack\n                result[top] = array[circularIdx]; // Update the result for the popped index\n            }\n            \n            stack.push(circularIdx); // Push the current index to the stack\n        }\n        \n        return result;\n    }\n}\n"
  },
  {
    "path": "Stacks/next_greater_element.js",
    "content": "/*\n\n  \tWrite a function that takes in an array of integers and returns a new array containing, at each index, the next\n\telement in the input array that's greater than the element at that index in the input array.\n\n\tSample Input:[2, 5, -3, -4, 6, 7, 2]\n\tOutput: [5, 6, 6, 6, 7, -1, 5]\n\tExplanation:\n\n\tThe given code snippet implements the Next Greater Element algorithm. Here's how it works:\n\n\t1. The function `NextGreaterElement` takes an input array of integers and returns an array of the same length\n\t   where each element represents the next greater element in the input array. If there is no greater element, the corresponding output element is set to -1.\n\n\t2. The `result` slice is initialized with -1 values, indicating that there are no greater elements initially.\n\n\t3. The `stack` is used to keep track of indices of elements from the input array. It will store indices in a\n\t   way that maintains a decreasing order of values from the input array.\n\n\t4. The algorithm performs two passes over the input array. In each pass, it considers the array elements in a\n\t   circular manner by using the modulo operator `%` on the index.\n\n\t5. In the inner loop, the algorithm checks if the current element is greater than the element at the top of the stack.\n\t   If it is, it means the current element is the next greater element for the element at the top of the stack.\n\n\t6. If a greater element is found, the top index is retrieved from the stack, and the corresponding element in the\n\t   `result` slice is updated with the current element from the input array.\n\n\t7. After updating the `result` slice, the top index is removed from the stack.\n\n\t8. The current circular index is then pushed onto the stack to potentially find the next greater element for it in\n\t   the future.\n\n\t9. Once the algorithm completes the two passes over the input array, the `result` slice contains the next greater\n\t   elements for each element in the input array, or -1 if there is no greater element.\n\n\t10. The `result` slice is returned as the output.\n\n\tThe algorithm utilizes a stack to efficiently find the next greater element for each element in the input array.\n\tBy iterating over the array twice in a circular manner, it ensures that all elements have been considered for finding the next greater elements.\n\n\n\tThe time complexity of the `NextGreaterElement` function is O(n), where n is the length of the input array.\n\tThis is because the function performs two passes over the input array, and in each pass, it processes each element once. The operations performed within each iteration, such as stack operations, have constant time complexity.\n\n    The space complexity of the function is O(n) as well. This is because the function creates two additional\n\tslices: `result` and `stack`, each with a maximum size of n. Therefore, the space required by the function grows linearly with the size of the input array.\n*/\nfunction nextGreaterElement(array) {\n  const result = new Array(array.length).fill(-1); // Initialize result array with -1 for all elements\n  const stack = []; // Stack to store indices of elements\n\n  for (let idx = 0; idx < array.length * 2; idx++) {\n    const circularIdx = idx % array.length; // Obtain the circular index of the current element\n\n    while (\n      stack.length &&\n      array[circularIdx] > array[stack[stack.length - 1]]\n    ) {\n      // While the stack is not empty and the current element is greater than the element at the top of the stack\n      const top = stack.pop(); // Pop the index from the stack\n      result[top] = array[circularIdx]; // Update the result for the popped index\n    }\n\n    stack.push(circularIdx); // Push the current index to the stack\n  }\n\n  return result;\n}\n"
  },
  {
    "path": "Stacks/next_greater_element.py",
    "content": "'''\n\n  \tWrite a function that takes in an array of integers and returns a new array containing, at each index, the next\n\telement in the input array that's greater than the element at that index in the input array.\n\n\tSample Input:[2, 5, -3, -4, 6, 7, 2]\n\tOutput: [5, 6, 6, 6, 7, -1, 5]\n\tExplanation:\n\n\tThe given code snippet implements the Next Greater Element algorithm. Here's how it works:\n\n\t1. The function `NextGreaterElement` takes an input array of integers and returns an array of the same length\n\t   where each element represents the next greater element in the input array. If there is no greater element, the corresponding output element is set to -1.\n\n\t2. The `result` slice is initialized with -1 values, indicating that there are no greater elements initially.\n\n\t3. The `stack` is used to keep track of indices of elements from the input array. It will store indices in a\n\t   way that maintains a decreasing order of values from the input array.\n\n\t4. The algorithm performs two passes over the input array. In each pass, it considers the array elements in a\n\t   circular manner by using the modulo operator `%` on the index.\n\n\t5. In the inner loop, the algorithm checks if the current element is greater than the element at the top of the stack.\n\t   If it is, it means the current element is the next greater element for the element at the top of the stack.\n\n\t6. If a greater element is found, the top index is retrieved from the stack, and the corresponding element in the\n\t   `result` slice is updated with the current element from the input array.\n\n\t7. After updating the `result` slice, the top index is removed from the stack.\n\n\t8. The current circular index is then pushed onto the stack to potentially find the next greater element for it in\n\t   the future.\n\n\t9. Once the algorithm completes the two passes over the input array, the `result` slice contains the next greater\n\t   elements for each element in the input array, or -1 if there is no greater element.\n\n\t10. The `result` slice is returned as the output.\n\n\tThe algorithm utilizes a stack to efficiently find the next greater element for each element in the input array.\n\tBy iterating over the array twice in a circular manner, it ensures that all elements have been considered for finding the next greater elements.\n\t\n\tThe time complexity of the `NextGreaterElement` function is O(n), where n is the length of the input array.\n\tThis is because the function performs two passes over the input array, and in each pass, it processes each element once. The operations performed within each iteration, such as stack operations, have constant time complexity.\n\n    The space complexity of the function is O(n) as well. This is because the function creates two additional\n\tslices: `result` and `stack`, each with a maximum size of n. Therefore, the space required by the function grows linearly with the size of the input array.\n'''\n\ndef next_greater_element(array):\n    result = [-1] * len(array)  # Initialize result array with -1 for all elements\n    stack = []  # Stack to store indices of elements\n    \n    for idx in range(len(array) * 2):\n        circular_idx = idx % len(array)  # Obtain the circular index of the current element\n        \n        while stack and array[circular_idx] > array[stack[-1]]:\n            # While the stack is not empty and the current element is greater than the element at the top of the stack\n            top = stack.pop()  # Pop the index from the stack\n            result[top] = array[circular_idx]  # Update the result for the popped index\n        \n        stack.append(circular_idx)  # Push the current index to the stack\n    \n    return result\n"
  },
  {
    "path": "Stacks/queue using stack.go",
    "content": "// Queue using stack\npackage main\n\nimport \"fmt\"\n\n// Queue represents a queue data structure using two stacks.\ntype Queue struct {\n\tenqueueStack []int // Stack for enqueue operations\n\tdequeueStack []int // Stack for dequeue operations\n}\n\n// Enqueue adds an element to the back of the queue.\nfunc (q *Queue) Enqueue(value int) {\n\tq.enqueueStack = append(q.enqueueStack, value)\n}\n\n// Dequeue removes and returns the front element of the queue.\nfunc (q *Queue) Dequeue() int {\n\t// If the dequeue stack is empty, transfer elements from the enqueue stack\n\tif len(q.dequeueStack) == 0 {\n\t\tfor len(q.enqueueStack) > 0 {\n\t\t\t// Pop an element from the enqueue stack and push it onto the dequeue stack\n\t\t\telement := q.enqueueStack[len(q.enqueueStack)-1]\n\t\t\tq.enqueueStack = q.enqueueStack[:len(q.enqueueStack)-1]\n\t\t\tq.dequeueStack = append(q.dequeueStack, element)\n\t\t}\n\t}\n\n\t// If the dequeue stack is still empty, the queue is empty\n\tif len(q.dequeueStack) == 0 {\n\t\tpanic(\"Queue is empty\")\n\t}\n\n\t// Pop and return the front element from the dequeue stack\n\telement := q.dequeueStack[len(q.dequeueStack)-1]\n\tq.dequeueStack = q.dequeueStack[:len(q.dequeueStack)-1]\n\treturn element\n}\n\nfunc main() {\n\tqueue := Queue{}\n\n\t// Enqueue elements\n\tqueue.Enqueue(1)\n\tqueue.Enqueue(2)\n\tqueue.Enqueue(3)\n\n\t// Dequeue elements\n\tfmt.Println(queue.Dequeue()) // Output: 1\n\tfmt.Println(queue.Dequeue()) // Output: 2\n\n\t// Enqueue more elements\n\tqueue.Enqueue(4)\n\tqueue.Enqueue(5)\n\n\t// Dequeue the remaining elements\n\tfmt.Println(queue.Dequeue()) // Output: 3\n\tfmt.Println(queue.Dequeue()) // Output: 4\n\tfmt.Println(queue.Dequeue()) // Output: 5\n}\n"
  },
  {
    "path": "Stacks/queue using stack.java",
    "content": "/*\nIssue:#253\nAuthor:maneesha\nDate:13/06/2023\n##Assignee:Mani1881\n//About:\n\nImplement Queue using Stacks in java\n//Input:\n\n>>Implement a first in first out (FIFO) queue using only two stacks.\n>>The implemented queue should support all the functions of a normal queue (push, peek, pop, and empty).\nImplement the MyQueue class:\n~void push(int x) Pushes element x to the back of the queue.\n~int pop() Removes the element from the front of the queue and returns it.\n~int peek() Returns the element at the front of the queue.\n~boolean empty() Returns true if the queue is empty, false .\n//Example:\n\n>> Sample Input:\n[\"MyQueue\", \"push\", \"push\", \"peek\", \"pop\", \"empty\"]\n[[], [1], [2], [], [], []]\n>>Sample Output:\n[null, null, null, 1, 1, false]\nExplanation\nMyQueue myQueue = new MyQueue();\nmyQueue.push(1); // queue is: [1](here we are not returning push element so in output we got null)\nmyQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)\nmyQueue.peek(); // return 1\nmyQueue.pop(); // return 1, queue is [2]\nmyQueue.empty(); // return false\n//Complexity:\n\n>>Time Complexity\npush:O(n)\npop:O(1)\npeek:O(1)\nempty:O(1)\n>>Space Complexity:O(n)\n//Example:\n\n//Explanation\n\n>>The provided code implements a queue using two stacks (`s1` and `s2`). \n>>The `push()` method transfers elements from `s1` to `s2`, adds the new element to `s1`, and then transfers elements back to `s1`.\n>>The `pop()` method removes and returns the top element of `s1`. \n>>The `peek()` method returns the top element of `s1` without removing it. \n>>The `empty()` method checks if `s1` is empty.\n>>This implementation maintains FIFO order.\n*/\nclass MyQueue \n{\nStack<Integer>s1=new Stack();\nStack<Integer>s2=new Stack();\n   \n    public void push(int x)\n    {\n        while(!s1.isEmpty())\n        {\n            s2.push(s1.pop());\n        }\n        s1.push(x);\n        while(!s2.empty())\n        {\n            s1.push(s2.pop());\n        }\n    }\n    \n    public int pop()\n    {\n        return s1.pop();\n    }\n    \n    public int peek() \n    {\n        return s1.peek();\n    }\n    \n    public boolean empty() \n    {\n        return s1.isEmpty();\n   }\n  public static void main(String[] args) \n  {\n    MyQueue queue = new MyQueue();\n    \n    // Pushing elements into the queue\n    queue.push(1);\n    queue.push(2);\n    queue.push(3);\n    \n    // Checking the front element of the queue\n    System.out.println(\"Front element: \" + queue.peek()); // Output: Front element: 1\n    \n    // Removing elements from the queue\n    System.out.println(\"Removed element: \" + queue.pop()); // Output: Removed element: 1\n    System.out.println(\"Removed element: \" + queue.pop()); // Output: Removed element: 2\n    \n    // Checking if the queue is empty\n    System.out.println(\"Is the queue empty? \" + queue.empty()); // Output: Is the queue empty? false\n    \n    // Pushing another element into the queue\n    queue.push(4);\n    \n    // Removing the remaining elements from the queue\n    System.out.println(\"Removed element: \" + queue.pop()); // Output: Removed element: 3\n    System.out.println(\"Removed element: \" + queue.pop()); // Output: Removed element: 4\n    \n    // Checking if the queue is empty after removing all elements\n    System.out.println(\"Is the queue empty? \" + queue.empty()); // Output: Is the queue empty? true\n}\n} \n"
  },
  {
    "path": "Stacks/queue using stack.js",
    "content": "// Queue using stack\nclass Queue {\n  constructor() {\n    this.enqueueStack = []; // Stack for enqueue operations\n    this.dequeueStack = []; // Stack for dequeue operations\n  }\n\n  enqueue(value) {\n    // Enqueue: Add an element to the back of the queue.\n    this.enqueueStack.push(value);\n  }\n\n  dequeue() {\n    // Dequeue: Remove and return the front element of the queue.\n    // If the dequeue stack is empty, transfer elements from the enqueue stack\n    if (this.dequeueStack.length === 0) {\n      while (this.enqueueStack.length > 0) {\n        // Pop an element from the enqueue stack and push it onto the dequeue stack\n        const element = this.enqueueStack.pop();\n        this.dequeueStack.push(element);\n      }\n    }\n\n    // If the dequeue stack is still empty, the queue is empty\n    if (this.dequeueStack.length === 0) {\n      throw new Error(\"Queue is empty\");\n    }\n\n    // Pop and return the front element from the dequeue stack\n    return this.dequeueStack.pop();\n  }\n}\n\n// Example usage\nconst queue = new Queue();\nqueue.enqueue(1);\nqueue.enqueue(2);\nqueue.enqueue(3);\nconsole.log(queue.dequeue()); // Output: 1\nconsole.log(queue.dequeue()); // Output: 2\nqueue.enqueue(4);\nqueue.enqueue(5);\nconsole.log(queue.dequeue()); // Output: 3\nconsole.log(queue.dequeue()); // Output: 4\nconsole.log(queue.dequeue()); // Output: 5\n"
  },
  {
    "path": "Stacks/queue using stack.py",
    "content": "# Queue using stack\nclass Queue:\n    def __init__(self):\n        self.enqueue_stack = []  # Stack for enqueue operations\n        self.dequeue_stack = []  # Stack for dequeue operations\n\n    def enqueue(self, value):\n        \"\"\"Enqueue: Add an element to the back of the queue.\"\"\"\n        self.enqueue_stack.append(value)\n\n    def dequeue(self):\n        \"\"\"Dequeue: Remove and return the front element of the queue.\"\"\"\n        # If the dequeue stack is empty, transfer elements from the enqueue stack\n        if not self.dequeue_stack:\n            while self.enqueue_stack:\n                # Pop an element from the enqueue stack and push it onto the dequeue stack\n                element = self.enqueue_stack.pop()\n                self.dequeue_stack.append(element)\n\n        # If the dequeue stack is still empty, the queue is empty\n        if not self.dequeue_stack:\n            raise IndexError(\"Queue is empty\")\n\n        # Pop and return the front element from the dequeue stack\n        return self.dequeue_stack.pop()\n\n# Example usage\nqueue = Queue()\nqueue.enqueue(1)\nqueue.enqueue(2)\nqueue.enqueue(3)\nprint(queue.dequeue())  # Output: 1\nprint(queue.dequeue())  # Output: 2\nqueue.enqueue(4)\nqueue.enqueue(5)\nprint(queue.dequeue())  # Output: 3\nprint(queue.dequeue())  # Output: 4\nprint(queue.dequeue())  # Output: 5\n"
  },
  {
    "path": "Stacks/queue_using_stacks.cpp",
    "content": "/* The basic difference in stack and queues is the order they are filled in practically.In Stacks, \nthey are inserted on top of previous element while In Queues they are inserted behind the last element.\nThe push() function is what we have to look out for. First we will empty out our primary stack s1 to another stack s2.\nThen We push the element to be inserted x in s1(or s2). \nThen just empty out the stack s2 back into s1. But the element x would be at the last place just like in a Queue.\nThe other Operations are the same as we have already implemented as a queue.*/\n\n\n/*Complexity Analysis: \n\nTime Complexity: \nPush operation : O(1). \nSame as pop operation in stack.\nPop operation : O(N). \nThe difference from above method is that in this method element is returned and all elements are restored back in a single call.\nAuxiliary Space: O(N). \nUse of stack for storing values.\n*/\n\n\n#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Queue {\n\tstack<int> s;\n\n\t// Enqueue an item to the queue\n\tvoid enQueue(int x)\n\t{\n\t\ts.push(x);\n\t}\n\n\t// Dequeue an item from the queue\n\tint deQueue()\n\t{\n\t\tif (s.empty()) {\n\t\t\tcout << \"Q is empty\";\n\t\t\texit(0);\n\t\t}\n\n\t\t// pop an item from the stack\n\t\tint x = s.top();\n\t\ts.pop();\n\n\t\t// if stack becomes empty, return\n\t\t// the popped item\n\t\tif (s.empty())\n\t\t\treturn x;\n\n\t\t// recursive call\n\t\tint item = deQueue();\n\n\t\t// push popped item back to the stack\n\t\ts.push(x);\n\n\t\t// return the result of deQueue() call\n\t\treturn item;\n\t}\n};\n\n// Driver code\nint main()\n{\n\tQueue q;\n\tq.enQueue(10);\n\tq.enQueue(20);\n\tq.enQueue(30);\n\n\tcout << q.deQueue() << '\\n';\n\tcout << q.deQueue() << '\\n';\n\tcout << q.deQueue() << '\\n';\n\n\treturn 0;\n}\n\n\n\n\n\n"
  },
  {
    "path": "Stacks/reverse_polish_notation.cpp",
    "content": "/*\nYou are given an array of strings tokens that represents an arithmetic expression in a Reverse Polish Notation.\n\nEvaluate the expression. Return an integer that represents the value of the expression.\n\nNote that:\n\nThe valid operators are '+', '-', '*', and '/'.\nEach operand may be an integer or another expression.\nThe division between two integers always truncates toward zero.\nThere will not be any division by zero.\nThe input represents a valid arithmetic expression in a reverse polish notation.\nThe answer and all the intermediate calculations can be represented in a 32-bit integer.\n \n\nExample 1:\n\nInput: tokens = [\"2\",\"1\",\"+\",\"3\",\"*\"]\nOutput: 9\nExplanation: ((2 + 1) * 3) = 9\nExample 2:\n\nInput: tokens = [\"4\",\"13\",\"5\",\"/\",\"+\"]\nOutput: 6\nExplanation: (4 + (13 / 5)) = 6\nExample 3:\n\nInput: tokens = [\"10\",\"6\",\"9\",\"3\",\"+\",\"-11\",\"*\",\"/\",\"*\",\"17\",\"+\",\"5\",\"+\"]\nOutput: 22\nExplanation: ((10 * (6 / ((9 + 3) * -11))) + 17) + 5\n= ((10 * (6 / (12 * -11))) + 17) + 5\n= ((10 * (6 / -132)) + 17) + 5\n= ((10 * 0) + 17) + 5\n= (0 + 17) + 5\n= 17 + 5\n= 22\n \n\nConstraints:\n\n1 <= tokens.length <= 104\ntokens[i] is either an operator: \"+\", \"-\", \"*\", or \"/\", or an integer in the range [-200, 200].\n*/\nclass Solution {\npublic:\n    int evalRPN(vector<string>& tokens) {\n        stack<int> S;\n        for(int i = 0; i < tokens.size(); i++){\n            if(tokens[i] == \"+\" || tokens[i] == \"-\" || tokens[i] == \"*\" || tokens[i] == \"/\"){\n                int v1 = S.top(); S.pop();\n                int v2 = S.top(); S.pop();\n                if(tokens[i] == \"+\"){\n                    S.push(v1 + v2);\n                }\n                if(tokens[i] == \"-\"){\n                    S.push(v2 - v1);\n                }\n                if(tokens[i] == \"*\"){\n                    S.push(v1 * v2);\n                }\n                if(tokens[i] == \"/\"){\n                    S.push(v2 / v1);\n                }\n            }\n            else{\n                S.push(atoi(tokens[i].c_str()));\n            }\n        }\n        return S.top();\n    }\n};"
  },
  {
    "path": "Stacks/stack.cpp",
    "content": "// Implemenmtation of  stack data structure\n/*\n    This implementation creates a class Stack that has a private integer top to keep track of the index \n    of the topmost element in the stack, and an integer array arr to store the elements of the stack. \n    The push, pop, peek, and isEmpty methods are used to add elements to, remove elements from, view \n    the topmost element in, and check if the stack is empty, respectively. The main function creates \n    an instance of Stack and demonstrates the use of the stack by pushing some elements onto it, \n    printing the topmost element, popping an element from the stack, and checking if the stack is empty.\n*/\n#include <iostream>\nusing namespace std;\n\nconst int MAX_SIZE = 100; // Maximum size of stack\n\nclass Stack {\nprivate:\n    int top; // Index of topmost element in stack\n    int arr[MAX_SIZE]; // Array to store elements of stack\npublic:\n    Stack() {\n        top = -1; // Initialize top index to -1, indicating empty stack\n    }\n\n    // Pushes an element onto the top of the stack\n    void push(int x) {\n        if (top == MAX_SIZE - 1) { // Check if stack is full\n            cout << \"Stack Overflow\\n\";\n            return;\n        }\n        arr[++top] = x; // Increment top index and add element to array\n    }\n\n    // Removes and returns the topmost element from the stack\n    int pop() {\n        if (top == -1) { // Check if stack is empty\n            cout << \"Stack Underflow\\n\";\n            return -1;\n        }\n        int val = arr[top]; // Store topmost element in a variable\n        top--; // Decrement top index to remove element from stack\n        return val; // Return topmost element\n    }\n\n    // Returns the topmost element in the stack without removing it\n    int peek() {\n        if (top == -1) { // Check if stack is empty\n            cout << \"Stack Underflow\\n\";\n            return -1;\n        }\n        return arr[top]; // Return topmost element\n    }\n\n    // Returns true if stack is empty, false otherwise\n    bool isEmpty() {\n        return top == -1;\n    }\n};\n\nint main() {\n    Stack s;\n\n    // Push some elements onto the stack\n    s.push(5);\n    s.push(10);\n    s.push(15);\n\n    // Print the topmost element without removing it\n    cout << \"Top element: \" << s.peek() << endl;\n\n    // Pop an element from the stack and print it\n    cout << \"Popped element: \" << s.pop() << endl;\n\n    // Check if stack is empty\n    cout << \"Is stack empty? \" << (s.isEmpty() ? \"Yes\" : \"No\") << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Stacks/stack.go",
    "content": "// Implement Stack Data Structure\n// TODO: Make Stack Generic\n\npackage main\n\nimport \"fmt\"\n\ntype Stack []string\n\n// IsEmpty func checks if the stack is empty\nfunc (s *Stack) IsEmpty() bool {\n\treturn len(*s) == 0\n}\n\n// Push func pushes a new value into the stack\nfunc (s *Stack) Push(str string) {\n\tfmt.Printf(\"%s pushed into stack\\n\", str)\n\t*s = append(*s, str)\n}\n// Pop func pops the top most value from stack if there is any\nfunc (s *Stack) Pop() (string, bool) {\n\tif s.IsEmpty() {\n\t\treturn \"\", false\n\t} else {\n\t\tindex := len(*s) - 1\n\t\telement := (*s)[index]\n\t\t*s = (*s)[:index]\n\t\treturn element, true\n\t}\n}\nfunc main() {\n\tvar stack Stack\n\t\n\t// push 3 values in stack\n\tstack.Push(\"Hello0\")\n\tstack.Push(\"Hello1\")\n\tstack.Push(\"Hello2\")\n\t\n\t// pop out all values from stack\n\tfor len(stack) > 0 {\n\t\tx, y := stack.Pop()\n\t\tif y == true {\n\t\t\tfmt.Printf(\"%s popped from stack\\n\", x)\n\t\t}\n\t}\n\n}"
  },
  {
    "path": "Stacks/stack.java",
    "content": "// Implemenmtation of  stack data structure\n/*\n    This implementation uses a generic type T to allow the stack to store elements of any type. \n    The stack is implemented using an array and has methods for pushing, popping, peeking, checking \n    if the stack is empty, and getting the size of the stack. The comments explain each step of the \n    implementation.\n*/\npublic class Stack<T> {\n    // array to store elements of the stack\n    private T[] elements;\n    // top index of the stack\n    private int top;\n\n    // constructor to initialize the stack with a given capacity\n    public Stack(int capacity) {\n        // create a new array of type T with the given capacity\n        elements = (T[]) new Object[capacity];\n        // initialize top index to -1\n        top = -1;\n    }\n\n    // push an element onto the top of the stack\n    public void push(T element) {\n        // check if the stack is full\n        if (top == elements.length - 1) {\n            // if the stack is full, throw an exception\n            throw new RuntimeException(\"Stack overflow\");\n        }\n        // increment top index\n        top++;\n        // insert the element at the top index\n        elements[top] = element;\n    }\n\n    // pop the top element from the stack and return it\n    public T pop() {\n        // check if the stack is empty\n        if (top == -1) {\n            // if the stack is empty, throw an exception\n            throw new RuntimeException(\"Stack underflow\");\n        }\n        // get the top element\n        T element = elements[top];\n        // decrement top index\n        top--;\n        // return the top element\n        return element;\n    }\n\n    // return the top element of the stack without removing it\n    public T peek() {\n        // check if the stack is empty\n        if (top == -1) {\n            // if the stack is empty, throw an exception\n            throw new RuntimeException(\"Stack underflow\");\n        }\n        // return the top element\n        return elements[top];\n    }\n\n    // return true if the stack is empty, false otherwise\n    public boolean isEmpty() {\n        return top == -1;\n    }\n\n    // return the size of the stack\n    public int size() {\n        return top + 1;\n    }\n}\n"
  },
  {
    "path": "Stacks/stack.js",
    "content": "// Implemenmtation of  stack data structure\n/*\n    We define a class called Stack with an empty array items to store the stack elements.\n    The class has four methods:\n    push(item): Adds an item to the top of the stack by using the push method of the Array object.\n    pop(): Removes and returns the item at the top of the stack using the pop method of the Array object.\n    peek(): Returns the item at the top of the stack without removing it using the slice method of the Array object.\n    isEmpty(): Returns true if the stack is empty, false otherwise by checking the length of the items array.\n\n    This implementation uses the built-in Array object of JavaScript to implement the stack data structure. \n    The push, pop, and slice methods are used to manipulate the items array to add, remove, and access the \n    top item of the stack, respectively. The isEmpty method simply checks if the items array is empty or not.\n*/\nclass Stack {\n  constructor() {\n    this.items = []; // initializing an empty array\n  }\n\n  // push function to add an element to the stack\n  push(element) {\n    this.items.push(element);\n  }\n\n  // pop function to remove the topmost element from the stack\n  pop() {\n    // checking if the stack is empty\n    if (this.items.length === 0) return \"Underflow\";\n    return this.items.pop();\n  }\n\n  // peek function to get the topmost element of the stack without removing it\n  peek() {\n    // checking if the stack is empty\n    if (this.items.length === 0) return \"No elements in Stack\";\n    return this.items[this.items.length - 1];\n  }\n\n  // isEmpty function to check if the stack is empty\n  isEmpty() {\n    return this.items.length === 0;\n  }\n\n  // printStack function to print the entire stack\n  printStack() {\n    let str = \"\";\n    for (let i = 0; i < this.items.length; i++) {\n      str += this.items[i] + \" \";\n    }\n    return str;\n  }\n}\n\n// creating an instance of the Stack class\nlet stack = new Stack();\n\n// adding elements to the stack\nstack.push(10);\nstack.push(20);\nstack.push(30);\n\n// printing the stack\nconsole.log(stack.printStack()); // Output: 10 20 30\n\n// removing the topmost element from the stack\nstack.pop();\n\n// printing the stack\nconsole.log(stack.printStack()); // Output: 10 20\n\n// checking the topmost element of the stack\nconsole.log(stack.peek()); // Output: 20\n\n// checking if the stack is empty\nconsole.log(stack.isEmpty()); // Output: false\n"
  },
  {
    "path": "Stacks/stack.py",
    "content": "# Implemenmtation of  stack data structure\n'''\n    In this implementation, the Stack class contains the following methods:\n\n    __init__: Constructor function to initialize an empty stack.\n    is_empty: Check if stack is empty.\n    push: Push an item onto the stack.\n    pop: Remove and return the top item from the stack.\n    peek: Return the top item from the stack without removing it.\n    size: Return the number of items in the stack.\n    Each method includes a docstring that explains what it does, along with any arguments and return values.\n'''\nclass Stack:\n    \"\"\"\n    Stack class implementation using list in Python\n    \"\"\"\n    def __init__(self):\n        \"\"\"\n        Constructor function to initialize an empty stack\n        \"\"\"\n        self.items = []\n    \n    def is_empty(self):\n        \"\"\"\n        Check if stack is empty\n        \n        Returns:\n        bool: True if stack is empty, False otherwise\n        \"\"\"\n        return len(self.items) == 0\n    \n    def push(self, item):\n        \"\"\"\n        Push an item onto the stack\n        \n        Args:\n        item: Item to be pushed onto the stack\n        \"\"\"\n        self.items.append(item)\n    \n    def pop(self):\n        \"\"\"\n        Remove and return the top item from the stack\n        \n        Returns:\n        item: Top item from the stack\n        \n        Raises:\n        IndexError: If stack is empty\n        \"\"\"\n        if self.is_empty():\n            raise IndexError(\"Stack is empty\")\n        return self.items.pop()\n    \n    def peek(self):\n        \"\"\"\n        Return the top item from the stack without removing it\n        \n        Returns:\n        item: Top item from the stack\n        \n        Raises:\n        IndexError: If stack is empty\n        \"\"\"\n        if self.is_empty():\n            raise IndexError(\"Stack is empty\")\n        return self.items[-1]\n    \n    def size(self):\n        \"\"\"\n        Return the number of items in the stack\n        \n        Returns:\n        int: Number of items in the stack\n        \"\"\"\n        return len(self.items)\n"
  },
  {
    "path": "Stacks/stack_array_based.go",
    "content": "// Array based Stack Implementation\n// Limitation : The maximum size of the stack must first be defined and it cannot be changed. Trying to push a new element into\n// a full Stack causes an implementation-specific exception.\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n)\n\ntype Stack struct {\n\ttop      int\n\tcapacity uint\n\tarray    []interface{}\n}\n\n// Init: Returns an Initialized Stack\nfunc (stack *Stack) Init(capacity uint) *Stack {\n\tstack.top = -1\n\tstack.capacity = capacity\n\tstack.array = make([]interface{}, capacity)\n\treturn stack\n}\n\n// NewStack: Returns a new Stack\nfunc NewStack(capacity uint) *Stack {\n\treturn new(Stack).Init(capacity)\n}\n\n// IsFull: Returns true if Stack is full or else false\n// Time complexity O(1)\nfunc (stack *Stack) IsFull() bool {\n\t// Stack is full when top is equal to the last index\n\treturn stack.top == int(stack.capacity)-1\n}\n\n// IsEmpty: Returns true if Stack is empty or else false\n// Time complexity O(1)\nfunc (stack *Stack) IsEmpty() bool {\n\t// Stack is empty when top is equal to -1\n\treturn stack.top == -1\n}\n\n// Size: Returns the size of Stack\n// Time complexity O(1)\nfunc (stack *Stack) Size() uint {\n\treturn uint(stack.top + 1)\n}\n\n// Push: Pushes new [data] into Stack\n// Time complexity O(1)\n// Space complexity for n push operations O(n)\nfunc (stack *Stack) Push(data interface{}) error {\n\tif stack.IsFull() {\n\t\treturn errors.New(\"Stack is full\")\n\t}\n\tstack.top++\n\tstack.array[stack.top] = data\n\tfmt.Printf(\"\\n%v Pushed to stack\", data)\n\treturn nil\n}\n\n// Pop: Pops top most data from Stack\n// Time complexity O(1)\nfunc (stack *Stack) Pop() (interface{}, error) {\n\tif stack.IsEmpty() {\n\t\treturn nil, errors.New(\"Stack is empty\")\n\t}\n\ttemp := stack.array[stack.top]\n\tfmt.Printf(\"\\n%v Popped from stack\", temp)\n\tstack.top--\n\treturn temp, nil\n}\n\n// Peek: Returns top most element from Stack\n// Time complexity O(1)\nfunc (stack *Stack) Peek() (interface{}, error) {\n\tif stack.IsEmpty() {\n\t\treturn nil, errors.New(\"Stack is empty\")\n\t}\n\ttemp := stack.array[stack.top]\n\tfmt.Printf(\"\\n%v is the topmost element in stack\", temp)\n\treturn temp, nil\n}\n\n// Drain: Removes all elements that are currently in Stack\n// Time complexity O(1)\nfunc (stack *Stack) Drain() {\n\tstack.array = nil\n\tstack.top = -1\n}\n\nfunc main() {\n\tstack := NewStack(50)\n\tstack.Push(1)\n\tstack.Push(2)\n\tstack.Push(3)\n\tfmt.Println(stack.Size()) // returns 3\n\tstack.Pop()\n\tstack.Pop()\n\tstack.Peek()\n\tstack.Drain()\n\tstack.Pop()\n\tstack.Peek()\n\tfmt.Println()\n\tfmt.Println(stack.Size()) // returns 0 after draining\n}"
  },
  {
    "path": "Stacks/stack_dynamic_array.go",
    "content": "// Using Repeated Array doubling technique.\n// If the array is full, create a new array of\n// twice the size, and copy the items. With this approach, pushing k items\n// takes time proportional to k\npackage main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n)\n\ntype Stack struct {\n\ttop      int\n\tcapacity uint\n\tarray    []interface{}\n}\n\n// Init: Returns an Initialized Stack\nfunc (stack *Stack) Init(capacity uint) *Stack {\n\tstack.top = -1\n\tstack.capacity = capacity\n\tstack.array = make([]interface{}, capacity)\n\treturn stack\n}\n\n// NewStack: Returns a new Stack\nfunc NewStack(capacity uint) *Stack {\n\treturn new(Stack).Init(capacity)\n}\n\n// Size: Returns the size of Stack\n// Time complexity O(1)\nfunc (stack *Stack) Size() uint {\n\treturn uint(stack.top + 1)\n}\n\n// IsFull: Returns true if Stack is full or else false\n// Time complexity O(1)\nfunc (stack *Stack) IsFull() bool {\n\t// Stack is full when top is equal to the last index\n\treturn stack.top == int(stack.capacity) - 1\n}\n\n// IsEmpty: Returns true if Stack is empty or else false\n// Time complexity O(1)\nfunc (stack *Stack) IsEmpty() bool {\n\t// Stack is empty when top is equal to -1\n\treturn stack.top == -1\n}\n\n// Resize: If the array is full, creates a new array of\n// twice the size, and copy the items\nfunc (stack *Stack) Resize() {\n\tfmt.Println(\"Resizing\")\n\tif stack.IsFull() {\n\t\tstack.capacity *= 2\n\t} else {\n\t\tstack.capacity /= 2\n\t}\n\ttarget := make([]interface{}, stack.capacity)\n\tcopy(target, stack.array[:stack.top+1])\n\tstack.array = target\n}\n\n// Push: Pushes new [data] into Stack, resizes to double if stack is full\n// Time complexity O(1)\n// Space complexity for n push operations O(n)\nfunc (stack *Stack) Push(data interface{}) error {\n\tif stack.IsFull() {\n\t\tstack.Resize()\n\t}\n\tstack.top++\n\tstack.array[stack.top] = data\n\tfmt.Printf(\"\\n%v Pushed to stack\", data)\n\treturn nil\n}\n\n// Pop: Pops top most data from Stack, resizes to hald if sizeof stack is less than half the capacity\n// Time complexity O(1)\nfunc (stack *Stack) Pop() (interface{}, error) {\n\tif stack.IsEmpty() {\n\t\treturn nil, errors.New(\"Stack is empty\")\n\t}\n\ttemp := stack.array[stack.top]\n\tfmt.Printf(\"\\n%v Popped from stack\", temp)\n\tstack.top--\n\tif stack.Size() < stack.capacity / 2 {\n\t\tstack.Resize()\n\t}\n\treturn temp, nil\n}\n\n// Peek: Returns top most element from Stack\n// Time complexity O(1)\nfunc (stack *Stack) Peek() (interface{}, error) {\n\tif stack.IsEmpty() {\n\t\treturn nil, errors.New(\"Stack is empty\")\n\t}\n\ttemp := stack.array[stack.top]\n\tfmt.Printf(\"\\n%v is the topmost element in stack\", temp)\n\treturn temp, nil\n}\n\n// Drain: Removes all elements that are currently in Stack\n// Time complexity O(1)\nfunc (stack *Stack) Drain() {\n\tstack.array = nil\n\tstack.top = -1\n}\n\n\nfunc IsOperator(c uint8) bool {\n\treturn strings.ContainsAny(string(c), \"+ & - & * & /\")\n}\n\nfunc IsOperand(c uint8) bool {\n\treturn c >= '0' && c <= '9'\n}\n\nfunc GetOperatorWeight(op string) int {\n\tswitch op {\n\t\tcase \"+\", \"-\" : return 1\n\t\tcase \"*\", \"/\" : return 2\n\t}\n\treturn -1\n}\n\nfunc ToPostfix(s string) string {\n\tstack := NewStack(1)\n\tpostfix := \"\"\n\tlength := len(s)\n\n\tfor i := 0; i < length; i++ {\n\t\tchar := string(s[i])\n\t\tif char == \" \" {\n\t\t\tcontinue\n\t\t}\n\t\tif char == \"(\" {\n\t\t\tstack.Push(char)\n\t\t} else if char == \")\" {\n\t\t\tfor !stack.IsEmpty() {\n\t\t\t\ttemp, _ := stack.Peek()\n\t\t\t\tstr := temp.(string)\n\t\t\t\tif str == \"(\" {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tpostfix += \" \" + str\n\t\t\t\tstack.Pop()\n\t\t\t}\n\t\t\tstack.Pop()\n\t\t}\n\t}\n}\n\nfunc HasHigherPrecedence(op1 string, op2 string) bool {\n\top1Weight := GetOperatorWeight(op1)\n\top2Weight := GetOperatorWeight(op2)\n\treturn op1Weight >= op2Weight\n}\n\nfunc main() {\n\tstack := NewStack(1)\n\tstack.Push(1)\n\tstack.Push(2)\n\tstack.Push(3)\n\tfmt.Println(stack.Size())\n\tstack.Pop()\n\tstack.Pop()\n\tstack.Pop()\n\tstack.Drain()\n\tstack.Peek()\n\tfmt.Println(ToPostfix(\"((1+(4+5+2)-3)+(6+8))\"))\n}"
  },
  {
    "path": "Stacks/stack_linked_list.go",
    "content": "package main\n\nimport \"fmt\"\n\ntype Stack struct {\n\ttop  *ListNode\n\tsize int\n}\n\ntype ListNode struct {\n\tdata interface{}\n\tnext *ListNode\n}\n\n// Size: Returns the size of Stack\nfunc (s *Stack) Length() int {\n\treturn s.size\n}\n\n// Push: Pushes new [data] into Stack\n// Time complexity O(1)\n// Space complexity for n push operations O(n)\nfunc (s *Stack) Push(data interface{}) {\n\ts.top = &ListNode{data, s.top}\n\ts.size++\n\tfmt.Printf(\"\\n%v Pushed to stack\", data)\n}\n\n// IsEmpty: Returns true if Stack is empty or else false\n// Time complexity O(1)\nfunc (s *Stack) IsEmpty() bool {\n\treturn s.size == 0\n}\n\n// IsFull: Returns false since its LL based implementation\n// Time complexity O(1)\nfunc (s *Stack) IsFull() bool {\n\treturn false\n}\n\n// Pop: Pops top most data from Stack\n// Time complexity O(1)\nfunc (s *Stack) Pop() (data interface{}) {\n\tif s.size > 0 {\n\t\tdata, s.top = s.top.data, s.top.next\n\t\ts.size--\n\t\tfmt.Printf(\"\\n%v Popped from stack\", data)\n\t\treturn data\n\t}\n\treturn nil\n}\n\n// Peek: Returns top most element from Stack\n// Time complexity O(1)\nfunc (s *Stack) Peek() (data interface{}) {\n\tif s.size > 0 {\n\t\tdata = s.top.data\n\t\tfmt.Printf(\"\\n%v is the topmost element in stack\", data)\n\t\treturn data\n\t}\n\treturn nil\n}\n\nfunc main() {\n\tstack := new(Stack)\n\tstack.Push(\"Hello\")\n\tstack.Push(\"World!\")\n\tstack.Push(\"Yo\")\n\tstack.Peek()\n\tfmt.Println(stack.Length())\n\tstack.Pop()\n\tstack.Pop()\n\tstack.Pop()\n}"
  },
  {
    "path": "Stacks/stack_using_queue.cpp",
    "content": "// stack using queues\n#include <iostream>\n#include <queue>\n\nclass StackUsingQueues {\npublic:\n    StackUsingQueues() {}\n\n    // Push an element onto the stack.\n    void push(int x) {\n        // Add the element to the primary queue.\n        primaryQueue.push(x);\n    }\n\n    // Remove and return the top element of the stack.\n    int pop() {\n        if (isEmpty()) {\n            throw std::runtime_error(\"Stack is empty\");\n        }\n\n        // Move elements from the primary queue to the temporary queue except the last one.\n        while (primaryQueue.size() > 1) {\n            tempQueue.push(primaryQueue.front());\n            primaryQueue.pop();\n        }\n\n        // Get the last element from the primary queue (top of the stack).\n        int topElement = primaryQueue.front();\n        primaryQueue.pop();\n\n        // Swap the primary and temporary queues.\n        primaryQueue = tempQueue;\n        while (!tempQueue.empty()) {\n            tempQueue.pop();\n        }\n\n        return topElement;\n    }\n\n    // Return the top element of the stack without removing it.\n    int top() {\n        if (isEmpty()) {\n            throw std::runtime_error(\"Stack is empty\");\n        }\n\n        int topElement = pop();\n\n        // Add the top element back to the stack.\n        push(topElement);\n\n        return topElement;\n    }\n\n    // Check if the stack is empty.\n    bool isEmpty() {\n        return primaryQueue.empty();\n    }\n\nprivate:\n    std::queue<int> primaryQueue;\n    std::queue<int> tempQueue;\n};\n\nint main() {\n    StackUsingQueues stack;\n\n    // Push elements onto the stack.\n    stack.push(1);\n    stack.push(2);\n    stack.push(3);\n\n    // Pop elements from the stack.\n    std::cout << stack.pop() << std::endl; // Output: 3\n    std::cout << stack.pop() << std::endl; // Output: 2\n\n    // Push more elements.\n    stack.push(4);\n    stack.push(5);\n\n    // Peek at the top element.\n    std::cout << stack.top() << std::endl; // Output: 5\n\n    // Check if the stack is empty.\n    std::cout << stack.isEmpty() << std::endl; // Output: 0 (false)\n\n    return 0;\n}\n"
  },
  {
    "path": "Stacks/stack_using_queue.go",
    "content": "// stack using queues\npackage main\n\nimport (\n\t\"container/list\"\n\t\"fmt\"\n)\n\n// Stack represents a stack data structure using two queues.\ntype Stack struct {\n\tqueue1 *list.List // Primary queue\n\tqueue2 *list.List // Temporary queue for operations\n}\n\n// Constructor creates a new stack.\nfunc NewStack() *Stack {\n\treturn &Stack{\n\t\tqueue1: list.New(),\n\t\tqueue2: list.New(),\n\t}\n}\n\n// Push adds an element to the top of the stack.\nfunc (s *Stack) Push(value int) {\n\t// Add the element to the primary queue\n\ts.queue1.PushBack(value)\n}\n\n// Pop removes and returns the top element of the stack.\nfunc (s *Stack) Pop() int {\n\t// Move elements from the primary queue to the temporary queue except the last one\n\tfor s.queue1.Len() > 1 {\n\t\telement := s.queue1.Front()\n\t\ts.queue1.Remove(element)\n\t\ts.queue2.PushBack(element.Value)\n\t}\n\n\t// Get the last element from the primary queue (top of the stack)\n\ttopElement := s.queue1.Front().Value\n\n\t// Swap the primary and temporary queues\n\ts.queue1, s.queue2 = s.queue2, s.queue1\n\n\treturn topElement.(int)\n}\n\n// Top returns the top element of the stack without removing it.\nfunc (s *Stack) Top() int {\n\t// Similar to Pop, but don't remove the last element\n\ttopElement := s.Pop()\n\n\t// Add the top element back to the stack\n\ts.Push(topElement)\n\n\treturn topElement\n}\n\n// IsEmpty checks if the stack is empty.\nfunc (s *Stack) IsEmpty() bool {\n\treturn s.queue1.Len() == 0\n}\n\nfunc main() {\n\tstack := NewStack()\n\n\t// Push elements onto the stack\n\tstack.Push(1)\n\tstack.Push(2)\n\tstack.Push(3)\n\n\t// Pop elements from the stack\n\tfmt.Println(stack.Pop()) // Output: 3\n\tfmt.Println(stack.Pop()) // Output: 2\n\n\t// Push more elements\n\tstack.Push(4)\n\tstack.Push(5)\n\n\t// Peek at the top element\n\tfmt.Println(stack.Top()) // Output: 5\n\n\t// Check if the stack is empty\n\tfmt.Println(stack.IsEmpty()) // Output: false\n}\n"
  },
  {
    "path": "Stacks/stack_using_queue.java",
    "content": "// stack using queues\nimport java.util.LinkedList;\nimport java.util.Queue;\n\npublic class StackUsingQueues {\n    private Queue<Integer> primaryQueue;\n    private Queue<Integer> tempQueue;\n\n    public StackUsingQueues() {\n        primaryQueue = new LinkedList<>();\n        tempQueue = new LinkedList<>();\n    }\n\n    public void push(int value) {\n        // Add the element to the primary queue\n        primaryQueue.offer(value);\n    }\n\n    public int pop() {\n        if (isEmpty()) {\n            throw new IllegalStateException(\"Stack is empty.\");\n        }\n\n        // Move elements from the primary queue to the temporary queue except the last one\n        while (primaryQueue.size() > 1) {\n            tempQueue.offer(primaryQueue.poll());\n        }\n\n        // Get the last element from the primary queue (top of the stack)\n        int topElement = primaryQueue.poll();\n\n        // Swap the primary and temporary queues\n        Queue<Integer> swap = primaryQueue;\n        primaryQueue = tempQueue;\n        tempQueue = swap;\n\n        return topElement;\n    }\n\n    public int top() {\n        if (isEmpty()) {\n            throw new IllegalStateException(\"Stack is empty.\");\n        }\n\n        int topElement = pop();\n\n        // Add the top element back to the stack\n        push(topElement);\n\n        return topElement;\n    }\n\n    public boolean isEmpty() {\n        return primaryQueue.isEmpty();\n    }\n\n    public static void main(String[] args) {\n        StackUsingQueues stack = new StackUsingQueues();\n\n        // Push elements onto the stack\n        stack.push(1);\n        stack.push(2);\n        stack.push(3);\n\n        // Pop elements from the stack\n        System.out.println(stack.pop()); // Output: 3\n        System.out.println(stack.pop()); // Output: 2\n\n        // Push more elements\n        stack.push(4);\n        stack.push(5);\n\n        // Peek at the top element\n        System.out.println(stack.top()); // Output: 5\n\n        // Check if the stack is empty\n        System.out.println(stack.isEmpty()); // Output: false\n    }\n}\n"
  },
  {
    "path": "Stacks/stack_using_queue.js",
    "content": "// Stack using queues\nclass StackUsingQueues {\n  constructor() {\n    this.primaryQueue = [];\n    this.tempQueue = [];\n  }\n\n  // Push an element onto the stack.\n  push(x) {\n    // Add the element to the primary queue.\n    this.primaryQueue.push(x);\n  }\n\n  // Remove and return the top element of the stack.\n  pop() {\n    if (this.isEmpty()) {\n      throw new Error(\"Stack is empty\");\n    }\n\n    // Move elements from the primary queue to the temporary queue except the last one.\n    while (this.primaryQueue.length > 1) {\n      this.tempQueue.push(this.primaryQueue.shift());\n    }\n\n    // Get the last element from the primary queue (top of the stack).\n    const topElement = this.primaryQueue.shift();\n\n    // Swap the primary and temporary queues.\n    [this.primaryQueue, this.tempQueue] = [this.tempQueue, this.primaryQueue];\n\n    return topElement;\n  }\n\n  // Return the top element of the stack without removing it.\n  top() {\n    if (this.isEmpty()) {\n      throw new Error(\"Stack is empty\");\n    }\n\n    const topElement = this.pop();\n\n    // Add the top element back to the stack.\n    this.push(topElement);\n\n    return topElement;\n  }\n\n  // Check if the stack is empty.\n  isEmpty() {\n    return this.primaryQueue.length === 0;\n  }\n}\n\nconst stack = new StackUsingQueues();\n\n// Push elements onto the stack.\nstack.push(1);\nstack.push(2);\nstack.push(3);\n\n// Pop elements from the stack.\nconsole.log(stack.pop()); // Output: 3\nconsole.log(stack.pop()); // Output: 2\n\n// Push more elements.\nstack.push(4);\nstack.push(5);\n\n// Peek at the top element.\nconsole.log(stack.top()); // Output: 5\n\n// Check if the stack is empty.\nconsole.log(stack.isEmpty()); // Output: false\n"
  },
  {
    "path": "Stacks/stack_using_queue.py",
    "content": "'''\nImplement Stack using Queues\n\nImplement a last-in-first-out (LIFO) stack using only two queues. The implemented stack should support all the functions of a normal stack (push, top, pop, and empty).\n\nImplement the MyStack class:\n\nvoid push(int x) Pushes element x to the top of the stack.\nint pop() Removes the element on the top of the stack and returns it.\nint top() Returns the element on the top of the stack.\nboolean empty() Returns true if the stack is empty, false otherwise.\nNotes:\n\nYou must use only standard operations of a queue, which means that only push to back, peek/pop from front, size and is empty operations are valid.\nDepending on your language, the queue may not be supported natively. You may simulate a queue using a list or deque (double-ended queue) as long as you use only a queue's standard operations.\n\nExample 1:\n\nInput\n[\"MyStack\", \"push\", \"push\", \"top\", \"pop\", \"empty\"]\n[[], [1], [2], [], [], []]\nOutput\n[null, null, null, 2, 2, false]\n\nExplanation\nMyStack myStack = new MyStack();\nmyStack.push(1);\nmyStack.push(2);\nmyStack.top(); // return 2\nmyStack.pop(); // return 2\nmyStack.empty(); // return False\n\nConstraints:\n\n1 <= x <= 9\nAt most 100 calls will be made to push, pop, top, and empty.\nAll the calls to pop and top are valid.\n'''\n\n\nclass MyStack:\n\n    def __init__(self):\n        \"\"\"\n        Initialize your data structure here.\n        \"\"\"\n        self.stack=[]\n\n    def push(self, x: int) -> None:\n        \"\"\"\n        Push element x onto stack.\n        \"\"\"\n        self.stack.append(x)\n        \n\n    def pop(self) -> int:\n        \"\"\"\n        Removes the element on top of the stack and returns that element.\n        \"\"\"\n        return self.stack.pop()\n\n    def top(self) -> int:\n        \"\"\"\n        Get the top element.\n        \"\"\"\n        return self.stack[-1]\n\n    def empty(self) -> bool:\n        \"\"\"\n        Returns whether the stack is empty.\n        \"\"\"\n        if(self.stack):\n            return False\n        return True\n\n\n# Your MyStack object will be instantiated and called as such:\n# obj = MyStack()\n# obj.push(x)\n# param_2 = obj.pop()\n# param_3 = obj.top()\n# param_4 = obj.empty()"
  },
  {
    "path": "Stacks/stacks_API.cpp",
    "content": "/*\n  In this implementation, we use a std::priority_queue named heap to simulate the behavior of a stack. The push operation inserts elements into the heap with a unique sequence number generated for each element. The pop operation removes the top element from the heap. The top operation returns the top element without removing it. The empty operation checks if the heap is empty.\n\nThe time complexity of the stack operations implemented using a heap is as follows:\n\npush: O(log n), where n is the number of elements in the stack.\npop: O(log n), where n is the number of elements in the stack.\ntop: O(1)\nempty: O(1)\nThe push and pop operations have a time complexity of O(log n) because the std::priority_queue internally maintains the heap property, ensuring that the highest priority (in this case, the highest sequence number) element is always at the top\n                       */\n\n\n\n#include <iostream>\n#include <queue>\n\nclass Stack {\nprivate:\n    std::priority_queue<int> heap;  // Using max heap to simulate stack behavior\n    int sequenceNumber;  // To keep track of the order of elements\n\npublic:\n    Stack() : sequenceNumber(0) {}\n\n    void push(int value) {\n        heap.push(std::make_pair(sequenceNumber++, value));\n    }\n\n    int pop() {\n        if (heap.empty()) {\n            throw std::runtime_error(\"Stack is empty\");\n        }\n\n        int value = heap.top().second;\n        heap.pop();\n        return value;\n    }\n\n    int top() const {\n        if (heap.empty()) {\n            throw std::runtime_error(\"Stack is empty\");\n        }\n\n        return heap.top().second;\n    }\n\n    bool empty() const {\n        return heap.empty();\n    }\n};\n\nint main() {\n    Stack stack;\n\n    stack.push(5);\n    stack.push(10);\n    stack.push(3);\n\n    std::cout << stack.top() << std::endl;  // Output: 3\n\n    stack.pop();\n\n    std::cout << stack.top() << std::endl;  // Output: 10\n\n    return 0;\n}\n"
  },
  {
    "path": "Stacks/stacks_using_queues.java",
    "content": "/* Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem : Implement Stack using Queues in Java\nIssue Number : #259\nProblem statement :\n\nExplanation of the below Java code :\n\nIn the above code, the main method demonstrates the usage of the stack by providing the user with a menu to select the operation they want to perform - push, pop, or quit. The user can input the value to push, and the program prints the pushed or popped value accordingly.\n\nThe program uses the Scanner class to take user input from the console. The push method adds the element to the first queue (q1) and updates the top variable. The pop method transfers all elements except the last one from q1 to q2, removes the last element from q1 and swaps the two queues. The peek method returns the top variable, and the isEmpty method checks if q1 is empty.\n\nWhen the user selects the push operation, the program prompts the user to enter the value to push, and it calls the push method to push the value onto the stack. When the user selects the pop operation, the program checks if the stack is empty and prints an error message if it is. Otherwise, it calls the pop method to pop the value from the stack and prints it.\n\nThe program continues to prompt the user for input until the user selects the quit operation\n\n\n*/\n-------------------------------------------------------------------------------------------------------//Java code begins here--------------------------------------------------------------------------------------------------------------------------\n\nimport java.util.LinkedList;\nimport java.util.Queue;\nimport java.util.Scanner;\n\npublic class StackUsingQueues {\n// Create two queues as instance variables\nprivate Queue<Integer> q1 = new LinkedList<>();\nprivate Queue<Integer> q2 = new LinkedList<>();\n\n// Create a variable to hold the top element of the stack\nprivate int top;\n\n// Method to push an element onto the stack\npublic void push(int x) {\n    q1.add(x); // Add the element to the first queue\n    top = x; // Update the top variable to hold the new element\n}\n\n// Method to pop an element from the stack\npublic int pop() {\n    // Move all elements except the last one from the first queue to the second queue\n    while (q1.size() > 1) {\n        top = q1.remove();\n        q2.add(top);\n    }\n    // Remove the last element from the first queue, which is the element to be popped\n    int popValue = q1.remove();\n    // Swap the queues so that the second queue becomes the first queue for the next operation\n    Queue<Integer> temp = q1;\n    q1 = q2;\n    q2 = temp;\n    return popValue; // Return the popped element\n}\n\n// Method to peek at the top element of the stack\npublic int peek() {\n    return top; // Return the top element of the stack\n}\n\n// Method to check if the stack is empty\npublic boolean isEmpty() {\n    return q1.isEmpty(); // Return whether the first queue is empty\n}\n\n// Main method to run the program\npublic static void main(String[] args) {\n    // Create a new instance of the StackUsingQueues class\n    StackUsingQueues stack = new StackUsingQueues();\n    // Create a new Scanner object to read input from the user\n    Scanner scanner = new Scanner(System.in);\n    // Create a loop to continuously prompt the user for input\n    while (true) {\n        System.out.println(\"Select operation -\\n\"\n                + \"1. Push\\n\"\n                + \"2. Pop\\n\"\n                + \"3. Quit\");\n        // Read the user's choice\n        int choice = scanner.nextInt();\n        // Check the user's choice and perform the corresponding operation\n        if (choice == 1) {\n            System.out.print(\"Enter value to push: \");\n            int val = scanner.nextInt();\n            stack.push(val);\n            System.out.println(\"Pushed value: \" + val);\n        } else if (choice == 2) {\n            if (stack.isEmpty()) {\n                System.out.println(\"Stack is empty.\");\n            } else {\n                int val = stack.pop();\n                System.out.println(\"Popped value: \" + val);\n            }\n        } else if (choice == 3) {\n            break;\n        } else {\n            System.out.println(\"Invalid choice. Please try again.\");\n        }\n    }\n}\n}\n"
  },
  {
    "path": "Stacks/stacks_with_queues.cpp",
    "content": "/*\nThis implementation maintains two queues, queue1 and queue2, where queue1 always holds the elements in the stack. When pushing a new element, it is added to queue2, and then all the elements from queue1 are moved to queue2, making the newly added element the front/top of the stack. Finally, the names of the two queues are swapped to maintain the order.\n\nThe pop() function removes and returns the front/top element of queue1, while the top() function returns the front/top element without removing it. Both functions check if queue1 is empty and throw an exception if the stack is empty.\n\nThe empty() function checks if queue1 is empty and returns true if it is, indicating an empty stack.\n\nTime complexity\n\npush(x): O(n)\npop(): O(1)\ntop(): O(1)\nempty(): O(1)\n*/\n  \n\n\n#include <queue>\n\nclass MyStack {\nprivate:\n    std::queue<int> queue1;\n    std::queue<int> queue2;\n    \npublic:\n    MyStack() {\n        \n    }\n    \n    void push(int x) {\n        // Add the new element to queue2\n        queue2.push(x);\n        \n        // Move all elements from queue1 to queue2\n        while (!queue1.empty()) {\n            queue2.push(queue1.front());\n            queue1.pop();\n        }\n        \n        // Swap the names of the two queues\n        std::swap(queue1, queue2);\n    }\n    \n    int pop() {\n        if (queue1.empty()) {\n            throw std::runtime_error(\"Stack is empty\");\n        }\n        \n        int topElement = queue1.front();\n        queue1.pop();\n        return topElement;\n    }\n    \n    int top() {\n        if (queue1.empty()) {\n            throw std::runtime_error(\"Stack is empty\");\n        }\n        \n        return queue1.front();\n    }\n    \n    bool empty() {\n        return queue1.empty();\n    }\n};\n\n"
  },
  {
    "path": "Stacks/stacks_with_queues.py",
    "content": "'''\n__init__() - This method initializes the stack by creating two queues. Since no operations are performed on the queues in this method, the time complexity is O(1).\n\npush(item) - This method adds an item to the top of the stack. Initially, it adds the item to an empty queue, which takes O(1) time. Then, it moves all the elements from the other queue to the empty queue, which takes O(n) time, where n is the number of elements in the stack. Finally, it swaps the names of the two queues, which is a constant time operation. Therefore, the overall time complexity of push(item) is O(n).\n\npop() - This method removes and returns the item at the top of the stack. It checks if the stack is empty, which takes O(1) time. Then, it removes and returns the front element of the non-empty queue, which is a constant time operation. Therefore, the overall time complexity of pop() is O(1).\n\ntop() - This method returns the item at the top of the stack without removing it. It checks if the stack is empty, which takes O(1) time. Then, it retrieves the front element of the non-empty queue, which is a constant time operation. Therefore, the overall time complexity of top() is O(1).\n\nis_empty() - This method checks if the stack is empty by checking if the queue is empty, which takes O(1) time. Therefore, the time complexity of is_empty() is O(1).\n\nsize() - This method returns the number of items in the stack by returning the size of the queue, which is a constant time operation. Therefore, the time complexity of size() is O(1).\n\nthe time complexity of the operations in the Stack class implemented using queues is as follows:\n\npush(item): O(n)\npop(): O(1)\ntop(): O(1)\nis_empty(): O(1)\nsize(): O(1)\n\n'''\n\nfrom queue import Queue\n\nclass Stack:\n    \"\"\"\n    Stack implementation using queues.\n    \"\"\"\n\n    def __init__(self):\n        \"\"\"\n        Initialize an empty stack.\n        \"\"\"\n        self.queue1 = Queue()\n        self.queue2 = Queue()\n\n    def push(self, item):\n        \"\"\"\n        Add an item to the top of the stack.\n        \"\"\"\n        # Add the item to the empty queue\n        self.queue1.put(item)\n\n        # Move all the elements from the other queue to the empty queue\n        while not self.queue2.empty():\n            self.queue1.put(self.queue2.get())\n\n        # Swap the names of the two queues\n        self.queue1, self.queue2 = self.queue2, self.queue1\n\n    def pop(self):\n        \"\"\"\n        Remove and return the item at the top of the stack.\n        \"\"\"\n        if self.queue2.empty():\n            raise IndexError(\"Stack is empty\")\n\n        # Remove and return the front element of the non-empty queue\n        return self.queue2.get()\n\n    def top(self):\n        \"\"\"\n        Return the item at the top of the stack without removing it.\n        \"\"\"\n        if self.queue2.empty():\n            raise IndexError(\"Stack is empty\")\n\n        # Get the front element of the non-empty queue\n        return self.queue2.queue[0]\n\n    def is_empty(self):\n        \"\"\"\n        Check if the stack is empty.\n        \"\"\"\n        return self.queue2.empty()\n\n    def size(self):\n        \"\"\"\n        Return the number of items in the stack.\n        \"\"\"\n        return self.queue2.qsize()\n\n\n"
  },
  {
    "path": "Stacks/valid_parentheses.cpp",
    "content": "/*\nGiven a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.\n\nAn input string is valid if:\n\nOpen brackets must be closed by the same type of brackets.\nOpen brackets must be closed in the correct order.\nEvery close bracket has a corresponding open bracket of the same type.\n \n\nExample 1:\nInput: s = \"()\"\nOutput: true\n\nExample 2:\nInput: s = \"()[]{}\"\nOutput: true\n\nExample 3:\nInput: s = \"(]\"\nOutput: false\n \nConstraints:\n\n1 <= s.length <= 104\ns consists of parentheses only '()[]{}'.\n*/\n\nclass Solution {\npublic:\n    bool Are_pair(char opening, char closing){\n        if (opening == '(' && closing == ')') return true;\n        else if (opening == '[' && closing == ']') return true;\n        else if (opening == '{' && closing == '}') return true;\n        return false;\n    }\n    bool isValid(string s) {\n        stack<char> Sta;\n        int len = s.size();\n        for(int i = 0; i < len; i++){\n            if(s[i] == '(' || s[i] == '[' || s[i] == '{'){\n                Sta.push(s[i]);\n            }\n            else if(s[i] == ')' || s[i] == ']' || s[i] == '}'){\n                if(Sta.empty() || !Are_pair(Sta.top(), s[i]))\n                    return false;\n                else\n                    Sta.pop();\n            }\n        }\n        return Sta.empty() ? true : false;\n    }\n};"
  },
  {
    "path": "Strings/Dp_plaindrome.py",
    "content": "def find_min_insertion_steps(s):\n    n = len(s)\n    dp = [[0] * n for _ in range(n)]\n\n    for length in range(2, n + 1):\n        for i in range(n - length + 1):\n            j = i + length - 1\n            if s[i] == s[j]:\n                dp[i][j] = dp[i + 1][j - 1]\n            else:\n                dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1\n\n    return dp[0][n - 1]\n\n# Test the function\nstring = \"abcd\"\nprint(\"Minimum Insertion Steps:\", find_min_insertion_steps(string))\n"
  },
  {
    "path": "Strings/KMP.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n)\n\n// computeLPSArray computes the Longest Prefix Suffix (LPS) array for the given pattern.\nfunc computeLPSArray(pattern string) []int {\n\tlength := len(pattern)\n\tlps := make([]int, length)\n\tlps[0] = 0\n\tj := 0\n\n\tfor i := 1; i < length; {\n\t\tif pattern[i] == pattern[j] {\n\t\t\tj++\n\t\t\tlps[i] = j\n\t\t\ti++\n\t\t} else {\n\t\t\tif j != 0 {\n\t\t\t\tj = lps[j-1]\n\t\t\t} else {\n\t\t\t\tlps[i] = 0\n\t\t\t\ti++\n\t\t\t}\n\t\t}\n\t}\n\n\treturn lps\n}\n\n// KMPSearch searches for occurrences of the pattern within the given text using the KMP algorithm.\nfunc KMPSearch(text, pattern string) []int {\n\tn := len(text)\n\tm := len(pattern)\n\tlps := computeLPSArray(pattern)\n\n\ti := 0 // Index for text\n\tj := 0 // Index for pattern\n\n\tpositions := make([]int, 0)\n\n\tfor i < n {\n\t\tif pattern[j] == text[i] {\n\t\t\ti++\n\t\t\tj++\n\t\t}\n\n\t\tif j == m {\n\t\t\tpositions = append(positions, i-j)\n\t\t\tj = lps[j-1]\n\t\t} else if i < n && pattern[j] != text[i] {\n\t\t\tif j != 0 {\n\t\t\t\tj = lps[j-1]\n\t\t\t} else {\n\t\t\t\ti++\n\t\t\t}\n\t\t}\n\t}\n\n\treturn positions\n}\n\nfunc main() {\n\ttext := \"ABABDABACDABABCABAB\"\n\tpattern := \"ABABCABAB\"\n\tpositions := KMPSearch(text, pattern)\n\n\tif len(positions) == 0 {\n\t\tfmt.Println(\"Pattern not found in the text.\")\n\t} else {\n\t\tfmt.Printf(\"Pattern found at positions: %v\\n\", positions)\n\t}\n}\n"
  },
  {
    "path": "Strings/Longest_palindromic_substring.py",
    "content": "'''\n    Given a string s, return the longest palindromic substring in s.\n\n    Example 1:\n    Input: s = \"babad\"\n    Output: \"bab\"\n    Explanation: \"aba\" is also a valid answer.\n    \n    Example 2:\n    Input: s = \"cbbd\"\n    Output: \"bb\"\n    \n    Constraints:\n    1 <= s.length <= 1000\n    s consist of only digits and English letters.\n'''\nclass Solution:\n    #Instead of checking if a value is palindrome from the end, we can consider each index to be the center\n    #Then, Check if the left and right indexed values to it are different.\n    #The edge case would to find even lengthed palindrome like the second example\n    #Reference: https://www.youtube.com/watch?v=XYQecbcd6_c\n\n    def __init__(self):\n        self.max_length = -1\n        self.max_palindrome = \"\"\n    def CheckLeftRight(self, s, index, value):\n        low, high = index, index\n        if(value == \"even\"):\n            high = index + 1\n        while(low >= 0 and high < len(s) and s[low] == s[high]):\n            if(high - low + 1 > self.max_length):\n                self.max_length = high - low + 1\n                self.max_palindrome = s[low:high + 1]\n            low -= 1\n            high += 1\n\n    def longestPalindrome(self, s: str) -> str:\n        for i in range(len(s)):\n            #odd values\n            Solution.CheckLeftRight(self, s, i, \"odd\")\n            #Even values\n            Solution.CheckLeftRight(self, s, i, \"even\")\n        return self.max_palindrome"
  },
  {
    "path": "Strings/MaxConcatenatedstr.java",
    "content": "class Solution {\npublic:\n    // i: arr[i] we are currently looking at\n\t// mask: Bitmask that represents all the characters that have been added to the current string\n\t// If 0-th bit in mask is set, it means that we have added \"a\" in the current string\n    int solve(vector<string> &arr, int i, int mask) {\n        int n = arr.size();\n        \n        if (i >= n)\n            return 0;\n        \n        // Skip concatenating arr[i]\n        int curRes = solve(arr, i+1, mask)\n\t\t\n\t\t// Mask to keep track of the characters that are present in arr[i]\n\t\tint curMask = 0;\n        \n        // Check whether any character in arr[i] is present in current string, i.e. \n\t\t// Check whether (arr[i]-'a')-th bit is set in mask\n        // If any existing character's bit is set, it means that we cannot concatenate arr[i]\n        // to the given string and so return curRes only which contains the result of skipping arr[i]\n        // Also, use curMask to maintain the characters in arr[i] that have been seen.\n\t\t// It is possible that arr[i] itself has duplicate characters in which case, we will not be able to concatenate arr[i]\n        // So check whether (c-'a')-th bit is set in curMask and after that set the (c-'a')-th bit in curMask\n        for (char &c: arr[i]) {\n            if (mask & (1 << (c - 'a')))\n                return curRes;\n            \n            if (curMask & (1 << (c - 'a')))\n                return curRes;\n            \n            curMask |= (1 << (c - 'a'));\n        }\n        \n        // All the bits that were set in curMask will be now set in mask, \n\t\t// in order to add all characters of arr[i] to the current string\n        mask |= curMask;\n        \n        // We make a call to i+1 with the updated mask and arr[i]'s length being added\n        curRes = max(curRes, (int) arr[i].length() + solve(arr, i+1, mask));\n        return curRes;\n    }\n    \n    int maxLength(vector<string>& arr) {\n        return solve(arr, 0, 0);\n    }\n};\n"
  },
  {
    "path": "Strings/Min_palindrome.js",
    "content": "function minInsertionStepsToPalindrome(str) {\n  const n = str.length;\n  // Create a 2D array to store the minimum steps needed to make substrings palindrome\n  const dp = Array.from({ length: n }, () => Array(n).fill(0));\n\n  // Base case: single characters are palindromes, so dp[i][i] = 0\n  for (let i = 0; i < n; i++) {\n    dp[i][i] = 0;\n  }\n\n  // Fill the dp table in bottom-up manner\n  for (let len = 2; len <= n; len++) {\n    for (let i = 0; i < n - len + 1; i++) {\n      const j = i + len - 1;\n      if (str[i] === str[j]) {\n        // If the characters at the ends are the same, no additional insertion is needed\n        dp[i][j] = dp[i + 1][j - 1];\n      } else {\n        // Otherwise, choose the minimum between inserting character at i or j\n        dp[i][j] = 1 + Math.min(dp[i + 1][j], dp[i][j - 1]);\n      }\n    }\n  }\n\n  return dp[0][n - 1];\n}\n\n// Example usage:\nconst str = \"abcd\";\nconst minInsertions = minInsertionStepsToPalindrome(str);\nconsole.log(\"Minimum insertion steps:\", minInsertions); // Output: 3 (abcd -> dabcbad)\n"
  },
  {
    "path": "Strings/Valid_palindrome.py",
    "content": "'''Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem :  Find Number of Good Pairs in Go\nIssue Number : #648\nProblem statement : Check whether a given string is a Valid Palindrome in Python\n\nExplanation of the below cpp code :\n\nThe is_valid_palindrome() function is the same as the one in the previous example, which checks whether a given string is a valid palindrome or not.\n\nThe input() function is used to take input from the user.\nIt displays a prompt message \"Enter a string:\" and waits for the user to enter a value followed by pressing the Enter key. The entered value is stored in the variable s.\n\nThe if statement checks if the input string s is a valid palindrome or not using the is_valid_palindrome() function.\nIf it is, it prints the message \"The string is a valid palindrome\", otherwise it prints \"The string is not a valid palindrome\".\n\nThe time complexity of the given code is O(n)\n\n'''\n------------------------------------------------------------------------------------------------------//Python code begins here----------------------------------------------------------------------------------------------------------------------------------\n\ndef is_valid_palindrome(s):\n    s = ''.join(filter(str.isalnum, s)).lower()\n    return s == s[::-1]\n\ns = input(\"Enter a string: \") #Taking input from user\n\nif is_valid_palindrome(s):\n    print(\"The string is a valid palindrome\") #True case\nelse:\n    print(\"The string is not a valid palindrome\")  #False case\n"
  },
  {
    "path": "Strings/case_specific_sorting_of_strings.cpp",
    "content": "case-specific sorting of strings (GFG)\nGiven a string S consisting of only uppercase and lowercase characters. The task is to sort uppercase and lowercase letters separately such that if the ith place in the original string had an Uppercase character then it should not have a lowercase character after being sorted and vice versa.\n\nExample 1:\n\nInput:\nN = 12\nS = defRTSersUXI\nOutput: deeIRSfrsTUX\nExplanation: Sorted form of given string\nwith the same case of character as that\nin original string is deeIRSfrsTUX\nExample 2:\n\nInput:\nN = 6\nS = srbDKi\nOutput: birDKs\nExplanation: Sorted form of given string\nwith the same case of character\nresult in output as birDKs.\nYour Task:\nYou only need to complete the function caseSort, that takes a string str and the length of the string n and returns sorted string.\n\nExplanation: In this problem, we  create three strings based on the given string.One for storing the capital letters named as caps string (string caps=\"\"), second for small letters (string small=\"\") and finally the third string (string ans=\"\") which would store the final result.\nWe will sort the strings in order to maintain  alphabetical order.\nThen we traverse the given string using  x (pointer) ,  i and j pointers for the caps and small strings. j pointer is used to traverse the string caps while i used to traverse the string small.\nx pointer is used to iterate through the given string as a whole and for each capital  letter found we will insert the the letter from string caps into the string ans.\nSimilarly, for each small letter, we will insert it from the string small into the ans string.\nFinally we return the ans string.\n\nCODE:\n\nclass Solution\n{\n    public:\n    //Function to perform case-specific sorting of strings.\n    string caseSort(string str, int n)\n    {\n        string small=\"\", caps = \"\",ans=\"\";\n        for(auto x:str){\n            if(isupper(x)){\n                caps+=x;\n            }\n            else{\n                small+=x;\n            }\n        }\n        sort(caps.begin(),caps.end());\n        sort(small.begin(),small.end());\n        int i=0,j=0;\n        for(auto x:str){\n            if(isupper(x)){\n                ans+=caps[j];\n                j++;\n            }\n            else{\n                ans+=small[i];\n                i++;\n            }\n        }\n        return ans;\n        // your code here\n    }\n};\n"
  },
  {
    "path": "Strings/check panagram.java",
    "content": "/*\n\tCheck whether a string is a Panagram or not.\n\n\tNote that a string is a Panagram if it contains all the character of the alphabets ignoring the case of the alphabets  \n\n\tFor example, \tstr = “Abcdefghijklmnopqrstuvwxyz”\n\t\t\tOutput: Yes\n\t\t\tExplanation: The given string contains all the letters from a to z (ignoring case).\n\n\t\t\tstr = \"AbhayChetri\"\n\t\t\tOutput: No \n\t\t\tExplaination: The given string doesn't contain all the letters from a to z. \n\nApproach:-  1.Convert each letter of the string to the lower or upper case.\n\t    2.Create a frequency array to mark the frequency of each letter from a to z.\n\t    3.Then, traverse the frequency array and if there is any letter that is not present in the given string then print \"No\", otherwise print \"Yes\".\n\n\tTime Complexity: O(N) \n\tAuxiliary Space: O(26)\n\n*/\n\nclass Abhay {\n\n\tstatic int size = 26;\n\n\t// Function to check if ch is a letter\n\tstatic boolean isLetter(char ch)\n\t{\n\t\tif (!Character.isLetter(ch))\n\t\t\treturn false;\n\n\t\treturn true;\n\t}\n\n\t// Function to check if a string\n\t// contains all the letters from\n\t// a to z\n\tstatic boolean allLetter(String str,\n\t\t\t\t\t\t\tint len)\n\t{\n\t\t// Convert the given string\n\t\t// into lowercase\n\t\tstr = str.toLowerCase();\n\n\t\t// Create a frequency array to\n\t\t// mark the present letters\n\t\tboolean[] present = new boolean[size];\n\n\t\t// Traverse for each character\n\t\t// of the string\n\t\tfor (int i = 0; i < len; i++) {\n\n\t\t\t// If the current character\n\t\t\t// is a letter\n\t\t\tif (isLetter(str.charAt(i))) {\n\n\t\t\t\t// Mark current letter as present\n\t\t\t\tint letter = str.charAt(i) - 'a';\n\t\t\t\tpresent[letter] = true;\n\t\t\t}\n\t\t}\n\n\t\t// Traverse for every letter\n\t\t// from a to z\n\t\tfor (int i = 0; i < size; i++) {\n\n\t\t\t// If the current character\n\t\t\t// is not present in string\n\t\t\t// then return false,\n\t\t\t// otherwise return true\n\t\t\tif (!present[i])\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t// Driver Code\n\tpublic static void main(String args[])\n\t{\n\n\t\t// Given string str\n\t\tString str = \"Abcdefghijklmnopqrstuvwxyz\";\n\t\tint len = str.length();\n\n\t\t// Function Call\n\t\tif (allLetter(str, len))\n\t\t\tSystem.out.println(\"Yes\");\n\t\telse\n\t\t\tSystem.out.println(\"No\");\n\t}\n}\n\n"
  },
  {
    "path": "Strings/check_anagrams.java",
    "content": "/**\n * You are given two lowercase strings A and B each of length N. Return 1 if they are anagrams to each other and 0 if not.\n *\n * Note : Two strings A and B are called anagrams to each other if A can be formed after rearranging the letters of B.\n *\n *\n * Problem Constraints\n * 1 <= N <= 105\n * A and B are lowercase strings\n *\n *\n * Input Format\n * Both arguments A and B are a string.\n *\n *\n * Output Format\n * Return 1 if they are anagrams and 0 if not\n *\n *\n * Example Input\n * Input 1:\n * A = \"cat\"\n * B = \"bat\"\n * Input 2:\n * A = \"secure\"\n * B = \"rescue\"\n *\n *\n * Example Output\n * Output 1:\n * 0\n * Output 2:\n * 1\n *\n *\n * Example Explanation\n * For Input 1:\n * The words cannot be rearranged to form the same word. So, they are not anagrams.\n * For Input 2:\n * They are an anagram.\n */\npackage Strings;\n\npublic class CheckAnagrams {\n    public static void main(String[] args) {\n        String string1 = \"secure\";\n        String string2 = \"rescue\";\n\n        int res = solve(string1, string2);\n        System.out.println(res);\n    }\n\n    public static int solve(String string1, String string2) {\n\n        // O(N) time | O(1) space\n\n        int[] freq1 = new int[26];\n        int[] freq2 = new int[26];\n        // build freq array and store count for each letter\n        for (int i = 0; i < string1.length(); i++) {\n            freq1[string1.charAt(i) - 'a']++;\n            freq2[string2.charAt(i) - 'a']++;\n        }\n        // compare if count of each letter \n        // if mismatch occurs then return 0\n        for (int i = 0; i < 26; i++) {\n            if (freq1[i] != freq2[i]) return 0;\n        }\n\n        return 1;\n\n//        char[] char1 = string1.toCharArray();\n//        Arrays.sort(char1);\n//\n//        char[] char2 = string2.toCharArray();\n//        Arrays.sort(char2);\n//\n//        String str1 = new String(char1);\n//        String str2 = new String(char2);\n//\n//        if (str1.equals(str2)) return 1;\n//        return 0;\n    }\n}\n"
  },
  {
    "path": "Strings/check_palindrome.cpp",
    "content": "#include <iostream>\n#include <string>\n\nusing namespace std;\n\n// 2 pointer approach to find if a number is palindrome or not\n// Time complexity O(n), Space complexity O(1).\n\nint palindrome_checker(string str)          // palindrome checker function\n{\n    int left = 0;\n    int right = str.length() - 1;           // initializing left and right variables\n    while(left < right) \n    {\n        if(str[left] != str[right])\n        {\n            return 0;\n        }\n        left = left + 1;                    // updating left and right variables\n        right = right - 1;\n    }\n    return 1;\n}\n\nint main()\n{\n    string str;\n    cin>>str;\n    int isPal = palindrome_checker(str);    // calling palindrome checker function\n    if(isPal == 1)\n    {\n        cout<<\"String is palindrome\";\n    }\n    else\n    {\n        cout<<\"String is not palindrome\";\n    }\n    return 0;\n}"
  },
  {
    "path": "Strings/check_permutations.cpp",
    "content": "// Check if a string is a permutation of other \n// Sample Input: s1 = abba s2 = baba\n// Output: true \n// Time Complexity O(n) Space complexity O(1)\n#include<bits/stdc++.h>\nusing namespace std;\nbool check_permutations(string a, string b){\n    vector<int> Freq(26, 0); // assuming only letters\n    for(int i = 0; i < a.length(); i++){\n        Freq[a[i] - 'a']++;\n    }\n    for(int x : Freq) cout << x << \",\";\n    cout << endl;\n    for(int i = 0; i < b.length(); i++){\n        if(Freq[b[i] - 'a'] > 0) // seen a letter\n            Freq[b[i] - 'a']--; // reduce count\n        else\n            Freq[b[i] - 'a']++; // not seen before so increase count    \n    }\n    for(int x : Freq) cout << x << \",\";\n    cout << endl;\n    int res = accumulate(Freq.begin(), Freq.end(), 0); // checl of sum of elements in freq is 0\n    return res == 0 ? true : false;\n}\nint main(){\n    string a, b;\n    cin >> a >> b;\n    if(check_permutations(a, b))\n        cout << \"TRUE\";\n    else \n        cout << \"FALSE\";    \n    return 0;\n}"
  },
  {
    "path": "Strings/count_occurances.java",
    "content": "/**\n * Find the number of occurrences of bob in string A consisting of lowercase English alphabets.\n *\n *\n *\n * Problem Constraints\n * 1 <= |A| <= 1000\n *\n *\n * Input Format\n * The first and only argument contains the string A, consisting of lowercase English alphabets.\n *\n *\n * Output Format\n * Return an integer containing the answer.\n *\n *\n * Example Input\n * Input 1:\n *\n *   \"abobc\"\n * Input 2:\n *\n *   \"bobob\"\n *\n *\n * Example Output\n * Output 1:\n *\n *   1\n * Output 2:\n *\n *   2\n *\n *\n * Example Explanation\n * Explanation 1:\n *\n *   The only occurrence is at second position.\n * Explanation 2:\n *\n *   Bob occures at first and third position.\n */\n\npackage Strings;\n\npublic class CountOccurrences {\n    public static void main(String[] args) {\n        String string = \"bobob\";\n\n        int res = solve(string);\n        System.out.println(res);\n    }\n    public static int solve(String string) {\n\n        // O(N) time | O(1) space\n        int res = 0;\n\n        for (int i = 0; i + 2 < string.length(); i++) {\n            if (string.charAt(i) == 'b' &&\n                    string.charAt(i + 1) == 'o' &&\n                    string.charAt(i + 2) == 'b')\n                ++res;\n        }\n\n//        for (int i = 0; i < string.length(); i++) {\n//            char c = string.charAt(i);\n//            StringBuilder sb = new StringBuilder();\n//            sb.append(c);\n//            for (int j = i + 1; j < string.length(); j++) {\n//                sb.append(string.charAt(j));\n//                if (sb.toString().equals(\"bob\")) {\n//                    res++;\n//                }\n//            }\n//        }\n        return res;\n    }\n}\n"
  },
  {
    "path": "Strings/group_anagrams.cpp",
    "content": "/*\n\tGroup Anagrams\n\n\tSample Input:  = [\"yo\", \"act\", \"flop\", \"tac\", \"foo\", \"cat\", \"oy\", \"olfp\"]\n\tOutput: [[\"yo\", \"oy\"], [\"flop\", \"olfp\"], [\"act\", \"tac\", \"cat\"], [\"foo\"]]\n\n\tExplanation:\n\n\tThe code snippet is a function that groups anagrams together. An anagram is a word or phrase formed by rearranging\n\tthe letters of another word or phrase.\n\n\tThe function first defines two functions: GroupAnagrams and sortWord. The GroupAnagrams function takes a list of words\n\tas input and returns a list of lists, where each inner list contains all the anagrams of a word in the original list.\n\tThe sortWord function takes a word as input and returns a string that contains the word's letters in sorted order.\n\n\tThe GroupAnagrams function works by first creating a map where the keys are sorted strings of words and the values are\n\tlists of words that have the same sorted string. Then, the function iterates through the list of words, calling the\n\tsortWord function to get the sorted string for each word. The function then adds the word to the list of words associated with the sorted string in the map. Finally, the function iterates through the map, adding each list of words to a list of lists.\n\n\tThe sortWord function works by converting the word to a byte array and then calling the sort.Slice function to sort\n\tthe byte array. The function then returns a string that contains the sorted byte array.\n\n\tO(w * n * log(n)) time | O(wn) space - where w is the number of words and n is the length of the longest word\n\n*/\n\n#include <iostream>\n#include <vector>\n#include <algorithm>\n#include <unordered_map>\n\n// Function to sort a word and return the sorted string\nstd::string sortWord(const std::string& word) {\n    std::string sortedWord = word;\n    std::sort(sortedWord.begin(), sortedWord.end());\n    return sortedWord;\n}\n\n// Function to group anagrams together\nstd::vector<std::vector<std::string>> GroupAnagrams(const std::vector<std::string>& words) {\n    // Create a map where the keys are sorted strings of words and the values are lists of words\n    // that have the same sorted string.\n    std::unordered_map<std::string, std::vector<std::string>> anagrams;\n\n    // Iterate through the words\n    for (const std::string& word : words) {\n        // Get the sorted string for the word\n        std::string sortedWord = sortWord(word);\n\n        // Add the word to the list of words associated with the sorted string in the map\n        anagrams[sortedWord].push_back(word);\n    }\n\n    // Create a vector of vectors, where each inner vector contains all the anagrams of a word in the original list\n    std::vector<std::vector<std::string>> result;\n    for (const auto& pair : anagrams) {\n        result.push_back(pair.second);\n    }\n\n    // Return the vector of vectors\n    return result;\n}\n\nint main() {\n    // Example usage\n    std::vector<std::string> words = { \"eat\", \"tea\", \"tan\", \"ate\", \"nat\", \"bat\" };\n    std::vector<std::vector<std::string>> groupedAnagrams = GroupAnagrams(words);\n\n    // Print the grouped anagrams\n    for (const std::vector<std::string>& group : groupedAnagrams) {\n        for (const std::string& word : group) {\n            std::cout << word << \" \";\n        }\n        std::cout << std::endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "Strings/group_anagrams.go",
    "content": "/*\n\tGroup Anagrams\n\n\tSample Input:  = [\"yo\", \"act\", \"flop\", \"tac\", \"foo\", \"cat\", \"oy\", \"olfp\"]\n\tOutput: [[\"yo\", \"oy\"], [\"flop\", \"olfp\"], [\"act\", \"tac\", \"cat\"], [\"foo\"]]\n\n\tExplanation:\n\n\tThe code snippet is a function that groups anagrams together. An anagram is a word or phrase formed by rearranging\n\tthe letters of another word or phrase.\n\n\tThe function first defines two functions: GroupAnagrams and sortWord. The GroupAnagrams function takes a list of words\n\tas input and returns a list of lists, where each inner list contains all the anagrams of a word in the original list.\n\tThe sortWord function takes a word as input and returns a string that contains the word's letters in sorted order.\n\n\tThe GroupAnagrams function works by first creating a map where the keys are sorted strings of words and the values are\n\tlists of words that have the same sorted string. Then, the function iterates through the list of words, calling the\n\tsortWord function to get the sorted string for each word. The function then adds the word to the list of words associated with the sorted string in the map. Finally, the function iterates through the map, adding each list of words to a list of lists.\n\n\tThe sortWord function works by converting the word to a byte array and then calling the sort.Slice function to sort\n\tthe byte array. The function then returns a string that contains the sorted byte array.\n\n\tO(w * n * log(n)) time | O(wn) space - where w is the number of words and n is the length of the longest word\n\n*/\npackage main\n\nimport \"sort\"\n\n// `GroupAnagrams` groups anagrams together.\nfunc GroupAnagrams(words []string) [][]string {\n    // Create a map where the keys are sorted strings of words and the values are lists of words\n    // that have the same sorted string.\n    anagrams := map[string][]string{}\n    for _, word := range words {\n        // Get the sorted string for the word.\n        sortedWord := sortWord(word)\n\n        // Add the word to the list of words associated with the sorted string in the map.\n        anagrams[sortedWord] = append(anagrams[sortedWord], word)\n    }\n\n    // Create a list of lists, where each inner list contains all the anagrams of a word in the original list.\n    result := [][]string{}\n    for _, group := range anagrams {\n        result = append(result, group)\n    }\n\n    // Return the list of lists.\n    return result\n}\n\n// `sortWord` takes a word as input and returns a string that contains the word's letters in sorted order.\nfunc sortWord(word string) string {\n    // Convert the word to a byte array.\n    wordBytes := []byte(word)\n\n    // Sort the byte array.\n    sort.Slice(wordBytes, func(i, j int) bool {\n        return wordBytes[i] < wordBytes[j]\n    })\n\n    // Return a string that contains the sorted byte array.\n    return string(wordBytes)\n}\n"
  },
  {
    "path": "Strings/group_anagrams.java",
    "content": "/*\n\tGroup Anagrams\n\n\tSample Input:  = [\"yo\", \"act\", \"flop\", \"tac\", \"foo\", \"cat\", \"oy\", \"olfp\"]\n\tOutput: [[\"yo\", \"oy\"], [\"flop\", \"olfp\"], [\"act\", \"tac\", \"cat\"], [\"foo\"]]\n\n\tExplanation:\n\n\tThe code snippet is a function that groups anagrams together. An anagram is a word or phrase formed by rearranging\n\tthe letters of another word or phrase.\n\n\tThe function first defines two functions: GroupAnagrams and sortWord. The GroupAnagrams function takes a list of words\n\tas input and returns a list of lists, where each inner list contains all the anagrams of a word in the original list.\n\tThe sortWord function takes a word as input and returns a string that contains the word's letters in sorted order.\n\n\tThe GroupAnagrams function works by first creating a map where the keys are sorted strings of words and the values are\n\tlists of words that have the same sorted string. Then, the function iterates through the list of words, calling the\n\tsortWord function to get the sorted string for each word. The function then adds the word to the list of words associated with the sorted string in the map. Finally, the function iterates through the map, adding each list of words to a list of lists.\n\n\tThe sortWord function works by converting the word to a byte array and then calling the sort.Slice function to sort\n\tthe byte array. The function then returns a string that contains the sorted byte array.\n\n\tO(w * n * log(n)) time | O(wn) space - where w is the number of words and n is the length of the longest word\n\n*/\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class GroupAnagrams {\n    public List<List<String>> groupAnagrams(String[] words) {\n        // Create a map where the keys are sorted strings of words and the values are lists of words\n        // that have the same sorted string.\n        Map<String, List<String>> anagrams = new HashMap<>();\n\n        // Iterate through the words\n        for (String word : words) {\n            // Get the sorted string for the word\n            String sortedWord = sortWord(word);\n\n            // Add the word to the list of words associated with the sorted string in the map\n            if (!anagrams.containsKey(sortedWord)) {\n                anagrams.put(sortedWord, new ArrayList<>());\n            }\n            anagrams.get(sortedWord).add(word);\n        }\n\n        // Create a list of lists, where each inner list contains all the anagrams of a word in the original array\n        List<List<String>> result = new ArrayList<>(anagrams.values());\n\n        // Return the list of lists\n        return result;\n    }\n\n    // Helper method to sort the characters in a word and return the sorted string\n    private String sortWord(String word) {\n        // Convert the word to a character array\n        char[] wordChars = word.toCharArray();\n\n        // Sort the character array\n        Arrays.sort(wordChars);\n\n        // Return the sorted string\n        return new String(wordChars);\n    }\n\n    public static void main(String[] args) {\n        // Example usage\n        String[] words = {\"eat\", \"tea\", \"tan\", \"ate\", \"nat\", \"bat\"};\n        GroupAnagrams groupAnagrams = new GroupAnagrams();\n        List<List<String>> groupedAnagrams = groupAnagrams.groupAnagrams(words);\n\n        // Print the grouped anagrams\n        for (List<String> group : groupedAnagrams) {\n            System.out.println(group);\n        }\n    }\n}\n"
  },
  {
    "path": "Strings/group_anagrams.js",
    "content": "/*\n\tGroup Anagrams\n\n\tSample Input:  = [\"yo\", \"act\", \"flop\", \"tac\", \"foo\", \"cat\", \"oy\", \"olfp\"]\n\tOutput: [[\"yo\", \"oy\"], [\"flop\", \"olfp\"], [\"act\", \"tac\", \"cat\"], [\"foo\"]]\n\n\tExplanation:\n\n\tThe code snippet is a function that groups anagrams together. An anagram is a word or phrase formed by rearranging\n\tthe letters of another word or phrase.\n\n\tThe function first defines two functions: GroupAnagrams and sortWord. The GroupAnagrams function takes a list of words\n\tas input and returns a list of lists, where each inner list contains all the anagrams of a word in the original list.\n\tThe sortWord function takes a word as input and returns a string that contains the word's letters in sorted order.\n\n\tThe GroupAnagrams function works by first creating a map where the keys are sorted strings of words and the values are\n\tlists of words that have the same sorted string. Then, the function iterates through the list of words, calling the\n\tsortWord function to get the sorted string for each word. The function then adds the word to the list of words associated with the sorted string in the map. Finally, the function iterates through the map, adding each list of words to a list of lists.\n\n\tThe sortWord function works by converting the word to a byte array and then calling the sort.Slice function to sort\n\tthe byte array. The function then returns a string that contains the sorted byte array.\n\n\tO(w * n * log(n)) time | O(wn) space - where w is the number of words and n is the length of the longest word\n\n*/\nfunction sortWord(word) {\n  // Sort the characters in the word and return the sorted string\n  return word.split(\"\").sort().join(\"\");\n}\n\nfunction groupAnagrams(words) {\n  // Create an object where the keys are sorted strings of words and the values are arrays of words\n  // that have the same sorted string.\n  const anagrams = {};\n\n  // Iterate through the words\n  for (const word of words) {\n    // Get the sorted string for the word\n    const sortedWord = sortWord(word);\n\n    // Add the word to the array associated with the sorted string in the object\n    if (!anagrams[sortedWord]) {\n      anagrams[sortedWord] = [];\n    }\n    anagrams[sortedWord].push(word);\n  }\n\n  // Create an array of arrays, where each inner array contains all the anagrams of a word in the original array\n  const result = Object.values(anagrams);\n\n  // Return the array of arrays\n  return result;\n}\n\n// Example usage\nconst words = [\"eat\", \"tea\", \"tan\", \"ate\", \"nat\", \"bat\"];\nconst groupedAnagrams = groupAnagrams(words);\n\n// Print the grouped anagrams\nfor (const group of groupedAnagrams) {\n  console.log(group);\n}\n"
  },
  {
    "path": "Strings/group_anagrams.py",
    "content": "'''\n\tGroup Anagrams\n\n\tSample Input:  = [\"yo\", \"act\", \"flop\", \"tac\", \"foo\", \"cat\", \"oy\", \"olfp\"]\n\tOutput: [[\"yo\", \"oy\"], [\"flop\", \"olfp\"], [\"act\", \"tac\", \"cat\"], [\"foo\"]]\n\n\tExplanation:\n\n\tThe code snippet is a function that groups anagrams together. An anagram is a word or phrase formed by rearranging\n\tthe letters of another word or phrase.\n\n\tThe function first defines two functions: GroupAnagrams and sortWord. The GroupAnagrams function takes a list of words\n\tas input and returns a list of lists, where each inner list contains all the anagrams of a word in the original list.\n\tThe sortWord function takes a word as input and returns a string that contains the word's letters in sorted order.\n\n\tThe GroupAnagrams function works by first creating a map where the keys are sorted strings of words and the values are\n\tlists of words that have the same sorted string. Then, the function iterates through the list of words, calling the\n\tsortWord function to get the sorted string for each word. The function then adds the word to the list of words associated with the sorted string in the map. Finally, the function iterates through the map, adding each list of words to a list of lists.\n\n\tThe sortWord function works by converting the word to a byte array and then calling the sort.Slice function to sort\n\tthe byte array. The function then returns a string that contains the sorted byte array.\n\n\tO(w * n * log(n)) time | O(wn) space - where w is the number of words and n is the length of the longest word\n\n'''\nfrom typing import List\nfrom collections import defaultdict\n\ndef sortWord(word: str) -> str:\n    # Sort the characters in the word and return the sorted string\n    return ''.join(sorted(word))\n\ndef GroupAnagrams(words: List[str]) -> List[List[str]]:\n    # Create a defaultdict where the keys are sorted strings of words and the values are lists of words\n    # that have the same sorted string.\n    anagrams = defaultdict(list)\n\n    # Iterate through the words\n    for word in words:\n        # Get the sorted string for the word\n        sortedWord = sortWord(word)\n\n        # Add the word to the list of words associated with the sorted string in the defaultdict\n        anagrams[sortedWord].append(word)\n\n    # Create a list of lists, where each inner list contains all the anagrams of a word in the original list\n    result = list(anagrams.values())\n\n    # Return the list of lists\n    return result\n\n# Example usage\nwords = [\"eat\", \"tea\", \"tan\", \"ate\", \"nat\", \"bat\"]\ngroupedAnagrams = GroupAnagrams(words)\n\n# Print the grouped anagrams\nfor group in groupedAnagrams:\n    print(group)\n"
  },
  {
    "path": "Strings/is_pallindrome.cpp",
    "content": "/*\n    Write a function that takes in a non-empty string and that returns a boolean\n    representing whether the string is a palindrome.\n    Sample Input: abba\n    Output: True\n    Sample Input: aberba\n    Output: False\n    \n    Explanation:\n    we define a function isPalindrome that takes in a string and returns true if the string is a palindrome, \n    and false otherwise. The function uses two indices, left and right, initialized to the beginning and \n    end of the string respectively. It then iterates through the string by moving the left index to the \n    right and the right index to the left, checking whether the characters at these indices match. \n    If the characters do not match, the function returns false, indicating that the string is not a \n    palindrome. If the entire string is iterated through and all characters match,\n    the function returns true, indicating that the string is a palindrome.\n\n    In the main function, we call the isPalindrome function on the string \"racecar\" and print the result. \n    The output will be \"racecar is a palindrome\".\n*/\n#include <iostream>\n#include <string>\n\nusing namespace std;\n\n/**\n * @brief Function to check whether a string is a palindrome or not\n * \n * @param str String to check\n * @return true if the string is a palindrome, false otherwise\n */\nbool isPalindrome(string str) {\n    int left = 0; // initialize left index to 0\n    int right = str.length() - 1; // initialize right index to last character\n\n    while (left < right) { // while left index is less than right index\n        if (str[left] != str[right]) { // if characters at left and right indices do not match\n            return false; // the string is not a palindrome\n        }\n        left++; // move left index to the right\n        right--; // move right index to the left\n    }\n    return true; // the string is a palindrome\n}\n\nint main() {\n    string str = \"racecar\";\n    bool isPal = isPalindrome(str);\n    if (isPal) {\n        cout << str << \" is a palindrome\" << endl;\n    } else {\n        cout << str << \" is not a palindrome\" << endl;\n    }\n    return 0;\n}\n"
  },
  {
    "path": "Strings/is_pallindrome.go",
    "content": "/*\n  Write a function that takes in a non-empty string and that returns a boolean\n  representing whether the string is a palindrome.\n  Sample Input: abba\n  Output: True\n  Sample Input: aberba\n  Output: False\n*/\npackage main\n\nimport \"fmt\"\n\nfunc IsPalindrome(str string) bool {\n\tstart := 0\n\tend := len(str) - 1\n\tfor start <= end {\n\t\t// if string doesn't match return false straight away\n\t\tif str[start] != str[end] {\n\t\t\treturn false\n\t\t}\n\t\t// string matches so bring start and end inwards\n\t\tstart++\n\t\tend--\n\t}\n\treturn true\n}\n\nfunc main() {\n\tmsg := IsPalindrome(\"HelleH\")\n\tfmt.Println(msg)\n\tmsg = IsPalindrome(\"Hello\")\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Strings/is_pallindrome.java",
    "content": "/*\n    Write a function that takes in a non-empty string and that returns a boolean\n    representing whether the string is a palindrome.\n    Sample Input: abba\n    Output: True\n    Sample Input: aberba\n    Output: False\n    \n    Explanation:\n    This function takes in a non-empty string and returns a boolean representing whether the string \n    is a palindrome. It first removes all non-alphanumeric characters from the string and converts \n    it to lowercase using the replaceAll() and toLowerCase() string methods, respectively.\n\n    It then initializes two pointers, one at the beginning and one at the end of the cleaned string. \n    It iterates through the string from both ends, comparing characters at each step. \n    If the characters do not match, it returns false.\n\n    If the loop completes without returning false, the string is a palindrome and the function \n    returns true.\n*/\n/**\n * This function takes in a non-empty string and returns a boolean representing\n * whether the string is a palindrome.\n * \n * @param str the string to check for palindrome\n * @return true if str is a palindrome, false otherwise\n */\npublic static boolean isPalindrome(String str) {\n    // Remove all non-alphanumeric characters from the string and convert to lowercase\n    String cleanStr = str.replaceAll(\"[^a-zA-Z0-9]\", \"\").toLowerCase();\n\n    // Initialize two pointers, one at the beginning and one at the end of the string\n    int left = 0;\n    int right = cleanStr.length() - 1;\n\n    // Iterate through the string from both ends, comparing characters\n    while (left < right) {\n        if (cleanStr.charAt(left) != cleanStr.charAt(right)) {\n            return false;\n        }\n        left++;\n        right--;\n    }\n\n    // If the loop completes without returning false, the string is a palindrome\n    return true;\n}\n"
  },
  {
    "path": "Strings/is_pallindrome.js",
    "content": "/*\n    Write a function that takes in a non-empty string and that returns a boolean\n    representing whether the string is a palindrome.\n    Sample Input: abba\n    Output: True\n    Sample Input: aberba\n    Output: False\n    \n    Explanation : \n    The function takes in a non-empty string as input and returns a boolean value indicating whether the string \n    is a palindrome or not. It first converts the input string to lowercase and removes any non-alphanumeric \n    characters using a regular expression. It then uses two pointers (one starting from the beginning of the \n    string and the other starting from the end) to compare characters from opposite ends of the string. \n    If any mismatch is found, the function returns false immediately. If the entire string is traversed \n    without finding any mismatches, the function returns true, indicating that the string is a palindrome.\n\n    Note that this implementation treats uppercase and lowercase letters as equivalent (i.e., \"A\" is the same as \"a\") \n    and ignores any non-alphanumeric characters (such as spaces or punctuation marks) when checking for palindromicity.\n*/\n/**\n * Checks if a given string is a palindrome.\n * @param {string} str - The input string to check.\n * @returns {boolean} True if the string is a palindrome, false otherwise.\n */\nfunction isPalindrome(str) {\n  // Convert the input string to lowercase and remove any non-alphanumeric characters\n  str = str.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n\n  // Use two pointers to compare characters from the start and end of the string\n  let left = 0;\n  let right = str.length - 1;\n  while (left < right) {\n    if (str[left] !== str[right]) {\n      return false;\n    }\n    left++;\n    right--;\n  }\n  return true;\n}\n"
  },
  {
    "path": "Strings/is_pallindrome.py",
    "content": "'''\n    Write a function that takes in a non-empty string and that returns a boolean\n    representing whether the string is a palindrome.\n    Sample Input: abba\n    Output: True\n    Sample Input: aberba\n    Output: False\n\n    Explanation:\n\n    In this implementation, we use Python's filter() function to remove all non-alphanumeric characters \n    from the string and lower() method to convert the string to lowercase. Then we check if the reversed \n    string is equal to the original string using the slice notation [::-1]. If the two strings are equal, \n    we return True, indicating that the input string is a palindrome; otherwise, we return False.\n'''\n\ndef is_palindrome(s: str) -> bool:\n    \"\"\"\n    This function takes in a non-empty string and returns a boolean indicating\n    whether the string is a palindrome or not.\n    \n    Parameters:\n    s (str): The input string\n    \n    Returns:\n    bool: True if s is a palindrome, False otherwise\n    \"\"\"\n    # Remove all non-alphanumeric characters and convert to lowercase\n    s = ''.join(filter(str.isalnum, s)).lower()\n    \n    # Check if the reversed string is equal to the original string\n    return s == s[::-1]\n"
  },
  {
    "path": "Strings/is_unique.cpp",
    "content": "/*\n    Implement an algorithm to determine if a string has all unique characters.\n    what if you cannot use additional data structures?\n\n    Explanation:\n   - The `isUniqueUsingBitVector` function takes a constant reference to a string `s` as input and returns a boolean value indicating whether the string has all unique characters.\n   - The variable `checker` is initialized as an integer, representing the bit vector to keep track of character occurrences.\n   - The function iterates over each character `c` in the string using a range-based for loop.\n   - For each character, the variable `val` is computed by subtracting the ASCII value of `'a'` from the ASCII value of the character. This gives the corresponding index (0-25) for lowercase alphabetic characters.\n   - The program checks if the bit at position `val` in `checker` is already set. If it is, it means the character has occurred before, and the function returns `false`.\n   - If the character is unique, the bit at position `val` in `checker` is set by performing a bitwise OR operation with `(1 << val)`. This marks the occurrence of the character in the bit vector.\n   - After iterating through all the characters, if no duplicate characters are found, the function returns `true`.\n   - In the `main` function, a few test cases are provided, and the result of calling `isUniqueUsingBitVector` with each test case is printed.\n\n*/\n#include <iostream>\n#include <string>\n\nbool isUniqueUsingBitVector(const std::string& s) {\n    int checker = 0; // Bit vector to keep track of character occurrences\n    for (char c : s) {\n        int val = c - 'a'; // Convert character to corresponding index (0-25)\n        if ((checker & (1 << val)) > 0) {\n            // If the bit corresponding to the character is already set, it means the character has occurred before\n            return false;\n        }\n        checker |= (1 << val); // Set the bit corresponding to the character to mark its occurrence\n    }\n    return true;\n}\n\nint main() {\n    std::string s = \"ABCDD\";\n    std::string t = \"ABCD\";\n    std::string u = \"AAAAAABCD\";\n    bool msg = isUniqueUsingBitVector(s);\n    std::cout << std::boolalpha << msg << std::endl;\n    msg = isUniqueUsingBitVector(t);\n    std::cout << std::boolalpha << msg << std::endl;\n    msg = isUniqueUsingBitVector(u);\n    std::cout << std::boolalpha << msg << std::endl;\n\n    msg = isUniqueUsingBitVector(\"aa\");\n    std::cout << std::boolalpha << msg << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Strings/is_unique.go",
    "content": "// Implement an algorithm to determine if a string has all unique characters.\n// what if you cannot use additional data structures?\n// Program Author : Abhisek Kumar Gupta\n// Approach 1 : compare every character of string with other character TC O(n^2)\n// Approach 2 : Sort the string and compare neighbouring character for dups TC O(n log(n))\n\npackage main\n\nimport \"fmt\"\n\n\nfunc is_unique_normal(s string) bool {\n\tif len(s) > 128 {\n\t\treturn false\n\t}\n\tvar visited  [128]bool\n\t\n\tfor i := 0; i < len(s); i++ {\n\t\tval := int(s[i]) // convert to ascii value\n\t\tif(visited[val]) { // if already seen then duplicate exists hence return false\n\t\t\treturn false\n\t\t}\n\t\tvisited[val] = true // mark seen as true so far\n\t}\n\treturn true\n}\n\nfunc IsUniqueUsingBitVector(s string) bool {\n\tchecker := 0\n\tfor _, s := range []rune(s){\n\t\tval := s - 'a'\n\t\tif (checker & (1 << uint32(val))) > 0 {\n\t\t\treturn false\n\t\t}\n\t\tchecker |= (1 << uint32(val))\n\t}\n\treturn true\n}\n\nfunc main() {\n\ts := \"ABCDD\"\n    t := \"ABCD\"\n    u := \"AAAAAABCD\"\n    msg := is_unique_normal(s)\n\tfmt.Println(msg)\n    msg = is_unique_normal(t)\n\tfmt.Println(msg)\n    msg = is_unique_normal(u)\n\tfmt.Println(msg)\n\n\tmsg = IsUniqueUsingBitVector(\"aa\")\n\tfmt.Println(msg)\n}"
  },
  {
    "path": "Strings/is_unique.java",
    "content": "/*\n    Implement an algorithm to determine if a string has all unique characters.\n    what if you cannot use additional data structures?\n\n    Explanation:\n   - The `isUniqueUsingBitVector` function takes a string `s` as input and returns a boolean value indicating whether the string has all unique characters.\n   - The variable `checker` is initialized as an integer, representing the bit vector to keep track of character occurrences.\n   - The function iterates over each character `c` in the string using a foreach loop.\n   - For each character, the variable `val` is computed by subtracting the ASCII value of `'a'` from the ASCII value of the character. This gives the corresponding index (0-25) for lowercase alphabetic characters.\n   - The program checks if the bit at position `val` in `checker` is already set. If it is, it means the character has occurred before, and the function returns `false`.\n   - If the character is unique, the bit at position `val` in `checker` is set by performing a bitwise OR operation with `(1 << val)`. This marks the occurrence of the character in the bit vector.\n   - After iterating through all the characters, if no duplicate characters are found, the function returns `true`.\n   - In the `main` function, a few test cases are provided, and the result of calling `isUniqueUsingBitVector` with each test case is printed.\n*/\npublic class Main {\n    public static boolean isUniqueUsingBitVector(String s) {\n        int checker = 0; // Bit vector to keep track of character occurrences\n        for (char c : s.toCharArray()) {\n            int val = c - 'a'; // Convert character to corresponding index (0-25)\n            if ((checker & (1 << val)) > 0) {\n                // If the bit corresponding to the character is already set, it means the character has occurred before\n                return false;\n            }\n            checker |= (1 << val); // Set the bit corresponding to the character to mark its occurrence\n        }\n        return true;\n    }\n\n    public static void main(String[] args) {\n        String s = \"ABCDD\";\n        String t = \"ABCD\";\n        String u = \"AAAAAABCD\";\n        boolean msg = isUniqueUsingBitVector(s);\n        System.out.println(msg);\n        msg = isUniqueUsingBitVector(t);\n        System.out.println(msg);\n        msg = isUniqueUsingBitVector(u);\n        System.out.println(msg);\n\n        msg = isUniqueUsingBitVector(\"aa\");\n        System.out.println(msg);\n    }\n}\n"
  },
  {
    "path": "Strings/is_unique.js",
    "content": "/*\n    Implement an algorithm to determine if a string has all unique characters.\n    what if you cannot use additional data structures?\n\n    Explanation:\n    \n    1. The `isUniqueUsingBitVector` function takes a string `s` as input and returns a boolean value indicating whether the string has all unique characters.\n    2. The variable `checker` is initialized as 0, representing the bit vector to keep track of character occurrences.\n    3. The function iterates over each character in the string using a for loop.\n    4. For each character, the variable `val` is computed by subtracting the ASCII value of `'a'` from the ASCII value of the character. This calculates the corresponding index (0-25) for lowercase alphabetic characters.\n    5. The program checks if the bit at position `val` in the `checker` is already set. If it is, it means the character has occurred before, and the function returns `false`.\n    6. If the character is unique, the bit at position `val` in the `checker` is set by performing a bitwise OR operation with `(1 << val)`. This marks the occurrence of the character in the bit vector.\n    7. After iterating through all the characters, if no duplicate characters are found, the function returns `true`.\n    8. In the test cases section, a few sample strings (`s`, `t`, `u`, and `\"aa\"`) are provided, and the result of calling `isUniqueUsingBitVector` with each test case is printed using `console.log()`.\n*/\n\nfunction isUniqueUsingBitVector(s) {\n  let checker = 0; // Bit vector to keep track of character occurrences\n\n  for (let i = 0; i < s.length; i++) {\n    const val = s.charCodeAt(i) - \"a\".charCodeAt(0); // Convert character to corresponding index (0-25)\n\n    if ((checker & (1 << val)) > 0) {\n      // If the bit corresponding to the character is already set, it means the character has occurred before\n      return false;\n    }\n\n    checker |= 1 << val; // Set the bit corresponding to the character to mark its occurrence\n  }\n\n  return true;\n}\n\n// Test cases\nconst s = \"ABCDD\";\nconst t = \"ABCD\";\nconst u = \"AAAAAABCD\";\n\nconsole.log(isUniqueUsingBitVector(s)); // false, 'D' appears more than once\nconsole.log(isUniqueUsingBitVector(t)); // true, all characters are unique\nconsole.log(isUniqueUsingBitVector(u)); // false, 'A' appears more than once\n\nconsole.log(isUniqueUsingBitVector(\"aa\")); // false, 'a' appears more than once\n"
  },
  {
    "path": "Strings/is_unique.py",
    "content": "'''\n    Implement an algorithm to determine if a string has all unique characters.\n    what if you cannot use additional data structures?\n    \n    Explanation:\n   - The `is_unique_using_bit_vector` function takes a string `s` as input and returns a boolean value indicating whether the string has all unique characters.\n   - The variable `checker` is initialized as an integer, representing the bit vector to keep track of character occurrences.\n   - The function iterates over each character `c` in the string using a for loop.\n   - For each character, the variable `val` is computed by subtracting the ASCII value of `'a'` from the ASCII value of the character. This gives the corresponding index (0-25) for lowercase alphabetic characters.\n   - The program checks if the bit at position `val` in `checker` is already set. If it is, it means the character has occurred before, and the function returns `False`.\n   - If the character is unique, the bit at position `val` in\n'''\ndef is_unique_using_bit_vector(s):\n    checker = 0  # Bit vector to keep track of character occurrences\n    for c in s:\n        val = ord(c) - ord('a')  # Convert character to corresponding index (0-25)\n        if (checker & (1 << val)) > 0:\n            # If the bit corresponding to the character is already set, it means the character has occurred before\n            return False\n        checker |= (1 << val)  # Set the bit corresponding to the character to mark its occurrence\n    return True\n\ns = \"ABCDD\"\nt = \"ABCD\"\nu = \"AAAAAABCD\"\nmsg = is_unique_using_bit_vector(s)\nprint(msg)\nmsg = is_unique_using_bit_vector(t)\nprint(msg)\nmsg = is_unique_using_bit_vector(u)\nprint(msg)\n\nmsg = is_unique_using_bit_vector(\"aa\")\nprint(msg)\n"
  },
  {
    "path": "Strings/length_of_longest_substring.java",
    "content": "/* Implement lengthOfLongestSubstring(s), which calculates the length of the longest possible substring that does not contain repeating characters.\n\nExample 1:\nInput: \"abcabcbaba\"\nOutput: 3\n\nExample 2:\nInput: \"dddddddd\"\nOutput: 1\n\nExample 3:\nInput: \"pwwkewo\"\nOutput: 4\n\nConstraints:\n0 <= s.length <= 5 * 10^4\n\nTime complexity: O(n^2)\nSpace complexity: O(1)\n\n*/\n\nclass Solution {\n    public int lengthOfLongestSubstring(String s) {\n        int length = s.length();\n        if (length==0) {\n            return 0;\n        }\n\n        int max = 1;\n        // Aiming to find substring of s that starts at index i and ends at j-1.\n        int i = 0;\n        int j = i+1;\n\n        while (j<length) {\n            while (j<length && (s.substring(i,j).indexOf(s.charAt(j)) == -1)) {\n                j++;\n            } \n\n            if ((j-i) > max) {\n                max = j-i;\n            }\n\n            i++;\n        }\n\n        return max;\n    }\n}\n"
  },
  {
    "path": "Strings/longest palindromic substring.java",
    "content": "/* \nIssue#415\n//Input:\nGiven a string s, return the longest palindromic substring in s.\n\n//Palindrome:A palindrome is a word, phrase, or sequence that reads the same forward and backward, like \"level\" or \"A man, a plan, a canal, Panama.\"\n\n//Example 1:\nInput: s = \"babad\"\nOutput: \"bab\"\nExplanation: \"aba\" is also a valid answer.\n//Example 2:\nInput: s = \"cbbd\"\nOutput: \"bb\"\n\n//Time complexity:\n>>Time Complexity: O(n2)\nas there is two recursion calls which are applied as two pointers so here Complexity would be O(n2).\n>>Space Complexity: O(n) which is nothing but the storage consumed in this process.\n\n//Explanation:\n>>The function first converts the input string into a character array. \n>>If the length of the string is less than 2, it means the string itself is a palindrome, so it returns the string as is.\n>>The function then iterates through each character of the string.\n>>For each character, it expands outwards from that character and checks if it forms a palindrome. \n>>It does this by calling the expandPalindrome function twice: once for odd-length palindromes with the current character as the center,\nand once for even-length palindromes with the current character and the next character as centers.\n>>The expandPalindrome function checks if the characters at positions j and k are equal, and if so, it expands the palindrome by decrementing j and incrementing k.\n>>It continues this process until the characters at positions j and k are no longer equal or reach the boundaries of the string.\n>>If a longer palindrome is found, the maxLen and lo variables are updated accordingly.\nmaxLen stores the length of the longest palindrome found so far, and lo stores the starting position of the longest palindrome.\n>>Finally, the function returns the substring of the original string from the starting position lo to lo + maxLen, which represents the longest palindrome found.\n\n*/\nclass Solution {\n    int maxLen = 0;  // Length of the longest palindrome\n    int lo = 0;     // Starting position of the longest palindrome\n\n    public String longestPalindrome(String s) {\n        char[] input = s.toCharArray(); // Convert the input word to individual characters\n\n        if (s.length() < 2) {\n            return s;   // If word has less than 2 letters, it is already a palindrome\n        }\n\n        for (int i = 0; i < input.length; i++) {\n            expandPalindrome(input, i, i);      // Check odd-length palindromes with current letter as center\n            expandPalindrome(input, i, i + 1);  // Check even-length palindromes with current and next letters as center\n        }\n        return s.substring(lo, lo + maxLen);    // Return the longest palindrome found\n    }\n\n    public void expandPalindrome(char[] s, int j, int k) {\n        while (j >= 0 && k < s.length && s[j] == s[k]) {\n            j--;    // Move left to expand potential palindrome\n            k++;    // Move right to expand potential palindrome\n        }\n        if (maxLen < k - j - 1) {\n            maxLen = k - j - 1; // Update length of longest palindrome if longer one is found\n            lo = j + 1;         // Update starting position of longest palindrome\n        }\n    }\n\n    public static void main(String[] args) {\n        Solution solution = new Solution();\n        String input = \"babad\";\n        String longestPalindrome = solution.longestPalindrome(input);\n        System.out.println(\"Longest Palindrome: \" + longestPalindrome);\n    }\n}\n\n\n\n"
  },
  {
    "path": "Strings/longest_common_prefix.cpp",
    "content": "/*\nWrite a function to find the longest common prefix string amongst an array of strings.\n\nIf there is no common prefix, return an empty string \"\".\n\n \n\nExample 1:\n\nInput: strs = [\"flower\",\"flow\",\"flight\"]\nOutput: \"fl\"\nExample 2:\n\nInput: strs = [\"dog\",\"racecar\",\"car\"]\nOutput: \"\"\nExplanation: There is no common prefix among the input strings.\n \n\nConstraints:\n\n1 <= strs.length <= 200\n0 <= strs[i].length <= 200\nstrs[i] consists of only lowercase English letters.\n\nTime complexity : O(strs)\n*/\n\n#include<bits/stdc++.h>\n\nclass Solution {\npublic:\n    string longestCommonPrefix(vector<string>& strs) {\n        if(strs.size() == 0) return \"\";\n        string ans = \"\";\n        //  fix one string and check the common prefix of this string with other strings\n        // s is the smallest string, so longest cant be greater than smallest string in array\n        string s = *min_element(strs.begin(), strs.end());\n        for(int i = 0; i < s.size(); i++){\n            for(int j = 0; j < strs.size(); j++){\n                if(s[i] != strs[j][i])\n                    return ans;\n            }\n            ans.push_back(s[i]);\n        }\n        return ans;\n    }\n};"
  },
  {
    "path": "Strings/longest_string.cpp",
    "content": "/*The code implements the dynamic programming approach to find the longest palindrome substring in a given string. It uses a two-dimensional table dp to store the results of subproblems, where dp[i][j] represents whether the substring from index i to index j is a palindrome.\n\nThe algorithm first checks for all substrings of length 1 and marks them as palindromes. Then it checks for substrings of length 2 and updates the start and maxLen variables if a palindrome of length 2 is found.\n\nAfter that, it checks for substrings of length greater than 2 by iterating over all possible lengths and positions. If a palindrome is found at a particular position, it updates the start and maxLen variables accordingly.\n\n*/\n\n#include <string>\n#include <vector>\n\nclass Solution {\npublic:\n    /**\n     * Finds the longest palindrome substring within a given string.\n     *\n     * @param s The input string.\n     * @return The longest palindrome substring.\n     */\n    std::string longestPalindrome(std::string s) {\n        int n = s.length();\n        if (n < 2) {\n            return s;\n        }\n\n        int start = 0;  // start index of the longest palindrome\n        int maxLen = 1; // length of the longest palindrome\n\n        // Initialize a table to store the results of subproblems\n        std::vector<std::vector<bool>> dp(n, std::vector<bool>(n, false));\n\n        // All substrings of length 1 are palindromes\n        for (int i = 0; i < n; i++) {\n            dp[i][i] = true;\n        }\n\n        // Check for substrings of length 2\n        for (int i = 0; i < n - 1; i++) {\n            if (s[i] == s[i + 1]) {\n                dp[i][i + 1] = true;\n                start = i;\n                maxLen = 2;\n            }\n        }\n\n        // Check for substrings of length greater than 2\n        for (int len = 3; len <= n; len++) {\n            for (int i = 0; i < n - len + 1; i++) {\n                int j = i + len - 1;\n                if (s[i] == s[j] && dp[i + 1][j - 1]) {\n                    dp[i][j] = true;\n                    start = i;\n                    maxLen = len;\n                }\n            }\n        }\n\n        // Return the longest palindrome substring\n        return s.substr(start, maxLen);\n    }\n};\n\n"
  },
  {
    "path": "Strings/one_edit.cpp",
    "content": "    /*\n    You're given two strings stringone and stringtwo. Write a function that determines if these\n\ttwo strings can be made equal using only one edit.\n\n\n    There are 3 possible edits:\n    Replace: One character in one string is swapped for a different character.\n    Add:: One character is added at any index in one string.\n    Remove: One character is removed at any index in one string.\n\n\tSample Input: StringOne: alaska StringTwo: aloska\n\tOutput: True\n\n\n\tExplanation:\n\tThe code snippet is implementing the \"One Edit Away\" algorithm, which determines whether two given\n\tstrings are one edit away from each other. An edit is defined as either inserting a character, removing a character, or replacing a character.\n\n\tThe `OneEdit` function takes two strings as input and returns a boolean indicating whether\n\tthey are one edit away. Here's the breakdown of the algorithm:\n\n\t1. Calculate the lengths of the two strings.\n\t2. Check if the difference in lengths is greater than 1. If so, return `false` because it's\n\t   not possible to make one edit to make the strings equal.\n\t3. Traverse both strings until the shorter one is fully traversed or an unequal character is\n\tfound.\n\t4. If an unequal character is found, check the remaining portion of the strings to determine\n\t   if they are still one edit away.\n\t5. Check the remaining characters in the longer string compared to the remaining characters\n\t   in the shorter string.\n\t6. Return `true` if the remaining portions match, indicating they are one edit away.\n\t7. If the loop completes without finding any unequal characters, the strings are either\n\t   identical or differ only in length by 1, which means they are one edit away.\n\t8. The `abs` and `min` functions are utility functions used to calculate the absolute value\n\t   and minimum of two integers, respectively.\n\n\tThe algorithm efficiently checks for the possibility of one edit by comparing the characters at corresponding indices and handling cases where the lengths of the strings are different.\n\n\tO(n) time | O(1) space - where n is the length of the shorter string\n\n\n*/\n#include <iostream>\n#include <string>\nusing namespace std;\n\nbool OneEdit(string stringOne, string stringTwo) {\n    int lengthOne = stringOne.length();\n    int lengthTwo = stringTwo.length();\n\n    // Check the difference in lengths between the two strings.\n    // If the difference is greater than 1, it is not possible to make one edit to make them equal.\n    if (abs(lengthOne - lengthTwo) > 1) {\n        return false;\n    }\n\n    // Traverse the strings until the shorter one is fully traversed or an unequal character is found.\n    for (int i = 0; i < min(lengthOne, lengthTwo); i++) {\n        // If an unequal character is found, check the remaining portion of the strings to determine if they are still one edit away.\n        if (stringOne[i] != stringTwo[i]) {\n            // Check the remaining characters in the longer string compared to the remaining characters in the shorter string.\n            // Return true if they match, indicating they are one edit away.\n            if (lengthOne > lengthTwo) {\n                return stringOne.substr(i + 1) == stringTwo.substr(i);\n            } else if (lengthTwo > lengthOne) {\n                return stringTwo.substr(i + 1) == stringOne.substr(i);\n            } else {\n                return stringOne.substr(i + 1) == stringTwo.substr(i + 1);\n            }\n        }\n    }\n\n    // If the loop completes without finding any unequal characters, the strings are either identical or differ only in length by 1.\n    return true;\n}\n\nint main() {\n    string stringOne = \"pale\";\n    string stringTwo = \"ple\";\n\n    // Check if the strings are one edit away\n    bool isOneEdit = OneEdit(stringOne, stringTwo);\n\n    // Print the result\n    cout << \"The strings are\" << (isOneEdit ? \"\" : \" not\") << \" one edit away.\" << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Strings/one_edit.go",
    "content": "/*\n    You're given two strings stringone and stringtwo. Write a function that determines if these\n\ttwo strings can be made equal using only one edit.\n\n\n    There are 3 possible edits:\n    Replace: One character in one string is swapped for a different character.\n    Add:: One character is added at any index in one string.\n    Remove: One character is removed at any index in one string.\n\n\tSample Input: StringOne: alaska StringTwo: aloska\n\tOutput: True\n\n\n\tExplanation:\n\tThe code snippet is implementing the \"One Edit Away\" algorithm, which determines whether two given\n\tstrings are one edit away from each other. An edit is defined as either inserting a character, removing a character, or replacing a character.\n\n\tThe `OneEdit` function takes two strings as input and returns a boolean indicating whether\n\tthey are one edit away. Here's the breakdown of the algorithm:\n\n\t1. Calculate the lengths of the two strings.\n\t2. Check if the difference in lengths is greater than 1. If so, return `false` because it's\n\t   not possible to make one edit to make the strings equal.\n\t3. Traverse both strings until the shorter one is fully traversed or an unequal character is\n\tfound.\n\t4. If an unequal character is found, check the remaining portion of the strings to determine\n\t   if they are still one edit away.\n\t5. Check the remaining characters in the longer string compared to the remaining characters\n\t   in the shorter string.\n\t6. Return `true` if the remaining portions match, indicating they are one edit away.\n\t7. If the loop completes without finding any unequal characters, the strings are either\n\t   identical or differ only in length by 1, which means they are one edit away.\n\t8. The `abs` and `min` functions are utility functions used to calculate the absolute value\n\t   and minimum of two integers, respectively.\n\n\tThe algorithm efficiently checks for the possibility of one edit by comparing the characters at corresponding indices and handling cases where the lengths of the strings are different.\n\n\tO(n) time | O(1) space - where n is the length of the shorter string\n\n\n*/\npackage main\n\nfunc OneEdit(stringOne string, stringTwo string) bool {\n    lengthOne := len(stringOne)\n    lengthTwo := len(stringTwo)\n\n    // Check the difference in lengths between the two strings.\n    // If the difference is greater than 1, it is not possible to make one edit to make them equal.\n    if abs(lengthOne - lengthTwo) > 1 {\n        return false\n    }\n\n    // Traverse the strings until the shorter one is fully traversed or an unequal character is found.\n    for i := 0; i < min(lengthOne, lengthTwo); i++ {\n        // If an unequal character is found, check the remaining portion of the strings to determine if they are still one edit away.\n        if stringOne[i] != stringTwo[i] {\n            // Check the remaining characters in the longer string compared to the remaining characters in the shorter string.\n            // Return true if they match, indicating they are one edit away.\n            if lengthOne > lengthTwo {\n                return stringOne[i+1:] == stringTwo[i:]\n            } else if lengthTwo > lengthOne {\n                return stringTwo[i+1:] == stringOne[i:]\n            } else {\n                return stringOne[i+1:] == stringTwo[i+1:]\n            }\n        }\n    }\n\n    // If the loop completes without finding any unequal characters, the strings are either identical or differ only in length by 1.\n    return true\n}\n\nfunc abs(a int) int {\n    if a < 0 {\n        return -a\n    }\n    return a\n}\n\nfunc min(a, b int) int {\n    if a < b {\n        return a\n    }\n    return b\n}\n"
  },
  {
    "path": "Strings/one_edit.java",
    "content": "/*\n    You're given two strings stringone and stringtwo. Write a function that determines if these\n\ttwo strings can be made equal using only one edit.\n\n\n    There are 3 possible edits:\n    Replace: One character in one string is swapped for a different character.\n    Add:: One character is added at any index in one string.\n    Remove: One character is removed at any index in one string.\n\n\tSample Input: StringOne: alaska StringTwo: aloska\n\tOutput: True\n\n\n\tExplanation:\n\tThe code snippet is implementing the \"One Edit Away\" algorithm, which determines whether two given\n\tstrings are one edit away from each other. An edit is defined as either inserting a character, removing a character, or replacing a character.\n\n\tThe `OneEdit` function takes two strings as input and returns a boolean indicating whether\n\tthey are one edit away. Here's the breakdown of the algorithm:\n\n\t1. Calculate the lengths of the two strings.\n\t2. Check if the difference in lengths is greater than 1. If so, return `false` because it's\n\t   not possible to make one edit to make the strings equal.\n\t3. Traverse both strings until the shorter one is fully traversed or an unequal character is\n\tfound.\n\t4. If an unequal character is found, check the remaining portion of the strings to determine\n\t   if they are still one edit away.\n\t5. Check the remaining characters in the longer string compared to the remaining characters\n\t   in the shorter string.\n\t6. Return `true` if the remaining portions match, indicating they are one edit away.\n\t7. If the loop completes without finding any unequal characters, the strings are either\n\t   identical or differ only in length by 1, which means they are one edit away.\n\t8. The `abs` and `min` functions are utility functions used to calculate the absolute value\n\t   and minimum of two integers, respectively.\n\n\tThe algorithm efficiently checks for the possibility of one edit by comparing the characters at corresponding indices and handling cases where the lengths of the strings are different.\n\n\tO(n) time | O(1) space - where n is the length of the shorter string\n\n\n*/\npublic class Main {\n    public static void main(String[] args) {\n        String stringOne = \"pale\";\n        String stringTwo = \"ple\";\n\n        // Check if the strings are one edit away\n        boolean isOneEdit = isOneEdit(stringOne, stringTwo);\n\n        // Print the result\n        System.out.println(\"The strings are\" + (isOneEdit ? \"\" : \" not\") + \" one edit away.\");\n    }\n\n    public static boolean isOneEdit(String stringOne, String stringTwo) {\n        int lengthOne = stringOne.length();\n        int lengthTwo = stringTwo.length();\n\n        // Check the difference in lengths between the two strings.\n        // If the difference is greater than 1, it is not possible to make one edit to make them equal.\n        if (Math.abs(lengthOne - lengthTwo) > 1) {\n            return false;\n        }\n\n        // Traverse the strings until the shorter one is fully traversed or an unequal character is found.\n        for (int i = 0; i < Math.min(lengthOne, lengthTwo); i++) {\n            // If an unequal character is found, check the remaining portion of the strings to determine if they are still one edit away.\n            if (stringOne.charAt(i) != stringTwo.charAt(i)) {\n                // Check the remaining characters in the longer string compared to the remaining characters in the shorter string.\n                // Return true if they match, indicating they are one edit away.\n                if (lengthOne > lengthTwo) {\n                    return stringOne.substring(i + 1).equals(stringTwo.substring(i));\n                } else if (lengthTwo > lengthOne) {\n                    return stringTwo.substring(i + 1).equals(stringOne.substring(i));\n                } else {\n                    return stringOne.substring(i + 1).equals(stringTwo.substring(i + 1));\n                }\n            }\n        }\n\n        // If the loop completes without finding any unequal characters, the strings are either identical or differ only in length by 1.\n        return true;\n    }\n}\n"
  },
  {
    "path": "Strings/one_edit.js",
    "content": "/*\n    You're given two strings stringone and stringtwo. Write a function that determines if these\n\ttwo strings can be made equal using only one edit.\n\n\n    There are 3 possible edits:\n    Replace: One character in one string is swapped for a different character.\n    Add:: One character is added at any index in one string.\n    Remove: One character is removed at any index in one string.\n\n\tSample Input: StringOne: alaska StringTwo: aloska\n\tOutput: True\n\n\n\tExplanation:\n\tThe code snippet is implementing the \"One Edit Away\" algorithm, which determines whether two given\n\tstrings are one edit away from each other. An edit is defined as either inserting a character, removing a character, or replacing a character.\n\n\tThe `OneEdit` function takes two strings as input and returns a boolean indicating whether\n\tthey are one edit away. Here's the breakdown of the algorithm:\n\n\t1. Calculate the lengths of the two strings.\n\t2. Check if the difference in lengths is greater than 1. If so, return `false` because it's\n\t   not possible to make one edit to make the strings equal.\n\t3. Traverse both strings until the shorter one is fully traversed or an unequal character is\n\tfound.\n\t4. If an unequal character is found, check the remaining portion of the strings to determine\n\t   if they are still one edit away.\n\t5. Check the remaining characters in the longer string compared to the remaining characters\n\t   in the shorter string.\n\t6. Return `true` if the remaining portions match, indicating they are one edit away.\n\t7. If the loop completes without finding any unequal characters, the strings are either\n\t   identical or differ only in length by 1, which means they are one edit away.\n\t8. The `abs` and `min` functions are utility functions used to calculate the absolute value\n\t   and minimum of two integers, respectively.\n\n\tThe algorithm efficiently checks for the possibility of one edit by comparing the characters at corresponding indices and handling cases where the lengths of the strings are different.\n\n\tO(n) time | O(1) space - where n is the length of the shorter string\n\n\n*/\nfunction isOneEdit(stringOne, stringTwo) {\n  const lengthOne = stringOne.length;\n  const lengthTwo = stringTwo.length;\n\n  // Check the difference in lengths between the two strings.\n  // If the difference is greater than 1, it is not possible to make one edit to make them equal.\n  if (Math.abs(lengthOne - lengthTwo) > 1) {\n    return false;\n  }\n\n  // Traverse the strings until the shorter one is fully traversed or an unequal character is found.\n  for (let i = 0; i < Math.min(lengthOne, lengthTwo); i++) {\n    // If an unequal character is found, check the remaining portion of the strings to determine if they are still one edit away.\n    if (stringOne[i] !== stringTwo[i]) {\n      // Check the remaining characters in the longer string compared to the remaining characters in the shorter string.\n      // Return true if they match, indicating they are one edit away.\n      if (lengthOne > lengthTwo) {\n        return stringOne.slice(i + 1) === stringTwo.slice(i);\n      } else if (lengthTwo > lengthOne) {\n        return stringTwo.slice(i + 1) === stringOne.slice(i);\n      } else {\n        return stringOne.slice(i + 1) === stringTwo.slice(i + 1);\n      }\n    }\n  }\n\n  // If the loop completes without finding any unequal characters, the strings are either identical or differ only in length by 1.\n  return true;\n}\n\nconst stringOne = \"pale\";\nconst stringTwo = \"ple\";\n\n// Check if the strings are one edit away\nconst isOneEdit = isOneEdit(stringOne, stringTwo);\n\n// Print the result\nconsole.log(`The strings are${isOneEdit ? \"\" : \" not\"} one edit away.`);\n"
  },
  {
    "path": "Strings/one_edit.py",
    "content": "'''\n    You're given two strings stringone and stringtwo. Write a function that determines if these\n\ttwo strings can be made equal using only one edit.\n\n\n    There are 3 possible edits:\n    Replace: One character in one string is swapped for a different character.\n    Add:: One character is added at any index in one string.\n    Remove: One character is removed at any index in one string.\n\n\tSample Input: StringOne: alaska StringTwo: aloska\n\tOutput: True\n\n\n\tExplanation:\n\tThe code snippet is implementing the \"One Edit Away\" algorithm, which determines whether two given\n\tstrings are one edit away from each other. An edit is defined as either inserting a character, removing a character, or replacing a character.\n\n\tThe `OneEdit` function takes two strings as input and returns a boolean indicating whether\n\tthey are one edit away. Here's the breakdown of the algorithm:\n\n\t1. Calculate the lengths of the two strings.\n\t2. Check if the difference in lengths is greater than 1. If so, return `false` because it's\n\t   not possible to make one edit to make the strings equal.\n\t3. Traverse both strings until the shorter one is fully traversed or an unequal character is\n\tfound.\n\t4. If an unequal character is found, check the remaining portion of the strings to determine\n\t   if they are still one edit away.\n\t5. Check the remaining characters in the longer string compared to the remaining characters\n\t   in the shorter string.\n\t6. Return `true` if the remaining portions match, indicating they are one edit away.\n\t7. If the loop completes without finding any unequal characters, the strings are either\n\t   identical or differ only in length by 1, which means they are one edit away.\n\t8. The `abs` and `min` functions are utility functions used to calculate the absolute value\n\t   and minimum of two integers, respectively.\n\n\tThe algorithm efficiently checks for the possibility of one edit by comparing the characters at corresponding indices and handling cases where the lengths of the strings are different.\n\n\tO(n) time | O(1) space - where n is the length of the shorter string\n\n'''\ndef OneEdit(stringOne, stringTwo):\n    lengthOne = len(stringOne)\n    lengthTwo = len(stringTwo)\n\n    # Check the difference in lengths between the two strings.\n    # If the difference is greater than 1, it is not possible to make one edit to make them equal.\n    if abs(lengthOne - lengthTwo) > 1:\n        return False\n\n    # Traverse the strings until the shorter one is fully traversed or an unequal character is found.\n    for i in range(min(lengthOne, lengthTwo)):\n        # If an unequal character is found, check the remaining portion of the strings to determine if they are still one edit away.\n        if stringOne[i] != stringTwo[i]:\n            # Check the remaining characters in the longer string compared to the remaining characters in the shorter string.\n            # Return True if they match, indicating they are one edit away.\n            if lengthOne > lengthTwo:\n                return stringOne[i+1:] == stringTwo[i:]\n            elif lengthTwo > lengthOne:\n                return stringTwo[i+1:] == stringOne[i:]\n            else:\n                return stringOne[i+1:] == stringTwo[i+1:]\n\n    # If the loop completes without finding any unequal characters, the strings are either identical or differ only in length by 1.\n    return True\n\ndef abs(a):\n    if a < 0:\n        return -a\n    return a\n\ndef min(a, b):\n    if a < b:\n        return a\n    return b\n"
  },
  {
    "path": "Strings/plaindrome_str.cpp",
    "content": "#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nbool isPalindrome(string s, int start, int end) {\n    while (start < end) {\n        if (s[start] != s[end]) {\n            return false;\n        }\n        start++;\n        end--;\n    }\n    return true;\n}\n\nvector<vector<string>> partitionPalindrome(string s) {\n    vector<vector<string>> result;\n    vector<string> current;\n\n    backtrack(s, 0, current, result);\n\n    return result;\n}\n\nvoid backtrack(string s, int start, vector<string>& current, vector<vector<string>>& result) {\n    if (start == s.length()) {\n        result.push_back(current);\n        return;\n    }\n\n    for (int end = start; end < s.length(); end++) {\n        if (isPalindrome(s, start, end)) {\n            current.push_back(s.substr(start, end - start + 1));\n            backtrack(s, end + 1, current, result);\n            current.pop_back();\n        }\n    }\n}\n\nint main() {\n    string s = \"aab\";\n    vector<vector<string>> partitions = partitionPalindrome(s);\n\n    for (auto partition : partitions) {\n        for (string palindrome : partition) {\n            cout << palindrome << \" \";\n        }\n        cout << endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "Strings/reverse_string.go",
    "content": "// Reverse a string\n// Program Author : Abhisek Kumar Gupta\n\npackage main\n\nimport \"fmt\"\n\nfunc reverse(s string) string {\n\t// since strings are immutable in go, we make array of runes\n\tchars := []rune(s)\n\t// swap start and end position characters\n\tfor i, j := 0, len(chars)-1; i < j; i, j = i+1, j-1 {\n\t\tchars[i], chars[j] = chars[j], chars[i]\n\t}\n\t// cast chars to string\n\treturn string(chars)\n}\n\nfunc main() {\n\tfmt.Printf(\"%v\\n\", reverse(\"abcdefg\"))\n}\n\n"
  },
  {
    "path": "Strings/reverse_words_in_a_string.cpp",
    "content": "/*\n\tGiven an input string s, reverse the order of the words.\n\tA word is defined as a sequence of non-space characters. The words in s will be separated by at least one space.\n\tReturn a string of the words in reverse order concatenated by a single space.\n\n\t[Note that s may contain leading or trailing spaces or multiple spaces between two words. The returned string should only have a single space separating the words. Do not include any extra spaces.]\n\t\n\n\tInput: s = \"the sky is blue\"\n\tOutput: \"blue is sky the\"\n\n\tInput: s = \"  hello world  \"\n\tOutput: \"world hello\"\n\n\tInput: s = \"a good   example\"\n\tOutput: \"example good a\"\n\t\n\tConstraints:\n\n\t> 1 <= s.length <= 104\n\t> s contains English letters (upper-case and lower-case), digits, and spaces ' '.\n\t> There is at least one word in s.\n \n*/\nclass Solution {\npublic:\n    string reverseWords(string s) {\n\t    //initialize the variables\n       string ans;\n        int i=0;\n       \n        while(i<s.length()){ //use the pointer to traverse the string\n           while(i<s.length() && s[i] == ' ') i++;\n            if(i>=s.length()) break; // if pointer exceeds the length of the string break!\n            int j=i+1; // initialize another pointer just ahead of i\n            while(j<s.length() && s[j] != ' ') j++;\n            string sub=s.substr(i,j-i); //find the individual substrings\n            if(ans.length() == 0) ans=sub;\n            else ans=sub + \" \" + ans; // concatenate the substrings in reverse\n            i=j+1;\n        }\n        return ans;\n    }\n};\n"
  },
  {
    "path": "Strings/reverse_words_in_a_string.go",
    "content": "/*\n\tGiven a sentence, reverse the order of its words without affecting the order of letters within a given word.\n*/\n// Time Complexity : O(n) n is length of string\n// Space complexity : O(n) as we used additional space to store the list of characters as strings are immutable in go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n)\n\n// reverseWords is our challenge function\nfunc reverseWords(sentence string) string {\n\t// We need to convert the input strings to lists of characters as strings are immutable in Go\n\tsentenceBytes := []byte(sentence)\n\n\t// To reverse all words in the string, we will first reverse the entire string.\n\tstrLen := len(sentenceBytes)\n\tsentenceBytes = strRev(sentenceBytes, 0, strLen-1)\n\tstrLen = len(sentenceBytes)\n\t// Now all the words are in the desired location, but\n\t// in reverse order: \"Hello World\" -> \"dlroW olleH\".\n\n\t// Now, let's iterate the sentence and reverse each word in place.\n\t// \"dlroW olleH\" -> \"World Hello\"\n\tstart, end := 0, 0\n\n\tfor {\n\t\t// find the start index of each word by detecting spaces.\n\t\tfor start < len(sentenceBytes) && sentenceBytes[start] == ' ' {\n\t\t\tstart += 1\n\t\t}\n\t\tif start == strLen {\n\t\t\tbreak\n\t\t}\n\n\t\t// Find the end index of the word.\n\t\tend = start + 1\n\t\tfor end < strLen && sentenceBytes[end] != ' ' {\n\t\t\tend += 1\n\t\t}\n\t\t\n\t\t// Let's call our helper function to reverse the word in-place.\n\t\tsentenceBytes = strRev(sentenceBytes, start, end-1)\n\t\tstart = end\n\t}\n\treturn string(sentenceBytes)\n}\n\n// strRev function that reverses a whole sentence character by character\nfunc strRev(str []byte, startRev int, endRev int) []byte {\n\t// Starting from the two ends of the list, and moving\n\t// in towards the centre of the string, swap the characters\n\tfor startRev < endRev {\n\t\ttemp := str[startRev] // temp store for swapping\n\t\tstr[startRev] = str[endRev] // swap step 1\n\t\tstr[endRev] = temp        // swap step 2\n\n\t\tstartRev += 1 // move forwards towards the middle\n\t\tendRev -= 1   // move backwards towards the middle\n\t}\n\n\t// Removing multiple spaces\n\t// Removing multiple spaces\n\ti := 0\n    j := len(str) - 1\n    strRes := make([]byte, 0)\n    for {\n        if str[i] != ' ' {\n            break\n        }\n\t\ti++\n    }\n    for {\n        if str[j] != ' ' {\n            break\n        }\n\t\tj--\n    }\n    for i <= j {\n        if str[i] == ' ' && strRes[len(strRes)-1] != ' ' {\n            strRes = append(strRes, str[i])\n        } else if str[i] != ' ' {\n            strRes = append(strRes, str[i])\n        }\n        i++\n    }\n\n\t// Returning the reversed sentence\n\treturn strRes\n}\n\n// Driver code\nfunc main() {\n\tstringToReverse := []string{\"Hello World!\", \"We love Python.\", \"The quick brown fox jumped over the lazy dog.\", \"Hey!\", \"To be, or not to be\", \"AAAAA\", \"Hello     World\"}\n\n\tfor i, str := range stringToReverse {\n\t\tfmt.Printf(\"%d.\\tActual string:      \\\"%s\\\"\\n\", i+1, str)\n\t\tfmt.Printf(\"\\tReversed string:    \\\"%s\\\"\\n\", reverseWords(str))\n\t\tfmt.Printf(\"%s\\n\", strings.Repeat(\"-\", 100))\n\t}\n\tfmt.Printf(\"%s\\n\", strings.Repeat(\"*\", 100))\n\tfor i, str := range stringToReverse {\n\t\tfmt.Printf(\"%d.\\tActual string:      \\\"%s\\\"\\n\", i+1, str)\n\t\tfmt.Printf(\"\\tReversed string:    \\\"%s\\\"\\n\", ReverseWordsNew(str))\n\t\tfmt.Printf(\"%s\\n\", strings.Repeat(\"-\", 100))\n\t}\n}\n\n// Using regexp and strings library\n\nfunc ReverseWordsNew(s string) string {\n    // trim leading and multiple spaces\n    trimmedString := trimHelper(s)\n    // convert string into array bytes since strings are immutable in go\n    sBytes := []byte(trimmedString)\n    // reverse the entire sBytes first\n    strlen := len(sBytes)\n    reversedString := revHelper(sBytes, 0, strlen - 1)\n    \n    // this way words will be in desired position \n\n    start, end := 0, 0\n    for {\n        for start < strlen && reversedString[start] == ' ' {\n            start += 1;\n        }\n        if start == strlen {\n            break\n        }\n        end = start + 1\n        for end < strlen && reversedString[end] != ' ' {\n            end += 1\n        }\n        reversedString = revHelper(reversedString, start, end - 1)\n        start = end\n    }\n    return string(reversedString)\n}\n\nfunc trimHelper(s string) string {\n    result := strings.TrimSpace(s)\n    regex := regexp.MustCompile(\"\\\\s+\")\n    result = regex.ReplaceAllString(result, \" \")\n    return result\n}\n\nfunc revHelper(s []byte, start int, end int) []byte {\n    for start < end {\n        s[start], s[end] = s[end], s[start]\n        start += 1\n        end -= 1\n    }\n    return s\n}"
  },
  {
    "path": "Strings/reverse_words_in_a_string.js",
    "content": "/// Problem Statement:\n/// You are given a string of length N. You need to reverse the string word by word. There can be multiple spaces between two words and there can be leading or trailing spaces but, in the output, reversed string you need to put a single space between two words, and your reversed string should not contain leading or trailing spaces.\n\n/// Sample Input:   You need to     reverse the  string       word    by  word\n/// Expected Output: word by word string the reverse to need You\n\n/// Decalaration of function which will receive string to reverese\nfunction reverseString(inputString) {\n    /// Trim function removes all the leading and trailing spaces, Split method store them in the array inputStringArray\n    var trimmedString = inputString.trim();\n    var inputStringArray = trimmedString.split(\" \");\n\n    /// Variable declaration to store the output result\n    var outputString = \"\";\n\n    /// Loop through the array in reverse order to reverse the string, subtracting -1 from length because length starts from 1 but index strats from 0\n    for (i = inputStringArray.length - 1; i >= 0; i--) {\n        /// If its a first iteration then store the word in variable otherwise concatenate it with the current string\n        if (inputStringArray[i] == \"\") {\n            continue;\n        } else {\n            outputString += inputStringArray[i] + \" \";\n        }\n    }\n    return outputString.trim();\n}\n\n// console.log(\"You are given a string of length N\");\n// console.log(reverseString(\"You are given a string of length N\"));\n\nconsole.log(\"  You need to     reverse the  string       word    by  word  \");\nconsole.log(\n    reverseString(\n        \"  You need to     reverse the  string       word    by  word  \"\n    )\n);\n"
  },
  {
    "path": "Strings/reverse_words_in_string.java",
    "content": "/**\n * Given an input string s, reverse the order of the words.\n *\n * A word is defined as a sequence of non-space characters. The words in s will be separated by at least one space.\n *\n * Return a string of the words in reverse order concatenated by a single space.\n *\n * Note that s may contain leading or trailing spaces or multiple spaces between two words. The returned string should only have a single space separating the words. Do not include any extra spaces.\n *\n *\n *\n * Example 1:\n *\n * Input: s = \"the sky is blue\"\n * Output: \"blue is sky the\"\n * Example 2:\n *\n * Input: s = \"  hello world  \"\n * Output: \"world hello\"\n * Explanation: Your reversed string should not contain leading or trailing spaces.\n */\n\npackage Strings;\n\npublic class ReverseWordsInString {\n    public static void main(String[] args) {\n        String string = \"the sky is blue\";\n\n        String res = solve(string);\n        System.out.println(res);\n    }\n    public static String solve(String string) {\n        // O(N) time | O(N) - where N is the length of the array.\n\n        //Convert String to String Builder\n        //and trim spaces at the same time\n        StringBuilder stringBuilder = trimSpaces(string);\n\n        System.out.println(string);\n\n        //reverse the whole word\n        reverse(stringBuilder, 0, stringBuilder.length() - 1);\n        System.out.println(stringBuilder);\n\n        //reverse each word\n        reverseEachWord(stringBuilder);\n        System.out.println(stringBuilder);\n\n        return stringBuilder.toString();\n    }\n\n    public static StringBuilder trimSpaces(String string) {\n        int leftIdx = 0, rightIdx = string.length() - 1;\n\n        // remove leading spaces\n        while (leftIdx <= rightIdx && string.charAt(leftIdx) == ' ') ++leftIdx;\n\n        // remove trailing spaces\n        while (leftIdx <= rightIdx && string.charAt(rightIdx) == ' ') --rightIdx;\n\n        // reduce multiple spaces to single one\n        StringBuilder stringBuilder = new StringBuilder();\n        while (leftIdx <= rightIdx) {\n            char currentChar = string.charAt(leftIdx);\n\n            if (currentChar != ' ') stringBuilder.append(currentChar);\n            else if (stringBuilder.charAt(stringBuilder.length() - 1) != ' ') stringBuilder.append(currentChar);\n\n            ++leftIdx;\n        }\n        return stringBuilder;\n    }\n\n    public static void reverse(StringBuilder stringBuilder, int leftIdx, int rightIdx) {\n        while (leftIdx < rightIdx) {\n            char temp = stringBuilder.charAt(leftIdx);\n            stringBuilder.setCharAt(leftIdx++, stringBuilder.charAt(rightIdx));\n            stringBuilder.setCharAt(rightIdx--, temp);\n        }\n    }\n    public static void reverseEachWord(StringBuilder stringBuilder) {\n        int len = stringBuilder.length();\n        int startIdx = 0, endIdx = 0;\n\n        while (startIdx < len) {\n            // go to the end of the word\n            while (endIdx < len && stringBuilder.charAt(endIdx) != ' ') ++endIdx;\n            // reverse the word\n            reverse(stringBuilder, startIdx, endIdx - 1);\n            // move to the next word\n            startIdx = endIdx + 1;\n            ++endIdx;\n       }\n    }\n\n}\n\n"
  },
  {
    "path": "Strings/valid_palindrome.js",
    "content": "/*Name : Abhinav kumar\nGithub username : Abhinavcode13\nRepository name : data-structures-and-algorithms\nProblem :Two Pointers: Check whether a given string is a Valid Palindrome in Javascript\nIssue Number : #649\nProblem statement : \n\nExplanation of the below Java code :\n\nwe first define the isPalindrome() function, which converts the input string to lowercase and removes all non-alphanumeric characters using a regular expression, and then uses two pointers to loop through the string and check whether it is a valid palindrome.\n\nWe then use the prompt() function to display a popup dialog box and prompt the user to enter a string input. The input value is then stored in the str variable.\n\nWe then call the isPalindrome() function with the input string as an argument to check whether it is a palindrome. If it is, we use the console.log() function to display a message saying that the input string is a palindrome. If it is not, we display a message saying that the input string is not a palindrome.\n\n\n\n*/\n\n-------------------------------------------------------------------------------------------------------//Java code begins here-------------------------------------------------------------------------------------------------------------------------------\n\nfunction isPalindrome(str) {\n  // Convert the input string to lowercase and remove non-alphanumeric characters\n  str = str.toLowerCase().replace(/[^a-z0-9]/g, '');\n\n  // Initialize two pointers, one starting from the beginning of the string, and the other from the end\n  let left = 0;\n  let right = str.length - 1;\n\n  // Loop through the string while the pointers haven't crossed each other\n  while (left < right) {\n    // If the characters at the left and right pointers don't match, the string is not a palindrome\n    if (str[left] !== str[right]) {\n      return false;\n    }\n\n    // Move the pointers towards each other\n    left++;\n    right--;\n  }\n\n  // If the loop finishes, the string is a palindrome\n  return true;\n}\n\n// Prompt the user for a string input\nlet str = prompt(\"Enter a string:\");\n\n// Check whether the input string is a palindrome\nif (isPalindrome(str)) {\n  console.log(`${str} is a palindrome!`);\n} else {\n  console.log(`${str} is not a palindrome.`);\n}\n"
  },
  {
    "path": "Strings/valid_pallindrome2.cpp",
    "content": "// Check whether a string can be a valid palindrome by removing at most one character from it\n/*\n    Write a function that takes a string as input and checks whether it can be a valid palindrome by removing at most one character from it.\n\n    Constraints: string.length The string only consists of English letters\n\n    Sample Input : \"madame\"\n    Output : True\n\n    Sample Input : \"masdasd\"\n    Output : False\t\n*/\nclass Solution {\npublic:\n    bool validate(string s, int start, int end){\n        int len = s.size();\n        while(start < end){\n            if(s[start] == s[end]){\n                start++;\n                end--;\n            }\n            // doesn't match then return false\n            else{\n                return false;\n            }\n        }\n        return true;\n    }\n    bool validPalindrome(string s) {\n        int len = s.size();\n        // initialize two pointers at opposite end of string\n        int start = 0, end = len - 1;\n        while(start < end){\n            // if value at left and right index match then move them closer\n            if(s[start] == s[end]){\n                start++;\n                end--;\n            }\n            else{ // if mismatch occurs then skip one and check rest\n                bool r1 = validate(s, start + 1, end); // skip one from left and check remaining\n                bool r2 = validate(s, start, end -1); // skip one from right and check remaining\n                return r1 || r2; // if either is true return true\n            }   \n        }\n        return true; \n    }\n};"
  },
  {
    "path": "Strings/valid_pallindrome2.go",
    "content": "// Check whether a string can be a valid palindrome by removing at most one character from it\n/*\n   The given Go program takes a string as input and checks if it can be a valid palindrome by removing at most one\n   character from it. The program starts by defining two pointers, left and right, that move towards each other from\n   opposite ends of the input string. At each step, if the characters at the left and right pointers are equal,\n   then they move towards the center of the string. If the characters are not equal, then we check whether removing\n   the character at the left or right pointer would make the rest of the string a palindrome. If both removals fail,\n   then the string cannot be a valid palindrome by removing at most one character. The program returns true\n   if the string can be made a valid palindrome by removing at most one character, false otherwise.\n\n  The time complexity of this algorithm is O(n), where n is the length of the input string.\n  The space complexity is O(1), as we only use constant extra space to store a few variables.\n\n*/\npackage main\n\n// isPalindromeWithRemoval checks if a string can be converted into a palindrome\n// by removing at most one character\nfunc isPalindromeWithRemoval(s string) bool {\n  // Define two pointers to check the string from both ends\n  i, j := 0, len(s)-1\n  \n  for i < j {\n      // If characters at the pointers are not equal\n      if s[i] != s[j] {\n          // Check if removing a character from the left pointer makes it a palindrome\n          leftStr := s[:i] + s[i+1:j+1]\n          if isPalindrome(leftStr) {\n              return true\n          }\n          // Check if removing a character from the right pointer makes it a palindrome\n          rightStr := s[:i] + s[i:j]\n          if isPalindrome(rightStr) {\n              return true\n          }\n          // If neither option works, it cannot be converted into a palindrome by removing at most one character\n          return false\n      }\n      // Move the pointers towards the middle of the string\n      i++\n      j--\n  }\n  return true\n}\n\n// isPalindrome checks if a string is a palindrome\nfunc isPalindrome(s string) bool {\n  // Define two pointers to check the string from both ends\n  i, j := 0, len(s)-1\n  \n  for i < j {\n      // If characters at the pointers are not equal, it is not a palindrome\n      if s[i] != s[j] {\n          return false\n      }\n      // Move the pointers towards the middle of the string\n      i++\n      j--\n  }\n  return true\n}\n"
  },
  {
    "path": "Strings/valid_pallindrome2.java",
    "content": "// Check whether a string can be a valid palindrome by removing at most one character from it\n/*\n   The given Go program takes a string as input and checks if it can be a valid palindrome by removing at most one\n   character from it. The program starts by defining two pointers, left and right, that move towards each other from\n   opposite ends of the input string. At each step, if the characters at the left and right pointers are equal,\n   then they move towards the center of the string. If the characters are not equal, then we check whether removing\n   the character at the left or right pointer would make the rest of the string a palindrome. If both removals fail,\n   then the string cannot be a valid palindrome by removing at most one character. The program returns true\n   if the string can be made a valid palindrome by removing at most one character, false otherwise.\n\n  The time complexity of this algorithm is O(n), where n is the length of the input string.\n  The space complexity is O(1), as we only use constant extra space to store a few variables.\n\n*/\npublic static boolean isPalindromeWithRemoval(String s) {\n  // Define two pointers to check the string from both ends\n  int i = 0, j = s.length() - 1;\n\n  while (i < j) {\n    // If characters at the pointers are not equal\n    if (s.charAt(i) != s.charAt(j)) {\n      // Check if removing a character from the left pointer makes it a palindrome\n      String leftStr = s.substring(0, i) + s.substring(i + 1);\n      if (isPalindrome(leftStr)) {\n        return true;\n      }\n      // Check if removing a character from the right pointer makes it a palindrome\n      String rightStr = s.substring(0, j) + s.substring(j + 1);\n      if (isPalindrome(rightStr)) {\n        return true;\n      }\n      // If neither option works, it cannot be converted into a palindrome by removing at most one character\n      return false;\n    }\n    // Move the pointers towards the middle of the string\n    i++;\n    j--;\n  }\n  return true;\n}\n\npublic static boolean isPalindrome(String s) {\n  // Define two pointers to check the string from both ends\n  int i = 0, j = s.length() - 1;\n\n  while (i < j) {\n    // If characters at the pointers are not equal, it is not a palindrome\n    if (s.charAt(i) != s.charAt(j)) {\n      return false;\n    }\n    // Move the pointers towards the middle of the string\n    i++;\n    j--;\n  }\n  return true;\n}\n"
  },
  {
    "path": "Strings/valid_pallindrome2.js",
    "content": "//  Check whether a string can be a valid palindrome by removing at most one character from it\n/*\n    The validPalindrome function takes a string s as input and returns true if the string can be a valid palindrome by removing \n    at most one character, and false otherwise. It works by initializing two pointers left and right to the left and right ends \n    of the string, respectively. It then moves the pointers inward while checking if the characters at the left and right indices \n    are equal. If they are not equal, it removes the left or right character, creates a new string, and checks if the new string \n    is a palindrome using the isPalindrome helper function. If the new string is a palindrome, it returns true. If not, it \n    continues moving the pointers inward and repeating the process. If the pointers meet, the string is already a palindrome, \n    or it can be made into one by removing at most one character, so it returns true.\n\n    The isPalindrome function takes a string s as input and returns true if the string is a palindrome, and false otherwise. \n    It works by initializing two pointers left and right to the left and right ends of the string, respectively. It then moves \n    the pointers inward while checking if the characters at the\n\n    Time complexity: O(n) : We iterate over the input string once with two pointers, which takes O(n) time.\n    Space complexity: O(1) : We only use a few constant amount of variables to keep track of the pointers, left and right. \n    Therefore, the space complexity is O(1).\n*/\n/**\n * Checks whether a string can be a valid palindrome by removing at most one character.\n * @param {string} s - The input string to check.\n * @return {boolean} - Returns true if the string can be a valid palindrome, false otherwise.\n */\nfunction validPalindrome(s) {\n  let left = 0; // Pointer to the left end of the string.\n  let right = s.length - 1; // Pointer to the right end of the string.\n\n  while (left < right) {\n    if (s[left] !== s[right]) {\n      // If characters at left and right indices are not equal.\n      // Check if string without left index is a palindrome.\n      let str1 = s.slice(0, left) + s.slice(left + 1);\n      if (isPalindrome(str1)) {\n        return true;\n      }\n      // Check if string without right index is a palindrome.\n      let str2 = s.slice(0, right) + s.slice(right + 1);\n      if (isPalindrome(str2)) {\n        return true;\n      }\n      // If string without left or right index is not a palindrome, return false.\n      return false;\n    }\n    // Move pointers inward if characters at left and right indices are equal.\n    left++;\n    right--;\n  }\n\n  // If we get here, the string is already a palindrome, or it can be made into one\n  // by removing at most one character, so return true.\n  return true;\n}\n\n/**\n * Checks whether a string is a palindrome.\n * @param {string} s - The input string to check.\n * @return {boolean} - Returns true if the string is a palindrome, false otherwise.\n */\nfunction isPalindrome(s) {\n  let left = 0; // Pointer to the left end of the string.\n  let right = s.length - 1; // Pointer to the right end of the string.\n\n  while (left < right) {\n    if (s[left] !== s[right]) {\n      // If characters at left and right indices are not equal, return false.\n      return false;\n    }\n    // Move pointers inward if characters at left and right indices are equal.\n    left++;\n    right--;\n  }\n\n  // If we get here, the string is a palindrome, so return true.\n  return true;\n}\n"
  },
  {
    "path": "Strings/valid_pallindrome2.py",
    "content": "// Check whether a string can be a valid palindrome by removing at most one character from it\n'''\n    Explanation:\n    The function valid_palindrome takes a string s as input and returns a boolean indicating whether the \n    string can be a valid palindrome by removing at most one character from it.\n\n    To check if the string can be a valid palindrome, we start by iterating over the string from both the \n    left and right ends at the same time. If we encounter two characters that are not the same, we need to \n    check if removing one of them would make the string a palindrome. We try removing the left character \n    first and create two new substrings - one with the left character removed and one with the right character removed.\n    We then check if either of the substrings is a palindrome. If either of the substrings is a palindrome, \n    then the original string can be a palindrome by removing the corresponding character. If neither of \n    the substrings is a palindrome, then the original string cannot be a palindrome even by removing a character.\n\n    If we have checked the whole string and haven't returned yet, it means that the original string is a palindrome.\n\n    The time complexity of the given function is O(n), where n is the length of the input string. \n    This is because we are iterating through the string only once and performing constant-time operations.\n\n    The space complexity of the function is also O(n), where n is the length of the input string. \n    This is because we are using a constant amount of extra space to keep track of the counts of characters. \n    The size of this extra space does not depend on the length of the input string.\n'''\n# using two-pointer Technique\ndef valid_palindrome(s: str) -> bool:\n    left, right = 0, len(s) - 1\n    \n    # iterate over the string from left and right at the same time\n    while left < right:\n        # if the characters at the left and right indices are not the same\n        if s[left] != s[right]:\n            # we need to check if removing one of them makes the string a palindrome\n            # we try removing the left character first\n            left_removed = s[left:right]\n            right_removed = s[left+1:right+1]\n            # if either of the substrings after removal is a palindrome, then the original string is also a palindrome\n            return left_removed == left_removed[::-1] or right_removed == right_removed[::-1]\n        \n        # move to the next pair of characters\n        left += 1\n        right -= 1\n    \n    # if we have checked the whole string and haven't returned yet, it's a palindrome\n    return True\n"
  },
  {
    "path": "Strings/well_formed_parentheses.cpp",
    "content": "/*\n    Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.\n\n    Example 1:\n    Input: n = 3\n    Output: [\"((()))\",\"(()())\",\"(())()\",\"()(())\",\"()()()\"]\n    \n    Example 2:\n    Input: n = 1\n    Output: [\"()\"]\n    \n    Constraints: 1 <= n <= 8\n*/ \n#include<bits/stdc++.h>\nclass Solution {\npublic:\nvector<string> ans;\nint N;\n    void solve(string s,int count)\n    {\n        if(s.size()==2*N)\n        ans.push_back(s);\n\n        if(count<N)\n        solve(s.push_back('('),count+1);\n        else\n        solve(s.push_back(')'),count);\n    }\n    vector<string> generateParenthesis(int n) {\n        string st;\n        solve(st,0);\n        return ans;\n    }\n};"
  },
  {
    "path": "Strings/well_formed_parentheses.java",
    "content": "/**\n\n   Time Complexity: O(2^n * n), Space Complexity: O(n).\n\n   Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.\n\n   Example 1:\n   Input: n = 3\n   Output: [\"((()))\",\"(()())\",\"(())()\",\"()(())\",\"()()()\"]\n\n\n   Example 2:\n   Input: n = 1\n   Output: [\"()\"]\n\n\n   Constraints:\n\n      1 <= n <= 8\n\n\n**/\n\n\nclass Solution {\n\n\n    public List<String> generateParenthesis(int n) {\n\n        ArrayList<String> validParenthesis = new ArrayList<String>();\n\t/**\n           We need to generate every n pair valid parenthses.\n\n           What we are going to do is try every possible combination\n           if we have a 2 pair parenthes p: ????\n           each question mark could be '(' or ')'.\n           ex: ()() or (()) or ((()\n           so we have a total of (2 ^ (2 * n)) combination.\n\n           if we say that an open bracket '(' can be expressed as 0\n           and a closed bracket ')' can be expressed 1.\n\n           0000 -> ((((\n           0001 -> ((()\n           0010 -> (()(\n           0011 -> (())\n           0100 -> ()((\n           0101 -> ()()\n            .\n            .\n            .\n            .\n            .\n           1111 -> ))))\n\n        **/\n        for (int i = 0; i < (1 << (2 * n)); ++i)\n    \t{\n\t    String aParenthesis = \"\";\n\t    for(int j = 0; j < 2 * n; ++j)\n\t    {\n\t\tif(((i >> j) & 1) == 1)\n\t\t{\n\t\t    aParenthesis += '(';\n\t\t}\n\t\telse\n\t\t    aParenthesis += ')';\n\t    }\n    \t    if(isValid(aParenthesis))\n    \t\tvalidParenthesis.add(aParenthesis);\n    \t}\n\n    \treturn validParenthesis;\n    }\n\n\n    /**\n        Function: isValid check if parenthesis is balanced or not.\n\n\n        For each open bracket we find we pushed it to the stack.\n\n        If We find a closed bracket we check the top of the stack\n           if it is an open bracket that's mean we find a corrsponding closing bracket so, we removed it.\n\n           else the top of the stack is a closed bracket that means there is no open bracket that matches that closed bracket,\n           that's means the parenthesis is NOT valid or balanced so, we return false.\n\n\n           At the end if we find that the stack is empty that's mean that each open breack has a  corrsponding closed bracket,\n           so, we return true otherwise we return false.\n    **/\n\n    public boolean isValid(String s) {\n\n        int n = s.length();\n\tStack<Character> st = new Stack<Character>();\n\n        for(int i = 0; i < n; ++i)\n\t{\n            char ch = s.charAt(i);\n\t    if( ch == '(')\n\t    {\n\t\tst.push(ch);\n\t    }\n\t    else\n\t    {\n\t        if(!st.empty() && st.peek() == '(')\n\t\t    st.pop();\n\t        else\n                    return false;\n\t    }\n\t}\n\n\treturn st.empty();\n    }\n}\n"
  },
  {
    "path": "Strings/zigzag_conversion.cpp",
    "content": "/*\n    The string \"PAYPALISHIRING\" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)\n    P   A   H   N\n    A P L S I I G\n    Y   I   R\n    And then read line by line: \"PAHNAPLSIIGYIR\"\n\n    Write the code that will take a string and make this conversion given a number of rows:\n    string convert(string s, int numRows);\n    \n    Example 1:\n    Input: s = \"PAYPALISHIRING\", numRows = 3\n    Output: \"PAHNAPLSIIGYIR\"\n    \n    Example 2:\n    Input: s = \"PAYPALISHIRING\", numRows = 4\n    Output: \"PINALSIGYAHRPI\"\n    Explanation:\n    P     I    N\n    A   L S  I G\n    Y A   H R\n    P     I\n    \n    Example 3:\n    Input: s = \"A\", numRows = 1\n    Output: \"A\"\n    \n    Constraints:\\\n    1 <= s.length <= 1000\n    s consists of English letters (lower-case and upper-case), ',' and '.'.\n    1 <= numRows <= 1000\n*/\n\n#include<bits/stdc++.h>\nclass Solution {\npublic:\n    string convert(string s, int numRows) {\n        if(numRows <= 1) return s;\n        string *A = new string[numRows];\n        int n = s.size();\n        int row = 0;\n        int step = 1;\n        for(int i = 0; i < n; i++){\n            A[row].push_back(s[i]);\n            if(row == 0) step = 1;\n            else if(row == numRows - 1) step = -1;\n            \n            row = row + step;\n        }\n        string ans = \"\";\n        for(int i = 0; i < numRows; i++){\n            ans += A[i];\n        }\n        return ans;\n    }\n};"
  },
  {
    "path": "Trees/AVL/avl.go",
    "content": "package main\n\n/*\n\tA binary tree is said to be an AVL tree, if:\n\t\t1 It is a binary search tree, and\n\t\t2 For any node N, the height of left subtree of N and height of right subtree of N differ by at most 1.\n*/\ntype AVLTreeNode struct {\n\tdata   int\n\tleft   *AVLTreeNode\n\tright  *AVLTreeNode\n\theight int\n}\n\n// Height: returns the height of AVL tree\n// Time Complexity: O(1)\nfunc Height(node *AVLTreeNode) int {\n\tif node == nil {\n\t\treturn -1\n\t} else {\n\t\treturn node.height\n\t}\n}\n\n// SingleLeftRotate: left rotate a root, and update node's height, return the new root\n// Time Complexity: O(1). Space Complexity: O(1).\nfunc SingleLeftRotate(X *AVLTreeNode) *AVLTreeNode {\n\tvar W *AVLTreeNode\n\tif X != nil {\n\t\tW = X.left\n\t\tX.left = W.right\n\t\tW.right = X\n\n\t\tX.height = Max(Height(X.left), Height(X.right)) + 1\n\t\tW.height = Max(Height(W.left), Height(W.right)) + 1\n\t\tX = W\n\t}\n\treturn X\n}\n\n// SingleRightRotate: right rotate a root, and update node's height, return the new root\n// Time Complexity: O(1). Space Complexity: O(1).\nfunc SingleRightRotate(X *AVLTreeNode) *AVLTreeNode {\n\tvar W *AVLTreeNode\n\tif X != nil {\n\t\tW = X.right\n\t\tX.right = W.right\n\t\tW.left = X\n\n\t\tX.height = Max(Height(X.left), Height(X.right)) + 1\n\t\tW.height = Max(Height(W.left), Height(W.right)) + 1\n\t\tX = W\n\t}\n\treturn X\n}\n// DoubleRotateRightLeft: left-right double rotation\nfunc DoubleRotateRightLeft(Z *AVLTreeNode) *AVLTreeNode {\n\tZ.right = SingleLeftRotate(Z.right)\n\treturn SingleRightRotate(Z)\n}\n\n// DoubleRotateLeftRight: right-left double rotation\nfunc DoubleRotateLeftRight(Z *AVLTreeNode) *AVLTreeNode {\n\tZ.left = SingleRightRotate(Z.left)\n\treturn SingleLeftRotate(Z)\n}\n\nfunc main() {\n\n}"
  },
  {
    "path": "Trees/Binary Search Trees/Kth_Largest_Value_In_BST.py",
    "content": "# Name : Manmay Ghosh\n# Github username : ManmayGhosh\n# Repository name : data-structures-and-algorithms\n# Problem :  Kth Largest Value In BST in Python\n# Issue Number : #1225\n\n# Explanation of the below Python code :\n\n# 1. The idea is to do reverse inorder traversal of BST. Keep a count of nodes visited.\n# 2. The reverse inorder traversal traverses all nodes in decreasing order, i.e, visit the right node then centre then left and continue traversing the nodes recursively.\n# 3. While doing the traversal, keep track of the count of nodes visited so far.\n# 4. When the count becomes equal to k, stop the traversal and print the key.\n\n# -------------------------------------------------------------------------//Python code begins here------------------------------------------------------------------------\n\nclass Node:\n\t# Constructor to create a new node\n\tdef __init__(self, val):\n\t\tself.key = val\n\t\tself.left = None\n\t\tself.right = None\n\t\t\n# This function will find k'th largest element in a tree.\ndef kthLargestUtil(root, k, c):\n\t\n\t# Base cases, c[0] >= k is important to avoid unnecessary recursive calls\n\tif root == None or c[0] >= k:\n\t\treturn\n\n\t# Follow reverse inorder traversal so that the largest element is visited first\n\tkthLargestUtil(root.right, k, c)\n\n\t# Increment count of visited nodes\n\tc[0] += 1\n\n\t# If c becomes k now, then this is the k'th largest\n\tif c[0] == k:\n\t\tprint(\"K'th largest element is\",root.key)\n\t\treturn\n\n\t# Recurssion for left subtree\n\tkthLargestUtil(root.left, k, c)\n\n\n# Function to find k'th largest element\ndef kthLargest(root, k):\n\t\n\t# Initialize count of nodes visited as 0\n\tc = [0]\n\n\t# Note that c is passed by reference\n\tkthLargestUtil(root, k, c)\n\n\n# Function to insert a new node in BST */\ndef insert(node, key):\n\t\n\tif node == None:\n\t\treturn Node(key)\n\n\tif key < node.key:\n\t\tnode.left = insert(node.left, key)\n\telif key > node.key:\n\t\tnode.right = insert(node.right, key)\n\n\treturn node\n\n# Driver Code\nif __name__ == '__main__':\n    root = None\n    root = insert(root, 50)\n    insert(root, 30)\n    insert(root, 20)\n    insert(root, 40)\n    insert(root, 70)\n    insert(root, 60)\n    insert(root, 80)\n    k = int(input(\"Enter the Kth element(should be greater than 1)\"))\n    kthLargest(root, k)\n\n\t\n\t\t\n  \n# Complexity Analysis:  \n# Time Complexity: O(n). \n# In worst case the code can traverse each and every node of the tree if the k given is equal to n (total number of nodes in the tree). Therefore overall time complexity is O(n).\n# Auxiliary Space: O(h). \n# Max recursion stack of height h at a given time.\n"
  },
  {
    "path": "Trees/Binary Search Trees/Kth_largest_BST.cpp",
    "content": "/*TASK\n Binary Search Tree : Get kth largest element in a BST\n A BST is a tree structure that is sorted by the nodes' data. \n Following rules are true for every picked node in a BST:\n -> all nodes to the left have data that is less than the data of the picked node\n -> all nodes to the right have data that is greater than the the data of the picked node\n -> all nodes have 2 children (left and right), but they can be empty (null) too.\n*/\n\n/*SAMPLE DATA\n Take a look on the following BST\n             3\n        2         7\n    1           5   9\n              4\n\n For k = 3, we should get 5 as an output, because 5 is the 3. largest element in the BST\n*/\n\n/*APPROACH\n an recursive algorithm that is going to get to the nodes in descending order.\n the visited nodes get appended to an array and if the kth node is visited the recursion will be left\n 1. start with the root node of a BST\n 2. for each node that is reached, do the first that is possible from the following:\n    \"if possible\" means that the node has a valid child in that direction that is not already visited\n    1. go to the right if possible to get to the far right node which also has the largest data\n    2. go to the left if possible to get larger data than going back \n        (If the algorithm goes back from the current node, all right nodes will be already visted, that means that we will land on a lower data node)\n    3. go back\n    \n    If we cannot do 1. we save this node as visited.\n    The kth visited node is also the kth largest.\n    if this node is reached it is getting saved in a class member variable.\n    In each recursion call this variable gets checked. If the node is set (we already found the kth largest node), \n        the recursion step returns before doing anything.\n    that is how the programm will get out of the recursion fast after finding the target node.\n3. if the member variable is set, that is the kth largest node, if its empty there is no kth largest node (out of range)\n\nSAMPLE\n    1. first we start with the root 3\n    2. we can go right, so we will do so (node 7)\n    3. we can go right (node 9)\n    4. we cannot go right, we save this in a visited node list (node 9, list 9)\n    5. we cannot go left, we go back (node 7)\n    6. we cannot go right, because 9 is already visited, we save this in visited nodes (node 7, list 9,7)\n    7. we can go left (node 5)\n    8. we cannot go right, we save this in visited nodes (node 5, list 9,7,5)\n    9. the list's size is equal to k, we will set the member variable to the last saved node 5 (node 5, list 9,7,5, member 5)\n    10. we have a member set, we go back (node 7)\n    11. we have a member set, we go back (node 3)\n    12. we have a member set, we go back (leaving recursion)\n    13. member variable holds 5, which is the 3. largest number in the BST\n*/\n\n/*COMPLEXITY\n    the algorithm has to go to the far right in h steps, where h is the height of the tree \n    and additionally k steps to get to the kth largest value. to break out the programm needs additionally h steps\n    Time complexity is O(2*h+k). The complexity class is O(n), because h is linear in a worst case (skewed to one side) and k is also linear.\n    Space complexity is O(h), because the algorithm needs to store a maximum of h recursion calls. \n    The complexity class is O(n), because h is linear in a worst case (skewed to one side).\n    But in a balanced tree it is only O(log(n)), because h is log(n), where n is the number of nodes in the balanced tree.\n*/\n#include <iostream>\n#include <algorithm>\n#include <vector>\nclass Node{\n    //Node class holds one node of the tree\n    //every node holds some data (int) and has two children\n    //an empty children gets represented with nullptr\npublic:\n    int data;\n    Node* left;\n    Node* right;\n\npublic:\n    Node(int item){\n        //init the node with no children\n        data = item;\n        left = nullptr;\n        right = nullptr;\n    }\n    virtual ~Node(){\n        /*\n        IMPORTANT to avoid memory leaks \n        a virtual constructor is required to correctly delete all children (and children of children)\n        checking if the child is not empty than calling the children's destructor\n        */\n        if(left != nullptr){delete left;}\n        if(right != nullptr){delete right;}\n    };\n};\n\nclass BinaryTree{\n    //holds the full tree (and tree functionalities)\nprivate:\n    Node* kth_largest;  //that is the member variable that our algorithm uses to save the target node\n    std::vector<Node*> visited_nodes;   //the list of visited nodes\npublic:\n    Node* root;     //pointer to the root node of the BST\n\nprivate:\n    void traverseRL(Node* node, int k){\n        //this method is traversing the BST from the largest to the smallest element\n        //this algorithm is taking the root node and the k\n        if(this->kth_largest != nullptr){   //are we ready?\n            return;\n        }\n        if(node->right != nullptr){         //can we go to the right?\n            traverseRL(node->right, k);     //go to the right\n        }\n        this->visited_nodes.push_back(node);    //cannot go more right, add to visited nodes\n        if(this->visited_nodes.size() == k){    //if the visited nodes list is long enough to hold the target node \n            this->kth_largest = node;           //save this node in the member variable\n            return;                         //start to break down the recursion\n        }\n        if(node->left != nullptr){          //can we go to the left?\n            traverseRL(node->left, k);      //go to the left\n        }\n        return;                            //this node is already dealt with\n    }\n\npublic:\n    BinaryTree(int root_data){\n        //creates a binary tree with one node (root) that gets some given data\n        kth_largest = nullptr;\n        root = new Node(root_data);\n    }\n    Node* insertNode(Node* node, int data){ //insert a new node on the right position (remember the BST rules)\n        if(node == nullptr){        //if we reach an empty spot we set the new node there\n            return new Node(data);\n        }\n        if(data <= node->data){ //data is smaller than the data of the current node\n            node->left = insertNode(node->left, data);  //we have to got to the left\n        }\n        else{                   //data is greater than the data of the current node\n            node->right = insertNode(node->right, data);    //we have to got to the right\n        }\n        return node;    //get the node back to the previous recursion layer\n    }\n    \n    Node* getKthLargest(int k){     //get the kth largest data node\n        this->kth_largest = nullptr;    //init the member variables that are needed for the algorithm\n        this->visited_nodes.clear();\n        this->traverseRL(this->root, k);    //perform the search\n        if(this->kth_largest == nullptr){   //kth largest element cannot be found (out of range)\n            std::cout << \"There is no \" << k << \". largest element in this tree\" << std::endl;\n            std::cout << \"Valid k's for a tree are numbers between 1 and the number of nodes inclusive\";\n            return nullptr;\n        }else{\n            return this->kth_largest;   //returrn the kth largest node\n        }\n    }\n};\n\nint main() {\n    //sample\n    int k = 3;\n    BinaryTree tree = BinaryTree(3);        //building up the sample BST\n    tree.insertNode(tree.root, 7);\n    tree.insertNode(tree.root, 2);\n    tree.insertNode(tree.root, 5);\n    tree.insertNode(tree.root, 9);\n    tree.insertNode(tree.root, 1);\n    tree.insertNode(tree.root, 4);\n    std::cout << tree.getKthLargest(k)->data << std::endl;  //print the result\n    return 0;\n}"
  },
  {
    "path": "Trees/Binary Search Trees/Kth_largest_BST.java",
    "content": "/**\n * A class to represent a node in the BST.\n */\nclass Node {\n    int data;\n    Node left, right;\n\n    Node(int data) {\n        this.data = data;\n        left = right = null;\n    }\n}\n\n/**\n * A class to represent a binary search tree.\n */\nclass BST {\n    Node root;\n\n    BST() {\n        root = null;\n    }\n\n    /**\n     * Function to find the kth largest element in the BST.\n    Time complexity: O(n), where n is the number of nodes in the BST. This is because we need to visit every node in the worst case to find the kth largest element.\n    Space complexity: O(h), where h is the height of the BST. This is because we're recursively traversing the tree using a call stack, which can have at most h frames in it\n    \n    The kthLargest() function takes an integer k as input and returns the kth largest element in the BST. It first creates an empty result list, calls the kthLargestHelper() function to traverse the BST in reverse inorder, and collects the kth largest element in the result list. It then returns the last element of the result list, which is the kth largest element in the BST.\n    \n    Time complexity: O(k), since we're only collecting up to k elements in the result list.\n    pace complexity: O(h), where h is the height of the BST. This is because we're recursively traversing the tree using a call stack, which can have at most h frames in it\n     */\n    public int kthLargest(int k) {\n        List<Integer> result = new ArrayList<>();\n        kthLargestHelper(root, result, k);\n        return result.get(result.size() - 1);\n    }\n\n\n     /**The kthLargestHelper() function is a helper function to traverse the BST in reverse inorder and collect the kth largest element in the result list. It first recursively calls itself on the right child of the current node, then adds the current node's `data */\n    private void kthLargestHelper(Node node, List<Integer> result, int k) {\n        if (node == null || result.size() == k) {\n            return;\n        }\n        kthLargestHelper(node.right, result, k);\n        if (result.size() < k) {\n            result.add(node.data);\n        }\n        kthLargestHelper(node.left, result, k);\n    }\n\n    /**\n     * Function to insert a node in the BST.\n     Time complexity: O(h), where h is the height of the BST. This is because we're traversing the tree from the root to the correct position for the new node.\n    Space complexity: O(1), since we're only creating a new node and not using any extra memory.\n     */\n    public void insert(int data) {\n        root = insertHelper(root, data);\n    }\n\n    /**\n     * Helper function to insert a node in the BST.\n     Time complexity: O(h), where h is the height of the BST. This is because we're traversing the tree from the root to the correct position for the new node.\nS   pace complexity: O(1), since we're only creating a new node and not using any extra memory.\n\n     */\n    private Node insertHelper(Node node, int data) {\n        if (node == null) {\n            node = new Node(data);\n            return node;\n        }\n        if (data < node.data) {\n            node.left = insertHelper(node.left, data);\n        } else if (data > node.data) {\n            node.right = insertHelper(node.right, data);\n        }\n        return node;\n    }\n}\n\n/**\n * A class to test the BST implementation.\n */\npublic class KthLargestBST {\n    public static void main(String[] args) {\n        BST bst = new BST();\n        bst.insert(50);\n        bst.insert(30);\n        bst.insert(20);\n        bst.insert(40);\n        bst.insert(70);\n        bst.insert(60);\n        bst.insert(80);\n        int k = 3;\n        int kthLargest = bst.kthLargest(k);\n        System.out.println(k + \"th largest element in the BST is \" + kthLargest);\n    }\n}\n\n/**Overall, the time complexity of finding the kth largest element in a BST using this code is O(n), and the space complexity is O(h). */\n"
  },
  {
    "path": "Trees/Binary Search Trees/Kth_largest_BST.js",
    "content": "/**\n The Node class represents a single node in the BST. It has three properties: value to store the node's value, left to store the reference to the left child node, and right to store the reference to the right child node.\n */\n class Node {\n    constructor(value) {\n      this.value = value;\n      this.left = null;\n      this.right = null;\n    }\n  }\n  \n  /**\n    the BST class represents the Binary Search Tree. It has one property: root to store the reference to the root node of the tree. \n    */\n  class BST {\n    constructor() {\n      this.root = null;\n    }\n  \n    /**\n    insert(value): This function inserts a new node with the given value into the BST. It uses the insertNode helper function for recursive insertion. The time complexity is O(log n) on average (O(n) in the worst case if the tree is heavily unbalanced), and the space complexity is O(1).    \n     * @param {number} value - The value to be inserted\n     */\n    insert(value) {\n      const newNode = new Node(value);\n  \n      if (this.root === null) {\n        this.root = newNode;\n      } else {\n        this.insertNode(this.root, newNode);\n      }\n    }\n  \n    /**\n    The insertNode(node, newNode) function is a helper function used by the insert(value) method in the BST class. It recursively inserts a new node (newNode).\n    \n    Here's a breakdown of how the insertNode function works:\n\n    *   It compares the value of the newNode with the value of the node to determine whether to go left or right in the BST.\n    *   If the value of newNode is less than the value of node, it checks if the left child of node is null. If it is, the newNode becomes the  left child; otherwise, the function recursively calls itself with the left child node of node.\n    *   If the value of newNode is greater than or equal to the value of node, it checks if the right child of node is null. If it is, the newNode becomes the right child; otherwise, the function recursively calls itself with the right child node of node.\n    *   This process continues until a suitable position is found for the newNode in the BST.\n\n    The time complexity of the insertNode function depends on the structure of the BST. In the average case, when the tree is balanced, the time complexity is O(log n), where n is the number of nodes in the tree. This is because at each level of the tree, the function divides the remaining nodes to be searched by half. However, in the worst case scenario, when the tree is heavily unbalanced (e.g., resembles a linked list), the time complexity becomes O(n), where n is the number of nodes in the tree. This happens when all nodes are in a straight line from the root.\n\n    The space complexity of the insertNode function is O(log n) in the average case and O(n) in the worst case. This is due to the recursive calls that consume memory on the call stack. In the average case, the maximum number of recursive calls is limited by the height of the balanced tree, which is logarithmic to the number of nodes. In the worst case, where the tree is unbalanced, the maximum number of recursive calls is equal to the number of nodes in the tree.\n    \n    * @param {Node} node - The current node being traversed\n     * @param {Node} newNode - The new node to be inserted\n     */\n    insertNode(node, newNode) {\n      if (newNode.value < node.value) {\n        if (node.left === null) {\n          node.left = newNode;\n        } else {\n          this.insertNode(node.left, newNode);\n        }\n      } else {\n        if (node.right === null) {\n          node.right = newNode;\n        } else {\n          this.insertNode(node.right, newNode);\n        }\n      }\n    }\n  \n    /**\n    findKthLargest(k): This function finds the Kth largest value in the BST. It first performs an in-order traversal of the tree to retrieve a sorted array of values. If K is larger than the number of nodes in the tree, it returns null. Otherwise, it returns the Kth largest value from the sorted array. The time complexity of this function is O(n), where n is the number of nodes in the tree. The space complexity is O(n) since it stores all the values in the array during the traversal.     \n     * @param {number} k - The Kth largest value to find\n     * @returns {number|null} - The Kth largest value, or null if it doesn't exist\n     */\n    findKthLargest(k) {\n      if (k <= 0) {\n        throw new Error('k should be a positive integer');\n      }\n  \n      const sortedValues = [];\n      this.inOrderTraversal(this.root, sortedValues);\n  \n      if (k > sortedValues.length) {\n        return null;\n      }\n  \n      return sortedValues[sortedValues.length - k];\n    }\n  \n    /**\n    inOrderTraversal(node, values): This is a helper function that performs an in-order traversal of the BST and stores the sorted values in the given array. It recursively visits the left subtree, then the current node, and finally the right subtree. The time complexity of this function is O(n), where n is the number of nodes in the tree, as it needs to visit each node exactly once. The space complexity is O(n) since it uses the array to store the values.\n     * @param {Node} node - The current node being traversed\n     * @param {Array} values - The array to store the sorted values\n     */\n    inOrderTraversal(node, values) {\n      if (node !== null) {\n        this.inOrderTraversal(node.left, values);\n        values.push(node.value);\n        this.inOrderTraversal(node.right, values);\n      }\n    }\n  }\n  // Sample input and imlplementation\n  /**\n        5\n      /   \\\n     3     7\n    / \\   / \\\n   2   4 6   8\n\n    Now, let's find the 3rd largest value in the BST.\n\n    The sorted order of the tree is [2, 3, 4, 5, 6, 7, 8].\n\n    The 3rd largest value is 6.\n\n    Here's the updated tree with the 3rd largest value marked:\n        5\n      /   \\\n     3     7\n    / \\   / \\\n   2   4 6*  8\n \n   As you can see, the 3rd largest value, 6, is marked with an asterisk (*).\n\n   */\n  // Create a new instance of BST\nconst bst = new BST();\n\n// Insert nodes into the BST\nbst.insert(5);\nbst.insert(3);\nbst.insert(7);\nbst.insert(2);\nbst.insert(4);\nbst.insert(6);\nbst.insert(8);\n\n// Find the 3rd largest value\nconst kthLargest = bst.findKthLargest(3);\nconsole.log(kthLargest); // Output: 6"
  },
  {
    "path": "Trees/Binary Search Trees/Validate_BST.cpp",
    "content": "// VALIDATE BINARY SEARCH TREE --->> LEETCODE\n\n\n\n// Given the root of a binary tree, determine if it is a valid binary search tree (BST).\n\n// A valid BST is defined as follows:\n\n// The left \n// subtree\n//  of a node contains only nodes with keys less than the node's key.\n// The right subtree of a node contains only nodes with keys greater than the node's key.\n// Both the left and right subtrees must also be binary search trees.\n\n// ALGORITHM-->\n// Follow these steps while the current node is not null:\n//    Process the current node and go to its right child if it doesn't have a left child.\n//   Find the inorder predecessor of the current node—that is, the rightmost node in the left subtree—if the present node has a left child, and see if its value is smaller than the value of the current node.\n\n// If the predecessor's right child is null, go to the current node's left child and change the predecessor's right child to point to it.\n//  In order to restore the binary tree's original structure, reset the predecessor's right child to null, process the current node, and then move to its right child if it is already referring to the current node.\n\n\n\n\n\n// C++ program to check if a given tree is BST.\n#include <bits/stdc++.h>\nusing namespace std;\n\n\n\nstruct Node {\n\t// structure of a node of the tree.\n\tint data;\n\tstruct Node *left, *right;\n\n\tNode(int data)\n\t{\n\t\tthis->data = data;\n\t\tleft = right = NULL;\n\t}\n};\n\n\nbool validate(Node* root,long long int min , long long int max){\n    if(!root)\n        return true;  // if the root is null then it is a valid BST. it means that the tree is empty or we had reached the end of tree. \n    // initializing the ans variable to false (temporarily).\n\tbool ans = false;    \n\n\t// checking if the root's data is in the range of min and max.\n    if(root->data<max && root->data>min)\n        ans = true;\n    else    \n        return ans; // if the root's data is not in the range of min and max then it is not a valid BST. hence returning false.\n    \n\t// changing min and max for the left and right subtree. and checking for the left and right subtree with respesct to tree root and returning the ans.\n\treturn ans && validate(root->left,min,root->data) &&\n    validate(root->right,root->data,max);       \n}\n\n\n    bool isValidBST(Node* root) {\n        if(!root)\n            return true;\n\n\t// calling  validate function so that it can check for the left and right subtree .. while giving the range of the values of the nodes.\n        return  validate(root ,-9223372036854775807,9223372036854775807 );\n    }\n\nint main()\n{\n\n\t// Initializing the tree.\n\tstruct Node* root = new Node(3);\n\troot->left = new Node(2);\n\troot->right = new Node(5);\n\troot->left->left = new Node(1);\n\troot->left->right = new Node(4);\n\n\t// calling the function to check BST.\n\tif (isValidBST(root))\n\t\tcout << \"Is BST\";\n\telse\n\t\tcout << \"Not a BST\";\n\n\treturn 0;\n}\n\n\n\n\n// T.C.  O(N)\n// S.C.  O(N) ---> for Auxillary stack"
  },
  {
    "path": "Trees/Binary Search Trees/Validate_BST.java",
    "content": "////// Explanation:\n// To validate a Binary Search Tree (BST), we need to ensure that the values of nodes in the left subtree of any node are less than the value of the node, and the values of nodes in the right subtree are greater than the value of the node. \n// Additionally, the left and right subtrees themselves must also be valid BSTs.\n\n////// Code:\nclass validateBST {\n    public static class Node {\n\t\tpublic int data;\n\t\tpublic Node left, right;\n\n\t\tpublic Node(int data) {\n\t\t\tthis.data = data;\n\t\t\tleft = null;\n\t\t\tright = null;\n\t\t}\n\t};\n\n\tstatic Node prev;\n\n\tstatic Boolean isBST(Node root) {\n\t    \n\t\t// traverse the tree in inorder fashion and // keep track of prev node\n\t\tif (root == null) \n\t\t    return true;\n\t\t    \n\t\t//If Left Node is not BST then return false\n\t\tif (!isBST(root.left)) \n\t\t    return false;\n\t\t    \n\t\t//Check if current node is less than its parent node\n\t\tif (prev != null && root.data <= prev.data) \n\t\t    return false;\n\t\t    \n        \tprev = root;\n\t\treturn isBST(root.right);\n\t}\n\n    public static void main(String[] args) {\n        \n\t    //Creating BST \n       \t    Node root = new Node(1);\n\t    root.left = new Node(-2);\n\t    root.right = new Node(3);\n\t    root.left.left = new Node(-4);\n\t    root.left.right = new Node(-1);\n\t    root.right.left = new Node(2);\n\t    root.right.right = new Node(7);\n\n\t\t// Function call\n\t\tif (isBST(root))\n\t\t\tSystem.out.println(\"Is Valid BST\");\n\t\telse\n\t\t\tSystem.out.println(\"Not a Valid BST\");\n    }\n}\n\n////// Complexity:\n// Time  Complexity: O(n) where n is number of nodes\n// Space Complexity: O(1)\n"
  },
  {
    "path": "Trees/Binary Search Trees/Validate_BST.js",
    "content": "/*\n\tWrite a function that takes in a potentially invalid Binary Search Tree (BST)\n  \tand returns a boolean representing whether the BST is valid.\n  \tSample Input :\n   \t     10\n       /     \\\n      5      15\n    /   \\   /   \\\n   2     5 13   22\n /           \\\n1            14\n\tOutput : True\n\n\tExplanation:\n\tThis code defines a Binary Search Tree (BST) struct with an integer value and left and right nodes that can \n\tpoint to other BST nodes. The struct also has a method called ValidateBst() that returns a boolean indicating \n\twhether the tree is a valid BST or not.\n\n\tThe BST struct has another method called validateBST() that is used by ValidateBst() to check whether the tree\n\tis a valid BST or not. The validateBST() method takes in two arguments, min and max, which represent the minimum \n\tand maximum values that the current node's value can take in order to be a valid BST.\n\n\tThe validateBST() method first checks whether the current node's value is within the valid range determined \n\tby the min and max arguments. If not, the method returns false, indicating that the tree is not a valid BST.\n\n\tIf the current node's value is within the valid range, the method then recursively calls itself on the left \n\tand right child nodes to check whether their values are within their valid ranges. The valid range for the \n\tleft child node is defined by the minimum value and the parent node's value, while the valid range for the \n\tright child node is defined by the parent node's value and the maximum value.\n\n\tIf all of the nodes in the tree satisfy the BST property, the method returns true, indicating that the tree \n\tis a valid BST.\n\n\tO(n) time | O(d) space - where n is the number of nodes in the BST and d is the depth (height) of the BST\n\n*/\nclass Node {\n     constructor(data) {\n         this.data = data;\n         this.left = null;\n         this.right = null;\n     }\n }\n \n// isBst is a method of BST that checks if the binary search tree is valid \nfunction isBST(root) {\n     let prev = null;\n \n     function inorderTraversal(node) {\n\n        // Base case\n         if (node === null) {\n             return true;\n         }\n         \n         // recursively check the left subtree, making sure all values are less than the current node's value\n         if (!inorderTraversal(node.left)) {\n             return false;\n         }\n \n        // if the current node's value is outside the allowed range, then the tree is invalid\n         if (prev !== null && node.data <= prev.data) {\n             return false;\n         }\n \n         prev = node;\n         return inorderTraversal(node.right);\n     }\n \n     return inorderTraversal(root);\n }\n \n // Create the tree\n const root = new Node(100);\n root.left = new Node(-2);\n root.right = new Node(3);\n root.left.left = new Node(-4);\n root.left.right = new Node(-1);\n root.right.left = new Node(2);\n root.right.right = new Node(7);\n \n // Function call\n if (isBST(root)) {\n     console.log(\"Is Valid BST\");\n } else {\n     console.log(\"Not a Valid BST\");\n }\n \n\n////// Complexity:\n// Time  Complexity: O(n) where n is number of nodes\n// Space Complexity: O(1)\n"
  },
  {
    "path": "Trees/Binary Search Trees/Validate_BST.py",
    "content": "'''\n\tWrite a function that takes in a potentially invalid Binary Search Tree (BST)\n  \tand returns a boolean representing whether the BST is valid.\n  \tSample Input :\n   \t     10\n       /     \\\n      5      15\n    /   \\   /   \\\n   2     5 13   22\n /           \\\n1            14\n\tOutput : True\n\n\tExplanation:\n\tThis code defines a Binary Search Tree (BST) struct with an integer value and left and right nodes that can \n\tpoint to other BST nodes. The struct also has a method called ValidateBst() that returns a boolean indicating \n\twhether the tree is a valid BST or not.\n\n\tThe BST struct has another method called validateBST() that is used by ValidateBst() to check whether the tree\n\tis a valid BST or not. The validateBST() method takes in two arguments, min and max, which represent the minimum \n\tand maximum values that the current node's value can take in order to be a valid BST.\n\n\tThe validateBST() method first checks whether the current node's value is within the valid range determined \n\tby the min and max arguments. If not, the method returns false, indicating that the tree is not a valid BST.\n\n\tIf the current node's value is within the valid range, the method then recursively calls itself on the left \n\tand right child nodes to check whether their values are within their valid ranges. The valid range for the \n\tleft child node is defined by the minimum value and the parent node's value, while the valid range for the \n\tright child node is defined by the parent node's value and the maximum value.\n\n\tIf all of the nodes in the tree satisfy the BST property, the method returns true, indicating that the tree \n\tis a valid BST.\n\n\tO(n) time | O(d) space - where n is the number of nodes in the BST and d is the depth (height) of the BST\n\n'''\nclass Node:\n    def __init__(self, data):\n        self.data = data\n        self.left = None\n        self.right = None\n\n\n# ValidateBst is a method of BST that checks if the binary search tree is valid\ndef is_bst(root):\n    global prev\n    prev = None\n    \n        #validateBST is a recursive helper function that checks if the binary search tree is valid\n        #min is the minimum value that a node in the subtree rooted at this node can have\n        #max is the maximum value that a node in the subtree rooted at this node can have\n    def inorder_traversal(node):\n        global prev\n        \n        # if the current node's value is outside the allowed range, then the tree is invalid\n        if node is None:\n            return True\n\n         # If left subtree is not BST return false\n        if not inorder_traversal(node.left):\n            return False\n\n        # recursively check the left subtree, making sure all values are less than the current node's value\n        if prev is not None and node.data <= prev.data:\n            return False\n\n        prev = node\n        return inorder_traversal(node.right)\n\n    return inorder_traversal(root)\n\n\n# Create the tree\nroot = Node(1)\nroot.left = Node(-2)\nroot.right = Node(3)\nroot.left.left = Node(-4)\nroot.left.right = Node(-1)\nroot.right.left = Node(2)\nroot.right.right = Node(7)\n\n# Function call\nif is_bst(root):\n    print(\"Is Valid BST\")\nelse:\n    print(\"Not a Valid BST\")\n\n## Complexity:\n# Time  Complexity: O(n) where n is number of nodes\n# Space Complexity: O(1)\n"
  },
  {
    "path": "Trees/Binary Search Trees/bst.go",
    "content": "/*\n\tBinary Search tree implementation\n\tIn computer science, a binary search tree (BST), also called an ordered or sorted binary tree, is a rooted binary tree data structure\n\twith the key of each internal node being greater than all the keys in the respective node's left subtree and less than the ones\n\tin its right subtree. The time complexity of operations on the binary search tree is directly proportional to the height of the tree.\n\n\tThe complexity analysis of BST shows that, on average, the insert, delete and search\n\ttakes O(log n) fot n nodes. In the worst case, they degrade to that of a singly linked list O(n).\n\n\tSource(https://en.wikipedia.org/wiki/Binary_search_tree)\n\n\tOpeartions on BST:\n\t1 Find/ Find Minimum / Find Maximum element in binary search trees\n\t2 Inserting an element in binary search trees\n\t3 Deleting an element from binary search trees\n\n*/\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"math/rand\"\n)\n\ntype BSTNode struct {\n\tleft *BSTNode\n\tdata int\n\tright *BSTNode\n}\n\n// ConstructBST returns a new, random binary tree\nfunc ConstructBST(n, k int) *BSTNode {\n\tvar root *BSTNode\n\tfor _, v := range rand.Perm(n) {\n\t\troot = Insert(root, (1 + v) * k)\n\t}\n\treturn root\n}\n\n// Insert, inserts an element in binary tree\nfunc Insert(root *BSTNode, data int) *BSTNode {\n\tif root == nil {\n\t\treturn &BSTNode{nil, data, nil}\n\t}\n\tif data < root.data {\n\t\troot.left = Insert(root.left, data)\n\t\treturn root\n\t}\n\troot.right = Insert(root.right, data)\n\treturn root\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: start with root and keep moving left or right recursively\n// if data we are searching is same as current node's data then return current node\n// if data is less than node's data then resurse left, else recurse right\n// if no data then it will return nil\nfunc SearchElementRecursive(root *BSTNode, data int) *BSTNode {\n\tif root == nil {\n\t\treturn root\n\t}\n\tif data < root.data {\n\t\treturn SearchElementRecursive(root.left, data)\n\t} else if data > root.data {\n\t\treturn SearchElementRecursive(root.right, data)\n\t}\n\treturn root\n}\n\n// Time Complexity: O(n). Space Complexity: O(1).\n// Approach: start with root and keep moving left or right\n// if data we are searching is same as current node's data then return current node\n// if data is less than node's data then resurse left, else recurse right\n// if no data then it will return nil\nfunc SearchElementNonRecursive(root *BSTNode, data int) *BSTNode {\n\tif root == nil {\n\t\treturn root\n\t}\n\tfor root != nil {\n\t\tif data == root.data {\n\t\t\treturn root\n\t\t} else if data < root.data {\n\t\t\troot = root.left\n\t\t} else {\n\t\t\troot = root.right\n\t\t}\n\t}\n\treturn nil\n}\n\n// FindMin: finds min element in BST,\n// Approach:  start with root and keep moving left\n// Min element is the left most node in BST\n// Time Complexity: O(n). Space Complexity: O(n).\nfunc FindMinRecursive(root *BSTNode) *BSTNode {\n\tif root == nil {\n\t\treturn nil\n\t} else if root.left == nil {\n\t\treturn root\n\t} else {\n\t\treturn FindMinRecursive(root.left)\n\t}\n}\n\n// FindMIn: finds max element in BST,\n// Approach:  start with root and keep moving right\n// Max element is the right most node in BST\n// Time Complexity: O(n). Space Complexity: O(1).\nfunc FindMinNonRecursive(root *BSTNode) *BSTNode {\n\tif root == nil {\n\t\treturn root\n\t}\n\tfor root.left != nil {\n\t\troot = root.left\n\t}\n\treturn root\n}\n\n// FindMax: finds min element in BST,\n// Approach:  start with root and keep moving left\n// min element is the left most node in BST\n// Time Complexity: O(n). Space Complexity: O(n).\nfunc FindMaxRecursive(root *BSTNode) *BSTNode {\n\tif root == nil {\n\t\treturn nil\n\t}\n\tif root.right == nil {\n\t\treturn root\n\t}\n\treturn FindMaxRecursive(root.right)\n}\n\n// FindMIn: finds max element in BST,\n// Approach:  start with root and keep moving right\n// Max element is the right most node in BST\n// Time Complexity: O(n). Space Complexity: O(1).\nfunc FindMaxNonRecursive(root *BSTNode) *BSTNode {\n\tif root == nil {\n\t\treturn nil\n\t}\n\tfor root.right != nil {\n\t\troot  = root.right\n\t}\n\treturn root\n}\nfunc DeleteMin(root *BSTNode) *BSTNode{\n\tif root.left == nil {\n\t\treturn root.right\n\t}\n\troot.left = DeleteMin(root.left)\n\treturn root\n}\n\n// DeleteFromBST deleted given value from bst and doesn't break the node\n// Time Complexity: O(n). Space Complexity: O(n).\nfunc DeleteFromBST(root *BSTNode, data int) *BSTNode {\n\tif root == nil {\n\t\treturn nil\n\t}\n\t// traverse left or right recursively until you find data\n\tif data < root.data {\n\t\tDeleteFromBST(root.left, data)\n\t} else if data > root.data {\n\t\tDeleteFromBST(root.right, data)\n\t} else {\n\t\t// straight forward conddition no child set root as nil and return root\n\t\tif root.right == nil && root.left == nil{\n\t\t\tfmt.Println(\"hit\")\n\t\t\troot = nil\n\t\t\treturn root\n\t\t}\n\t\t// if left is nil and right has children set root as root.right \n\t\tif root.left == nil && root.right != nil {\n\t\t\ttemp := root.right\n\t\t\troot = temp\n\t\t\treturn root\n\t\t}\n\t\t// if right is nil and left has children set root as root.left\n\t\tif root.right == nil && root.left != nil {\n\t\t\tfmt.Println(\" boom\")\n\t\t\ttemp := root.left\n\t\t\troot = temp\n\t\t\treturn root \n\t\t}\n\t\t// if both left and right have children\n\t\t// find min in the right sub tree, \n\t\t// set root.data as minimum value you found you found in right sub tree\n\t\t// call DeleteFromBST and delete min value\n\t\ttemp := FindMinNonRecursive(root.right)\n\t\tDeleteMin(root.right)\n\t\troot.data = temp.data\n\t\troot.right = DeleteFromBST(root.right, temp.data)\n\t\t\n\t}\n\treturn root\n}\n\n\n// Pre-order traversal\n// Preorder traversal is defined as follows:\n// 1 Visit the root.\n// 2 Traverse the left subtree in Preorder.\n// 3 Traverse the right subtree in Preorder.\n// Time Complexity: O(n). Space Complexity: O(n).\n// The nodes of tree would be visited in the order: 1 2 4 5 3 6 7\nfunc PreOrder(root *BSTNode) {\n\tif root == nil {\n\t\treturn\n\t}\n\tfmt.Print(root.data)\n\tPreOrder(root.left)\n\tPreOrder(root.right)\n}\n\nfunc InOrder(root *BSTNode) {\n\tif root == nil {\n\t\treturn\n\t}\n\tInOrder(root.left)\n\tfmt.Print(root.data)\n\tInOrder(root.right)\n}\n// IsBST: checks whether a given tree is a valid BST or not\n// Time Complexity: O(n2). Space Complexity: O(n).\nfunc IsBST(root *BSTNode) bool {\n\tif root == nil {\n\t\treturn true\n\t}\n\t// if max on left tree is greater then root then return false\n\tmax := FindMaxRecursive(root.left)\n\tif root.left != nil && max.data > root.data {\n\t\treturn false\n\t}\n\t// if min on right tree is less then root then return false\n\tmin := FindMinNonRecursive(root.right)\n\tif root.right != nil && min.data < root.data {\n\t\treturn false\n\t}\n\t// recursively check if left or right is not a BST\n\tif !IsBST(root.left) || !IsBST(root.right) {\n\t\treturn false\n\t}\n\treturn true\n}\n// Time Complexity: O(n). Space Complexity: O(n).\nfunc IsBSTOptimal(root *BSTNode, min, max int) bool {\n\tif root == nil {\n\t\treturn true\n\t}\n\treturn (\n\t\troot.data > min && \n\t\troot.data < max && \n\t\tIsBSTOptimal(root.left, min, root.data) &&  \n\t\tIsBSTOptimal(root.right, root.data, max))\n}\n\n// IsBSTInorder: Using Inorder traversal we can solve this problem \n// Inorder traversal gives us sorted values, while traversing the BST in inorder,\n// at each node check the condition that its key value should be greater than \n// the key value of its previous visited node, initialize prev with minimum integer value\n// Time Complexity: O(n). Space Complexity: O(n).\nfunc IsBSTInorder(root *BSTNode, prev *int) bool {\n\tif root == nil {\n\t\treturn true\n\t}\n\tif !IsBSTInorder(root.left, prev) {\n\t\treturn false\n\t}\n\t// compare root value with prev visited value\n\tif root.data < *prev {\n\t\treturn false\n\t}\n\t// set prev value as root's value\n\t*prev = root.data\n\treturn IsBSTInorder(root.right, prev)\n}\n\n// Helper created balanced binary search tree\n// also it ensures height is balanced\n// Approach : Using Divide and Conquer strategy\n// It is similar to binary seaarch algorithm \nfunc Helper(Arr []int, low int, high int) *BSTNode {\n\tif low > high {\n\t\treturn nil\n\t}\n\t// middle element will form the root of BST\n\tmid := low + (high - low) / 2\n\t// create new node (allocate memory)\n\tnode := new(BSTNode)\n\t// assign data to newly created node\n\tnode.data = Arr[mid]\n\t// elements left from mid will form left sub tree\n\tnode.left = Helper(Arr, low, mid - 1)\n\t// elements right from mid will form right sub tree\n\tnode.right = Helper(Arr, mid + 1, high)\n\treturn node\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\nfunc ConvertSortedArrayToBST(Arr []int) *BSTNode {\n\tif Arr == nil {\n\t\treturn nil\n\t}\n\treturn Helper(Arr, 0, len(Arr)-1)\n}\n\n// Time Complexity: O(n). Space Complexity: O(1).\nfunc kthSmallest(root *BSTNode, k int) *BSTNode {\n\tcounter := 0\n\treturn helperKthSmallest(root, k, &counter)\n}\n\n// Helper method to find kth smallest element\n// Approach: Inorder traversal gives us sorted list , so we can determine kth smallest \n// element in tree easily\nfunc helperKthSmallest(root *BSTNode, k int, counter *int) *BSTNode {\n\tif root == nil {\n\t\treturn nil\n\t}\n\tleft := helperKthSmallest(root.left, k, counter)\n\tif left != nil {\n\t\treturn left\n\t}\n\t// while traversing the tree keep track of the number of elements visited\n\t*counter += 1\n\tif *counter == k {\n\t\treturn root\n\t}\n\treturn helperKthSmallest(root.right, k, counter)\n}\n\n// FloorInBST gives floor value of the supplied key in BST\n// Floor of the key is the largest key in the BST \n// less than tor equal to the key \n// Time Complexity: O(n). Space Complexity: O(n).\nfunc FloorInBST(root *BSTNode, key int) *BSTNode {\n\tif root == nil {\n\t\treturn root\n\t}\n\tif key > root.data {\n\t\tr := FloorInBST(root.right, key)\n\t\tif r == nil {\n\t\t\treturn root\n\t\t} else {\n\t\t\treturn r\n\t\t}\n\t} else if key < root.data {\n\t\treturn FloorInBST(root.left, key)\n\t} else {\n\t\treturn root\n\t}\n}\n\n// CeilInBST gives ceil value of the supplied key in BST\n// Ceil of the key is the smallest key in the BST \n// greater than tor equal to the key \n// Time Complexity: O(n). Space Complexity: O(n).\nfunc CeilInBST(root *BSTNode, key int) *BSTNode {\n\tif root == nil {\n\t\treturn root\n\t}\n\tif root.data == key {\n\t\treturn root\n\t} else if root.data < key {\n\t\treturn CeilInBST(root.right, key)\n\t} else {\n\t\tl := CeilInBST(root.left, key)\n\t\tif l != nil {\n\t\t\treturn l\n\t\t}\n\t}\n\treturn root\n}\n\n// RangePrintBST prints the value in trees which lies in range  from start and end\n// Approach: Traverse in inorder, if key lie within range then print them\n// Time Complexity: O(n). Space Complexity: O(n).\nfunc RangePrintBST(root *BSTNode, start int, end int) {\n\tif root == nil {\n\t\treturn\n\t}\n\t// look in left side\n\tif root.data >= start {\n\t\tRangePrintBST(root.left, start, end)\n\t}\n\t// if value lies within supplied range print them\n\tif root.data >= start && root.data <= end {\n\t\tfmt.Printf(\"%v \", root.data)\n\t}\n\t// look in right side\n\tif root.data <= end {\n\t\tRangePrintBST(root.right, start, end)\n\t}\n}\n\n// RangePrintQueueBST prints the value in trees which lies in range  \n// from start and end using queue (level order traversal)\n// Approach: while adding the elements to queue check for range\n// Time Complexity: O(n). Space Complexity: O(n).\nfunc RangePrintQueueBST(root *BSTNode, start, end int) {\n\tif root == nil {\n\t\treturn\n\t}\n\tvar result [][]int\n\tqueue := []*BSTNode{root}\n\tfor len(queue) > 0 {\n\t\tqlen := len(queue)\n\t\tvar level []int\n\t\tfor i := 0; i < qlen; i++ {\n\t\t\tnode := queue[0]\n\t\t\tlevel = append(level, node.data)\n\t\t\tqueue = queue[1:]\n\t\t\t// if data lies within range then print data\n\t\t\tif node.data >= start && node.data <= end {\n\t\t\t\tfmt.Printf(\"%v\", node.data)\n\t\t\t}\n\t\t\t// append left node to queue\n\t\t\tif node.left != nil && node.data >= start {\n\t\t\t\tqueue = append(queue, node.left)\n\t\t\t}\n\t\t\t// append right node to queue\n\t\t\tif node.right != nil && node.data <= end {\n\t\t\t\tqueue = append(queue, node.right)\n\t\t\t}\n\t\t}\n\t\tresult = append(result, level)\n\t}\n}\n\n// CountTrees: returns how many structurally unique BST's are possible\n// Approach: Consider each value to be root, recursively find the size of the left and right\n// subtrees. Let p be the root in BST with n nodes from 1 to n\n// The left subtree has p - 1 nodes, right tree has n - p nodes.\nfunc CountTrees(n int) int {\n\tif n <= 1 {\n\t\treturn 1\n\t} else {\n\t\tsum := 0\n\t\t// iterate through all values that could be the root\n\t\tfor root := 1; root <= n; root++ {\n\t\t\tleft := CountTrees(root - 1)\n\t\t\tright := CountTrees(n - root)\n\t\t\t// number of possible trees withcurr root = left * right\n\t\t\tsum += left * right\n\t\t}\n\t\treturn sum\n\t}\n}\n\nfunc main() {\n\ttree := ConstructBST(10, 1)\n\tfmt.Println(tree)\n\tfmt.Println(SearchElementRecursive(tree, 5))\n\tfmt.Println(SearchElementNonRecursive(tree, 5))\n\tfmt.Println(FindMinRecursive(tree))\n\tfmt.Println(FindMinNonRecursive(tree))\n\tfmt.Println(FindMaxRecursive(tree))\n\tfmt.Println(FindMaxNonRecursive(tree))\n\tPreOrder(tree)\n\t\n\ttree = DeleteFromBST(tree, 6)\n\tfmt.Println()\n\tPreOrder(tree)\n\t//fmt.Println(SearchElementRecursive(tree, 7))\n\tfmt.Print(IsBST(tree))\n\tfmt.Print(IsBSTOptimal(tree, math.MinInt32, math.MaxInt32))\n\tvar prev = math.MinInt32\n\tfmt.Println(IsBSTInorder(tree, &prev))\n\n\tarr := []int {1, 2, 3, 4, 5 ,6}\n\tnode := ConvertSortedArrayToBST(arr)\n\tInOrder(node)\n\tfmt.Println(kthSmallest(tree, 3))\n\tRangePrintBST(tree, 3, 7)\n\tRangePrintQueueBST(tree, 3, 7)\n}"
  },
  {
    "path": "Trees/Binary Search Trees/find_closest_value.cpp",
    "content": "/*\n  Write a function that takes in a Binary Search Tree (BST) and a target integer\n  value and returns the closest value to that target value contained in the BST.\n\nSample Input : 12\n\n  \t\t 10\n       /     \\\n      5      15\n    /   \\   /   \\\n   2     5 13   22\n /           \\\n1            14\nOutput : 13\n\n    Explanation:\n    \n    The code defines a BST (Binary Search Tree) class with member functions to find the closest value to a given target value. \n    The findClosestValue function is the public interface that initializes the closest value with the root value and calls \n    the helper function. The findClosestValueHelper function recursively traverses the tree, updating the closest value based \n    on the absolute difference between the target and the current node value. It then continues the search in the appropriate \n    subtree based on the comparison with the target value. The absDiff function calculates the absolute difference between two \n    integers.\n\n\tTime and Space complexity:\n\n\tAverage: O(log(n)) time | O(1) space - where n is the number of nodes in the BST\n\tWorst: O(n) time | O(1) space - where n is the number of nodes in the BST\n*/\n#include <cmath>\n\nclass BST {\npublic:\n    int value;\n    BST* left;\n    BST* right;\n\n    BST(int val) {\n        value = val;\n        left = nullptr;\n        right = nullptr;\n    }\n\n    int findClosestValue(int target) {\n        // Call the helper function with the initial closest value as the root value\n        return findClosestValueHelper(target, value);\n    }\n\nprivate:\n    int findClosestValueHelper(int target, int closest) {\n        // Compare the absolute difference between the target and the current closest value\n        // with the absolute difference between the target and the current node value\n        if (std::abs(target - closest) > std::abs(target - value)) {\n            closest = value;\n        }\n\n        // Look for the target in the left subtree if the target is smaller than the current node value\n        if (target < value && left != nullptr) {\n            return left->findClosestValueHelper(target, closest);\n        }\n        // Look for the target in the right subtree if the target is greater than the current node value\n        else if (target > value && right != nullptr) {\n            return right->findClosestValueHelper(target, closest);\n        }\n\n        return closest;\n    }\n};\n\nint main() {\n    // Create a BST instance\n    BST* bst = new BST(10);\n    bst->left = new BST(5);\n    bst->right = new BST(15);\n    bst->left->left = new BST(2);\n    bst->left->right = new BST(5);\n    bst->right->left = new BST(13);\n    bst->right->right = new BST(22);\n    bst->left->left->left = new BST(1);\n    bst->right->left->right = new BST(14);\n\n    // Find the closest value to the target\n    int target = 12;\n    int closestValue = bst->findClosestValue(target);\n\n    // Print the result\n    std::cout << \"The closest value to \" << target << \" is \" << closestValue << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Trees/Binary Search Trees/find_closest_value.go",
    "content": "/*\n  Write a function that takes in a Binary Search Tree (BST) and a target integer\n  value and returns the closest value to that target value contained in the BST.\n\nSample Input : 12\n\n  \t\t 10\n       /     \\\n      5      15\n    /   \\   /   \\\n   2     5 13   22\n /           \\\n1            14\nOutput : 13\n\n    Explanation:\n\n    The code defines a BST (Binary Search Tree) class with member functions to find the closest value to a given target value.\n    The findClosestValue function is the public interface that initializes the closest value with the root value and calls\n    the helper function. The findClosestValueHelper function recursively traverses the tree, updating the closest value based\n    on the absolute difference between the target and the current node value. It then continues the search in the appropriate\n    subtree based on the comparison with the target value. The absDiff function calculates the absolute difference between two\n    integers.\n\n\tTime and Space complexity:\n\n\tAverage: O(log(n)) time | O(1) space - where n is the number of nodes in the BST\n\tWorst: O(n) time | O(1) space - where n is the number of nodes in the BST\n*/\npackage main\n\ntype BST struct {\n\tValue int\n\n\tLeft  *BST\n\tRight *BST\n}\n\nfunc (tree *BST) FindClosestValue(target int) int {\n\t// call helper function\n    return tree.findClosestValue(target, tree.Value)\n}\n\nfunc (tree *BST) findClosestValue(target, closest int) int {\n    if absDiff(target, closest) > absDiff(target, tree.Value) {\n        closest = tree.Value\n    }\n\t// look for target in left sub tree\n    if target < tree.Value && tree.Left != nil {\n        return tree.Left.findClosestValue(target, closest)\n    } else if target > tree.Value && tree.Right != nil {\n\t\t// // look for target in right sub tree\n        return tree.Right.findClosestValue(target, closest)\n    }\n    return closest\n}\n\nfunc absDiff(a, b int) int {\n    if a > b {\n        return a - b\n    }\n    return b - a\n}\n"
  },
  {
    "path": "Trees/Binary Search Trees/find_closest_value.js",
    "content": "/*\n  Write a function that takes in a Binary Search Tree (BST) and a target integer\n  value and returns the closest value to that target value contained in the BST.\n\nSample Input : 12\n\n  \t\t 10\n       /     \\\n      5      15\n    /   \\   /   \\\n   2     5 13   22\n /           \\\n1            14\nOutput : 13\n\n    Explanation:\n    \n    The code defines a BST (Binary Search Tree) class with member functions to find the closest value to a given target value. \n    The findClosestValue function is the public interface that initializes the closest value with the root value and calls \n    the helper function. The findClosestValueHelper function recursively traverses the tree, updating the closest value based \n    on the absolute difference between the target and the current node value. It then continues the search in the appropriate \n    subtree based on the comparison with the target value. The absDiff function calculates the absolute difference between two \n    integers.\n\n\tTime and Space complexity:\n\n\tAverage: O(log(n)) time | O(1) space - where n is the number of nodes in the BST\n\tWorst: O(n) time | O(1) space - where n is the number of nodes in the BST\n*/\nclass BST {\n  constructor(value) {\n    this.value = value;\n    this.left = null;\n    this.right = null;\n  }\n\n  findClosestValue(target) {\n    // Call the helper function with the initial closest value as the root value\n    return this._findClosestValueHelper(target, this.value);\n  }\n\n  _findClosestValueHelper(target, closest) {\n    // Compare the absolute difference between the target and the current closest value\n    // with the absolute difference between the target and the current node value\n    if (Math.abs(target - closest) > Math.abs(target - this.value)) {\n      closest = this.value;\n    }\n\n    // Look for the target in the left subtree if the target is smaller than the current node value\n    if (target < this.value && this.left) {\n      return this.left._findClosestValueHelper(target, closest);\n    }\n    // Look for the target in the right subtree if the target is greater than the current node value\n    else if (target > this.value && this.right) {\n      return this.right._findClosestValueHelper(target, closest);\n    }\n\n    return closest;\n  }\n}\n\n// Create a BST instance\nconst bst = new BST(10);\nbst.left = new BST(5);\nbst.right = new BST(15);\nbst.left.left = new BST(2);\nbst.left.right = new BST(5);\nbst.right.left = new BST(13);\nbst.right.right = new BST(22);\nbst.left.left.left = new BST(1);\nbst.right.left.right = new BST(14);\n\n// Find the closest value to the target\nconst target = 12;\nconst closestValue = bst.findClosestValue(target);\n\n// Print the result\nconsole.log(`The closest value to ${target} is ${closestValue}`);\n"
  },
  {
    "path": "Trees/Binary Search Trees/find_closest_value.py",
    "content": "'''\n  Write a function that takes in a Binary Search Tree (BST) and a target integer\n  value and returns the closest value to that target value contained in the BST.\n\nSample Input : 12\n\n  \t\t 10\n       /     \\\n      5      15\n    /   \\   /   \\\n   2     5 13   22\n /           \\\n1            14\nOutput : 13\n\n    Explanation:\n\n    The code defines a BST (Binary Search Tree) class with member functions to find the closest value to a given target value.\n    The findClosestValue function is the public interface that initializes the closest value with the root value and calls\n    the helper function. The findClosestValueHelper function recursively traverses the tree, updating the closest value based\n    on the absolute difference between the target and the current node value. It then continues the search in the appropriate\n    subtree based on the comparison with the target value. The absDiff function calculates the absolute difference between two\n    integers.\n\n\tTime and Space complexity:\n\n\tAverage: O(log(n)) time | O(1) space - where n is the number of nodes in the BST\n\tWorst: O(n) time | O(1) space - where n is the number of nodes in the BST\n'''\nclass BST:\n    def __init__(self, value):\n        self.value = value\n        self.left = None\n        self.right = None\n\n    def find_closest_value(self, target):\n        # Call the helper function with the initial closest value as the root value\n        return self._find_closest_value_helper(target, self.value)\n\n    def _find_closest_value_helper(self, target, closest):\n        # Compare the absolute difference between the target and the current closest value\n        # with the absolute difference between the target and the current node value\n        if abs(target - closest) > abs(target - self.value):\n            closest = self.value\n\n        # Look for the target in the left subtree if the target is smaller than the current node value\n        if target < self.value and self.left:\n            return self.left._find_closest_value_helper(target, closest)\n        # Look for the target in the right subtree if the target is greater than the current node value\n        elif target > self.value and self.right:\n            return self.right._find_closest_value_helper(target, closest)\n\n        return closest\n\n# Create a BST instance\nbst = BST(10)\nbst.left = BST(5)\nbst.right = BST(15)\nbst.left.left = BST(2)\nbst.left.right = BST(5)\nbst.right.left = BST(13)\nbst.right.right = BST(22)\nbst.left.left.left = BST(1)\nbst.right.left.right = BST(14)\n\n# Find the closest value to the target\ntarget = 12\nclosest_value = bst.find_closest_value(target)\n\n# Print the result\nprint(f\"The closest value to {target} is {closest_value}\")\n"
  },
  {
    "path": "Trees/Binary Search Trees/insert_into_bst.cpp",
    "content": "// Binary Search Tree : Insert into Binary Search Tree\n// Program Author : Abhisek Kumar Gupta\n/*\n    Input :  7 3 9 2 4 8 10\n    Output : \n                  7\n                /   \\\n               3     9\n              / \\   / \\ \n             2  4  8  10\n     Inorder   : 2 3 4 7 8 9 10 \n     Preorder  : 7 3 2 4 9 8 10\n     Postorder : 2 4 3 8 10 9 7        \n*/\n#include<bits/stdc++.h>\nusing namespace std;\n\nclass Node{\n    public:\n        int data;\n        Node* left;\n        Node* right;\n\n        Node(int x){\n            data = x;\n            left = NULL;\n            right = NULL;\n        }\n};\nvoid bfs(Node* root){\n    queue<Node*> q;\n    q.push(root);\n    q.push(NULL);\n    while(!q.empty()){\n        Node* element = q.front();\n        if(element == NULL){\n            cout << \"\\n\";\n            q.pop();\n            if(!q.empty()){\n                q.push(NULL);\n            }\n        }\n        else{\n            cout << element->data << \"->\";\n            q.pop();\n            if(element->left != NULL){\n                q.push(element->left);\n            }\n            if(element->right != NULL){\n                q.push(element->right);\n            }\n        }\n    }\n    return;\n}\nNode* insert_into_binary_search_tree(Node* root, int data){\n    if(root == NULL){\n        return new Node(data);\n    }\n    if(data <= root->data){\n        root->left = insert_into_binary_search_tree(root->left, data);\n    }\n    else{\n        root->right = insert_into_binary_search_tree(root->right, data);\n    }\n    return root;\n}\nNode* build_binary_search_tree(){\n    int data;\n    cin >> data;\n    Node* root = NULL;\n    while(data != -1){\n        root = insert_into_binary_search_tree(root, data);\n        cin >> data;\n    }\n    return root;\n}\nvoid inorder(Node*root){\n    if(root == NULL)\n        return;\n    inorder(root->left);\n    cout << root->data << \"->\";\n    inorder(root->right);    \n}\nvoid pre_order(Node*root){\n    if(root == NULL)\n        return;\n    cout << root->data << \"->\";    \n    pre_order(root->left);\n    pre_order(root->right);    \n}\nvoid post_order(Node*root){\n    if(root == NULL)\n        return;\n    post_order(root->left);\n    post_order(root->right);\n    cout << root->data << \"->\";    \n}\nint main(){\n    Node* root = build_binary_search_tree();\n    cout << endl << \"Inorder Traversal\";\n    inorder(root);\n    cout << endl << \"Preorder Traversal\";\n    pre_order(root);\n    cout << endl << \"Postorder Traversal\";\n    post_order(root);\n    cout << endl;\n    bfs(root);\n\n}\n"
  },
  {
    "path": "Trees/Binary Search Trees/kth_largest.go",
    "content": "// Kth largest in BST\npackage main\n\n// Approach 1: Using Brute Force\n// Since Inorder traversal of BSt always comes in sorted order, we can directly access kth from end\ntype BST struct {\n\tValue int\n\n\tLeft  *BST\n\tRight *BST\n}\n\nfunc FindKthLargestValueInBst(tree *BST, k int) int {\n\tsortedValues := make([]int, 0)\n    inOrderTraverse(tree, &sortedValues)\n\treturn sortedValues[len(sortedValues) - k]\n}\n\nfunc inOrderTraverse(tree *BST, sortedValues *[]int) {\n    if tree.Left != nil {\n        inOrderTraverse(tree.Left, sortedValues)\n    }\n    *sortedValues = append(*sortedValues, tree.Value)\n    if tree.Right != nil {\n        inOrderTraverse(tree.Right, sortedValues)\n    }\n}    \n\n\n// Approach 2: Using Reverse InOrder Traversal      \n/*\n\tThe given code implements a function to find the Kth largest value in a Binary Search Tree (BST). Here's how it works:\n\n\t1. The `BST` struct represents a node in the BST, with a `Value` field and pointers to the left and right child nodes.\n\n\t2. The `treeInfo` struct is a helper struct used to store information during the traversal of the BST. It contains two fields: `numberOfNodesVisited` to keep track of the number of nodes visited, and `latestVisitedNodeValue` to store the value of the latest visited node.\n\n\t3. The `FindKthLargestValueInBst` function takes the root of the BST and the value of K as input and returns the Kth largest value in the BST.\n\n\t4. Inside the `FindKthLargestValueInBst` function, a `treeInfo` instance is created to track the traversal progress.\n\n\t5. The `reverseInOrderTraverse` function is called to perform a reverse in-order traversal of the BST. It starts from the right child, then visits the current node, and finally visits the left child.\n\n\t6. In the `reverseInOrderTraverse` function, the base case is checked: if the current node is `nil` or the desired Kth largest value has already been found (i.e., `numberOfNodesVisited` is equal to K), the function returns.\n\n\t7. The `reverseInOrderTraverse` function is recursively called on the right child node, which traverses the BST in descending order.\n\n\t8. After the right subtree is traversed, the function checks if `numberOfNodesVisited` is still less than K. If so, it increments `numberOfNodesVisited`, assigns the current node's value to `latestVisitedNodeValue`, and recursively calls the function on the left child node.\n\n\t9. The reverse in-order traversal ensures that the largest values are visited first, so when `numberOfNodesVisited` reaches K, the value stored in `latestVisitedNodeValue` will be the Kth largest value in the BST.\n\n\t10. Finally, the Kth largest value is returned by the `FindKthLargestValueInBst` function.\n\n\tThe code efficiently finds the Kth largest value in a BST by performing a reverse in-order traversal, keeping track of the \n\tnumber of visited nodes and the latest visited node value. \n\t\n\tThe time complexity of the algorithm is O(H + K), where H is the height of the BST and K is the input value.\n\t\n\tThe space complexity of the code is O(h), where h is the height of the BST.\n\tDuring the execution of the FindKthLargestValueInBst function, the space usage is primarily determined by the recursive \n\tcalls to the reverseInOrderTraverse function. Each recursive call adds a new frame to the call stack, \n\tconsuming additional memory.\n\n\tIn the worst case scenario, where the BST is skewed and has a height of h (resembling a linked list), the space \n\tcomplexity will be O(h). This is because the function will make h recursive calls before reaching the base case.\n\n\tHowever, in a balanced BST where the height is log(N), where N is the number of nodes in the tree, the space \n\tcomplexity will be O(log(N)).\n\n\tIt's important to note that the space complexity only accounts for the additional space used by the recursive calls \n\tand the call stack. The space required to store the BST itself is not considered in this analysis as it is part of \n\tthe input data.\n\n*/         \n// Helper struct to store traversal information\ntype treeInfo struct {\n\tnumberOfNodesVisited   int\n\tlatestVisitedNodeValue int\n}\n\n// FindKthLargestValueInBst finds the Kth largest value in the BST\nfunc FindKthLargestValueInBst2(tree *BST, k int) int {\n\t// Create treeInfo to track traversal progress\n\ttreeInfo := treeInfo{0, -1}\n\treverseInOrderTraverse(tree, k, &treeInfo)\n\treturn treeInfo.latestVisitedNodeValue\n}\n\n// reverseInOrderTraverse performs reverse in-order traversal of the BST\nfunc reverseInOrderTraverse(tree *BST, k int, treeInfo *treeInfo) {\n\t// Base case: if current node is nil or Kth largest value found, return\n\tif tree == nil || treeInfo.numberOfNodesVisited == k {\n\t\treturn\n\t}\n\n\t// Traverse the right subtree\n\treverseInOrderTraverse(tree.Right, k, treeInfo)\n\n\t// Check if Kth largest value has been found\n\tif treeInfo.numberOfNodesVisited < k {\n\t\t// Increment the count of visited nodes and update the latest visited node value\n\t\ttreeInfo.numberOfNodesVisited++\n\t\ttreeInfo.latestVisitedNodeValue = tree.Value\n\n\t\t// Traverse the left subtree\n\t\treverseInOrderTraverse(tree.Left, k, treeInfo)\n\t}\n}"
  },
  {
    "path": "Trees/Binary Search Trees/min_height_BST.cpp",
    "content": "/*\n\n  \tWrite a function that takes in a non-empty sorted array of distinct integers, constructs a BST from the integers, and returns the root of the BST.\n  \tThe function should minimize the height of the BST.\n\tSmple Input : [1, 2, 5, 7, 10, 13, 14, 15, 22]\n\tOutput:\n\n\t      10\n       /     \\\n      2      14\n    /   \\   /   \\\n   1     5 13   15\n          \\       \\\n           7      22\n\n\tExplanation:\n\n\tThe given code is used to construct a minimum height binary search tree (BST) from a sorted array.\n\tThe goal is to create a balanced BST where the difference in height between the left and right subtrees is minimized.\n\n\tThe MinHeightBST function serves as a wrapper function that initializes the construction process by calling\n\tthe constructMinHeightBST helper function.\n\n\tThe constructMinHeightBST function recursively constructs the minimum height BST. It takes the sorted array,\n\ta partially constructed bst, and the start and end indices that define the range of elements from the array currently being considered.\n\n\tThe function follows these steps:\n\n\tBase Case: If end < start, it means there are no elements to consider in the current range, so it returns nil indicating an empty subtree.\n\n\tCalculate the mid index as the midpoint of the current range (start and end).\n\n\tGet the value from the array at the mid index.\n\n\tIf the bst is nil, indicating that there are no values in the BST yet, create a new BST node with the value.\n\tOtherwise, insert the value into the existing bst using the Insert method.\n\n\tRecursively call constructMinHeightBST for the left half of the array by passing start and mid-1 as the new range.\n\tThis constructs the left subtree.\n\n\tRecursively call constructMinHeightBST for the right half of the array by passing mid+1 and end as the new range.\n\tThis constructs the right subtree.\n\n\tFinally, return the bst which represents the constructed minimum height BST.\n\n\tThe BST struct represents a node in the binary search tree. It has a Value field to store the node's value and\n\tLeft and Right fields to point to the left and right child nodes, respectively.\n\n\tThe Insert method is used to insert a new value into the BST. It recursively finds the appropriate position to\n\tinsert the value based on the comparison with the current node's value and updates the left or right child accordingly.\n\n\tOverall, this code efficiently constructs a minimum height BST from a sorted array by recursively dividing the\n\tarray and inserting the mid-value into the BST, ensuring a balanced structure.\n\n\tTime Complexity:\n\n\tThe MinHeightBST function calls the constructMinHeightBST helper function, which performs a binary search-like\n\toperation to divide the array and construct the BST. This process is recursive and takes O(log n) time, where\n\tn is the number of elements in the array.\n\n\tThe bst.Insert(value) operation in constructMinHeightBST has a time complexity of O(log n) in the worst case,\n\tas it involves traversing the height of the BST to find the appropriate position to insert the value.\n\tSince each element in the array is inserted into the BST once, the overall time complexity is O(n log n),\n\twhere n is the number of elements in the array.\n\n\tSpace Complexity:\n\n\tThe space complexity is determined by the stack space used during recursive calls and the space required\n\tto store the BST.\n\n\tThe recursive calls in constructMinHeightBST consume additional stack space proportional to the height of\n\tthe tree. In the worst case scenario, where the BST is skewed and its height is equal to the number of\n\telements (n), the space complexity becomes O(n).\n\n\tThe space required to store the BST is also O(n) in the worst case since each element in the array is\n\tinserted into the BST.\n\n\tTherefore, the overall space complexity is O(n) due to the stack space and the BST storage.\n\tIn summary, the time complexity is O(n log n) and the space complexity is O(n).\n\n\n\n*/\n#include <iostream>\n#include <vector>\n\nstruct TreeNode {\n    int value;\n    TreeNode* left;\n    TreeNode* right;\n\n    TreeNode(int x) : value(x), left(nullptr), right(nullptr) {}\n};\n\nTreeNode* minHeightBST(std::vector<int>& array) {\n    // Call helper method with start index, end index, and a nullptr root node\n    return constructMinHeightBST(array, nullptr, 0, array.size() - 1);\n}\n\nTreeNode* constructMinHeightBST(std::vector<int>& array, TreeNode* bst, int start, int end) {\n    // Base case\n    if (end < start) {\n        return nullptr;\n    }\n    int mid = (start + end) / 2;\n    int value = array[mid];\n    // If the BST is empty, create a new root node\n    if (bst == nullptr) {\n        bst = new TreeNode(value);\n    } else {\n        // Insert the value into the existing BST\n        bst->insert(value);\n    }\n    // Recursively construct the left and right subtrees\n    bst->left = constructMinHeightBST(array, bst->left, start, mid - 1);\n    bst->right = constructMinHeightBST(array, bst->right, mid + 1, end);\n    return bst;\n}\n\nclass BST {\npublic:\n    int value;\n    BST* left;\n    BST* right;\n\n    BST(int x) : value(x), left(nullptr), right(nullptr) {}\n\n    void insert(int value) {\n        if (value < this->value) {\n            if (left == nullptr) {\n                left = new BST(value);\n            } else {\n                left->insert(value);\n            }\n        } else {\n            if (right == nullptr) {\n                right = new BST(value);\n            } else {\n                right->insert(value);\n            }\n        }\n    }\n};\n\nint main() {\n    std::vector<int> array = {1, 2, 3, 4, 5, 6, 7};\n    TreeNode* root = minHeightBST(array);\n\n    // Printing the BST is left as an exercise\n\n    // Clean up memory\n    deleteTree(root);\n\n    return 0;\n}\n\nvoid deleteTree(TreeNode* root) {\n    if (root == nullptr) {\n        return;\n    }\n    deleteTree(root->left);\n    deleteTree(root->right);\n    delete root;\n}\n"
  },
  {
    "path": "Trees/Binary Search Trees/min_height_BST.go",
    "content": "/*\n\n  \tWrite a function that takes in a non-empty sorted array of distinct integers, constructs a BST from the integers, and returns the root of the BST.\n  \tThe function should minimize the height of the BST.\n\tSmple Input : [1, 2, 5, 7, 10, 13, 14, 15, 22]\n\tOutput:\n\n\t      10\n       /     \\\n      2      14\n    /   \\   /   \\\n   1     5 13   15\n          \\       \\\n           7      22\n\n\tExplanation:\n\n\tThe given code is used to construct a minimum height binary search tree (BST) from a sorted array.\n\tThe goal is to create a balanced BST where the difference in height between the left and right subtrees is minimized.\n\n\tThe MinHeightBST function serves as a wrapper function that initializes the construction process by calling\n\tthe constructMinHeightBST helper function.\n\n\tThe constructMinHeightBST function recursively constructs the minimum height BST. It takes the sorted array,\n\ta partially constructed bst, and the start and end indices that define the range of elements from the array currently being considered.\n\n\tThe function follows these steps:\n\n\tBase Case: If end < start, it means there are no elements to consider in the current range, so it returns nil indicating an empty subtree.\n\n\tCalculate the mid index as the midpoint of the current range (start and end).\n\n\tGet the value from the array at the mid index.\n\n\tIf the bst is nil, indicating that there are no values in the BST yet, create a new BST node with the value.\n\tOtherwise, insert the value into the existing bst using the Insert method.\n\n\tRecursively call constructMinHeightBST for the left half of the array by passing start and mid-1 as the new range.\n\tThis constructs the left subtree.\n\n\tRecursively call constructMinHeightBST for the right half of the array by passing mid+1 and end as the new range.\n\tThis constructs the right subtree.\n\n\tFinally, return the bst which represents the constructed minimum height BST.\n\n\tThe BST struct represents a node in the binary search tree. It has a Value field to store the node's value and\n\tLeft and Right fields to point to the left and right child nodes, respectively.\n\n\tThe Insert method is used to insert a new value into the BST. It recursively finds the appropriate position to\n\tinsert the value based on the comparison with the current node's value and updates the left or right child accordingly.\n\n\tOverall, this code efficiently constructs a minimum height BST from a sorted array by recursively dividing the\n\tarray and inserting the mid-value into the BST, ensuring a balanced structure.\n\n\tTime Complexity:\n\n\tThe MinHeightBST function calls the constructMinHeightBST helper function, which performs a binary search-like\n\toperation to divide the array and construct the BST. This process is recursive and takes O(log n) time, where\n\tn is the number of elements in the array.\n\n\tThe bst.Insert(value) operation in constructMinHeightBST has a time complexity of O(log n) in the worst case,\n\tas it involves traversing the height of the BST to find the appropriate position to insert the value.\n\tSince each element in the array is inserted into the BST once, the overall time complexity is O(n log n),\n\twhere n is the number of elements in the array.\n\n\tSpace Complexity:\n\n\tThe space complexity is determined by the stack space used during recursive calls and the space required\n\tto store the BST.\n\n\tThe recursive calls in constructMinHeightBST consume additional stack space proportional to the height of\n\tthe tree. In the worst case scenario, where the BST is skewed and its height is equal to the number of\n\telements (n), the space complexity becomes O(n).\n\n\tThe space required to store the BST is also O(n) in the worst case since each element in the array is\n\tinserted into the BST.\n\n\tTherefore, the overall space complexity is O(n) due to the stack space and the BST storage.\n\tIn summary, the time complexity is O(n log n) and the space complexity is O(n).\n\n\n\n*/\npackage main\n\nfunc MinHeightBST(array []int) *BST {\n\t// call helper method with start index, end index array and nil node\n\treturn constructMinHeightBST(array, nil, 0, len(array)-1)\n}\n\nfunc constructMinHeightBST(array []int, bst *BST, start int, end int) *BST {\n\t// base case\n\tif end < start {\n\t\treturn nil\n\t}\n\tmid := (start + end) / 2\n\tvalue := array[mid]\n\t// there are no value in bst\n\tif bst == nil {\n\t\tbst = &BST{Value: value}\n\t} else {\n\t\tbst.Insert(value)\n\t}\n\tconstructMinHeightBST(array, bst, start, mid-1)\n\tconstructMinHeightBST(array, bst, mid+1, end)\n\treturn bst\n}\n\ntype BST struct {\n\tValue int\n\n\tLeft  *BST\n\tRight *BST\n}\n\nfunc (tree *BST) Insert(value int) *BST {\n\tif value < tree.Value {\n\t\tif tree.Left == nil {\n\t\t\ttree.Left = &BST{Value: value}\n\t\t} else {\n\t\t\ttree.Left.Insert(value)\n\t\t}\n\t} else {\n\t\tif tree.Right == nil {\n\t\t\ttree.Right = &BST{Value: value}\n\t\t} else {\n\t\t\ttree.Right.Insert(value)\n\t\t}\n\t}\n\treturn tree\n}\n"
  },
  {
    "path": "Trees/Binary Search Trees/min_height_BST.java",
    "content": "/*\n\n  \tWrite a function that takes in a non-empty sorted array of distinct integers, constructs a BST from the integers, and returns the root of the BST.\n  \tThe function should minimize the height of the BST.\n\tSmple Input : [1, 2, 5, 7, 10, 13, 14, 15, 22]\n\tOutput:\n\n\t      10\n       /     \\\n      2      14\n    /   \\   /   \\\n   1     5 13   15\n          \\       \\\n           7      22\n\n\tExplanation:\n\n\tThe given code is used to construct a minimum height binary search tree (BST) from a sorted array.\n\tThe goal is to create a balanced BST where the difference in height between the left and right subtrees is minimized.\n\n\tThe MinHeightBST function serves as a wrapper function that initializes the construction process by calling\n\tthe constructMinHeightBST helper function.\n\n\tThe constructMinHeightBST function recursively constructs the minimum height BST. It takes the sorted array,\n\ta partially constructed bst, and the start and end indices that define the range of elements from the array currently being considered.\n\n\tThe function follows these steps:\n\n\tBase Case: If end < start, it means there are no elements to consider in the current range, so it returns nil indicating an empty subtree.\n\n\tCalculate the mid index as the midpoint of the current range (start and end).\n\n\tGet the value from the array at the mid index.\n\n\tIf the bst is nil, indicating that there are no values in the BST yet, create a new BST node with the value.\n\tOtherwise, insert the value into the existing bst using the Insert method.\n\n\tRecursively call constructMinHeightBST for the left half of the array by passing start and mid-1 as the new range.\n\tThis constructs the left subtree.\n\n\tRecursively call constructMinHeightBST for the right half of the array by passing mid+1 and end as the new range.\n\tThis constructs the right subtree.\n\n\tFinally, return the bst which represents the constructed minimum height BST.\n\n\tThe BST struct represents a node in the binary search tree. It has a Value field to store the node's value and\n\tLeft and Right fields to point to the left and right child nodes, respectively.\n\n\tThe Insert method is used to insert a new value into the BST. It recursively finds the appropriate position to\n\tinsert the value based on the comparison with the current node's value and updates the left or right child accordingly.\n\n\tOverall, this code efficiently constructs a minimum height BST from a sorted array by recursively dividing the\n\tarray and inserting the mid-value into the BST, ensuring a balanced structure.\n\n\tTime Complexity:\n\n\tThe MinHeightBST function calls the constructMinHeightBST helper function, which performs a binary search-like\n\toperation to divide the array and construct the BST. This process is recursive and takes O(log n) time, where\n\tn is the number of elements in the array.\n\n\tThe bst.Insert(value) operation in constructMinHeightBST has a time complexity of O(log n) in the worst case,\n\tas it involves traversing the height of the BST to find the appropriate position to insert the value.\n\tSince each element in the array is inserted into the BST once, the overall time complexity is O(n log n),\n\twhere n is the number of elements in the array.\n\n\tSpace Complexity:\n\n\tThe space complexity is determined by the stack space used during recursive calls and the space required\n\tto store the BST.\n\n\tThe recursive calls in constructMinHeightBST consume additional stack space proportional to the height of\n\tthe tree. In the worst case scenario, where the BST is skewed and its height is equal to the number of\n\telements (n), the space complexity becomes O(n).\n\n\tThe space required to store the BST is also O(n) in the worst case since each element in the array is\n\tinserted into the BST.\n\n\tTherefore, the overall space complexity is O(n) due to the stack space and the BST storage.\n\tIn summary, the time complexity is O(n log n) and the space complexity is O(n).\n\n\n\n*/\npublic class JuiceBottling {\n\n    public static int[] juiceBottling(int[] prices) {\n        int numSizes = prices.length;\n        int[] maxProfit = new int[numSizes];         // Array to store the maximum profit for each bottle size\n        int[] dividingPoints = new int[numSizes];    // Array to store the dividing points that maximize profit\n\n        // Loop through each bottle size\n        for (int size = 0; size < numSizes; size++) {\n            // Loop through possible dividing points for the current size\n            for (int dividingPoint = 0; dividingPoint < size + 1; dividingPoint++) {\n                // Calculate the possible profit by combining the previous maximum profit\n                // with the price at the current dividing point\n                int possibleProfit = maxProfit[size - dividingPoint] + prices[dividingPoint];\n\n                // Update maxProfit and dividingPoints if the new possible profit is greater\n                if (possibleProfit > maxProfit[size]) {\n                    maxProfit[size] = possibleProfit;\n                    dividingPoints[size] = dividingPoint;\n                }\n            }\n        }\n\n        int[] solution = new int[numSizes];\n        int currentDividingPoint = numSizes - 1;\n        // Reconstruct the solution by tracing back from the end\n        // using the dividing points information\n        while (currentDividingPoint > 0) {\n            solution[currentDividingPoint] = dividingPoints[currentDividingPoint];\n            currentDividingPoint -= dividingPoints[currentDividingPoint];\n        }\n        return solution;\n    }\n\n    public static void main(String[] args) {\n        int[] prices = {3, 5, 8, 9, 10, 17, 17, 20};\n        int[] result = juiceBottling(prices);\n\n        System.out.print(\"Dividing Points for Maximum Profit:\");\n        for (int point : result) {\n            System.out.print(\" \" + point);\n        }\n        System.out.println();\n    }\n}\n"
  },
  {
    "path": "Trees/Binary Search Trees/min_height_BST.js",
    "content": "/*\n\n  \tWrite a function that takes in a non-empty sorted array of distinct integers, constructs a BST from the integers, and returns the root of the BST.\n  \tThe function should minimize the height of the BST.\n\tSmple Input : [1, 2, 5, 7, 10, 13, 14, 15, 22]\n\tOutput:\n\n\t      10\n       /     \\\n      2      14\n    /   \\   /   \\\n   1     5 13   15\n          \\       \\\n           7      22\n\n\tExplanation:\n\n\tThe given code is used to construct a minimum height binary search tree (BST) from a sorted array.\n\tThe goal is to create a balanced BST where the difference in height between the left and right subtrees is minimized.\n\n\tThe MinHeightBST function serves as a wrapper function that initializes the construction process by calling\n\tthe constructMinHeightBST helper function.\n\n\tThe constructMinHeightBST function recursively constructs the minimum height BST. It takes the sorted array,\n\ta partially constructed bst, and the start and end indices that define the range of elements from the array currently being considered.\n\n\tThe function follows these steps:\n\n\tBase Case: If end < start, it means there are no elements to consider in the current range, so it returns nil indicating an empty subtree.\n\n\tCalculate the mid index as the midpoint of the current range (start and end).\n\n\tGet the value from the array at the mid index.\n\n\tIf the bst is nil, indicating that there are no values in the BST yet, create a new BST node with the value.\n\tOtherwise, insert the value into the existing bst using the Insert method.\n\n\tRecursively call constructMinHeightBST for the left half of the array by passing start and mid-1 as the new range.\n\tThis constructs the left subtree.\n\n\tRecursively call constructMinHeightBST for the right half of the array by passing mid+1 and end as the new range.\n\tThis constructs the right subtree.\n\n\tFinally, return the bst which represents the constructed minimum height BST.\n\n\tThe BST struct represents a node in the binary search tree. It has a Value field to store the node's value and\n\tLeft and Right fields to point to the left and right child nodes, respectively.\n\n\tThe Insert method is used to insert a new value into the BST. It recursively finds the appropriate position to\n\tinsert the value based on the comparison with the current node's value and updates the left or right child accordingly.\n\n\tOverall, this code efficiently constructs a minimum height BST from a sorted array by recursively dividing the\n\tarray and inserting the mid-value into the BST, ensuring a balanced structure.\n\n\tTime Complexity:\n\n\tThe MinHeightBST function calls the constructMinHeightBST helper function, which performs a binary search-like\n\toperation to divide the array and construct the BST. This process is recursive and takes O(log n) time, where\n\tn is the number of elements in the array.\n\n\tThe bst.Insert(value) operation in constructMinHeightBST has a time complexity of O(log n) in the worst case,\n\tas it involves traversing the height of the BST to find the appropriate position to insert the value.\n\tSince each element in the array is inserted into the BST once, the overall time complexity is O(n log n),\n\twhere n is the number of elements in the array.\n\n\tSpace Complexity:\n\n\tThe space complexity is determined by the stack space used during recursive calls and the space required\n\tto store the BST.\n\n\tThe recursive calls in constructMinHeightBST consume additional stack space proportional to the height of\n\tthe tree. In the worst case scenario, where the BST is skewed and its height is equal to the number of\n\telements (n), the space complexity becomes O(n).\n\n\tThe space required to store the BST is also O(n) in the worst case since each element in the array is\n\tinserted into the BST.\n\n\tTherefore, the overall space complexity is O(n) due to the stack space and the BST storage.\n\tIn summary, the time complexity is O(n log n) and the space complexity is O(n).\n\n\n\n*/\nclass TreeNode {\n  constructor(value) {\n    this.value = value;\n    this.left = null;\n    this.right = null;\n  }\n}\n\n// Function to construct a minimum-height BST\nfunction minHeightBST(array) {\n  // Call the helper method with start index, end index, and a null root node\n  return constructMinHeightBST(array, null, 0, array.length - 1);\n}\n\n// Recursive helper function to construct a minimum-height BST\nfunction constructMinHeightBST(array, bst, start, end) {\n  // Base case\n  if (end < start) {\n    return null;\n  }\n  const mid = Math.floor((start + end) / 2);\n  const value = array[mid];\n  // If the BST is empty, create a new root node\n  if (bst === null) {\n    bst = new TreeNode(value);\n  } else {\n    // Insert the value into the existing BST\n    bst.insert(value);\n  }\n  // Recursively construct the left and right subtrees\n  bst.left = constructMinHeightBST(array, bst.left, start, mid - 1);\n  bst.right = constructMinHeightBST(array, bst.right, mid + 1, end);\n  return bst;\n}\n\n// Class for Binary Search Tree (BST)\nclass BST {\n  constructor(value) {\n    this.value = value;\n    this.left = null;\n    this.right = null;\n  }\n\n  insert(value) {\n    if (value < this.value) {\n      if (this.left === null) {\n        this.left = new BST(value);\n      } else {\n        this.left.insert(value);\n      }\n    } else {\n      if (this.right === null) {\n        this.right = new BST(value);\n      } else {\n        this.right.insert(value);\n      }\n    }\n  }\n}\n\n// Example usage:\nconst array = [1, 2, 3, 4, 5, 6, 7];\nconst root = minHeightBST(array);\n\n// Printing the BST is left as an exercise\n"
  },
  {
    "path": "Trees/Binary Search Trees/min_height_BST.py",
    "content": "'''\n  \tWrite a function that takes in a non-empty sorted array of distinct integers, constructs a BST from the integers, and returns the root of the BST.\n  \tThe function should minimize the height of the BST.\n\tSmple Input : [1, 2, 5, 7, 10, 13, 14, 15, 22]\n\tOutput:\n\n\t      10\n       /     \\\n      2      14\n    /   \\   /   \\\n   1     5 13   15\n          \\       \\\n           7      22\n\n\tExplanation:\n\n\tThe given code is used to construct a minimum height binary search tree (BST) from a sorted array.\n\tThe goal is to create a balanced BST where the difference in height between the left and right subtrees is minimized.\n\n\tThe MinHeightBST function serves as a wrapper function that initializes the construction process by calling\n\tthe constructMinHeightBST helper function.\n\n\tThe constructMinHeightBST function recursively constructs the minimum height BST. It takes the sorted array,\n\ta partially constructed bst, and the start and end indices that define the range of elements from the array currently being considered.\n\n\tThe function follows these steps:\n\n\tBase Case: If end < start, it means there are no elements to consider in the current range, so it returns nil indicating an empty subtree.\n\n\tCalculate the mid index as the midpoint of the current range (start and end).\n\n\tGet the value from the array at the mid index.\n\n\tIf the bst is nil, indicating that there are no values in the BST yet, create a new BST node with the value.\n\tOtherwise, insert the value into the existing bst using the Insert method.\n\n\tRecursively call constructMinHeightBST for the left half of the array by passing start and mid-1 as the new range.\n\tThis constructs the left subtree.\n\n\tRecursively call constructMinHeightBST for the right half of the array by passing mid+1 and end as the new range.\n\tThis constructs the right subtree.\n\n\tFinally, return the bst which represents the constructed minimum height BST.\n\n\tThe BST struct represents a node in the binary search tree. It has a Value field to store the node's value and\n\tLeft and Right fields to point to the left and right child nodes, respectively.\n\n\tThe Insert method is used to insert a new value into the BST. It recursively finds the appropriate position to\n\tinsert the value based on the comparison with the current node's value and updates the left or right child accordingly.\n\n\tOverall, this code efficiently constructs a minimum height BST from a sorted array by recursively dividing the\n\tarray and inserting the mid-value into the BST, ensuring a balanced structure.\n\n\tTime Complexity:\n\n\tThe MinHeightBST function calls the constructMinHeightBST helper function, which performs a binary search-like\n\toperation to divide the array and construct the BST. This process is recursive and takes O(log n) time, where\n\tn is the number of elements in the array.\n\n\tThe bst.Insert(value) operation in constructMinHeightBST has a time complexity of O(log n) in the worst case,\n\tas it involves traversing the height of the BST to find the appropriate position to insert the value.\n\tSince each element in the array is inserted into the BST once, the overall time complexity is O(n log n),\n\twhere n is the number of elements in the array.\n\n\tSpace Complexity:\n\n\tThe space complexity is determined by the stack space used during recursive calls and the space required\n\tto store the BST.\n\n\tThe recursive calls in constructMinHeightBST consume additional stack space proportional to the height of\n\tthe tree. In the worst case scenario, where the BST is skewed and its height is equal to the number of\n\telements (n), the space complexity becomes O(n).\n\n\tThe space required to store the BST is also O(n) in the worst case since each element in the array is\n\tinserted into the BST.\n\n\tTherefore, the overall space complexity is O(n) due to the stack space and the BST storage.\n\tIn summary, the time complexity is O(n log n) and the space complexity is O(n).\n\n\n'''\nclass TreeNode:\n    def __init__(self, value):\n        self.value = value\n        self.left = None\n        self.right = None\n\ndef min_height_bst(array):\n    # Call helper method with start index, end index, and a None root node\n    return construct_min_height_bst(array, None, 0, len(array) - 1)\n\ndef construct_min_height_bst(array, bst, start, end):\n    # Base case\n    if end < start:\n        return None\n    mid = (start + end) // 2\n    value = array[mid]\n    # If the BST is empty, create a new root node\n    if bst is None:\n        bst = TreeNode(value)\n    else:\n        # Insert the value into the existing BST\n        bst.insert(value)\n    # Recursively construct the left and right subtrees\n    bst.left = construct_min_height_bst(array, bst.left, start, mid - 1)\n    bst.right = construct_min_height_bst(array, bst.right, mid + 1, end)\n    return bst\n\nclass BST:\n    def __init__(self, value):\n        self.value = value\n        self.left = None\n        self.right = None\n\n    def insert(self, value):\n        if value < self.value:\n            if self.left is None:\n                self.left = BST(value)\n            else:\n                self.left.insert(value)\n        else:\n            if self.right is None:\n                self.right = BST(value)\n            else:\n                self.right.insert(value)\n\n# Example usage:\narray = [1, 2, 3, 4, 5, 6, 7]\nroot = min_height_bst(array)\n\n# Printing the BST is left as an exercise\n"
  },
  {
    "path": "Trees/Binary Search Trees/reconstruct_bst.cpp",
    "content": "/*\n    Reconstruct BST\n\tThe pre-order traversal of a Binary Tree is a traversal technique that starts at the tree's root node and visits nodes in the following order:\n\t\tCurrent Node\n\t\tLeft Subtree\n\t\tRight Subtree\n\n  \tGiven a non-empty array of integers representing the pre-order traversal of a Binary Search Tree (BST),\n\twrite a function that creates the relevant BST and returns its root node.\n\n    The input array will contain the values of BST nodes in the order in which these nodes would be visited with a pre-order traversal.\n\n\tSample Input: [10, 4, 2, 1, 5, 17, 19, 18]\n\tSample Output:\n\t    10\n      /    \\\n     4      17\n   /   \\      \\\n  2     5     19\n /           /\n1           18\n\n    The ReconstructBst function takes a slice preOrderTraversalValues which represents the pre-order traversal of a binary search tree.\n\tIt reconstructs the BST using a range-based approach. Here's how the algorithm works:\n\n\tThe ReconstructBst function initializes a treeInfo struct to keep track of the current root index.\n\n\tThe ReconstructBst function calls the reconstructBSTFromRange helper function, passing the minimum and maximum integer values\n\tas the initial range, the pre-order traversal values, and the treeInfo struct.\n\n\tThe reconstructBSTFromRange function first checks if the current root index has reached the end of the pre-order traversal values.\n\tIf so, it returns nil indicating an empty subtree.\n\n\tIt retrieves the value of the current root from the pre-order traversal values.\n\n\tIt checks if the root value is outside the valid range defined by the lower and upper bounds. If so, it returns\n\n\tThe time complexity of the ReconstructBst function is O(n), where n is the number of nodes in the reconstructed BST.\n\tThis is because the function processes each node exactly once.\n\n\tThe space complexity of the ReconstructBst function is O(n), where n is the number of nodes in the reconstructed BST.\n\tThis is because the function creates BST nodes and recursively calls itself to construct the left and right subtrees.\n\tThe space complexity is determined by the height of the BST, which can be at most n in the worst case for a skewed BST.\n\n*/\n#include <iostream>\n#include <vector>\n#include <climits>\n\n// Definition for a binary tree node.\nstruct TreeNode {\n    int val;\n    TreeNode* left;\n    TreeNode* right;\n    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}\n};\n\n// A helper class to keep track of the current root index during reconstruction.\nclass TreeInfo {\npublic:\n    int rootIdx;\n    TreeInfo(int idx) : rootIdx(idx) {}\n};\n\n// Function to reconstruct the BST from a pre-order traversal.\nTreeNode* reconstructBst(std::vector<int>& preOrderTraversalValues) {\n    // Create a TreeInfo object to keep track of the current root index.\n    TreeInfo treeInfo(0);\n\n    // Call the helper function to reconstruct the BST from the given range and return the result.\n    return reconstructBstFromRange(INT_MIN, INT_MAX, preOrderTraversalValues, treeInfo);\n}\n\n// Recursive helper function to reconstruct the BST within a given range.\nTreeNode* reconstructBstFromRange(int lowerBound, int upperBound, std::vector<int>& preOrderTraversalValues, TreeInfo& currentSubtreeInfo) {\n    // Check if the root index has reached the end of the pre-order traversal values. If so, return nullptr indicating an empty subtree.\n    if (currentSubtreeInfo.rootIdx == preOrderTraversalValues.size()) {\n        return nullptr;\n    }\n\n    // Get the value of the current root from the pre-order traversal values.\n    int rootValue = preOrderTraversalValues[currentSubtreeInfo.rootIdx];\n\n    // Check if the root value is out of the valid range defined by the lower and upper bounds. If so, return nullptr indicating an invalid subtree.\n    if (rootValue < lowerBound || rootValue >= upperBound) {\n        return nullptr;\n    }\n\n    // Increment the root index to move to the next element in the pre-order traversal values.\n    currentSubtreeInfo.rootIdx++;\n\n    // Recursively reconstruct the left subtree within the range (lowerBound, rootValue) using the updated root index.\n    TreeNode* leftSubtree = reconstructBstFromRange(lowerBound, rootValue, preOrderTraversalValues, currentSubtreeInfo);\n\n    // Recursively reconstruct the right subtree within the range (rootValue, upperBound) using the updated root index.\n    TreeNode* rightSubtree = reconstructBstFromRange(rootValue, upperBound, preOrderTraversalValues, currentSubtreeInfo);\n\n    // Create a new TreeNode with the current root value and the reconstructed left and right subtrees.\n    TreeNode* rootNode = new TreeNode(rootValue);\n    rootNode->left = leftSubtree;\n    rootNode->right = rightSubtree;\n\n    return rootNode;\n}\n\n// Function to delete the BST and free memory.\nvoid deleteBst(TreeNode* root) {\n    if (root == nullptr) {\n        return;\n    }\n    deleteBst(root->left);\n    deleteBst(root->right);\n    delete root;\n}\n\nint main() {\n    std::vector<int> preOrderTraversalValues = {10, 5, 2, 7, 15, 12, 20};\n    TreeInfo treeInfo(0); // Initialize treeInfo with root index 0\n    TreeNode* root = reconstructBstFromRange(INT_MIN, INT_MAX, preOrderTraversalValues, treeInfo);\n\n    // Printing the reconstructed BST is left as an exercise\n\n    // Clean up memory\n    deleteBst(root);\n\n    return 0;\n}\n"
  },
  {
    "path": "Trees/Binary Search Trees/reconstruct_bst.go",
    "content": "/*\n\tReconstruct BST\n\tThe pre-order traversal of a Binary Tree is a traversal technique that starts at the tree's root node and visits nodes in the following order:\n\t\tCurrent Node\n\t\tLeft Subtree\n\t\tRight Subtree\n\n  \tGiven a non-empty array of integers representing the pre-order traversal of a Binary Search Tree (BST),\n\twrite a function that creates the relevant BST and returns its root node.\n\n    The input array will contain the values of BST nodes in the order in which these nodes would be visited with a pre-order traversal.\n\n\tSample Input: [10, 4, 2, 1, 5, 17, 19, 18]\n\tSample Output:\n\t    10\n      /    \\\n     4      17\n   /   \\      \\\n  2     5     19\n /           /\n1           18\n\n\tExplanation:\n\n\tApproach 1:\n\n\tThe ReconstructBst function takes a slice preOrderTraversalValues which represents the pre-order traversal of a binary search tree.\n\tIt reconstructs the BST using a recursive approach. Here's how the algorithm works:\n\n\tThe base case is defined when the preOrderTraversalValues slice is empty, in which case it returns nil indicating an empty tree.\n\n\tThe first element in the preOrderTraversalValues slice represents the current node value of the BST.\n\n\tThe algorithm finds the index (rightSubTreeRootIdx) where the right subtree starts by iterating over the remaining elements in\n\tthe preOrderTraversalValues slice and finding the first value greater than or equal to the current value.\n\n\tIt recursively calls ReconstructBst on the sub-array representing the left subtree (preOrderTraversalValues[1:rightSubTreeRootIdx])\n\tto reconstruct the left subtree.\n\n\tIt recursively calls ReconstructBst on the sub-array representing the right subtree (preOrderTraversalValues[rightSubTreeRootIdx:])\n\tto reconstruct the right subtree.\n\n\tFinally, it creates a new BST node with the current value, the reconstructed left subtree, and the reconstructed right subtree,\n\tand returns the node.\n\n\tThe algorithm builds the BST in a top-down manner by dividing the pre-order traversal values into left and right subtrees.\n\tIt constructs the left subtree first and then the right subtree.\n\n\tThe time complexity of the algorithm is O(n^2) in the worst case, where n is the number of nodes in the BST.\n\n\n\t******************************************************************************************\n\n\tApproach 2:\n\n\tThe ReconstructBst function takes a slice preOrderTraversalValues which represents the pre-order traversal of a binary search tree.\n\tIt reconstructs the BST using a range-based approach. Here's how the algorithm works:\n\n\tThe ReconstructBst function initializes a treeInfo struct to keep track of the current root index.\n\n\tThe ReconstructBst function calls the reconstructBSTFromRange helper function, passing the minimum and maximum integer values\n\tas the initial range, the pre-order traversal values, and the treeInfo struct.\n\n\tThe reconstructBSTFromRange function first checks if the current root index has reached the end of the pre-order traversal values.\n\tIf so, it returns nil indicating an empty subtree.\n\n\tIt retrieves the value of the current root from the pre-order traversal values.\n\n\tIt checks if the root value is outside the valid range defined by the lower and upper bounds. If so, it returns\n\n\tThe time complexity of the ReconstructBst function is O(n), where n is the number of nodes in the reconstructed BST.\n\tThis is because the function processes each node exactly once.\n\n\tThe space complexity of the ReconstructBst function is O(n), where n is the number of nodes in the reconstructed BST.\n\tThis is because the function creates BST nodes and recursively calls itself to construct the left and right subtrees.\n\tThe space complexity is determined by the height of the BST, which can be at most n in the worst case for a skewed BST.\n*/\npackage main\n\nimport \"math\"\n\n// BST represents a binary search tree node.\ntype BST struct {\n\tValue int\n\tLeft  *BST\n\tRight *BST\n}\n\n// Approach 1: Time complexity O(n^2) Space O(n), where n is length of input array\n// ReconstructBst takes a slice of integers representing the pre-order traversal of a BST and returns the reconstructed BST.\nfunc ReconstructBst(preOrderTraversalValues []int) *BST {\n\t// Base case: If the pre-order traversal is empty, return nil indicating an empty tree.\n\tif len(preOrderTraversalValues) == 0 {\n\t\treturn nil\n\t}\n\n\t// Get the current value from the pre-order traversal values.\n\tcurrentVal := preOrderTraversalValues[0]\n\n\t// Find the index where the right subtree starts by searching for the first value greater than or equal to the current value.\n\trightSubTreeRootIdx := len(preOrderTraversalValues)\n\tfor i := 1; i < len(preOrderTraversalValues); i++ {\n\t\tvalue := preOrderTraversalValues[i]\n\t\tif value >= currentVal {\n\t\t\trightSubTreeRootIdx = i\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// Recursively reconstruct the left and right subtrees by calling the ReconstructBst function on the appropriate sub-arrays.\n\tleftSubTree := ReconstructBst(preOrderTraversalValues[1:rightSubTreeRootIdx])\n\trightSubTree := ReconstructBst(preOrderTraversalValues[rightSubTreeRootIdx:])\n\n\t// Create a new BST node with the current value and the reconstructed left and right subtrees.\n\treturn &BST{Value: currentVal, Left: leftSubTree, Right: rightSubTree}\n}\n\n\n// Approach 2: Time complexity O(n) Space O(n), where n is length of input array\n\n// treeInfo is a helper struct to keep track of the current root index during the reconstruction process.\ntype treeInfo struct {\n\trootIdx int\n}\n\n// ReconstructBst takes a slice of integers representing the pre-order traversal of a BST and returns the reconstructed BST.\nfunc ReconstructBst2(preOrderTraversalValues []int) *BST {\n\t// Create a treeInfo struct to keep track of the current root index.\n\ttreeInfo := &treeInfo{rootIdx: 0}\n\n\t// Call the helper function to reconstruct the BST from the given range and return the result.\n\treturn reconstructBSTFromRange(math.MinInt32, math.MaxInt32, preOrderTraversalValues, treeInfo)\n}\n\n// reconstructBSTFromRange reconstructs the BST recursively within the given range using the pre-order traversal values.\nfunc reconstructBSTFromRange(lowerBound, upperBound int, preOrderTraversalValues []int, currentSubtreeInfo *treeInfo) *BST {\n\t// Check if the root index has reached the end of the pre-order traversal values. If so, return nil indicating an empty subtree.\n\tif currentSubtreeInfo.rootIdx == len(preOrderTraversalValues) {\n\t\treturn nil\n\t}\n\n\t// Get the value of the current root from the pre-order traversal values.\n\trootValue := preOrderTraversalValues[currentSubtreeInfo.rootIdx]\n\n\t// Check if the root value is out of the valid range defined by the lower and upper bounds. If so, return nil indicating an invalid subtree.\n\tif rootValue < lowerBound || rootValue >= upperBound {\n\t\treturn nil\n\t}\n\n\t// Increment the root index to move to the next element in the pre-order traversal values.\n\tcurrentSubtreeInfo.rootIdx++\n\n\t// Recursively reconstruct the left subtree within the range (lowerBound, rootValue) using the updated root index.\n\tleftSubtree := reconstructBSTFromRange(lowerBound, rootValue, preOrderTraversalValues, currentSubtreeInfo)\n\n\t// Recursively reconstruct the right subtree within the range (rootValue, upperBound) using the updated root index.\n\trightSubtree := reconstructBSTFromRange(rootValue, upperBound, preOrderTraversalValues, currentSubtreeInfo)\n\n\t// Create a new BST node with the current root value and the reconstructed left and right subtrees.\n\treturn &BST{Value: rootValue, Left: leftSubtree, Right: rightSubtree}\n}\n"
  },
  {
    "path": "Trees/Binary Search Trees/reconstruct_bst.java",
    "content": "/*\n    Reconstruct BST\n\tThe pre-order traversal of a Binary Tree is a traversal technique that starts at the tree's root node and visits nodes in the following order:\n\t\tCurrent Node\n\t\tLeft Subtree\n\t\tRight Subtree\n\n  \tGiven a non-empty array of integers representing the pre-order traversal of a Binary Search Tree (BST),\n\twrite a function that creates the relevant BST and returns its root node.\n\n    The input array will contain the values of BST nodes in the order in which these nodes would be visited with a pre-order traversal.\n\n\tSample Input: [10, 4, 2, 1, 5, 17, 19, 18]\n\tSample Output:\n\t    10\n      /    \\\n     4      17\n   /   \\      \\\n  2     5     19\n /           /\n1           18\n\n    The ReconstructBst function takes a slice preOrderTraversalValues which represents the pre-order traversal of a binary search tree.\n\tIt reconstructs the BST using a range-based approach. Here's how the algorithm works:\n\n\tThe ReconstructBst function initializes a treeInfo struct to keep track of the current root index.\n\n\tThe ReconstructBst function calls the reconstructBSTFromRange helper function, passing the minimum and maximum integer values\n\tas the initial range, the pre-order traversal values, and the treeInfo struct.\n\n\tThe reconstructBSTFromRange function first checks if the current root index has reached the end of the pre-order traversal values.\n\tIf so, it returns nil indicating an empty subtree.\n\n\tIt retrieves the value of the current root from the pre-order traversal values.\n\n\tIt checks if the root value is outside the valid range defined by the lower and upper bounds. If so, it returns\n\n\tThe time complexity of the ReconstructBst function is O(n), where n is the number of nodes in the reconstructed BST.\n\tThis is because the function processes each node exactly once.\n\n\tThe space complexity of the ReconstructBst function is O(n), where n is the number of nodes in the reconstructed BST.\n\tThis is because the function creates BST nodes and recursively calls itself to construct the left and right subtrees.\n\tThe space complexity is determined by the height of the BST, which can be at most n in the worst case for a skewed BST.\n\n*/\nclass TreeNode {\n    int value;\n    TreeNode left;\n    TreeNode right;\n\n    TreeNode(int x) {\n        value = x;\n        left = null;\n        right = null;\n    }\n}\n\nclass TreeInfo {\n    int rootIdx;\n\n    TreeInfo(int idx) {\n        rootIdx = idx;\n    }\n}\n\npublic class ReconstructBST {\n\n    public static TreeNode reconstructBst(int[] preOrderTraversalValues) {\n        // Create a TreeInfo object to keep track of the current root index.\n        TreeInfo treeInfo = new TreeInfo(0);\n\n        // Call the helper function to reconstruct the BST from the given range and return the result.\n        return reconstructBstFromRange(Integer.MIN_VALUE, Integer.MAX_VALUE, preOrderTraversalValues, treeInfo);\n    }\n\n    private static TreeNode reconstructBstFromRange(int lowerBound, int upperBound, int[] preOrderTraversalValues, TreeInfo currentSubtreeInfo) {\n        // Check if the root index has reached the end of the pre-order traversal values. If so, return null indicating an empty subtree.\n        if (currentSubtreeInfo.rootIdx == preOrderTraversalValues.length) {\n            return null;\n        }\n\n        // Get the value of the current root from the pre-order traversal values.\n        int rootValue = preOrderTraversalValues[currentSubtreeInfo.rootIdx];\n\n        // Check if the root value is out of the valid range defined by the lower and upper bounds. If so, return null indicating an invalid subtree.\n        if (rootValue < lowerBound || rootValue >= upperBound) {\n            return null;\n        }\n\n        // Increment the root index to move to the next element in the pre-order traversal values.\n        currentSubtreeInfo.rootIdx++;\n\n        // Recursively reconstruct the left subtree within the range (lowerBound, rootValue) using the updated root index.\n        TreeNode leftSubtree = reconstructBstFromRange(lowerBound, rootValue, preOrderTraversalValues, currentSubtreeInfo);\n\n        // Recursively reconstruct the right subtree within the range (rootValue, upperBound) using the updated root index.\n        TreeNode rightSubtree = reconstructBstFromRange(rootValue, upperBound, preOrderTraversalValues, currentSubtreeInfo);\n\n        // Create a new TreeNode with the current root value and the reconstructed left and right subtrees.\n        TreeNode rootNode = new TreeNode(rootValue);\n        rootNode.left = leftSubtree;\n        rootNode.right = rightSubtree;\n\n        return rootNode;\n    }\n\n    public static void main(String[] args) {\n        int[] preOrderTraversalValues = {10, 5, 2, 7, 15, 12, 20};\n        TreeNode root = reconstructBst(preOrderTraversalValues);\n\n        // Printing the reconstructed BST is left as an exercise\n    }\n}\n"
  },
  {
    "path": "Trees/Binary Search Trees/reconstruct_bst.js",
    "content": "/** Reconstruct BST\n\tThe pre-order traversal of a Binary Tree is a traversal technique that starts at the tree's root \n        node and visits nodes in the following order:\n\t\tCurrent Node\n\t\tLeft Subtree\n\t\tRight Subtree\n\n  \tGiven a non-empty array of integers representing the pre-order traversal of a Binary Search Tree \n        (BST), write a function that creates the relevant BST and returns its root node.\n\n        The input array will contain the values of BST nodes in the order in which these nodes would be \n        visited with a pre-order traversal.\n\tSample Input: [10, 4, 2, 1, 5, 17, 19, 18]\n\tSample Output:\n\t      10\n      /    \\\n     4      17\n   /   \\      \\\n  2     5     19\n /           /\n1           18         \n*/\n/**\n * Class representing a node in the Binary Search Tree (BST).\n */\n class TreeNode {\n    /**\n     * Create a new TreeNode.\n     * @param {*} value - The value to be stored in the node.\n     */\n    constructor(value) {\n      this.val = value;\n      this.left = null;\n      this.right = null;\n    }\n  }\n  \n  /**\n   * Reconstructs a Binary Search Tree (BST) from its pre-order traversal.\n   * @param {number[]} preorder - The pre-order traversal array of the BST.\n   * @return {TreeNode} - The root node of the reconstructed BST.\n   */\n  function constructBST(preorder) {\n    // Base case: if the array is empty, return null\n    if (preorder.length === 0) {\n      return null;\n    }\n  \n    // The first element in the pre-order array is the root value\n    const rootValue = preorder[0];\n    const rootNode = new TreeNode(rootValue);\n  \n    // Find the index where the elements are greater than the root value\n    let i = 1;\n    while (i < preorder.length && preorder[i] < rootValue) {\n      i++;\n    }\n  \n    // Split the remaining elements into left and right subtrees\n    const leftSubtree = preorder.slice(1, i);\n    const rightSubtree = preorder.slice(i);\n  \n    // Recursively construct the left and right subtrees\n    rootNode.left = constructBST(leftSubtree);\n    rootNode.right = constructBST(rightSubtree);\n  \n    return rootNode;\n  }\n  \n  // Example usage\n  const preorder = [10, 4, 2, 1, 5, 17, 19, 18];\n  const root = constructBST(preorder);\n  \n  /**\n   * Prints the values of the BST in ascending order using an in-order traversal.\n   * @param {TreeNode} node - The root node of the BST.\n   */\n  function printInOrder(node) {\n    if (node === null) {\n      return;\n    }\n  \n    printInOrder(node.left);\n    console.log(node.val);\n    printInOrder(node.right);\n  }\n  \n  // Print the values of the reconstructed BST in ascending order\n  printInOrder(root);\n\n/** \n * The time complexity of the constructBST function can be analyzed as follows:\n\nIn each recursive call, we split the pre-order traversal array into two parts based on the root value. This operation takes O(N) time, where N is the number of elements in the array.\nSince the function is called recursively for the left and right subtrees, the total time complexity can be expressed as a summation of the work done in each recursive call.\nIn the worst case, the pre-order traversal array is completely unbalanced, resulting in a linear chain of nodes. In this case, the function will make N recursive calls, each taking O(N) time.\nTherefore, the overall time complexity of the constructBST function is O(N^2) in the worst case.\nHowever, in the average case, when the BST is balanced, the time complexity can be approximated as O(NlogN).\n */\n\n/**\n * In each recursive call, the function creates new arrays for the left and right subtrees using the slice method. The space required for these arrays is proportional to the size of the pre-order traversal array.\nIn the worst case, when the BST is completely unbalanced, the size of the arrays will be O(N), where N is the number of elements in the pre-order traversal array.\nTherefore, the overall space complexity of the `constructBST function is O(N) in the worst case.\n */"
  },
  {
    "path": "Trees/Binary Search Trees/reconstruct_bst.py",
    "content": "'''\n    Reconstruct BST\n\tThe pre-order traversal of a Binary Tree is a traversal technique that starts at the tree's root node and visits nodes in the following order:\n\t\tCurrent Node\n\t\tLeft Subtree\n\t\tRight Subtree\n\n  \tGiven a non-empty array of integers representing the pre-order traversal of a Binary Search Tree (BST),\n\twrite a function that creates the relevant BST and returns its root node.\n\n    The input array will contain the values of BST nodes in the order in which these nodes would be visited with a pre-order traversal.\n\n\tSample Input: [10, 4, 2, 1, 5, 17, 19, 18]\n\tSample Output:\n\t    10\n      /    \\\n     4      17\n   /   \\      \\\n  2     5     19\n /           /\n1           18\n\n    The ReconstructBst function takes a slice preOrderTraversalValues which represents the pre-order traversal of a binary search tree.\n\tIt reconstructs the BST using a range-based approach. Here's how the algorithm works:\n\n\tThe ReconstructBst function initializes a treeInfo struct to keep track of the current root index.\n\n\tThe ReconstructBst function calls the reconstructBSTFromRange helper function, passing the minimum and maximum integer values\n\tas the initial range, the pre-order traversal values, and the treeInfo struct.\n\n\tThe reconstructBSTFromRange function first checks if the current root index has reached the end of the pre-order traversal values.\n\tIf so, it returns nil indicating an empty subtree.\n\n\tIt retrieves the value of the current root from the pre-order traversal values.\n\n\tIt checks if the root value is outside the valid range defined by the lower and upper bounds. If so, it returns\n\n\tThe time complexity of the ReconstructBst function is O(n), where n is the number of nodes in the reconstructed BST.\n\tThis is because the function processes each node exactly once.\n\n\tThe space complexity of the ReconstructBst function is O(n), where n is the number of nodes in the reconstructed BST.\n\tThis is because the function creates BST nodes and recursively calls itself to construct the left and right subtrees.\n\tThe space complexity is determined by the height of the BST, which can be at most n in the worst case for a skewed BST.\n\n'''\nclass TreeNode:\n    def __init__(self, val):\n        self.val = val\n        self.left = None\n        self.right = None\n\nclass TreeInfo:\n    def __init__(self, root_idx):\n        self.root_idx = root_idx\n\ndef reconstruct_bst(pre_order_traversal_values):\n    # Create a TreeInfo object to keep track of the current root index.\n    tree_info = TreeInfo(0)\n\n    # Call the helper function to reconstruct the BST from the given range and return the result.\n    return reconstruct_bst_from_range(float('-inf'), float('inf'), pre_order_traversal_values, tree_info)\n\ndef reconstruct_bst_from_range(lower_bound, upper_bound, pre_order_traversal_values, current_subtree_info):\n    # Check if the root index has reached the end of the pre-order traversal values. If so, return None indicating an empty subtree.\n    if current_subtree_info.root_idx == len(pre_order_traversal_values):\n        return None\n\n    # Get the value of the current root from the pre-order traversal values.\n    root_value = pre_order_traversal_values[current_subtree_info.root_idx]\n\n    # Check if the root value is out of the valid range defined by the lower and upper bounds. If so, return None indicating an invalid subtree.\n    if root_value < lower_bound or root_value >= upper_bound:\n        return None\n\n    # Increment the root index to move to the next element in the pre-order traversal values.\n    current_subtree_info.root_idx += 1\n\n    # Recursively reconstruct the left subtree within the range (lower_bound, root_value) using the updated root index.\n    left_subtree = reconstruct_bst_from_range(lower_bound, root_value, pre_order_traversal_values, current_subtree_info)\n\n    # Recursively reconstruct the right subtree within the range (root_value, upper_bound) using the updated root index.\n    right_subtree = reconstruct_bst_from_range(root_value, upper_bound, pre_order_traversal_values, current_subtree_info)\n\n    # Create a new TreeNode with the current root value and the reconstructed left and right subtrees.\n    root_node = TreeNode(root_value)\n    root_node.left = left_subtree\n    root_node.right = right_subtree\n\n    return root_node\n\n# Example usage:\npre_order_traversal_values = [10, 5, 2, 7, 15, 12, 20]\ntree_info = TreeInfo(0)  # Initialize tree_info with root index 0\nroot = reconstruct_bst_from_range(float('-inf'), float('inf'), pre_order_traversal_values, tree_info)\n\n# Printing the reconstructed BST is left as an exercise\n"
  },
  {
    "path": "Trees/Binary Search Trees/search.cpp",
    "content": "// Binary Search Tree : Searching in Binary Search Tree\n// Program Author : Abhisek Kumar Gupta\n/*\n    Input :  7 3 9 2 4 8 10 -1\n    Value to be searched : 99\n    Output : \n                  7\n                /   \\\n               3     9\n              / \\   / \\ \n             2  4  8  10\n            Not present in BST\n    Value to be searched : 8   \n            Present in BST      \n*/\n#include<bits/stdc++.h>\nusing namespace std;\n\nclass Node{\n    public:\n        int data;\n        Node* left;\n        Node* right;\n\n        Node(int x){\n            data = x;\n            left = NULL;\n            right = NULL;\n        }\n};\nvoid bfs(Node* root){\n    queue<Node*> q;\n    q.push(root);\n    q.push(NULL);\n    while(!q.empty()){\n        Node* element = q.front();\n        if(element == NULL){\n            cout << \"\\n\";\n            q.pop();\n            if(!q.empty()){\n                q.push(NULL);\n            }\n        }\n        else{\n            cout << element->data << \"->\";\n            q.pop();\n            if(element->left != NULL){\n                q.push(element->left);\n            }\n            if(element->right != NULL){\n                q.push(element->right);\n            }\n        }\n    }\n    return;\n}\nNode* insert_into_binary_search_tree(Node* root, int data){\n    if(root == NULL){\n        return new Node(data);\n    }\n    if(data <= root->data){\n        root->left = insert_into_binary_search_tree(root->left, data);\n    }\n    else{\n        root->right = insert_into_binary_search_tree(root->right, data);\n    }\n    return root;\n}\nNode* build_binary_search_tree(){\n    int data;\n    cin >> data;\n    Node* root = NULL;\n    while(data != -1){\n        root = insert_into_binary_search_tree(root, data);\n        cin >> data;\n    }\n    return root;\n}\nbool search_in_BST(Node* root, int value_to_be_searched){\n    if(root == NULL)\n        return false;\n    if(value_to_be_searched == root->data)\n        return true;\n    if(value_to_be_searched <= root->data){\n        return search_in_BST(root->left, value_to_be_searched);\n    }\n    else{\n        return search_in_BST(root->right, value_to_be_searched);\n    }        \n}\nint main(){\n    Node* root = build_binary_search_tree();\n    bfs(root);\n    int value_to_be_searched;\n    cin >> value_to_be_searched;\n    if(search_in_BST(root, value_to_be_searched)){\n        cout << \"Present in BST\\n\";\n    }\n    else{\n        cout << \"Not present in BST\\n\";\n    }\n    return 0;\n}\n"
  },
  {
    "path": "Trees/Binary Search Trees/validate_bst.go",
    "content": "/*\n\tWrite a function that takes in a potentially invalid Binary Search Tree (BST)\n  \tand returns a boolean representing whether the BST is valid.\n  \tSample Input :\n   \t     10\n       /     \\\n      5      15\n    /   \\   /   \\\n   2     5 13   22\n /           \\\n1            14\n\tOutput : True\n\n\tExplanation:\n\tThis code defines a Binary Search Tree (BST) struct with an integer value and left and right nodes that can \n\tpoint to other BST nodes. The struct also has a method called ValidateBst() that returns a boolean indicating \n\twhether the tree is a valid BST or not.\n\n\tThe BST struct has another method called validateBST() that is used by ValidateBst() to check whether the tree\n\tis a valid BST or not. The validateBST() method takes in two arguments, min and max, which represent the minimum \n\tand maximum values that the current node's value can take in order to be a valid BST.\n\n\tThe validateBST() method first checks whether the current node's value is within the valid range determined \n\tby the min and max arguments. If not, the method returns false, indicating that the tree is not a valid BST.\n\n\tIf the current node's value is within the valid range, the method then recursively calls itself on the left \n\tand right child nodes to check whether their values are within their valid ranges. The valid range for the \n\tleft child node is defined by the minimum value and the parent node's value, while the valid range for the \n\tright child node is defined by the parent node's value and the maximum value.\n\n\tIf all of the nodes in the tree satisfy the BST property, the method returns true, indicating that the tree \n\tis a valid BST.\n\n\tO(n) time | O(d) space - where n is the number of nodes in the BST and d is the depth (height) of the BST\n\n*/\npackage main\n\nimport \"math\"\n\ntype BST struct {\n\tValue int\n\n\tLeft  *BST\n\tRight *BST\n}\n\n// ValidateBst is a method of BST that checks if the binary search tree is valid\nfunc (tree *BST) ValidateBst() bool {\n\treturn tree.validateBST(math.MinInt32, math.MaxInt32)\n}\n\n// validateBST is a recursive helper function that checks if the binary search tree is valid\n// min is the minimum value that a node in the subtree rooted at this node can have\n// max is the maximum value that a node in the subtree rooted at this node can have\nfunc (tree *BST) validateBST(min, max int) bool {\n\t// if the current node's value is outside the allowed range, then the tree is invalid\n\tif tree.Value < min || tree.Value >= max {\n\t\treturn false\n\t}\n\t// recursively check the left subtree, making sure all values are less than the current node's value\n\tif tree.Left != nil && !tree.Left.validateBST(min, tree.Value) {\n\t\treturn false\n\t}\n\t// recursively check the right subtree, making sure all values are greater than or equal to the current node's value\n\tif tree.Right != nil && !tree.Right.validateBST(tree.Value, max) {\n\t\treturn false\n\t}\n\t// if we reach this point, then the tree is valid\n\treturn true\n}\n"
  },
  {
    "path": "Trees/Binary Trees/Trie.js",
    "content": "/*\nDescription\nA trie (pronounced as \"try\") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.\n\nImplement the Trie class:\n\nTrie() Initializes the trie object.\nvoid insert(String word) Inserts the string word into the trie.\nboolean search(String word) Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.\nboolean startsWith(String prefix) Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise.\n\nInput\n[\"Trie\", \"insert\", \"search\", \"search\", \"startsWith\", \"insert\", \"search\"]\n[[], [\"apple\"], [\"apple\"], [\"app\"], [\"app\"], [\"app\"], [\"app\"]]\nOutput\n[null, null, true, false, true, null, true]\n\nExplanation\nTrie trie = new Trie();\ntrie.insert(\"apple\");\ntrie.search(\"apple\");   // return True\ntrie.search(\"app\");     // return False\ntrie.startsWith(\"app\"); // return True\ntrie.insert(\"app\");\ntrie.search(\"app\");     // return True\n\nTime Complexity for each operation is O(n)\nSpace Complexity O(n*m) where n is the number of words inserted and m is the average length of the words.\n\nExplanation:\ninsert() -> traverse through each character of the input word and initializes it if necessary. If the end of the word is reached set isEnd to true.\nsearch() -> Search In each child node until the end of the word is reached, then if end of the node is also reached return true else false.\nstartsWith() -> Similar to search method but we only check if end of the prefix is reached and we don't need to check if it is the end of the node.\n\n*/\n\n\nclass Trie {\n  constructor() {\n    this.root = new Node();\n  }\n\n  insert(word) {\n    this.root.insert(word, 0);\n  }\n\n  search(word) {\n    return this.root.search(word, 0);\n  }\n\n  startsWith(prefix) {\n    return this.root.startsWith(prefix, 0);\n  }\n}\n\nclass Node {\n  constructor() {\n    this.nodes = new Array(26);\n    this.isEnd = false;\n  }\n\n  // Function to insert the word in the tree\n  insert(word, idx) {\n    if (idx >= word.length) return; // handle edge case\n    const i = word.charCodeAt(idx) - 'a'.charCodeAt(0);\n    if (!this.nodes[i]) {\n      this.nodes[i] = new Node();   // initialize the node[i] if the letter was not found before\n    }\n\n    if (idx === word.length - 1) this.nodes[i].isEnd = true;    // signifies that this is the end of the word\n    this.nodes[i].insert(word, idx + 1);    // recursive call to populate the child node\n  }\n\n  // Function to search the word in the tree\n  search(word, idx) {\n    if (idx >= word.length) return false;\n    const node = this.nodes[word.charCodeAt(idx) - 'a'.charCodeAt(0)];\n    if (!node) return false;    // if the node is null it means that it was not initialised hence the character was never found.\n    if (idx === word.length - 1 && node.isEnd) return true; //if it is the last character and the end of the node then return true\n\n    return node.search(word, idx + 1);  // recursive call search in the child node\n  }\n\n  //Function to search the prefix in tree\n  startsWith(prefix, idx) {\n    if (idx >= prefix.length) return false;\n    const node = this.nodes[prefix.charCodeAt(idx) - 'a'.charCodeAt(0)];\n    if (!node) return false;\n    if (idx === prefix.length - 1) return true; // Very similar to above method but here we don't need to check if it is the end of the node.\n\n    return node.startsWith(prefix, idx + 1);\n  }\n}\n"
  },
  {
    "path": "Trees/Binary Trees/bfs.cpp",
    "content": "// Binary Tree : Breadth First Search TC : O(n)\n// Program Author : Abhisek Kumar Gupta\n/*\n            40\n            /   \\\n        10      30\n        / \\     /  \\\n       5  -1  -1  28\n      / \\        /  \\\n    1   -1      15    20\n   / \\          /\\    /\\\n   1 -1        -1 -1 -1 -1\n   /\\\n -1 -1\n    Input : 40 10 5 1 1 -1 -1 -1 -1 -1 30 -1 28 15 -1 -1 20 -1 -1\n    Output : 40 10 30 5 28 1 15 20 1    \n*/\n\n#include<bits/stdc++.h>\nusing namespace std;\n\nclass Node{\n    public:\n        int data;\n        Node* left;\n        Node* right;\n\n        Node(int x){\n            data = x;\n        }\n};\n\nNode* build_binary_tree(){\n    int data;\n    cin >> data;\n    if(data == -1)\n        return NULL;\n    Node* root = new Node(data);\n    root->left = build_binary_tree();\n    root->right = build_binary_tree();\n    return root;    \n}\nvoid bfs(Node* root){\n    queue<Node*> q;\n    q.push(root);\n    while(!q.empty()){\n        Node* element = q.front();\n        cout << element->data << \"->\";\n        q.pop();\n        if(element->left != NULL){\n            q.push(element->left);\n        }\n        if(element->right != NULL){\n            q.push(element->right);\n        }\n    }\n    return;\n}\nint main(){\n    Node* root = build_binary_tree();\n    bfs(root);\n    return 0;\n}"
  },
  {
    "path": "Trees/Binary Trees/bfs.go",
    "content": "/*\n\tBreadth First Search:\n\tSample Input:\n\t\tA\n     /  |  \\\n    B   C   D\n   / \\     / \\\n  E   F   G   H\n     / \\   \\\n    I   J   K\n\tOutput: [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\"]\n\n\tExplanation:\n\tThis code defines a struct `Node` with two properties: `Name`, a string representing the name of the node,\n\tand `Children`, a slice of pointers to other `Node` objects representing the children of the node.\n\n\tThe method `BreadthFirstSearch` is defined on `Node`. This method takes an empty string slice `array` as\n\tan argument and performs a breadth-first search traversal of the tree rooted at the current node.\n\n\tIt returns a slice of strings representing the names of the nodes visited in breadth-first order.\n\n\tThe breadth-first search algorithm starts with a queue containing only the current node. The algorithm then proceeds as follows:\n\n\t1. Dequeue the first node from the queue.\n\t2. Add the name of the dequeued node to the `array`.\n\t3. Enqueue all the children of the dequeued node to the end of the queue.\n\t4. Repeat steps 1-3 until the queue is empty.\n\n\tAt the end of the algorithm, the `array` contains the names of all the nodes visited in breadth-first order. The method returns this `array`.\n\n\tTime complexity: O(v + e)\n\tSpace complexity: O(v)\n\twhere v is the number of vertices of the input graph and e is the number of edges of the input graph\n*/\npackage main\n\n// Define a Node struct that has a name and a slice of child nodes.\ntype Node struct {\n\tName     string\n\tChildren []*Node\n}\n\n// Define a method BreadthFirstSearch on the Node struct that takes an array of strings as an argument.\n// This method performs a breadth-first search on the tree starting from the node the method is called on.\n// It appends the names of all nodes visited to the input array and returns the modified array.\nfunc (n *Node) BreadthFirstSearch(array []string) []string {\n\t// Create a queue of nodes starting with the current node.\n\tqueue := []*Node{n}\n\t\n\t// While there are still nodes in the queue to be visited:\n\tfor len(queue) > 0 {\n\t\t// Dequeue the first node in the queue and add its name to the array.\n\t\tcurrent := queue[0]\n\t\tqueue = queue[1:]\n\t\tarray = append(array, current.Name)\n\n\t\t// Add all of the node's children to the end of the queue.\n\t\tfor _, child := range current.Children {\n\t\t\tqueue = append(queue, child)\n\t\t}\n\t}\n\n\t// Return the modified array.\n\treturn array\n}\n"
  },
  {
    "path": "Trees/Binary Trees/binary_tree.go",
    "content": "/*\n\tA tree is called binary tree if each node has zero child, one child or two children. Empty tree is also a valid binary\n\ttree. We can visualize a binary tree as consisting of a root and two disjoint binary trees, called the left and right\n\tsubtrees of the root.\n\n\tTypes of Binary Trees\n\t1) Strict Binary Tree: A binary tree is called  strict binary tree if each node has exactly two children or no children.\n\t2) Full Binary Tree: A binary tree is called full binary tree if each node has exactly two children and all leaf nodes\n\t   are at the same level.\n\t3) Complete Binary Tree: Before defining the complete binary tree, let us assume that the height of the binary tree\n\t   is ℎ. In complete binary trees, if we give numbering for the nodes by starting at the root (let us say the root node\n\t   has 1) then we get a complete sequence from 1 to the number of nodes in the tree. While traversing we should give\n\t   numbering for nil pointers also. A binary tree is called complete binary tree if all leaf nodes are at height ℎ or ℎ − 1\n\t   and also without any missing number in the sequence.\n\n\t              1\n                /   \\\n               2      3\n              / \\    / \\\n             4   5  6   7\n*/\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n)\n\ntype BinaryTreeNode struct {\n\tleft  *BinaryTreeNode\n\tdata  int\n\tright *BinaryTreeNode\n}\n// NewBinaryTree returns a new, random binary tree\nfunc NewBinaryTree(n, k int) *BinaryTreeNode {\n\tvar root * BinaryTreeNode\n\tfor _, v := range rand.Perm(n) {\n\t\troot = Insert(root, (1 + v) * k)\n\t}\n\treturn root\n}\n// Insert, inserts an element in binary tree \nfunc Insert(root *BinaryTreeNode, v int) *BinaryTreeNode {\n\tif root == nil {\n\t\t// fmt.Printf(\"%d root\", v)\n\t\treturn &BinaryTreeNode{nil, v, nil}\n\t}\n\t// data less than root of data the insert in left subtree\n\tif v < root.data {\n\t\t// fmt.Printf(\"%d left\\n\", v)\n\t\troot.left = Insert(root.left, v)\n\t\treturn root\n\t}\n\t// data greater than or equal to root of data the insert in right subtree\n\t// fmt.Printf(\"%d right\\n\", v)\n\troot.right = Insert(root.right, v)\n\treturn root\n}\n\n// Pre-order traversal\n// Preorder traversal is defined as follows:\n// 1 Visit the root.\n// 2 Traverse the left subtree in Preorder.\n// 3 Traverse the right subtree in Preorder.\n// Time Complexity: O(n). Space Complexity: O(n).\n// The nodes of tree would be visited in the order: 1 2 4 5 3 6 7\nfunc PreOrder(root *BinaryTreeNode) {\n\n\tif root == nil {\n\t\treturn\n\t}\n\tfmt.Printf(\"%d \", root.data)\n\tPreOrder(root.left)\n\tPreOrder(root.right)\n}\n\n// Inorder traversal is defined as follows:\n// 1 Traverse the left subtree in Inorder.\n// 2 Visit the root.\n// 3 Traverse the right subtree in Inorder.\n// Time Complexity: O(n). Space Complexity: O(n).\n// The nodes of tree would be visited in the order: 4 2 5 1 6 3 7\nfunc InOrder(root *BinaryTreeNode) {\n\tif root == nil {\n\t\treturn\n\t}\n\tInOrder(root.left)\n\tfmt.Printf(\"%d\", root.data)\n\tInOrder(root.right)\n}\n\n// PostOrder traversal is defined as follows:\n// 1 Traverse the left subtree in PostOrder.\n// 2 Traverse the right subtree in PostOrder.\n// 3 Visit the root.\n// The nodes of the tree would be visited in the order: 4 5 2 6 7 3 1\nfunc PostOrder(root *BinaryTreeNode) {\n\tif root == nil {\n\t\treturn\n\t}\n\tPostOrder(root.left)\n\tPostOrder(root.right)\n\tfmt.Printf(\"%d\", root.data)\n}\n\n\n\nfunc main() {\n\tt1 := NewBinaryTree(10, 1)\n\tPreOrder(t1)\n\tfmt.Println()\n\tInOrder(t1)\n\tfmt.Println()\n\tPostOrder(t1)\n\tfmt.Println()\n}"
  },
  {
    "path": "Trees/Binary Trees/branch_sum.go",
    "content": "/*\n  Write a function that takes in a Binary Tree and returns a list of its branch\n  sums ordered from leftmost branch sum to rightmost branch sum.\n\n  A branch sum is the sum of all values in a Binary Tree branch. A Binary Tree\n  branch is a path of nodes in a tree that starts at the root node and ends at\n  any leaf node.\n\n  Sample INput:\n           1\n        /     \\\n       2       3\n     /   \\    /  \\\n    4     5  6    7\n  /   \\  /\n 8    9 10\n\n Output: [15, 16, 18, 10, 11] length of output will be always total number of leaves\n Time and Space complexity : O(n) time | O(n) space - where n is the number of nodes in the Binary Tree\n*/\npackage main\n\ntype BinaryTree struct {\n\tValue int\n\tLeft  *BinaryTree\n\tRight *BinaryTree\n}\n\nfunc BranchSums(root *BinaryTree) []int {\n\tsums := []int{}\n    calculateBranchSums(root, 0, &sums)\n    return sums\n}\n/*\n\nAs you recursively traverse the tree, if you reach a leaf node \n(a node with no \"left\" or \"right\" Binary Tree nodes), \nadd the relevant running sum that you've calculated to a list of \nsums (which you'll also have to pass to the recursive function). \nIf you reach a node that isn't a leaf node, keep recursively traversing \nits children nodes, passing the correctly updated running sum to them.\n*/\nfunc calculateBranchSums(node *BinaryTree, runningSum int, sums *[]int) {\n    if node == nil {\n        return\n    }\n    runningSum += node.Value\n    if node.Left == nil && node.Right == nil {\n        *sums = append(*sums, runningSum)\n    }\n    calculateBranchSums(node.Left, runningSum, sums)\n    calculateBranchSums(node.Right, runningSum, sums)\n}"
  },
  {
    "path": "Trees/Binary Trees/build_tree_preorder.cpp",
    "content": "// Pre-Order Traversal of a Binary-Tree\n// Program Author : Abhisek Kumar Gupta\n#include<bits/stdc++.h>\nusing namespace std;\nclass Node{\n    public: \n        int data;\n        Node *left;\n        Node *right;\n\n        Node(int x){\n            data = x;\n            left = NULL;\n            right = NULL;\n        }\n\n};\n\nNode* build_binary_tree(){\n    int data;\n    cin >> data;\n    if(data == -1)\n        return NULL;\n    Node* root = new Node(data);\n    root->left = build_binary_tree();\n    root->right = build_binary_tree();\n    return root;     \n}\n\nvoid print_binary_tree(Node* root){\n    if(root == NULL)\n        return;\n    cout << root->data << \"->\";\n    print_binary_tree(root->left);\n    print_binary_tree(root->right);    \n}\n\nint main(){\n    Node* root = build_binary_tree();\n    print_binary_tree(root);\n}"
  },
  {
    "path": "Trees/Binary Trees/calculate_size.go",
    "content": "// Size of binary tree\npackage main\n\ntype BinaryTreeNode struct {\n\tleft  *BinaryTreeNode\n\tdata  int\n\tright *BinaryTreeNode\n}\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: calculate the size of left and right subtree recursively\n// add 1 (curr node) and return to its parent\nfunc Size(root *BinaryTreeNode) int {\n\tif root == nil {\n\t\treturn 0\n\t} else {\n\t\treturn Size(root.left) + 1 + Size(root.right)\n\t}\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: use level order traversal and count nodes\nfunc SizeWithoutUsingRecursion(root *BinaryTreeNode) int {\n\tif root == nil {\n\t\treturn 0\n\t}\n\tvar result int\n\tqueue := []*BinaryTreeNode{root}\n\tfor len(queue) > 0 {\n\t\tqlen := len(queue)\n\t\t//var level []int\n\t\tfor i := 0; i < qlen; i++ {\n\t\t\tnode := queue[0]\n\t\t\tresult++\n\t\t\t//level = append(level, node.data)\n\t\t\tqueue = queue[1:]\n\t\t\tif node.left != nil {\n\t\t\t\tqueue = append(queue, node.left)\n\t\t\t}\n\t\t\tif node.right != nil {\n\t\t\t\tqueue = append(queue, node.right)\n\t\t\t}\n\t\t}\n\t}\n\treturn result\n}"
  },
  {
    "path": "Trees/Binary Trees/count_nodes.cpp",
    "content": "// Binary Tree : Count Number of Nodes\n// Program Author : Abhisek Kumar Gupta\n/*\n            40\n            /   \\\n        10      30\n        / \\     /  \\\n       5  -1  -1  28\n      / \\        /  \\\n    1   -1      15    20\n   / \\          /\\    /\\\n   1 -1        -1 -1 -1 -1\n   /\\\n -1 -1\n    Input : 40 10 5 1 1 -1 -1 -1 -1 -1 30 -1 28 15 -1 -1 20 -1 -1\n    Output : 9  \n*/\n\n#include<bits/stdc++.h>\nusing namespace std;\nclass Node{\n    public:\n        int data;\n        Node* left;\n        Node* right;\n\n        Node(int d){\n            data = d;\n        }        \n};\nNode* build_binary_tree(){\n    int data;\n    cin >> data;\n    if(data == -1){\n        return NULL;\n    }\n    Node* root = new Node(data);\n    root->left = build_binary_tree();\n    root->right = build_binary_tree();\n    return root;\n}\nint count_number_of_nodes(Node* root){\n    if(root == NULL)\n        return 0;\n    return 1 + count_number_of_nodes(root->left) + count_number_of_nodes(root->right);    \n}\nint main(){\n    Node* root = build_binary_tree();\n    int number_of_nodes = count_number_of_nodes(root);\n    cout << number_of_nodes;\n    return 0;\n} "
  },
  {
    "path": "Trees/Binary Trees/delete.go",
    "content": "// Delete binary tree\npackage main\n\ntype BinaryTreeNode struct {\n\tleft  *BinaryTreeNode\n\tdata  int\n\tright *BinaryTreeNode\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: before deleting parent node, delete all its children nodes\n// using post order traversal we can solve this problem \nfunc DeleteTree(root *BinaryTreeNode) *BinaryTreeNode {\n\tif root == nil {\n\t\treturn nil\n\t}\n\t// delete both subtrees\n\troot.left = DeleteTree(root.left)\n\troot.right = DeleteTree(root.right)\n\t// delete current node after deleting subtrees\n\troot = nil\n\treturn root\n}"
  },
  {
    "path": "Trees/Binary Trees/dfs.cpp",
    "content": "// Implementation of Depth First Search\n/*\n\tThis code demonstrates a basic implementation of Depth-First Search (DFS) on a graph represented by nodes.\n\tIt uses a recursive approach to traverse the graph in a depth-first manner, printing the values of the visited nodes.\n\tThe algorithm maintains a set of visited nodes to avoid visiting the same node multiple times.\n\tThe DFS function serves as the entry point to start the DFS traversal, and the dfsHelper\n\tfunction recursively visits each node and its children.\n\tSample Input :\n\t//          1\n\t//        /   \\\n\t//       2     3\n\t//      / \\   / \\\n\t//     4   5 6   7\n\tOutput : 1 2 4 5 3 6 7\n\n\tThe time complexity of Depth-First Search (DFS) on a graph is O(V + E), where V represents the number of vertices (nodes)\n\tin the graph and E represents the number of edges. In the worst case, DFS may visit all vertices and edges of the graph.\n\n\tThe space complexity of DFS is determined by the maximum depth of the recursion stack. In the case of a tree-like\n\tstructure, where each node has only one child, the maximum depth is equal to the height of the tree.\n\tTherefore, the space complexity of DFS on such a tree-like structure is O(H), where H represents the height of the tree.\n\tIn the worst case, where the graph is a linear structure, the height of the tree is equal to the number of vertices,\n\tso the space complexity becomes O(V).\n*/\n#include <iostream>\n#include <vector>\n#include <unordered_map>\n\nusing namespace std;\n\n// Node represents a node in a graph.\nstruct Node {\n    int value;\n    vector<Node*> children;\n};\n\n// DFS traverses the graph using Depth-First Search starting from the given node.\nvoid DFS(Node* node) {\n    // Create a set to keep track of visited nodes.\n    unordered_map<Node*, bool> visited;\n\n    // Call the recursive helper function to perform DFS.\n    dfsHelper(node, visited);\n}\n\n// dfsHelper is a recursive function that performs Depth-First Search on the graph.\nvoid dfsHelper(Node* node, unordered_map<Node*, bool>& visited) {\n    // Mark the current node as visited.\n    visited[node] = true;\n\n    // Process the current node (print its value in this case).\n    cout << node->value << endl;\n\n    // Traverse the children of the current node.\n    for (Node* child : node->children) {\n        // If the child node has not been visited, recursively call dfsHelper on it.\n        if (!visited[child]) {\n            dfsHelper(child, visited);\n        }\n    }\n}\n\nint main() {\n    // Create a sample graph.\n    //          1\n    //        /   \\\n    //       2     3\n    //      / \\   / \\\n    //     4   5 6   7\n    Node node1{1};\n    Node node2{2};\n    Node node3{3};\n    Node node4{4};\n    Node node5{5};\n    Node node6{6};\n    Node node7{7};\n\n    node1.children = {&node2, &node3};\n    node2.children = {&node4, &node5};\n    node3.children = {&node6, &node7};\n\n    // Perform DFS starting from node1.\n    cout << \"Depth-First Search:\" << endl;\n    DFS(&node1);\n\n    return 0;\n}\n"
  },
  {
    "path": "Trees/Binary Trees/dfs.go",
    "content": "// Implementation of Depth First Search\n/*\n\tThis code demonstrates a basic implementation of Depth-First Search (DFS) on a graph represented by nodes.\n\tIt uses a recursive approach to traverse the graph in a depth-first manner, printing the values of the visited nodes.\n\tThe algorithm maintains a set of visited nodes to avoid visiting the same node multiple times.\n\tThe DFS function serves as the entry point to start the DFS traversal, and the dfsHelper\n\tfunction recursively visits each node and its children.\n\tSample Input :\n\t//          1\n\t//        /   \\\n\t//       2     3\n\t//      / \\   / \\\n\t//     4   5 6   7\n\tOutput : 1 2 4 5 3 6 7\n\n\tThe time complexity of Depth-First Search (DFS) on a graph is O(V + E), where V represents the number of vertices (nodes)\n\tin the graph and E represents the number of edges. In the worst case, DFS may visit all vertices and edges of the graph.\n\n\tThe space complexity of DFS is determined by the maximum depth of the recursion stack. In the case of a tree-like\n\tstructure, where each node has only one child, the maximum depth is equal to the height of the tree.\n\tTherefore, the space complexity of DFS on such a tree-like structure is O(H), where H represents the height of the tree.\n\tIn the worst case, where the graph is a linear structure, the height of the tree is equal to the number of vertices,\n\tso the space complexity becomes O(V).\n*/\npackage main\n\nimport \"fmt\"\n\n// Node represents a node in a graph.\ntype Node struct {\n\tValue    int\n\tChildren []*Node\n}\n\n// DFS traverses the graph using Depth-First Search starting from the given node.\nfunc DFS(node *Node) {\n\t// Create a set to keep track of visited nodes.\n\tvisited := make(map[*Node]bool)\n\n\t// Call the recursive helper function to perform DFS.\n\tdfsHelper(node, visited)\n}\n\n// dfsHelper is a recursive function that performs Depth-First Search on the graph.\nfunc dfsHelper(node *Node, visited map[*Node]bool) {\n\t// Mark the current node as visited.\n\tvisited[node] = true\n\n\t// Process the current node (print its value in this case).\n\tfmt.Println(node.Value)\n\n\t// Traverse the children of the current node.\n\tfor _, child := range node.Children {\n\t\t// If the child node has not been visited, recursively call dfsHelper on it.\n\t\tif !visited[child] {\n\t\t\tdfsHelper(child, visited)\n\t\t}\n\t}\n}\n\nfunc main() {\n\t// Create a sample graph.\n\t//          1\n\t//        /   \\\n\t//       2     3\n\t//      / \\   / \\\n\t//     4   5 6   7\n\tnode1 := &Node{Value: 1}\n\tnode2 := &Node{Value: 2}\n\tnode3 := &Node{Value: 3}\n\tnode4 := &Node{Value: 4}\n\tnode5 := &Node{Value: 5}\n\tnode6 := &Node{Value: 6}\n\tnode7 := &Node{Value: 7}\n\n\tnode1.Children = []*Node{node2, node3}\n\tnode2.Children = []*Node{node4, node5}\n\tnode3.Children = []*Node{node6, node7}\n\n\t// Perform DFS starting from node1.\n\tfmt.Println(\"Depth-First Search:\")\n\tDFS(node1)\n}\n"
  },
  {
    "path": "Trees/Binary Trees/dfs.java",
    "content": "// Implementation of Depth First Search\n/*\n\tThis code demonstrates a basic implementation of Depth-First Search (DFS) on a graph represented by nodes.\n\tIt uses a recursive approach to traverse the graph in a depth-first manner, printing the values of the visited nodes.\n\tThe algorithm maintains a set of visited nodes to avoid visiting the same node multiple times.\n\tThe DFS function serves as the entry point to start the DFS traversal, and the dfsHelper\n\tfunction recursively visits each node and its children.\n\tSample Input :\n\t//          1\n\t//        /   \\\n\t//       2     3\n\t//      / \\   / \\\n\t//     4   5 6   7\n\tOutput : 1 2 4 5 3 6 7\n\n\tThe time complexity of Depth-First Search (DFS) on a graph is O(V + E), where V represents the number of vertices (nodes)\n\tin the graph and E represents the number of edges. In the worst case, DFS may visit all vertices and edges of the graph.\n\n\tThe space complexity of DFS is determined by the maximum depth of the recursion stack. In the case of a tree-like\n\tstructure, where each node has only one child, the maximum depth is equal to the height of the tree.\n\tTherefore, the space complexity of DFS on such a tree-like structure is O(H), where H represents the height of the tree.\n\tIn the worst case, where the graph is a linear structure, the height of the tree is equal to the number of vertices,\n\tso the space complexity becomes O(V).\n*/\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\n// Node represents a node in a graph.\nclass Node {\n    int value;\n    List<Node> children;\n\n    public Node(int value) {\n        this.value = value;\n        this.children = new ArrayList<>();\n    }\n}\n\n// DFS traverses the graph using Depth-First Search starting from the given node.\nclass DepthFirstSearch {\n    public static void DFS(Node node) {\n        // Create a set to keep track of visited nodes.\n        Set<Node> visited = new HashSet<>();\n\n        // Call the recursive helper function to perform DFS.\n        dfsHelper(node, visited);\n    }\n\n    // dfsHelper is a recursive function that performs Depth-First Search on the graph.\n    private static void dfsHelper(Node node, Set<Node> visited) {\n        // Mark the current node as visited.\n        visited.add(node);\n\n        // Process the current node (print its value in this case).\n        System.out.println(node.value);\n\n        // Traverse the children of the current node.\n        for (Node child : node.children) {\n            // If the child node has not been visited, recursively call dfsHelper on it.\n            if (!visited.contains(child)) {\n                dfsHelper(child, visited);\n            }\n        }\n    }\n}\n\npublic class Main {\n    public static void main(String[] args) {\n        // Create a sample graph.\n        //          1\n        //        /   \\\n        //       2     3\n        //      / \\   / \\\n        //     4   5 6   7\n        Node node1 = new Node(1);\n        Node node2 = new Node(2);\n        Node node3 = new Node(3);\n        Node node4 = new Node(4);\n        Node node5 = new Node(5);\n        Node node6 = new Node(6);\n        Node node7 = new Node(7);\n\n        node1.children.add(node2);\n        node1.children.add(node3);\n        node2.children.add(node4);\n        node2.children.add(node5);\n        node3.children.add(node6);\n        node3.children.add(node7);\n\n        // Perform DFS starting from node1.\n        System.out.println(\"Depth-First Search:\");\n        DepthFirstSearch.DFS(node1);\n    }\n}\n"
  },
  {
    "path": "Trees/Binary Trees/dfs.js",
    "content": "// Implementation of Depth First Search\n/*\n\tThis code demonstrates a basic implementation of Depth-First Search (DFS) on a graph represented by nodes.\n\tIt uses a recursive approach to traverse the graph in a depth-first manner, printing the values of the visited nodes.\n\tThe algorithm maintains a set of visited nodes to avoid visiting the same node multiple times.\n\tThe DFS function serves as the entry point to start the DFS traversal, and the dfsHelper\n\tfunction recursively visits each node and its children.\n\tSample Input :\n\t//          1\n\t//        /   \\\n\t//       2     3\n\t//      / \\   / \\\n\t//     4   5 6   7\n\tOutput : 1 2 4 5 3 6 7\n\n\tThe time complexity of Depth-First Search (DFS) on a graph is O(V + E), where V represents the number of vertices (nodes)\n\tin the graph and E represents the number of edges. In the worst case, DFS may visit all vertices and edges of the graph.\n\n\tThe space complexity of DFS is determined by the maximum depth of the recursion stack. In the case of a tree-like\n\tstructure, where each node has only one child, the maximum depth is equal to the height of the tree.\n\tTherefore, the space complexity of DFS on such a tree-like structure is O(H), where H represents the height of the tree.\n\tIn the worst case, where the graph is a linear structure, the height of the tree is equal to the number of vertices,\n\tso the space complexity becomes O(V).\n*/\n// Node represents a node in a graph.\nclass Node {\n  constructor(value) {\n    this.value = value;\n    this.children = [];\n  }\n}\n\n// DFS traverses the graph using Depth-First Search starting from the given node.\nfunction DFS(node) {\n  // Create a set to keep track of visited nodes.\n  let visited = new Set();\n\n  // Call the recursive helper function to perform DFS.\n  dfsHelper(node, visited);\n}\n\n// dfsHelper is a recursive function that performs Depth-First Search on the graph.\nfunction dfsHelper(node, visited) {\n  // Mark the current node as visited.\n  visited.add(node);\n\n  // Process the current node (print its value in this case).\n  console.log(node.value);\n\n  // Traverse the children of the current node.\n  for (let child of node.children) {\n    // If the child node has not been visited, recursively call dfsHelper on it.\n    if (!visited.has(child)) {\n      dfsHelper(child, visited);\n    }\n  }\n}\n\n// Create a sample graph.\n//          1\n//        /   \\\n//       2     3\n//      / \\   / \\\n//     4   5 6   7\nlet node1 = new Node(1);\nlet node2 = new Node(2);\nlet node3 = new Node(3);\nlet node4 = new Node(4);\nlet node5 = new Node(5);\nlet node6 = new Node(6);\nlet node7 = new Node(7);\n\nnode1.children = [node2, node3];\nnode2.children = [node4, node5];\nnode3.children = [node6, node7];\n\n// Perform DFS starting from node1.\nconsole.log(\"Depth-First Search:\");\nDFS(node1);\n"
  },
  {
    "path": "Trees/Binary Trees/dfs.py",
    "content": "'''\n    Implementation of Depth First Search\n\t\n    This code demonstrates a basic implementation of Depth-First Search (DFS) on a graph represented by nodes.\n\tIt uses a recursive approach to traverse the graph in a depth-first manner, printing the values of the visited nodes.\n\tThe algorithm maintains a set of visited nodes to avoid visiting the same node multiple times.\n\tThe DFS function serves as the entry point to start the DFS traversal, and the dfsHelper\n\tfunction recursively visits each node and its children.\n\tSample Input :\n\t//          1\n\t//        /   \\\n\t//       2     3\n\t//      / \\   / \\\n\t//     4   5 6   7\n\tOutput : 1 2 4 5 3 6 7\n\n\tThe time complexity of Depth-First Search (DFS) on a graph is O(V + E), where V represents the number of vertices (nodes)\n\tin the graph and E represents the number of edges. In the worst case, DFS may visit all vertices and edges of the graph.\n\n\tThe space complexity of DFS is determined by the maximum depth of the recursion stack. In the case of a tree-like\n\tstructure, where each node has only one child, the maximum depth is equal to the height of the tree.\n\tTherefore, the space complexity of DFS on such a tree-like structure is O(H), where H represents the height of the tree.\n\tIn the worst case, where the graph is a linear structure, the height of the tree is equal to the number of vertices,\n\tso the space complexity becomes O(V).\n'''\n# Node represents a node in a graph.\nclass Node:\n    def __init__(self, value):\n        self.value = value\n        self.children = []\n\n# DFS traverses the graph using Depth-First Search starting from the given node.\ndef DFS(node):\n    # Create a set to keep track of visited nodes.\n    visited = set()\n\n    # Call the recursive helper function to perform DFS.\n    dfsHelper(node, visited)\n\n# dfsHelper is a recursive function that performs Depth-First Search on the graph.\ndef dfsHelper(node, visited):\n    # Mark the current node as visited.\n    visited.add(node)\n\n    # Process the current node (print its value in this case).\n    print(node.value)\n\n    # Traverse the children of the current node.\n    for child in node.children:\n        # If the child node has not been visited, recursively call dfsHelper on it.\n        if child not in visited:\n            dfsHelper(child, visited)\n\n# Create a sample graph.\n#          1\n#        /   \\\n#       2     3\n#      / \\   / \\\n#     4   5 6   7\nnode1 = Node(1)\nnode2 = Node(2)\nnode3 = Node(3)\nnode4 = Node(4)\nnode5 = Node(5)\nnode6 = Node(6)\nnode7 = Node(7)\n\nnode1.children = [node2, node3]\nnode2.children = [node4, node5]\nnode3.children = [node6, node7]\n\n# Perform DFS starting from node1.\nprint(\"Depth-First Search:\")\nDFS(node1)\n"
  },
  {
    "path": "Trees/Binary Trees/diameter.cpp",
    "content": "/*\n\tWrite a function that takes in a Binary Tree and returns its diameter. The diameter of a binary tree\n\tis defined as the length of its longest path, even if that path doesn't pass through the root of the tree.\n\n\tSample Input :\n\t          1\n            /   \\\n           3     2\n         /   \\\n        7     4\n       /       \\\n      8         5\n     /           \\\n    9             6\n\tOutput: 6\n\tDiameter being 9 -> 8 -> 7 -> 3 -> 4 -> 5 -> 6\n\n\tExplanation:\n\tThis code calculates the diameter of a binary tree, which is defined as the length of the longest path between any two\n\tnodes in the tree. The BinaryTreeDiameter function takes the root of the binary tree as input and returns the diameter.\n\n\tThe getTreeInfo function is a helper function that recursively calculates the height and diameter of the binary tree.\n\tIt takes a node of the binary tree as input and returns a TreeInfo struct containing the height and diameter of the tree.\n\n\tIn the getTreeInfo function:\n\n\tThe base case is when the tree is nil, indicating an empty tree. In this case, it returns a TreeInfo with height 0 and\n\tdiameter 0.\n\n\tThe height and diameter of the left and right subtrees are calculated recursively by calling getTreeInfo on the left\n\tand right child nodes.\n\n\tThe longest path passing through the root node is determined by adding the heights of the left and right subtrees.\n\n\tThe maximum diameter seen so far is calculated by taking the maximum of the diameters of the left and right subtrees.\n\n\tThe current diameter is determined by taking the maximum among the longest path through the root and the maximum\n\tdiameter seen so far.\n\n\tThe current height is calculated by taking the maximum height among the left and right subtrees and adding 1.\n\n\tFinally, the function returns a TreeInfo struct with the current height and diameter.\n\tThe max function is a helper function that returns the maximum of two integers.\n\n\tOverall, the code effectively calculates the diameter of a binary tree by recursively calculating the height and\n\tdiameter of the tree and considering the longest path passing through the root.\n\n\tAverage case:\n\tTime Complexity O(n) when the tree is balanced\n\tSpace complexity: O(h) where n is the number of nodes in the Binary Tree and h is the height of the Binary Tree\n*/\n#include <iostream>\n\nstruct BinaryTree {\n    int value;\n    BinaryTree* left;\n    BinaryTree* right;\n};\n\nstruct TreeInfo {\n    int height;\n    int diameter;\n};\n\n// Calculates the diameter of a binary tree.\nint BinaryTreeDiameter(BinaryTree* tree) {\n    return getTreeInfo(tree).diameter;\n}\n\n// Recursively calculates the height and diameter of the binary tree.\nTreeInfo getTreeInfo(BinaryTree* tree) {\n    // Base case: If the tree is nullptr, return height 0 and diameter 0.\n    if (tree == nullptr) {\n        return {0, 0};\n    }\n\n    // Recursively calculate the height and diameter of the left and right subtrees.\n    TreeInfo leftTreeInfo = getTreeInfo(tree->left);\n    TreeInfo rightTreeInfo = getTreeInfo(tree->right);\n\n    // Calculate the longest path passing through the root node.\n    int longestPathThroughRoot = leftTreeInfo.height + rightTreeInfo.height;\n\n    // Calculate the maximum diameter seen so far.\n    int maxDiameterSoFar = std::max(leftTreeInfo.diameter, rightTreeInfo.diameter);\n\n    // Calculate the current diameter, which is the maximum among the longest path through root and max diameter so far.\n    int currentDiameter = std::max(longestPathThroughRoot, maxDiameterSoFar);\n\n    // Calculate the current height, which is the maximum height among the left and right subtrees plus 1.\n    int currentHeight = 1 + std::max(leftTreeInfo.height, rightTreeInfo.height);\n\n    // Return the current height and diameter as the tree information.\n    return {currentHeight, currentDiameter};\n}\n\n// Returns the maximum of two integers.\nint max(int a, int b) {\n    return (a > b) ? a : b;\n}\n\nint main() {\n    // Test the BinaryTreeDiameter function with a sample binary tree\n    BinaryTree* tree = new BinaryTree{1,\n                                    new BinaryTree{2,\n                                                    new BinaryTree{4, nullptr, nullptr},\n                                                    new BinaryTree{5, nullptr, nullptr}},\n                                    new BinaryTree{3,\n                                                    nullptr,\n                                                    new BinaryTree{6,\n                                                                    new BinaryTree{7, nullptr, nullptr},\n                                                                    nullptr}}};\n\n    int diameter = BinaryTreeDiameter(tree);\n    std::cout << \"Diameter of the binary tree: \" << diameter << std::endl;\n\n    delete tree;\n\n    return 0;\n}\n"
  },
  {
    "path": "Trees/Binary Trees/diameter.go",
    "content": "/*\n\tWrite a function that takes in a Binary Tree and returns its diameter. The diameter of a binary tree\n\tis defined as the length of its longest path, even if that path doesn't pass through the root of the tree.\n\n\tSample Input :\n\t          1\n            /   \\\n           3     2\n         /   \\\n        7     4\n       /       \\\n      8         5\n     /           \\\n    9             6\n\tOutput: 6\n\tDiameter being 9 -> 8 -> 7 -> 3 -> 4 -> 5 -> 6\n\n\tExplanation:\n\tThis code calculates the diameter of a binary tree, which is defined as the length of the longest path between any two\n\tnodes in the tree. The BinaryTreeDiameter function takes the root of the binary tree as input and returns the diameter.\n\n\tThe getTreeInfo function is a helper function that recursively calculates the height and diameter of the binary tree.\n\tIt takes a node of the binary tree as input and returns a TreeInfo struct containing the height and diameter of the tree.\n\n\tIn the getTreeInfo function:\n\n\tThe base case is when the tree is nil, indicating an empty tree. In this case, it returns a TreeInfo with height 0 and\n\tdiameter 0.\n\n\tThe height and diameter of the left and right subtrees are calculated recursively by calling getTreeInfo on the left\n\tand right child nodes.\n\n\tThe longest path passing through the root node is determined by adding the heights of the left and right subtrees.\n\n\tThe maximum diameter seen so far is calculated by taking the maximum of the diameters of the left and right subtrees.\n\n\tThe current diameter is determined by taking the maximum among the longest path through the root and the maximum\n\tdiameter seen so far.\n\n\tThe current height is calculated by taking the maximum height among the left and right subtrees and adding 1.\n\n\tFinally, the function returns a TreeInfo struct with the current height and diameter.\n\tThe max function is a helper function that returns the maximum of two integers.\n\n\tOverall, the code effectively calculates the diameter of a binary tree by recursively calculating the height and\n\tdiameter of the tree and considering the longest path passing through the root.\n\n\tAverage case:\n\tTime Complexity O(n) when the tree is balanced\n\tSpace complexity: O(h) where n is the number of nodes in the Binary Tree and h is the height of the Binary Tree\n*/\npackage main\n\n// This is an input class. Do not edit.\ntype BinaryTree struct {\n\tValue int\n\n\tLeft  *BinaryTree\n\tRight *BinaryTree\n}\n\ntype TreeInfo struct {\n\theight   int\n\tdiameter int\n}\n\n// Calculates the diameter of a binary tree.\nfunc BinaryTreeDiameter(tree *BinaryTree) int {\n\treturn getTreeInfo(tree).diameter\n}\n\n// Recursively calculates the height and diameter of the binary tree.\nfunc getTreeInfo(tree *BinaryTree) TreeInfo {\n\t// Base case: If the tree is nil, return height 0 and diameter 0.\n\tif tree == nil {\n\t\treturn TreeInfo{0, 0}\n\t}\n\n\t// Recursively calculate the height and diameter of the left and right subtrees.\n\tleftTreeInfo := getTreeInfo(tree.Left)\n\trightTreeInfo := getTreeInfo(tree.Right)\n\n\t// Calculate the longest path passing through the root node.\n\tlongestPathThroughRoot := leftTreeInfo.height + rightTreeInfo.height\n\n\t// Calculate the maximum diameter seen so far.\n\tmaxDiameterSoFar := max(leftTreeInfo.diameter, rightTreeInfo.diameter)\n\n\t// Calculate the current diameter, which is the maximum among the longest path through root and max diameter so far.\n\tcurrentDiameter := max(longestPathThroughRoot, maxDiameterSoFar)\n\n\t// Calculate the current height, which is the maximum height among the left and right subtrees plus 1.\n\tcurrentHeight := 1 + max(leftTreeInfo.height, rightTreeInfo.height)\n\n\t// Return the current height and diameter as the tree information.\n\treturn TreeInfo{currentHeight, currentDiameter}\n}\n\n// Returns the maximum of two integers.\nfunc max(a, b int) int {\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n"
  },
  {
    "path": "Trees/Binary Trees/diameter.java",
    "content": "/*\n\tWrite a function that takes in a Binary Tree and returns its diameter. The diameter of a binary tree\n\tis defined as the length of its longest path, even if that path doesn't pass through the root of the tree.\n\n\tSample Input :\n\t          1\n            /   \\\n           3     2\n         /   \\\n        7     4\n       /       \\\n      8         5\n     /           \\\n    9             6\n\tOutput: 6\n\tDiameter being 9 -> 8 -> 7 -> 3 -> 4 -> 5 -> 6\n\n\tExplanation:\n\tThis code calculates the diameter of a binary tree, which is defined as the length of the longest path between any two\n\tnodes in the tree. The BinaryTreeDiameter function takes the root of the binary tree as input and returns the diameter.\n\n\tThe getTreeInfo function is a helper function that recursively calculates the height and diameter of the binary tree.\n\tIt takes a node of the binary tree as input and returns a TreeInfo struct containing the height and diameter of the tree.\n\n\tIn the getTreeInfo function:\n\n\tThe base case is when the tree is nil, indicating an empty tree. In this case, it returns a TreeInfo with height 0 and\n\tdiameter 0.\n\n\tThe height and diameter of the left and right subtrees are calculated recursively by calling getTreeInfo on the left\n\tand right child nodes.\n\n\tThe longest path passing through the root node is determined by adding the heights of the left and right subtrees.\n\n\tThe maximum diameter seen so far is calculated by taking the maximum of the diameters of the left and right subtrees.\n\n\tThe current diameter is determined by taking the maximum among the longest path through the root and the maximum\n\tdiameter seen so far.\n\n\tThe current height is calculated by taking the maximum height among the left and right subtrees and adding 1.\n\n\tFinally, the function returns a TreeInfo struct with the current height and diameter.\n\tThe max function is a helper function that returns the maximum of two integers.\n\n\tOverall, the code effectively calculates the diameter of a binary tree by recursively calculating the height and\n\tdiameter of the tree and considering the longest path passing through the root.\n\n\tAverage case:\n\tTime Complexity O(n) when the tree is balanced\n\tSpace complexity: O(h) where n is the number of nodes in the Binary Tree and h is the height of the Binary Tree\n*/\npublic class BinaryTree {\n    int value;\n    BinaryTree left;\n    BinaryTree right;\n    \n    public BinaryTree(int value) {\n        this.value = value;\n        this.left = null;\n        this.right = null;\n    }\n}\n\nclass TreeInfo {\n    int height;\n    int diameter;\n    \n    public TreeInfo(int height, int diameter) {\n        this.height = height;\n        this.diameter = diameter;\n    }\n}\n\npublic class Main {\n    // Calculates the diameter of a binary tree.\n    public static int binaryTreeDiameter(BinaryTree tree) {\n        return getTreeInfo(tree).diameter;\n    }\n    \n    // Recursively calculates the height and diameter of the binary tree.\n    private static TreeInfo getTreeInfo(BinaryTree tree) {\n        // Base case: If the tree is null, return height 0 and diameter 0.\n        if (tree == null) {\n            return new TreeInfo(0, 0);\n        }\n        \n        // Recursively calculate the height and diameter of the left and right subtrees.\n        TreeInfo leftTreeInfo = getTreeInfo(tree.left);\n        TreeInfo rightTreeInfo = getTreeInfo(tree.right);\n        \n        // Calculate the longest path passing through the root node.\n        int longestPathThroughRoot = leftTreeInfo.height + rightTreeInfo.height;\n        \n        // Calculate the maximum diameter seen so far.\n        int maxDiameterSoFar = Math.max(leftTreeInfo.diameter, rightTreeInfo.diameter);\n        \n        // Calculate the current diameter, which is the maximum among the longest path through root and max diameter so far.\n        int currentDiameter = Math.max(longestPathThroughRoot, maxDiameterSoFar);\n        \n        // Calculate the current height, which is the maximum height among the left and right subtrees plus 1.\n        int currentHeight = Math.max(leftTreeInfo.height, rightTreeInfo.height) + 1;\n        \n        // Return the current height and diameter as the tree information.\n        return new TreeInfo(currentHeight, currentDiameter);\n    }\n    \n    public static void main(String[] args) {\n        // Example usage\n        BinaryTree tree = new BinaryTree(1);\n        tree.left = new BinaryTree(2);\n        tree.right = new BinaryTree(3);\n        tree.left.left = new BinaryTree(4);\n        tree.left.right = new BinaryTree(5);\n        \n        int diameter = binaryTreeDiameter(tree);\n        System.out.println(\"Diameter of the binary tree: \" + diameter);\n    }\n}\n"
  },
  {
    "path": "Trees/Binary Trees/diameter.js",
    "content": "/*\n\tWrite a function that takes in a Binary Tree and returns its diameter. The diameter of a binary tree\n\tis defined as the length of its longest path, even if that path doesn't pass through the root of the tree.\n\n\tSample Input :\n\t          1\n            /   \\\n           3     2\n         /   \\\n        7     4\n       /       \\\n      8         5\n     /           \\\n    9             6\n\tOutput: 6\n\tDiameter being 9 -> 8 -> 7 -> 3 -> 4 -> 5 -> 6\n\n\tExplanation:\n\tThis code calculates the diameter of a binary tree, which is defined as the length of the longest path between any two\n\tnodes in the tree. The BinaryTreeDiameter function takes the root of the binary tree as input and returns the diameter.\n\n\tThe getTreeInfo function is a helper function that recursively calculates the height and diameter of the binary tree.\n\tIt takes a node of the binary tree as input and returns a TreeInfo struct containing the height and diameter of the tree.\n\n\tIn the getTreeInfo function:\n\n\tThe base case is when the tree is nil, indicating an empty tree. In this case, it returns a TreeInfo with height 0 and\n\tdiameter 0.\n\n\tThe height and diameter of the left and right subtrees are calculated recursively by calling getTreeInfo on the left\n\tand right child nodes.\n\n\tThe longest path passing through the root node is determined by adding the heights of the left and right subtrees.\n\n\tThe maximum diameter seen so far is calculated by taking the maximum of the diameters of the left and right subtrees.\n\n\tThe current diameter is determined by taking the maximum among the longest path through the root and the maximum\n\tdiameter seen so far.\n\n\tThe current height is calculated by taking the maximum height among the left and right subtrees and adding 1.\n\n\tFinally, the function returns a TreeInfo struct with the current height and diameter.\n\tThe max function is a helper function that returns the maximum of two integers.\n\n\tOverall, the code effectively calculates the diameter of a binary tree by recursively calculating the height and\n\tdiameter of the tree and considering the longest path passing through the root.\n\n\tAverage case:\n\tTime Complexity O(n) when the tree is balanced\n\tSpace complexity: O(h) where n is the number of nodes in the Binary Tree and h is the height of the Binary Tree\n*/\nclass BinaryTree {\n  constructor(value) {\n    this.value = value;\n    this.left = null;\n    this.right = null;\n  }\n}\n\nclass TreeInfo {\n  constructor(height, diameter) {\n    this.height = height;\n    this.diameter = diameter;\n  }\n}\n\nfunction binaryTreeDiameter(tree) {\n  return getTreeInfo(tree).diameter;\n}\n\nfunction getTreeInfo(tree) {\n  // Base case: If the tree is null, return height 0 and diameter 0.\n  if (tree === null) {\n    return new TreeInfo(0, 0);\n  }\n\n  // Recursively calculate the height and diameter of the left and right subtrees.\n  const leftTreeInfo = getTreeInfo(tree.left);\n  const rightTreeInfo = getTreeInfo(tree.right);\n\n  // Calculate the longest path passing through the root node.\n  const longestPathThroughRoot = leftTreeInfo.height + rightTreeInfo.height;\n\n  // Calculate the maximum diameter seen so far.\n  const maxDiameterSoFar = Math.max(\n    leftTreeInfo.diameter,\n    rightTreeInfo.diameter\n  );\n\n  // Calculate the current diameter, which is the maximum among the longest path through root and max diameter so far.\n  const currentDiameter = Math.max(longestPathThroughRoot, maxDiameterSoFar);\n\n  // Calculate the current height, which is the maximum height among the left and right subtrees plus 1.\n  const currentHeight = Math.max(leftTreeInfo.height, rightTreeInfo.height) + 1;\n\n  // Return the current height and diameter as the tree information.\n  return new TreeInfo(currentHeight, currentDiameter);\n}\n\n// Example usage\nconst tree = new BinaryTree(1);\ntree.left = new BinaryTree(2);\ntree.right = new BinaryTree(3);\ntree.left.left = new BinaryTree(4);\ntree.left.right = new BinaryTree(5);\n\nconst diameter = binaryTreeDiameter(tree);\nconsole.log(\"Diameter of the binary tree:\", diameter);\n"
  },
  {
    "path": "Trees/Binary Trees/diameter.py",
    "content": "'''\n\tWrite a function that takes in a Binary Tree and returns its diameter. The diameter of a binary tree\n\tis defined as the length of its longest path, even if that path doesn't pass through the root of the tree.\n\n\tSample Input :\n\t          1\n            /   \\\n           3     2\n         /   \\\n        7     4\n       /       \\\n      8         5\n     /           \\\n    9             6\n\tOutput: 6\n\tDiameter being 9 -> 8 -> 7 -> 3 -> 4 -> 5 -> 6\n\n\tExplanation:\n\tThis code calculates the diameter of a binary tree, which is defined as the length of the longest path between any two\n\tnodes in the tree. The BinaryTreeDiameter function takes the root of the binary tree as input and returns the diameter.\n\n\tThe getTreeInfo function is a helper function that recursively calculates the height and diameter of the binary tree.\n\tIt takes a node of the binary tree as input and returns a TreeInfo struct containing the height and diameter of the tree.\n\n\tIn the getTreeInfo function:\n\n\tThe base case is when the tree is nil, indicating an empty tree. In this case, it returns a TreeInfo with height 0 and\n\tdiameter 0.\n\n\tThe height and diameter of the left and right subtrees are calculated recursively by calling getTreeInfo on the left\n\tand right child nodes.\n\n\tThe longest path passing through the root node is determined by adding the heights of the left and right subtrees.\n\n\tThe maximum diameter seen so far is calculated by taking the maximum of the diameters of the left and right subtrees.\n\n\tThe current diameter is determined by taking the maximum among the longest path through the root and the maximum\n\tdiameter seen so far.\n\n\tThe current height is calculated by taking the maximum height among the left and right subtrees and adding 1.\n\n\tFinally, the function returns a TreeInfo struct with the current height and diameter.\n\tThe max function is a helper function that returns the maximum of two integers.\n\n\tOverall, the code effectively calculates the diameter of a binary tree by recursively calculating the height and\n\tdiameter of the tree and considering the longest path passing through the root.\n\n\tAverage case:\n\tTime Complexity O(n) when the tree is balanced\n\tSpace complexity: O(h) where n is the number of nodes in the Binary Tree and h is the height of the Binary Tree\n'''\nclass BinaryTree:\n    def __init__(self, value):\n        self.value = value\n        self.left = None\n        self.right = None\n\nclass TreeInfo:\n    def __init__(self, height, diameter):\n        self.height = height\n        self.diameter = diameter\n\ndef binary_tree_diameter(tree):\n    return get_tree_info(tree).diameter\n\ndef get_tree_info(tree):\n    # Base case: If the tree is None, return height 0 and diameter 0.\n    if tree is None:\n        return TreeInfo(0, 0)\n\n    # Recursively calculate the height and diameter of the left and right subtrees.\n    left_tree_info = get_tree_info(tree.left)\n    right_tree_info = get_tree_info(tree.right)\n\n    # Calculate the longest path passing through the root node.\n    longest_path_through_root = left_tree_info.height + right_tree_info.height\n\n    # Calculate the maximum diameter seen so far.\n    max_diameter_so_far = max(left_tree_info.diameter, right_tree_info.diameter)\n\n    # Calculate the current diameter, which is the maximum among the longest path through root and max diameter so far.\n    current_diameter = max(longest_path_through_root, max_diameter_so_far)\n\n    # Calculate the current height, which is the maximum height among the left and right subtrees plus 1.\n    current_height = max(left_tree_info.height, right_tree_info.height) + 1\n\n    # Return the current height and diameter as the tree information.\n    return TreeInfo(current_height, current_diameter)\n\n# Example usage\ntree = BinaryTree(1)\ntree.left = BinaryTree(2)\ntree.right = BinaryTree(3)\ntree.left.left = BinaryTree(4)\ntree.left.right = BinaryTree(5)\n\ndiameter = binary_tree_diameter(tree)\nprint(\"Diameter of the binary tree:\", diameter)\n"
  },
  {
    "path": "Trees/Binary Trees/find_branch_sum.go",
    "content": "/*\n\tWrite a function that takes in a Binary Tree and returns a list of its branch\n\tsums ordered from leftmost branch sum to rightmost branch sum.\n\n\n\tA branch sum is the sum of all values in a Binary Tree branch. A Binary Tree\n\tbranch is a path of nodes in a tree that starts at the root node and ends at\n\tany leaf node.\n\n\tSample Input\n\t       1\n        /     \\\n       2       3\n     /   \\    /  \\\n    4     5  6    7\n  /   \\  /\n 8    9 10\n\n \tOutput:[15, 16, 18, 10, 11]\n\n*/\n\n/*\n\tAs you recursively traverse the tree, if you reach a leaf node (a node with no \"left\" or \"right\" Binary Tree nodes),\n\tadd the relevant running sum that you've calculated to a list of sums (which you'll also have to pass to the recursive\n\tfunction). If you reach a node that isn't a leaf node, keep recursively traversing its children nodes,\n\tpassing the correctly updated running sum to them.\n\n\tTime and Space complexity : O(n) time | O(n) space - where n is the number of nodes in the Binary Tree\n*/\npackage main\n\ntype BinaryTree struct {\n\tValue int\n\tLeft  *BinaryTree\n\tRight *BinaryTree\n}\n\nfunc BranchSums(root *BinaryTree) []int {\n\tsums := []int{}\n    calculateBranchSums(root, 0, &sums)\n    return sums\n}\n\nfunc calculateBranchSums(node *BinaryTree, runningSum int, sums *[]int) {\n    if node == nil {\n        return\n    }\n    runningSum += node.Value\n    if node.Left == nil && node.Right == nil {\n        *sums = append(*sums, runningSum)\n    }\n    calculateBranchSums(node.Left, runningSum, sums)\n    calculateBranchSums(node.Right, runningSum, sums)\n}"
  },
  {
    "path": "Trees/Binary Trees/find_max.go",
    "content": "// Find max in Binary tree\npackage main\n\nimport \"math\"\n\ntype BinaryTreeNode struct {\n\tleft  *BinaryTreeNode\n\tdata  int\n\tright *BinaryTreeNode\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: find maximum in left sub tree, find maximum in right subtree\n// compare them with root data and select the one which is giving the max value\n// recursive appraoch\nfunc FindMax(root *BinaryTreeNode) int {\n\tmax := math.MinInt32\n\tif root != nil {\n\t\trootVal := root.data\n\t\tleft := FindMax(root.left)\n\t\tright := FindMax(root.right)\n\t\tif left > max {\n\t\t\tmax = left\n\t\t} else {\n\t\t\tmax = right\n\t\t}\n\t\tif rootVal > max {\n\t\t\tmax = rootVal\n\t\t}\n\t}\n\treturn max\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: Using level order traversal observe the elements data\nfunc FindMaxWithoutRecursion(root *BinaryTreeNode) int {\n\tmax := math.MinInt32\n\tif root == nil {\n\t\treturn max\n\t}\n\tqueue := []*BinaryTreeNode{root}\n\tfor len(queue) > 0 {\n\t\tqlen := len(queue)\n\t\tfor i := 0; i < qlen; i++ {\n\t\t\tnode := queue[0]\n\t\t\tif node.data > max {\n\t\t\t\tmax = node.data\n\t\t\t}\n\t\t\tqueue = queue[1:]\n\t\t\tif node.left != nil {\n\t\t\t\tqueue = append(queue, node.left)\n\t\t\t}\n\t\t\tif node.right != nil {\n\t\t\t\tqueue = append(queue, node.right)\n\t\t\t}\n\t\t}\n\t}\n\treturn max\n}"
  },
  {
    "path": "Trees/Binary Trees/height.cpp",
    "content": "// Compute Height of a Binary-Tree\n// Program Author : Abhisek Kumar Gupta\n/*\n            40\n            /   \\\n        10      30\n        / \\     /  \\\n       5  -1  -1  28\n        / \\       /  \\\n    1   -1      15    20\n    / \\          /\\    /\\\n   1 -1        -1 -1 -1 -1\n   /\\\n -1 -1\n    Input : 40 10 5 1 1 -1 -1 -1 -1 -1 30 -1 28 15 -1 -1 20 -1 -1\n    Output : 5\n*/\n#include<bits/stdc++.h>\nusing namespace std;\nclass Node{\n    public:\n        int data;\n        Node* left;\n        Node* right;\n\n        Node(int x){\n            data = x;\n        }\n};\nNode* build_binary_tree(){\n    int data;\n    cin >> data;\n    if(data == -1)\n        return NULL;\n    Node* root = new Node(data);\n    root->left = build_binary_tree();\n    root->right = build_binary_tree();\n    return root;        \n}\nint compute_height_of_binary_tree(Node* root){\n    if(root == NULL){\n        return 0;\n    }\n    int left_height = compute_height_of_binary_tree(root->left);\n    int right_height = compute_height_of_binary_tree(root->right);\n    return max(left_height, right_height) + 1;\n}\nint main(){\n    Node* root = build_binary_tree();\n    int height = compute_height_of_binary_tree(root);\n    cout << \"Height of Tree is \" << height;\n    return 0;\n}\n"
  },
  {
    "path": "Trees/Binary Trees/height.go",
    "content": "// Binary tree Find height\npackage main\n\ntype BinaryTreeNode struct {\n\tleft  *BinaryTreeNode\n\tdata  int\n\tright *BinaryTreeNode\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: Recursively calculate height of left and right subtrees of a node \n// and assign height to the node as max of heights of two children + 1\nfunc Height(root *BinaryTreeNode) int {\n\tif root == nil {\n\t\treturn 0\n\t} else {\n\t\t// compute depth of each subtree\n\t\tleftHeight := Height(root.left)\n\t\trightHeight := Height(root.right)\n\t\tif leftHeight > rightHeight {\n\t\t\treturn leftHeight + 1\n\t\t} else {\n\t\t\treturn rightHeight + 1\n\t\t}\n\n\t}\n}"
  },
  {
    "path": "Trees/Binary Trees/height_balanced_binary_tree.cpp",
    "content": "/*\n\tYou're given the root node of a Binary Tree. Write a function that returns true\n\tif this Binary Tree is height balanced and false if it isn't.\n\n\tExplanation:\n\n\tThe provided code is for checking whether a binary tree is height-balanced or not. Here's how it works:\n\n\t- The code defines a `BinaryTree` struct representing a node in a binary tree. Each node has a value and\n\tpointers to its left and right child nodes.\n\n\t- The code also defines a `TreeeInfo` struct to store information about a binary tree. It includes a boolean\n\tfield `isBalanced` indicating whether the tree is balanced or not, and an integer field `height` representing\n\tthe height of the tree.\n\n\t- The `HeightBalancedBinaryTree` function is the main function that checks if a binary tree is height-balanced.\n\tIt takes the root of the tree as input and returns a boolean value indicating the balance status.\n\n\t- The `getTreeInfo` function is a helper function that recursively calculates the information of a binary tree.\n\tIt takes a binary tree node as input and returns the `TreeeInfo` struct containing the balance status and height\n\tof the tree.\n\n\t- In the `getTreeInfo` function, there are two base cases:\n\t- If the current tree node is `nil`, it is considered balanced with height -1.\n\t- If the current tree node is not `nil`, the function recursively calculates the tree information of its\n\tleft and right subtrees.\n\n\t- After getting the information of the left and right subtrees, the code checks if both subtrees are balanced\n\t(`isBalanced` field is `true`) and their height difference is at most 1. If so, the current tree is considered\n\tbalanced.\n\n\t- The height of the current tree is calculated by taking the maximum height of the left and right subtrees and\n\tadding 1.\n\n\t- Finally, the `max` function is used to get the maximum of two integers, and the `abs` function is used to get\n\tthe absolute value of an integer.\n\n\tTo determine whether a binary tree is height-balanced, you can call the `HeightBalancedBinaryTree` function with\n\tthe root of the tree. It will return `true` if the tree is balanced and `false` otherwise.\n\n\tThe time complexity of the `HeightBalancedBinaryTree` function is O(N), where N is the number of nodes in the\n\tbinary tree. This is because the function needs to traverse each node of the tree once to calculate the tree\n\tinformation.\n\n\tThe space complexity of the `HeightBalancedBinaryTree` function is O(H), where H is the height of the binary tree.\n\tThis is because the recursive calls to the `getTreeInfo` function will utilize the call stack, and the maximum\n\tdepth of the recursive calls is equal to the height of the tree. Additionally, the space complexity of the\n\t`getTreeInfo` function itself is O(1) as it uses a constant amount of space for the `TreeeInfo` struct.\n\n\tOverall, the space complexity is determined by the height of the binary tree, and the time complexity is\n\tdetermined by the number of nodes in the binary tree.\n\n*/\n#include <iostream>\n#include <cmath>\n\n// Node class represents a node in a binary tree\nclass BinaryTree {\npublic:\n    int value;\n    BinaryTree* left;\n    BinaryTree* right;\n\n    BinaryTree(int value) {\n        this->value = value;\n        this->left = nullptr;\n        this->right = nullptr;\n    }\n};\n\n// TreeInfo class represents the information of a binary tree, including its balance status and height\nclass TreeInfo {\npublic:\n    bool isBalanced;\n    int height;\n\n    TreeInfo(bool isBalanced, int height) {\n        this->isBalanced = isBalanced;\n        this->height = height;\n    }\n};\n\n// heightBalancedBinaryTree checks if a binary tree is height-balanced\nbool heightBalancedBinaryTree(BinaryTree* tree) {\n    // Retrieve the tree information using the helper function\n    TreeInfo treeInfo = getTreeInfo(tree);\n\n    // Return the balance status of the tree\n    return treeInfo.isBalanced;\n}\n\n// getTreeInfo retrieves the information of a binary tree, including its balance status and height\nTreeInfo getTreeInfo(BinaryTree* tree) {\n    // Base case: If the tree is nullptr, it is considered balanced with height -1\n    if (tree == nullptr) {\n        return TreeInfo(true, -1);\n    }\n\n    // Recursively calculate the tree information of the left and right subtrees\n    TreeInfo leftSubtreeInfo = getTreeInfo(tree->left);\n    TreeInfo rightSubtreeInfo = getTreeInfo(tree->right);\n\n    // Check if both left and right subtrees are balanced and their height difference is at most 1\n    bool isBalanced = leftSubtreeInfo.isBalanced && rightSubtreeInfo.isBalanced &&\n                      std::abs(leftSubtreeInfo.height - rightSubtreeInfo.height) <= 1;\n\n    // Calculate the height of the current tree by taking the maximum height of the left and right subtrees plus 1\n    int height = std::max(leftSubtreeInfo.height, rightSubtreeInfo.height) + 1;\n\n    // Create and return the tree information\n    return TreeInfo(isBalanced, height);\n}\n\n// Helper function to create a binary tree\nBinaryTree* createBinaryTree(int value) {\n    return new BinaryTree(value);\n}\n\n// Main function\nint main() {\n    // Create a sample binary tree\n    //          1\n    //        /   \\\n    //       2     3\n    //      / \\   /\n    //     4   5 6\n    BinaryTree* node1 = createBinaryTree(1);\n    BinaryTree* node2 = createBinaryTree(2);\n    BinaryTree* node3 = createBinaryTree(3);\n    BinaryTree* node4 = createBinaryTree(4);\n    BinaryTree* node5 = createBinaryTree(5);\n    BinaryTree* node6 = createBinaryTree(6);\n\n    node1->left = node2;\n    node1->right = node3;\n    node2->left = node4;\n    node2->right = node5;\n    node3->left = node6;\n\n    // Check if the binary tree is height-balanced\n    bool isBalanced = heightBalancedBinaryTree(node1);\n\n    // Print the result\n    if (isBalanced) {\n        std::cout << \"The binary tree is height-balanced.\" << std::endl;\n    } else {\n        std::cout << \"The binary tree is not height-balanced.\" << std::endl;\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "Trees/Binary Trees/height_balanced_binary_tree.go",
    "content": "/*\n\tYou're given the root node of a Binary Tree. Write a function that returns true\n\tif this Binary Tree is height balanced and false if it isn't.\n\n\tExplanation:\n\n\tThe provided code is for checking whether a binary tree is height-balanced or not. Here's how it works:\n\n\t- The code defines a `BinaryTree` struct representing a node in a binary tree. Each node has a value and\n\tpointers to its left and right child nodes.\n\n\t- The code also defines a `TreeeInfo` struct to store information about a binary tree. It includes a boolean\n\tfield `isBalanced` indicating whether the tree is balanced or not, and an integer field `height` representing\n\tthe height of the tree.\n\n\t- The `HeightBalancedBinaryTree` function is the main function that checks if a binary tree is height-balanced.\n\tIt takes the root of the tree as input and returns a boolean value indicating the balance status.\n\n\t- The `getTreeInfo` function is a helper function that recursively calculates the information of a binary tree.\n\tIt takes a binary tree node as input and returns the `TreeeInfo` struct containing the balance status and height\n\tof the tree.\n\n\t- In the `getTreeInfo` function, there are two base cases:\n\t- If the current tree node is `nil`, it is considered balanced with height -1.\n\t- If the current tree node is not `nil`, the function recursively calculates the tree information of its\n\tleft and right subtrees.\n\n\t- After getting the information of the left and right subtrees, the code checks if both subtrees are balanced\n\t(`isBalanced` field is `true`) and their height difference is at most 1. If so, the current tree is considered\n\tbalanced.\n\n\t- The height of the current tree is calculated by taking the maximum height of the left and right subtrees and\n\tadding 1.\n\n\t- Finally, the `max` function is used to get the maximum of two integers, and the `abs` function is used to get\n\tthe absolute value of an integer.\n\n\tTo determine whether a binary tree is height-balanced, you can call the `HeightBalancedBinaryTree` function with\n\tthe root of the tree. It will return `true` if the tree is balanced and `false` otherwise.\n\n\tThe time complexity of the `HeightBalancedBinaryTree` function is O(N), where N is the number of nodes in the\n\tbinary tree. This is because the function needs to traverse each node of the tree once to calculate the tree\n\tinformation.\n\n\tThe space complexity of the `HeightBalancedBinaryTree` function is O(H), where H is the height of the binary tree.\n\tThis is because the recursive calls to the `getTreeInfo` function will utilize the call stack, and the maximum\n\tdepth of the recursive calls is equal to the height of the tree. Additionally, the space complexity of the\n\t`getTreeInfo` function itself is O(1) as it uses a constant amount of space for the `TreeeInfo` struct.\n\n\tOverall, the space complexity is determined by the height of the binary tree, and the time complexity is\n\tdetermined by the number of nodes in the binary tree.\n\n*/\npackage main\n\nimport \"fmt\"\n\n// This is an input class. Do not edit.\ntype BinaryTree struct {\n\tValue int\n\n\tLeft  *BinaryTree\n\tRight *BinaryTree\n}\n\ntype TreeeInfo struct {\n\tisBalanced bool\n\theight     int\n}\n\n// HeightBalancedBinaryTree checks if a binary tree is height-balanced.\nfunc HeightBalancedBinaryTree(tree *BinaryTree) bool {\n\t// Retrieve the tree information using the helper function.\n\ttreeInfo := getTreeInfo(tree)\n\n\t// Return the balance status of the tree.\n\treturn treeInfo.isBalanced\n}\n\n// getTreeInfo retrieves the information of a binary tree, including its balance status and height.\nfunc getTreeInfo(tree *BinaryTree) TreeeInfo {\n\t// Base case: If the tree is nil, it is considered balanced with height -1.\n\tif tree == nil {\n\t\treturn TreeeInfo{isBalanced: true, height: -1}\n\t}\n\n\t// Recursively calculate the tree information of the left and right subtrees.\n\tleftSubtreeInfo := getTreeInfo(tree.Left)\n\trightSubtreeInfo := getTreeInfo(tree.Right)\n\n\t// Check if both left and right subtrees are balanced and their height difference is at most 1.\n\tisBalanced := leftSubtreeInfo.isBalanced && rightSubtreeInfo.isBalanced &&\n\t\tabs(leftSubtreeInfo.height - rightSubtreeInfo.height) <= 1\n\n\t// Calculate the height of the current tree by taking the maximum height of the left and right subtrees plus 1.\n\theight := max(leftSubtreeInfo.height, rightSubtreeInfo.height) + 1\n\n\t// Create and return the tree information.\n\treturn TreeeInfo{\n\t\tisBalanced: isBalanced,\n\t\theight:     height,\n\t}\n}\n\n// max returns the maximum of two integers.\nfunc max(a, b int) int {\n\tif a > b {\n\t\treturn a\n\t}\n\treturn b\n}\n\n// abs returns the absolute value of an integer.\nfunc abs(a int) int {\n\tif a < 0 {\n\t\treturn -a\n\t}\n\treturn a\n}\n\nfunc main() {\n\t// Create a binary tree\n\ttree := &BinaryTree{\n\t\tValue: 1,\n\t\tLeft: &BinaryTree{\n\t\t\tValue: 2,\n\t\t\tLeft: &BinaryTree{\n\t\t\t\tValue: 4,\n\t\t\t},\n\t\t\tRight: &BinaryTree{\n\t\t\t\tValue: 5,\n\t\t\t},\n\t\t},\n\t\tRight: &BinaryTree{\n\t\t\tValue: 3,\n\t\t\tRight: &BinaryTree{\n\t\t\t\tValue: 6,\n\t\t\t\tLeft: &BinaryTree{\n\t\t\t\t\tValue: 7,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\t// Check if the binary tree is height-balanced\n\tisBalanced := HeightBalancedBinaryTree(tree)\n\n\t// Output the result\n\tif isBalanced {\n\t\tfmt.Println(\"The binary tree is height-balanced.\")\n\t} else {\n\t\tfmt.Println(\"The binary tree is not height-balanced.\")\n\t}\n}\n"
  },
  {
    "path": "Trees/Binary Trees/height_balanced_binary_tree.java",
    "content": "/*\n\tYou're given the root node of a Binary Tree. Write a function that returns true\n\tif this Binary Tree is height balanced and false if it isn't.\n\n\tExplanation:\n\n\tThe provided code is for checking whether a binary tree is height-balanced or not. Here's how it works:\n\n\t- The code defines a `BinaryTree` struct representing a node in a binary tree. Each node has a value and\n\tpointers to its left and right child nodes.\n\n\t- The code also defines a `TreeeInfo` struct to store information about a binary tree. It includes a boolean\n\tfield `isBalanced` indicating whether the tree is balanced or not, and an integer field `height` representing\n\tthe height of the tree.\n\n\t- The `HeightBalancedBinaryTree` function is the main function that checks if a binary tree is height-balanced.\n\tIt takes the root of the tree as input and returns a boolean value indicating the balance status.\n\n\t- The `getTreeInfo` function is a helper function that recursively calculates the information of a binary tree.\n\tIt takes a binary tree node as input and returns the `TreeeInfo` struct containing the balance status and height\n\tof the tree.\n\n\t- In the `getTreeInfo` function, there are two base cases:\n\t- If the current tree node is `nil`, it is considered balanced with height -1.\n\t- If the current tree node is not `nil`, the function recursively calculates the tree information of its\n\tleft and right subtrees.\n\n\t- After getting the information of the left and right subtrees, the code checks if both subtrees are balanced\n\t(`isBalanced` field is `true`) and their height difference is at most 1. If so, the current tree is considered\n\tbalanced.\n\n\t- The height of the current tree is calculated by taking the maximum height of the left and right subtrees and\n\tadding 1.\n\n\t- Finally, the `max` function is used to get the maximum of two integers, and the `abs` function is used to get\n\tthe absolute value of an integer.\n\n\tTo determine whether a binary tree is height-balanced, you can call the `HeightBalancedBinaryTree` function with\n\tthe root of the tree. It will return `true` if the tree is balanced and `false` otherwise.\n\n\tThe time complexity of the `HeightBalancedBinaryTree` function is O(N), where N is the number of nodes in the\n\tbinary tree. This is because the function needs to traverse each node of the tree once to calculate the tree\n\tinformation.\n\n\tThe space complexity of the `HeightBalancedBinaryTree` function is O(H), where H is the height of the binary tree.\n\tThis is because the recursive calls to the `getTreeInfo` function will utilize the call stack, and the maximum\n\tdepth of the recursive calls is equal to the height of the tree. Additionally, the space complexity of the\n\t`getTreeInfo` function itself is O(1) as it uses a constant amount of space for the `TreeeInfo` struct.\n\n\tOverall, the space complexity is determined by the height of the binary tree, and the time complexity is\n\tdetermined by the number of nodes in the binary tree.\n\n*/\n// Node class represents a node in a binary tree\nclass BinaryTree {\n    int value;\n    BinaryTree left;\n    BinaryTree right;\n  \n    BinaryTree(int value) {\n        this.value = value;\n        this.left = null;\n        this.right = null;\n    }\n}\n\n// TreeInfo class represents the information of a binary tree, including its balance status and height\nclass TreeInfo {\n    boolean isBalanced;\n    int height;\n  \n    TreeInfo(boolean isBalanced, int height) {\n        this.isBalanced = isBalanced;\n        this.height = height;\n    }\n}\n\n// heightBalancedBinaryTree checks if a binary tree is height-balanced\nclass HeightBalancedBinaryTree {\n    public static boolean heightBalancedBinaryTree(BinaryTree tree) {\n        // Retrieve the tree information using the helper function\n        TreeInfo treeInfo = getTreeInfo(tree);\n      \n        // Return the balance status of the tree\n        return treeInfo.isBalanced;\n    }\n  \n    // getTreeInfo retrieves the information of a binary tree, including its balance status and height\n    private static TreeInfo getTreeInfo(BinaryTree tree) {\n        // Base case: If the tree is null, it is considered balanced with height -1\n        if (tree == null) {\n            return new TreeInfo(true, -1);\n        }\n      \n        // Recursively calculate the tree information of the left and right subtrees\n        TreeInfo leftSubtreeInfo = getTreeInfo(tree.left);\n        TreeInfo rightSubtreeInfo = getTreeInfo(tree.right);\n      \n        // Check if both left and right subtrees are balanced and their height difference is at most 1\n        boolean isBalanced = leftSubtreeInfo.isBalanced && rightSubtreeInfo.isBalanced &&\n            Math.abs(leftSubtreeInfo.height - rightSubtreeInfo.height) <= 1;\n      \n        // Calculate the height of the current tree by taking the maximum height of the left and right subtrees plus 1\n        int height = Math.max(leftSubtreeInfo.height, rightSubtreeInfo.height) + 1;\n      \n        // Create and return the tree information\n        return new TreeInfo(isBalanced, height);\n    }\n  \n    // Helper function to create a binary tree\n    private static BinaryTree createBinaryTree(int value) {\n        return new BinaryTree(value);\n    }\n  \n    // Main function\n    public static void main(String[] args) {\n        // Create a sample binary tree\n        //          1\n        //        /   \\\n        //       2     3\n        //      / \\   /\n        //     4   5 6\n        BinaryTree node1 = createBinaryTree(1);\n        BinaryTree node2 = createBinaryTree(2);\n        BinaryTree node3 = createBinaryTree(3);\n        BinaryTree node4 = createBinaryTree(4);\n        BinaryTree node5 = createBinaryTree(5);\n        BinaryTree node6 = createBinaryTree(6);\n      \n        node1.left = node2;\n        node1.right = node3;\n        node2.left = node4;\n        node2.right = node5;\n        node3.left = node6;\n      \n        // Check if the binary tree is height-balanced\n        boolean isBalanced = heightBalancedBinaryTree(node1);\n      \n        // Print the result\n        if (isBalanced) {\n            System.out.println(\"The binary tree is height-balanced.\");\n        } else {\n            System.out.println(\"The binary tree is not height-balanced.\");\n        }\n    }\n}\n"
  },
  {
    "path": "Trees/Binary Trees/height_balanced_binary_tree.js",
    "content": "/*\n\tYou're given the root node of a Binary Tree. Write a function that returns true\n\tif this Binary Tree is height balanced and false if it isn't.\n\n\tExplanation:\n\n\tThe provided code is for checking whether a binary tree is height-balanced or not. Here's how it works:\n\n\t- The code defines a `BinaryTree` struct representing a node in a binary tree. Each node has a value and\n\tpointers to its left and right child nodes.\n\n\t- The code also defines a `TreeeInfo` struct to store information about a binary tree. It includes a boolean\n\tfield `isBalanced` indicating whether the tree is balanced or not, and an integer field `height` representing\n\tthe height of the tree.\n\n\t- The `HeightBalancedBinaryTree` function is the main function that checks if a binary tree is height-balanced.\n\tIt takes the root of the tree as input and returns a boolean value indicating the balance status.\n\n\t- The `getTreeInfo` function is a helper function that recursively calculates the information of a binary tree.\n\tIt takes a binary tree node as input and returns the `TreeeInfo` struct containing the balance status and height\n\tof the tree.\n\n\t- In the `getTreeInfo` function, there are two base cases:\n\t- If the current tree node is `nil`, it is considered balanced with height -1.\n\t- If the current tree node is not `nil`, the function recursively calculates the tree information of its\n\tleft and right subtrees.\n\n\t- After getting the information of the left and right subtrees, the code checks if both subtrees are balanced\n\t(`isBalanced` field is `true`) and their height difference is at most 1. If so, the current tree is considered\n\tbalanced.\n\n\t- The height of the current tree is calculated by taking the maximum height of the left and right subtrees and\n\tadding 1.\n\n\t- Finally, the `max` function is used to get the maximum of two integers, and the `abs` function is used to get\n\tthe absolute value of an integer.\n\n\tTo determine whether a binary tree is height-balanced, you can call the `HeightBalancedBinaryTree` function with\n\tthe root of the tree. It will return `true` if the tree is balanced and `false` otherwise.\n\n\tThe time complexity of the `HeightBalancedBinaryTree` function is O(N), where N is the number of nodes in the\n\tbinary tree. This is because the function needs to traverse each node of the tree once to calculate the tree\n\tinformation.\n\n\tThe space complexity of the `HeightBalancedBinaryTree` function is O(H), where H is the height of the binary tree.\n\tThis is because the recursive calls to the `getTreeInfo` function will utilize the call stack, and the maximum\n\tdepth of the recursive calls is equal to the height of the tree. Additionally, the space complexity of the\n\t`getTreeInfo` function itself is O(1) as it uses a constant amount of space for the `TreeeInfo` struct.\n\n\tOverall, the space complexity is determined by the height of the binary tree, and the time complexity is\n\tdetermined by the number of nodes in the binary tree.\n\n*/\n// Node class represents a node in a binary tree\nclass BinaryTree {\n  constructor(value) {\n    this.value = value;\n    this.left = null;\n    this.right = null;\n  }\n}\n\n// TreeInfo class represents the information of a binary tree, including its balance status and height\nclass TreeInfo {\n  constructor(isBalanced, height) {\n    this.isBalanced = isBalanced;\n    this.height = height;\n  }\n}\n\n// heightBalancedBinaryTree checks if a binary tree is height-balanced\nfunction heightBalancedBinaryTree(tree) {\n  // Retrieve the tree information using the helper function\n  const treeInfo = getTreeInfo(tree);\n\n  // Return the balance status of the tree\n  return treeInfo.isBalanced;\n}\n\n// getTreeInfo retrieves the information of a binary tree, including its balance status and height\nfunction getTreeInfo(tree) {\n  // Base case: If the tree is null, it is considered balanced with height -1\n  if (tree === null) {\n    return new TreeInfo(true, -1);\n  }\n\n  // Recursively calculate the tree information of the left and right subtrees\n  const leftSubtreeInfo = getTreeInfo(tree.left);\n  const rightSubtreeInfo = getTreeInfo(tree.right);\n\n  // Check if both left and right subtrees are balanced and their height difference is at most 1\n  const isBalanced =\n    leftSubtreeInfo.isBalanced &&\n    rightSubtreeInfo.isBalanced &&\n    Math.abs(leftSubtreeInfo.height - rightSubtreeInfo.height) <= 1;\n\n  // Calculate the height of the current tree by taking the maximum height of the left and right subtrees plus 1\n  const height = Math.max(leftSubtreeInfo.height, rightSubtreeInfo.height) + 1;\n\n  // Create and return the tree information\n  return new TreeInfo(isBalanced, height);\n}\n\n// Helper function to create a binary tree\nfunction createBinaryTree(value) {\n  return new BinaryTree(value);\n}\n\n// Main function\nfunction main() {\n  // Create a sample binary tree\n  //          1\n  //        /   \\\n  //       2     3\n  //      / \\   /\n  //     4   5 6\n  const node1 = createBinaryTree(1);\n  const node2 = createBinaryTree(2);\n  const node3 = createBinaryTree(3);\n  const node4 = createBinaryTree(4);\n  const node5 = createBinaryTree(5);\n  const node6 = createBinaryTree(6);\n\n  node1.left = node2;\n  node1.right = node3;\n  node2.left = node4;\n  node2.right = node5;\n  node3.left = node6;\n\n  // Check if the binary tree is height-balanced\n  const isBalanced = heightBalancedBinaryTree(node1);\n\n  // Print the result\n  if (isBalanced) {\n    console.log(\"The binary tree is height-balanced.\");\n  } else {\n    console.log(\"The binary tree is not height-balanced.\");\n  }\n}\n\n// Call the main function\nmain();\n"
  },
  {
    "path": "Trees/Binary Trees/height_balanced_binary_tree.py",
    "content": "'''\n\tYou're given the root node of a Binary Tree. Write a function that returns true\n\tif this Binary Tree is height balanced and false if it isn't.\n\n\tExplanation:\n\n\tThe provided code is for checking whether a binary tree is height-balanced or not. Here's how it works:\n\n\t- The code defines a `BinaryTree` struct representing a node in a binary tree. Each node has a value and\n\tpointers to its left and right child nodes.\n\n\t- The code also defines a `TreeeInfo` struct to store information about a binary tree. It includes a boolean\n\tfield `isBalanced` indicating whether the tree is balanced or not, and an integer field `height` representing\n\tthe height of the tree.\n\n\t- The `HeightBalancedBinaryTree` function is the main function that checks if a binary tree is height-balanced.\n\tIt takes the root of the tree as input and returns a boolean value indicating the balance status.\n\n\t- The `getTreeInfo` function is a helper function that recursively calculates the information of a binary tree.\n\tIt takes a binary tree node as input and returns the `TreeeInfo` struct containing the balance status and height\n\tof the tree.\n\n\t- In the `getTreeInfo` function, there are two base cases:\n\t- If the current tree node is `nil`, it is considered balanced with height -1.\n\t- If the current tree node is not `nil`, the function recursively calculates the tree information of its\n\tleft and right subtrees.\n\n\t- After getting the information of the left and right subtrees, the code checks if both subtrees are balanced\n\t(`isBalanced` field is `true`) and their height difference is at most 1. If so, the current tree is considered\n\tbalanced.\n\n\t- The height of the current tree is calculated by taking the maximum height of the left and right subtrees and\n\tadding 1.\n\n\t- Finally, the `max` function is used to get the maximum of two integers, and the `abs` function is used to get\n\tthe absolute value of an integer.\n\n\tTo determine whether a binary tree is height-balanced, you can call the `HeightBalancedBinaryTree` function with\n\tthe root of the tree. It will return `true` if the tree is balanced and `false` otherwise.\n\n\tThe time complexity of the `HeightBalancedBinaryTree` function is O(N), where N is the number of nodes in the\n\tbinary tree. This is because the function needs to traverse each node of the tree once to calculate the tree\n\tinformation.\n\n\tThe space complexity of the `HeightBalancedBinaryTree` function is O(H), where H is the height of the binary tree.\n\tThis is because the recursive calls to the `getTreeInfo` function will utilize the call stack, and the maximum\n\tdepth of the recursive calls is equal to the height of the tree. Additionally, the space complexity of the\n\t`getTreeInfo` function itself is O(1) as it uses a constant amount of space for the `TreeeInfo` struct.\n\n\tOverall, the space complexity is determined by the height of the binary tree, and the time complexity is\n\tdetermined by the number of nodes in the binary tree.\n\n'''\n\n# This is an input class. Do not edit.\nclass BinaryTree:\n    def __init__(self, value):\n        self.value = value\n        self.left = None\n        self.right = None\n\nclass TreeInfo:\n    def __init__(self, is_balanced, height):\n        self.is_balanced = is_balanced\n        self.height = height\n\n# Checks if a binary tree is height-balanced.\ndef height_balanced_binary_tree(tree):\n    # Retrieve the tree information using the helper function.\n    tree_info = get_tree_info(tree)\n    \n    # Return the balance status of the tree.\n    return tree_info.is_balanced\n\n# Retrieves the information of a binary tree, including its balance status and height.\ndef get_tree_info(tree):\n    # Base case: If the tree is None, it is considered balanced with height -1.\n    if tree is None:\n        return TreeInfo(True, -1)\n    \n    # Recursively calculate the tree information of the left and right subtrees.\n    left_subtree_info = get_tree_info(tree.left)\n    right_subtree_info = get_tree_info(tree.right)\n    \n    # Check if both left and right subtrees are balanced and their height difference is at most 1.\n    is_balanced = left_subtree_info.is_balanced and right_subtree_info.is_balanced and \\\n        abs(left_subtree_info.height - right_subtree_info.height) <= 1\n    \n    # Calculate the height of the current tree by taking the maximum height of the left and right subtrees plus 1.\n    height = max(left_subtree_info.height, right_subtree_info.height) + 1\n    \n    # Create and return the tree information.\n    return TreeInfo(is_balanced, height)\n\n# Returns the maximum of two integers.\ndef max(a, b):\n    return a if a > b else b\n\n# Returns the absolute value of an integer.\ndef abs(a):\n    return -a if a < 0 else a\n\n# Main function\ndef main():\n    # Create a sample binary tree\n    #          1\n    #        /   \\\n    #       2     3\n    #      / \\   /\n    #     4   5 6\n    node1 = BinaryTree(1)\n    node2 = BinaryTree(2)\n    node3 = BinaryTree(3)\n    node4 = BinaryTree(4)\n    node5 = BinaryTree(5)\n    node6 = BinaryTree(6)\n    \n    node1.left = node2\n    node1.right = node3\n    node2.left = node4\n    node2.right = node5\n    node3.left = node6\n    \n    # Check if the binary tree is height-balanced\n    is_balanced = height_balanced_binary_tree(node1)\n    \n    # Print the result\n    if is_balanced:\n        print(\"The binary tree is height-balanced.\")\n    else:\n        print(\"The binary tree is not height-balanced.\")\n\n# Call the main function\nif __name__ == \"__main__\":\n    main()\n\n\n"
  },
  {
    "path": "Trees/Binary Trees/inorder_traversal.cpp",
    "content": "// In-Order Traversal of a Binary-Tree\n// Program Author : Abhisek Kumar Gupta\n/*\n          40\n        /   \\\n       10     30\n      / \\     /  \\\n     5   -1  -1  28\n    / \\         /  \\\n   1   -1      15    20\n  / \\          /\\    /\\\n -1 -1        -1 -1 -1 -1\n Input : 40 10 5 1 -1 -1 -1 -1 30 -1 28 15 -1 -1 20 -1 -1\n Output : 1->5->10->40->30->15->28->20  \n*/\n#include <iostream>\n#include <vector>\n#include <stack>\n\n// Definition for a binary tree node.\nstruct TreeNode {\n    int val;\n    TreeNode* left;\n    TreeNode* right;\n    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}\n};\n\nclass Solution {\npublic:\n    std::vector<int> inorderTraversal(TreeNode* root) {\n        // Vector to store the in-order traversal result\n        std::vector<int> result;\n\n        // Stack to simulate the recursive call stack\n        std::stack<TreeNode*> stack;\n\n        // Current node starts from the root\n        TreeNode* current = root;\n\n        // Continue traversal until the current node is null and the stack is empty\n        while (current != nullptr || !stack.empty()) {\n            // Traverse all the way to the leftmost node, pushing each node onto the stack\n            while (current != nullptr) {\n                stack.push(current);\n                current = current->left;\n            }\n\n            // Pop the top node from the stack (current leftmost node)\n            current = stack.top();\n            stack.pop();\n\n            // Add the value of the current node to the result vector\n            result.push_back(current->val);\n\n            // Move to the right subtree of the current node\n            current = current->right;\n        }\n\n        // Return the final in-order traversal result\n        return result;\n    }\n};\n\n// Example usage\nint main() {\n    // Create a sample binary tree\n    TreeNode* root = new TreeNode(1);\n    root->right = new TreeNode(2);\n    root->right->left = new TreeNode(3);\n\n    // Perform in-order traversal\n    Solution solution;\n    std::vector<int> result = solution.inorderTraversal(root);\n\n    // Print the result\n    for (int val : result) {\n        std::cout << val << \" \";\n    }\n\n    // Output: 1 3 2\n    return 0;\n}\n\n"
  },
  {
    "path": "Trees/Binary Trees/inorder_traversal.go",
    "content": "package main\n\nimport \"fmt\"\n\n// TreeNode definition\ntype TreeNode struct {\n\tVal   int\n\tLeft  *TreeNode\n\tRight *TreeNode\n}\n\nfunc inorderTraversal(root *TreeNode) []int {\n\tvar result []int\n\tvar stack []*TreeNode\n\tcurrent := root\n\n\tfor current != nil || len(stack) > 0 {\n\t\t// Traverse all the way to the leftmost node, pushing each node onto the stack\n\t\tfor current != nil {\n\t\t\tstack = append(stack, current)\n\t\t\tcurrent = current.Left\n\t\t}\n\n\t\t// Pop the top node from the stack (current leftmost node)\n\t\tcurrent, stack = stack[len(stack)-1], stack[:len(stack)-1]\n\n\t\t// Add the value of the current node to the result slice\n\t\tresult = append(result, current.Val)\n\n\t\t// Move to the right subtree of the current node\n\t\tcurrent = current.Right\n\t}\n\n\treturn result\n}\n\nfunc main() {\n\t// Create a sample binary tree\n\troot := &TreeNode{Val: 1, Right: &TreeNode{Val: 2, Left: &TreeNode{Val: 3}}}\n\n\t// Perform in-order traversal\n\tresult := inorderTraversal(root)\n\n\t// Print the result\n\tfmt.Println(result) // Output: [1 3 2]\n}\n"
  },
  {
    "path": "Trees/Binary Trees/inorder_traversal.java",
    "content": "\n/**\n * Given the root of a binary tree, return the inorder traversal of its nodes' values.\n * Definition for a binary tree node.\n * public class TreeNode {\n *     int val;\n *     TreeNode left;\n *     TreeNode right;\n *     TreeNode() {}\n *     TreeNode(int val) { this.val = val; }\n *     TreeNode(int val, TreeNode left, TreeNode right) {\n *         this.val = val;\n *         this.left = left;\n *         this.right = right;\n *     }\n * }\n */\n/**\n \n */\nclass Solution {\n    public List<Integer> inorderTraversal(TreeNode root) {\n        // List to store the in-order traversal result\n        List<Integer> result = new ArrayList<>();\n\n        // Stack to simulate the recursive call stack\n        Stack<TreeNode> stack = new Stack<>();\n\n        // Current node starts from the root\n        TreeNode current = root;\n\n        // Continue traversal until current node is null and stack is empty\n        while (current != null || !stack.isEmpty()) {\n            // Traverse all the way to the leftmost node, pushing each node onto the stack\n            while (current != null) {\n                stack.push(current);\n                current = current.left;\n            }\n\n            // Pop the top node from the stack (current leftmost node)\n            current = stack.pop();\n\n            // Add the value of the current node to the result list\n            result.add(current.val);\n\n            // Move to the right subtree of the current node\n            current = current.right;\n        }\n\n        // Return the final in-order traversal result\n        return result;\n    }\n}\n"
  },
  {
    "path": "Trees/Binary Trees/inorder_traversal.js",
    "content": "class TreeNode {\n  constructor(val) {\n    this.val = val;\n    this.left = this.right = null;\n  }\n}\n\nclass Solution {\n  inorderTraversal(root) {\n    const result = [];\n    const stack = [];\n    let current = root;\n\n    while (current || stack.length > 0) {\n      // Traverse all the way to the leftmost node, pushing each node onto the stack\n      while (current) {\n        stack.push(current);\n        current = current.left;\n      }\n\n      // Pop the top node from the stack (current leftmost node)\n      current = stack.pop();\n\n      // Add the value of the current node to the result array\n      result.push(current.val);\n\n      // Move to the right subtree of the current node\n      current = current.right;\n    }\n\n    return result;\n  }\n}\n\n// Example usage\nconst root = new TreeNode(1);\nroot.right = new TreeNode(2);\nroot.right.left = new TreeNode(3);\n\nconst solution = new Solution();\nconst result = solution.inorderTraversal(root);\n\nconsole.log(result); // Output: [1, 3, 2]\n"
  },
  {
    "path": "Trees/Binary Trees/inorder_traversal.py",
    "content": "class TreeNode:\n    def __init__(self, val):\n        self.val = val\n        self.left = self.right = None\n\nclass Solution:\n    def inorderTraversal(self, root):\n        result = []\n        stack = []\n        current = root\n\n        while current or stack:\n            # Traverse all the way to the leftmost node, pushing each node onto the stack\n            while current:\n                stack.append(current)\n                current = current.left\n\n            # Pop the top node from the stack (current leftmost node)\n            current = stack.pop()\n\n            # Add the value of the current node to the result list\n            result.append(current.val)\n\n            # Move to the right subtree of the current node\n            current = current.right\n\n        return result\n\n# Example usage\nroot = TreeNode(1)\nroot.right = TreeNode(2)\nroot.right.left = TreeNode(3)\n\nsolution = Solution()\nresult = solution.inorderTraversal(root)\n\nprint(result)  # Output: [1, 3, 2]\n"
  },
  {
    "path": "Trees/Binary Trees/invert.cpp",
    "content": "// Invert Binary tree\n#include <iostream>\n\nclass BinaryTreeNode {\npublic:\n    int data;\n    BinaryTreeNode* left;\n    BinaryTreeNode* right;\n\n    BinaryTreeNode(int val) : data(val), left(nullptr), right(nullptr) {}\n};\n\nBinaryTreeNode* invertTree(BinaryTreeNode* root) {\n    if (root != nullptr) {\n        root->left = invertTree(root->right);\n        root->right = invertTree(root->left);\n    }\n    return root;\n}\n\nBinaryTreeNode* invertTree2(BinaryTreeNode* root) {\n    if (root != nullptr) {\n        // swap the pointers in this node\n        BinaryTreeNode* temp = root->left;\n        root->left = root->right;\n        root->right = temp;\n\n        invertTree2(root->left);\n        invertTree2(root->right);\n    }\n    return root;\n}\n\nint main() {\n    // Example usage:\n    // Construct a binary tree\n    BinaryTreeNode* root = new BinaryTreeNode(1);\n    root->left = new BinaryTreeNode(2);\n    root->right = new BinaryTreeNode(3);\n    root->left->left = new BinaryTreeNode(4);\n    root->left->right = new BinaryTreeNode(5);\n\n    // Invert the binary tree using the first approach\n    BinaryTreeNode* invertedRoot = invertTree(root);\n\n    // Invert the binary tree using the second approach\n    BinaryTreeNode* invertedRoot2 = invertTree2(root);\n\n    // Additional code for printing or further usage...\n\n    return 0;\n}\n"
  },
  {
    "path": "Trees/Binary Trees/invert.go",
    "content": "// Invert Binary tree\npackage main\n\ntype BinaryTreeNode struct {\n\tleft  *BinaryTreeNode\n\tdata  int\n\tright *BinaryTreeNode\n}\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: The inverse of an empty tree is an empty tree\n// The inverse of a tree with root r, and subtrees right and left is a tree with\n// root, whose right subtree is the inverse of left and whoose left subtree\n// is the inverse of right\nfunc InvertTree(root *BinaryTreeNode) *BinaryTreeNode {\n\tif root != nil {\n\t\troot.left, root.right = InvertTree(root.right), InvertTree(root.left)\n\t}\n\treturn root\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\n// Method2 : swap pointers\nfunc InvertTree2(root *BinaryTreeNode) *BinaryTreeNode {\n\tif root == nil {\n\t\treturn root\n\t}\n\t// swap the pointers in this node\n\troot.left, root.right = root.right, root.left\n\tInvertTree(root.left)\n\tInvertTree(root.right)\n\treturn root\n}\n"
  },
  {
    "path": "Trees/Binary Trees/invert.java",
    "content": "class BinaryTreeNode {\n    int data;\n    BinaryTreeNode left, right;\n\n    public BinaryTreeNode(int data) {\n        this.data = data;\n        this.left = this.right = null;\n    }\n}\n\npublic class BinaryTreeInverter {\n    // Time Complexity: O(n). Space Complexity: O(n).\n    // Approach: The inverse of an empty tree is an empty tree\n    // The inverse of a tree with root r, and subtrees right and left is a tree with\n    // root, whose right subtree is the inverse of left and whose left subtree\n    // is the inverse of right\n    public BinaryTreeNode invertTree(BinaryTreeNode root) {\n        if (root != null) {\n            root.left = invertTree(root.right);\n            root.right = invertTree(root.left);\n        }\n        return root;\n    }\n\n    // Time Complexity: O(n). Space Complexity: O(1).\n    // Method2: swap pointers\n    public BinaryTreeNode invertTree2(BinaryTreeNode root) {\n        if (root != null) {\n            // swap the pointers in this node\n            BinaryTreeNode temp = root.left;\n            root.left = root.right;\n            root.right = temp;\n\n            invertTree2(root.left);\n            invertTree2(root.right);\n        }\n        return root;\n    }\n\n    // Additional methods or code as needed...\n\n    public static void main(String[] args) {\n        // Example usage:\n        // Construct a binary tree\n        BinaryTreeNode root = new BinaryTreeNode(1);\n        root.left = new BinaryTreeNode(2);\n        root.right = new BinaryTreeNode(3);\n        root.left.left = new BinaryTreeNode(4);\n        root.left.right = new BinaryTreeNode(5);\n\n        BinaryTreeInverter inverter = new BinaryTreeInverter();\n\n        // Invert the binary tree using the first approach\n        BinaryTreeNode invertedRoot = inverter.invertTree(root);\n\n        // Invert the binary tree using the second approach\n        BinaryTreeNode invertedRoot2 = inverter.invertTree2(root);\n\n        // Additional code for printing or further usage...\n    }\n}\n"
  },
  {
    "path": "Trees/Binary Trees/invert.js",
    "content": "class BinaryTreeNode {\n  constructor(data) {\n    this.data = data;\n    this.left = this.right = null;\n  }\n}\n\nclass BinaryTreeInverter {\n  // Time Complexity: O(n). Space Complexity: O(n).\n  // Approach: The inverse of an empty tree is an empty tree\n  // The inverse of a tree with root r, and subtrees right and left is a tree with\n  // root, whose right subtree is the inverse of left and whoose left subtree\n  // is the inverse of right\n  invertTree(root) {\n    if (root !== null) {\n      root.left = this.invertTree(root.right);\n      root.right = this.invertTree(root.left);\n    }\n    return root;\n  }\n\n  // Time Complexity: O(n). Space Complexity: O(1).\n  // Method2: swap pointers\n  invertTree2(root) {\n    if (root !== null) {\n      // swap the pointers in this node\n      let temp = root.left;\n      root.left = root.right;\n      root.right = temp;\n\n      this.invertTree2(root.left);\n      this.invertTree2(root.right);\n    }\n    return root;\n  }\n\n  // Additional methods or code as needed...\n\n  // Example usage:\n  static main() {\n    // Construct a binary tree\n    let root = new BinaryTreeNode(1);\n    root.left = new BinaryTreeNode(2);\n    root.right = new BinaryTreeNode(3);\n    root.left.left = new BinaryTreeNode(4);\n    root.left.right = new BinaryTreeNode(5);\n\n    let inverter = new BinaryTreeInverter();\n\n    // Invert the binary tree using the first approach\n    let invertedRoot = inverter.invertTree(root);\n\n    // Invert the binary tree using the second approach\n    let invertedRoot2 = inverter.invertTree2(root);\n\n    // Additional code for printing or further usage...\n  }\n}\n\n// Example usage:\nBinaryTreeInverter.main();\n"
  },
  {
    "path": "Trees/Binary Trees/invert.py",
    "content": "# Invert Binary tree\nclass BinaryTreeNode:\n    def __init__(self, data):\n        self.left = None\n        self.data = data\n        self.right = None\n\ndef invert_tree(root):\n    if root:\n        root.left, root.right = invert_tree(root.right), invert_tree(root.left)\n    return root\n\ndef invert_tree2(root):\n    if root is not None:\n        # swap the pointers in this node\n        root.left, root.right = root.right, root.left\n        invert_tree2(root.left)\n        invert_tree2(root.right)\n    return root\n\n# Example usage:\n# Assuming you have a binary tree\nroot = BinaryTreeNode(1)\nroot.left = BinaryTreeNode(2)\nroot.right = BinaryTreeNode(3)\nroot.left.left = BinaryTreeNode(4)\nroot.left.right = BinaryTreeNode(5)\n\n# Invert the binary tree using the first approach\ninverted_root = invert_tree(root)\n\n# Invert the binary tree using the second approach\ninverted_root2 = invert_tree2(root)\n"
  },
  {
    "path": "Trees/Binary Trees/is_symmetric.cpp",
    "content": "/*\n  Write a function that takes in a Binary Tree and returns if that tree is symmetrical. A tree is symmetrical \n  if the left and right subtrees are mirror images of each other.\n\n    Explanation:\n\n    1. The code defines a class `BinaryTree` representing a binary tree node. It has an `int` value and pointers \n       to its left and right children.\n    2. The `SymmetricalTree` function is the main entry point. It calls the helper function `treesAreMirrored` \n       to check if the left and right subtrees are mirrored.\n    3. The `treesAreMirrored` function checks if two binary trees are mirrored. It uses recursion to compare \n       corresponding nodes in the left and right subtrees.\n    4. In the `treesAreMirrored` function, the base case checks if both the left and right trees are non-null \n       and have the same value. If so, it recursively checks if their subtrees are mirrored.\n    5. If either the left or right tree is null or their values are not equal, they are not mirrored. \n       If both the left and right trees are null, they are considered mirrored.\n    6. In the `main` function, a binary tree is created for testing purposes.\n    7. The `SymmetricalTree` function is called to check if the binary tree is symmetrical.\n    8. The result is printed to the console.\n    9. Memory cleanup is performed by deleting the dynamically allocated nodes.\n\n    The time and space complexity of the given code snippet can be analyzed as follows:\n\n    1. Time Complexity:\n    - The `SymmetricalTree` function calls the `treesAreMirrored` function, which performs a recursive traversal of the binary tree.\n    - In the worst case, the recursion visits each node once, so the time complexity is O(N), where N is the number of nodes in the tree.\n\n    2. Space Complexity:\n   - The space complexity is determined by the maximum depth of the recursion stack.\n   - In the worst case, the binary tree is linear, resulting in a recursion depth of N, where N is the number of nodes in the tree.\n   - Therefore, the space complexity is O(N) due to the recursion stack usage.\n\n    It's important to note that the space complexity can be optimized by using an iterative approach instead of recursion. By using an iterative algorithm that leverages a stack or queue to perform a level-order traversal, we can achieve a space complexity of O(W), where W is the maximum width (number of nodes at the same level) of the binary tree.\n\n*/\n#include <iostream>\n\nusing namespace std;\n\n// This is an input class. Do not edit.\nclass BinaryTree {\npublic:\n    int Value;\n    BinaryTree* Left;\n    BinaryTree* Right;\n};\n\n// SymmetricalTree checks if a binary tree is symmetrical.\nbool SymmetricalTreeRecursive(BinaryTree* tree) {\n    // Call the helper function to check if the left and right subtrees are mirrored.\n    return treesAreMirrored(tree->Left, tree->Right);\n}\n\n// treesAreMirrored checks if two binary trees are mirrored.\nbool treesAreMirrored(BinaryTree* left, BinaryTree* right) {\n    // Base case: If both left and right trees are non-null and have the same value,\n    // recursively check if their subtrees are mirrored.\n    if (left != nullptr && right != nullptr && left->Value == right->Value) {\n        return treesAreMirrored(left->Left, right->Right) && treesAreMirrored(left->Right, right->Left);\n    }\n\n    // If either left or right tree is null or their values are not equal, they are not mirrored.\n    // Also, if both left and right trees are null, they are considered mirrored.\n    return left == right;\n}\n\n// Approach 2: Iterative Approach using Stack\n/*\n    In this iterative approach, we use two stacks (stackLeft and stackRight) to perform a mirror traversal of the \n    left and right subtrees. The process is similar to the original code snippet but implemented iteratively \n    using a while loop and stacks. The stacks are initialized with the left and right children of the root node, \n    and in each iteration, we compare the corresponding nodes from both stacks and check for asymmetry. \n    The children of the left and right nodes are pushed onto their respective stacks in reverse order to \n    maintain the mirror traversal. The loop continues until both stacks are empty or an asymmetry is detected. \n    Finally, the function returns whether the tree is symmetric or not.\n\n    The time complexity of this algorithm is O(n), where n is the number of nodes in the binary tree, as \n\tit traverses each node once. The space complexity is O(max(d, h)), where d is the maximum width of \n\tthe tree (number of nodes at the widest level) and h is the height of the tree. The space complexity \n\tdepends on the maximum number of nodes stored in the stacks during the traversal.\n\n\n*/\nstruct BinaryTree {\n    int value;\n    BinaryTree* left;\n    BinaryTree* right;\n};\n\nbool SymmetricalTreeIterative(BinaryTree* tree) {\n    std::stack<BinaryTree*> stackLeft;\n    std::stack<BinaryTree*> stackRight;\n    stackLeft.push(tree->left);   // Initialize stackLeft with the left child of the root node\n    stackRight.push(tree->right); // Initialize stackRight with the right child of the root node\n\n    // Perform mirror traversal of the left and right subtrees\n    while (!stackLeft.empty()) {\n        BinaryTree* left = stackLeft.top();\n        BinaryTree* right = stackRight.top();\n        stackLeft.pop();\n        stackRight.pop();\n\n        if (left == nullptr && right == nullptr) {\n            continue; // Both left and right subtrees are symmetric, continue to the next iteration\n        }\n\n        if (left == nullptr || right == nullptr || left->value != right->value) {\n            return false; // Asymmetry detected, tree is not symmetric\n        }\n\n        // Push the children of left and right onto the respective stacks in reverse order\n        stackLeft.push(left->left);\n        stackLeft.push(left->right);\n        stackRight.push(right->right);\n        stackRight.push(right->left);\n    }\n\n    return true; // Tree is symmetric\n}\n\n\nint main() {\n    // Create a binary tree for testing\n    BinaryTree* tree = new BinaryTree();\n    tree->Value = 1;\n    tree->Left = new BinaryTree();\n    tree->Left->Value = 2;\n    tree->Right = new BinaryTree();\n    tree->Right->Value = 2;\n    tree->Left->Left = new BinaryTree();\n    tree->Left->Left->Value = 3;\n    tree->Right->Right = new BinaryTree();\n    tree->Right->Right->Value = 3;\n\n    // Check if the tree is symmetrical\n    bool isSymmetrical = SymmetricalTree(tree);\n\n    // Output the result\n    if (isSymmetrical) {\n        cout << \"The binary tree is symmetrical.\" << endl;\n    } else {\n        cout << \"The binary tree is not symmetrical.\" << endl;\n    }\n\n    // Clean up the allocated memory\n    delete tree->Left->Left;\n    delete tree->Right->Right;\n    delete tree->Left;\n    delete tree->Right;\n    delete tree;\n\n    return 0;\n}\n"
  },
  {
    "path": "Trees/Binary Trees/is_symmetric.go",
    "content": "/*\n  Write a function that takes in a Binary Tree and returns if that tree is symmetrical. A tree is symmetrical \n  if the left and right subtrees are mirror images of each other.\n*/\npackage main\n\n// This is an input class. Do not edit.\ntype BinaryTree struct {\n\tValue int\n\n\tLeft  *BinaryTree\n\tRight *BinaryTree\n}\n/*\nThe code consists of two functions. The SymmetricalTree function serves as an entry point and checks if the \nbinary tree is symmetrical by calling the treesAreMirrored helper function with the left and right subtrees \nof the root node.\n\nThe treesAreMirrored function is a recursive helper function that checks if two binary trees are mirrored. \nIt uses a bottom-up approach to compare corresponding nodes of the left and right subtrees. \n\nThe function performs the following steps:\n\n\t1. Base case: If both the left and right trees are non-nil and have the same value, recursively check if \n\ttheir respective subtrees are mirrored by calling treesAreMirrored with the left subtree's left and \n\tthe right subtree's right children, as well as the left subtree's right and the right subtree's left children.\n\n\t2. If either the left or right tree is nil or their values are not equal, they are not mirrored, and the function returns false.\n\n\t3. If both the left and right trees are nil, they are considered mirrored, and the function returns true.\n\t\n\tThe recursive nature of the treesAreMirrored function allows it to traverse and compare corresponding nodes \n\tin a symmetrical manner. If the function successfully reaches the base case for all nodes, it indicates \n\tthat the binary tree is symmetrical.\n\n\tOverall, the code leverages recursion and the concept of mirror images to determine if a binary tree is symmetrical or not.\n\tThe time and space complexity of the code snippet can be analyzed as follows:\n\n\tTime Complexity:\n\tThe time complexity of the SymmetricalTree function primarily depends on the size of the binary tree. \n\tIn the worst case, where the tree is symmetric, the function needs to traverse all the nodes of the tree once.\n\n\tLet's assume there are 'n' nodes in the tree. In the worst case, the function will visit each node exactly once. \n\tTherefore, the time complexity is O(n), where 'n' is the number of nodes in the binary tree.\n\n\tSpace Complexity:\n\tThe space complexity is determined by the recursive calls and the stack space used during the recursion.\n\n\tIn the worst case, when the binary tree is highly unbalanced and resembles a linked list, the depth of the \n\trecursion can be 'n' (the number of nodes in the tree). This means that the space required on the function \n\tcall stack will be O(n).\n\n\tAdditionally, the space complexity also includes the space used to store the function arguments and local variables. \n\tHowever, as these are constant-sized values (pointers), they don't contribute significantly to the overall space complexity.\n\n\tTherefore, the overall space complexity is O(n), where 'n' is the number of nodes in the binary tree, considering the worst-case scenario.\n\n\tIn summary, the time complexity is O(n), and the space complexity is O(n), where 'n' is the number of nodes in the binary tree.\n*/\n// Approach 1: Recursive Approach\n// SymmetricalTree checks if a binary tree is symmetrical.\nfunc SymmetricalTreerecursive(tree *BinaryTree) bool {\n\t// Call the helper function to check if the left and right subtrees are mirrored.\n\treturn treesAreMirrored(tree.Left, tree.Right)\n}\n\n// treesAreMirrored checks if two binary trees are mirrored.\nfunc treesAreMirrored(left, right *BinaryTree) bool {\n\t// Base case: If both left and right trees are non-nil and have the same value,\n\t// recursively check if their subtrees are mirrored.\n\tif left != nil && right != nil && left.Value == right.Value {\n\t\treturn treesAreMirrored(left.Left, right.Right) && treesAreMirrored(left.Right, right.Left)\n\t}\n\n\t// If either left or right tree is nil or their values are not equal, they are not mirrored.\n\t// Also, if both left and right trees are nil, they are considered mirrored.\n\treturn left == right\n}\n\n/*  Explanation:\n\n\tThe code snippet defines a function SymmetricalTree that checks if a binary tree is symmetrical. \n\tThe binary tree is represented by the BinaryTree struct, which has a Value field and pointers to \n\tits left and right child nodes.\n\n\tThe function uses two stacks, stackLeft and stackRight, to perform a mirror traversal of the \n\tleft and right subtrees of the input tree. It starts by pushing the left child of the root \n\tnode onto stackLeft and the right child of the root node onto stackRight.\n\n\tThe function then enters a loop that continues until the stackLeft is empty. In each iteration \n\tof the loop, it pops the top nodes from stackLeft and stackRight, assigning them to variables \n\tleft and right, respectively.\n\n\tIf both left and right are nil, it means the corresponding subtrees are symmetric, so the loop \n\tcontinues to the next iteration.\n\n\tIf either left or right is nil, or their values are not equal, it means the tree is not symmetric, \n\tand the function returns false.\n\n\tOtherwise, it pushes the left child of left and the right child of right onto stackLeft and stackRight, \n\trespectively, in reverse order. This ensures that the subsequent nodes popped from the stacks are \n\tcompared as mirror images.\n\n\tOnce the loop is completed, and no asymmetry has been detected, the function returns true, indicating \n\tthat the binary tree is symmetric.\n\n\tThe time complexity of this algorithm is O(n), where n is the number of nodes in the binary tree, as \n\tit traverses each node once. The space complexity is O(max(d, h)), where d is the maximum width of \n\tthe tree (number of nodes at the widest level) and h is the height of the tree. The space complexity \n\tdepends on the maximum number of nodes stored in the stacks during the traversal.\n*/\n\n// Approach 2: Iterative Approach using Stack\nfunc SymmetricalTreeIterative(tree *BinaryTree) bool {\n\tstackLeft := []*BinaryTree{tree.Left}   // Initialize stackLeft with the left child of the root node\n\tstackRight := []*BinaryTree{tree.Right} // Initialize stackRight with the right child of the root node\n\n\t// Perform mirror traversal of the left and right subtrees\n\tfor len(stackLeft) > 0 {\n\t\tvar left, right *BinaryTree\n\t\tleft, stackLeft = stackLeft[len(stackLeft)-1], stackLeft[:len(stackLeft)-1]       // Pop the top node from stackLeft\n\t\tright, stackRight = stackRight[len(stackRight)-1], stackRight[:len(stackRight)-1] // Pop the top node from stackRight\n\n\t\tif left == nil && right == nil {\n\t\t\tcontinue // Both left and right subtrees are symmetric, continue to the next iteration\n\t\t}\n\n\t\tif left == nil || right == nil || left.Value != right.Value {\n\t\t\treturn false // Asymmetry detected, tree is not symmetric\n\t\t}\n\n\t\t// Push the children of left and right onto the respective stacks in reverse order\n\t\tstackLeft = append(stackLeft, left.Left, left.Right)\n\t\tstackRight = append(stackRight, right.Right, right.Left)\n\t}\n\n\treturn true // Tree is symmetric\n}"
  },
  {
    "path": "Trees/Binary Trees/is_symmetric.java",
    "content": "/*\n  Write a function that takes in a Binary Tree and returns if that tree is symmetrical. A tree is symmetrical \n  if the left and right subtrees are mirror images of each other.\n*/\nimport java.util.Stack;\n\npublic class BinaryTree {\n    // Assume that BinaryTree has properties: left, right, and value.\n\n    public boolean isSymmetricalTreeIterative(BinaryTree tree) {\n        Stack<BinaryTree> stackLeft = new Stack<>();\n        Stack<BinaryTree> stackRight = new Stack<>();\n\n        // Initialize stackLeft with the left child of the root node\n        // Initialize stackRight with the right child of the root node\n        stackLeft.push(tree.getLeft());\n        stackRight.push(tree.getRight());\n\n        // Perform mirror traversal of the left and right subtrees\n        while (!stackLeft.isEmpty()) {\n            BinaryTree left = stackLeft.pop();\n            BinaryTree right = stackRight.pop();\n\n            if (left == null && right == null) {\n                continue; // Both left and right subtrees are symmetric, continue to the next iteration\n            }\n\n            if (left == null || right == null || left.getValue() != right.getValue()) {\n                return false; // Asymmetry detected, tree is not symmetric\n            }\n\n            // Push the children of left and right onto the respective stacks in reverse order\n            stackLeft.push(left.getLeft());\n            stackLeft.push(left.getRight());\n\n            stackRight.push(right.getRight());\n            stackRight.push(right.getLeft());\n        }\n\n        return true; // Tree is symmetric\n    }\n\n    // Other methods and properties for BinaryTree class\n}\n"
  },
  {
    "path": "Trees/Binary Trees/is_symmetric.js",
    "content": "/*\n  Write a function that takes in a Binary Tree and returns if that tree is symmetrical. A tree is symmetrical \n  if the left and right subtrees are mirror images of each other.\n*/\nclass BinaryTree {\n  constructor(value, left = null, right = null) {\n    this.value = value;\n    this.left = left;\n    this.right = right;\n  }\n}\n\nfunction isSymmetricalTreeIterative(tree) {\n  const stackLeft = (tree && [tree.left]) || []; // Initialize stackLeft with the left child of the root node\n  const stackRight = (tree && [tree.right]) || []; // Initialize stackRight with the right child of the root node\n\n  // Perform mirror traversal of the left and right subtrees\n  while (stackLeft.length > 0) {\n    const left = stackLeft.pop() || null; // Pop the top node from stackLeft\n    const right = stackRight.pop() || null; // Pop the top node from stackRight\n\n    if (!left && !right) {\n      continue; // Both left and right subtrees are symmetric, continue to the next iteration\n    }\n\n    if (!left || !right || left.value !== right.value) {\n      return false; // Asymmetry detected, tree is not symmetric\n    }\n\n    // Push the children of left and right onto the respective stacks in reverse order\n    if (left) {\n      stackLeft.push(left.left, left.right);\n    }\n    if (right) {\n      stackRight.push(right.right, right.left);\n    }\n  }\n\n  return true; // Tree is symmetric\n}\n\n// Example usage:\n// Construct a symmetric tree\nconst symmetricTree = new BinaryTree(\n  1,\n  new BinaryTree(2, new BinaryTree(3), new BinaryTree(4)),\n  new BinaryTree(2, new BinaryTree(4), new BinaryTree(3))\n);\n\nconsole.log(isSymmetricalTreeIterative(symmetricTree)); // Output: true\n"
  },
  {
    "path": "Trees/Binary Trees/is_symmetric.py",
    "content": "'''\n  Write a function that takes in a Binary Tree and returns if that tree is symmetrical. A tree is symmetrical \n  if the left and right subtrees are mirror images of each other.\n'''\nclass BinaryTree:\n    def __init__(self, value, left=None, right=None):\n        self.value = value\n        self.left = left\n        self.right = right\n\ndef is_symmetrical_tree_iterative(tree):\n    stack_left = [tree.left] if tree else []  # Initialize stackLeft with the left child of the root node\n    stack_right = [tree.right] if tree else []  # Initialize stackRight with the right child of the root node\n\n    # Perform mirror traversal of the left and right subtrees\n    while stack_left:\n        left = stack_left.pop() if stack_left else None\n        right = stack_right.pop() if stack_right else None\n\n        if not left and not right:\n            continue  # Both left and right subtrees are symmetric, continue to the next iteration\n\n        if not left or not right or left.value != right.value:\n            return False  # Asymmetry detected, tree is not symmetric\n\n        # Push the children of left and right onto the respective stacks in reverse order\n        stack_left.extend([left.left, left.right] if left else [])\n        stack_right.extend([right.right, right.left] if right else [])\n\n    return True  # Tree is symmetric\n\n# Example usage:\n# Construct a symmetric tree\nsymmetric_tree = BinaryTree(1, BinaryTree(2, BinaryTree(3), BinaryTree(4)), BinaryTree(2, BinaryTree(4), BinaryTree(3)))\n\nprint(is_symmetrical_tree_iterative(symmetric_tree))  # Output: True\n"
  },
  {
    "path": "Trees/Binary Trees/level_by_level.cpp",
    "content": "// Binary Tree : Breadth First Search Print level by level TC : O(n)\n// Program Author : Abhisek Kumar Gupta\n/*\n            40\n            /   \\\n        10      30\n        / \\     /  \\\n       5  -1  -1  28\n      / \\        /  \\\n    1   -1      15    20\n   / \\          /\\    /\\\n   1 -1        -1 -1 -1 -1\n   /\\\n -1 -1\n    Input : 40 10 5 1 1 -1 -1 -1 -1 -1 30 -1 28 15 -1 -1 20 -1 -1\n    Output : 40-> \n            10-> 30-> \n            5-> 28->\n            1-> 15-> 20->\n            1->\n*/\n\n#include<bits/stdc++.h>\nusing namespace std;\nclass Node{\n    public:\n        int data;\n        Node* left;\n        Node* right;\n\n        Node(int x){\n            data = x;\n        }\n};\nNode* build_binary_tree(){\n    int data;\n    cin >> data;\n    if(data == -1){\n        return NULL;\n    }\n    Node* root = new Node(data);\n    root->left = build_binary_tree();\n    root->right = build_binary_tree();\n    return root;\n}\nvoid bfs(Node* root){\n    queue<Node*> q;\n    q.push(root);\n    q.push(NULL);\n    while(!q.empty()){\n        Node* element = q.front();\n        if(element == NULL){\n            q.pop();\n            cout << \"\\n\";\n            if(!q.empty()){\n                q.push(NULL);\n            }\n        }\n        else{\n            cout << element->data << \"->\";\n            q.pop();\n            if(element->left !=NULL){\n                q.push(element->left);\n            }\n            if(element->right != NULL){\n                q.push(element->right);\n            }\n        }\n    }\n    return;\n}\nint main(){\n    Node* root = build_binary_tree();\n    bfs(root);\n    return 0;\n}"
  },
  {
    "path": "Trees/Binary Trees/level_order_traversal.cpp",
    "content": "// Level order Traversal of a Binary Tree TC O(n^2)\n// Program Author : Abhisek Kumar Gupta\n/*\n            40\n            /   \\\n        10      30\n        / \\     /  \\\n       5  -1  -1  28\n      / \\        /  \\\n    1   -1      15    20\n   / \\          /\\    /\\\n   1 -1        -1 -1 -1 -1\n   /\\\n -1 -1\n    Input : 40 10 5 1 1 -1 -1 -1 -1 -1 30 -1 28 15 -1 -1 20 -1 -1\n    Output : 40\n            10 30\n            5 28\n            1 15 20\n            1    \n*/\n#include<bits/stdc++.h>\nusing namespace std;\nclass Node{\n    public:\n        int data;\n        Node* left;\n        Node* right;\n\n        Node(int x){\n            data = x;\n        }\n};\nNode* build_binary_tree(){\n    int data;\n    cin >> data;\n    if(data == -1){\n        return NULL;\n    }\n    Node* root = new Node(data);\n    root->left = build_binary_tree();\n    root->right = build_binary_tree();\n    return root;\n}\nint compute_height_of_binary_tree(Node* root){\n    if(root == NULL)\n        return 0;\n    int left_height = compute_height_of_binary_tree(root->left);\n    int right_height = compute_height_of_binary_tree(root->right);\n    return max(left_height, right_height) + 1;    \n}\nvoid print_kth_level(Node* root, int k){\n    if(root == NULL)\n        return;\n    if(k == 1){\n        cout << root->data << \" \";\n        return;\n    }\n    print_kth_level(root->left, k - 1);\n    print_kth_level(root->right, k- 1);\n    return;    \n}\nvoid level_order_traversal(Node* root){\n    int height = compute_height_of_binary_tree(root);\n    for(int i = 1; i <= height; i++){\n        print_kth_level(root, i);\n        cout << \"\\n\";\n    }    \n}\nint main(){\n    Node* root = build_binary_tree();\n    level_order_traversal(root);\n    return 0;\n}\n\n"
  },
  {
    "path": "Trees/Binary Trees/level_order_traversal.go",
    "content": "package main\n\ntype BinaryTreeNode struct {\n\tleft  *BinaryTreeNode\n\tdata  int\n\tright *BinaryTreeNode\n}\n\n// Level order traversal is defined as follows:\n// 1 Visit the root.\n// 2 While traversing level 􀝈, keep all the elements at level 􀝈 + 1 in queue.\n// 3 Go to the next level and visit all the nodes at that level.\n// 4 Repeat this until all levels are completed.\n// The nodes of the tree are visited in the order: [1] [2 3] [ 4 5 6 7]\n// Time Complexity: O(n), Space Complexity: O(n) In the worst case, all the nodes on the entire last level could be in the queue.\nfunc LevelOrder(root *BinaryTreeNode) [][]int {\n\tif root == nil {\n\t\treturn [][]int{}\n\t}\n\t// Data from each level is being returned as a separate list\n\tvar result [][]int\n\tqueue := []*BinaryTreeNode{root}\n\tfor len(queue) > 0 {\n\t\tqlen := len(queue)\n\t\tvar level []int\n\t\tfor i:= 0; i < qlen; i++ {\n\t\t\tnode := queue[0]\n\t\t\tlevel = append(level, node.data)\n\t\t\tqueue = queue[1:]\n\t\t\t// if there are left children then append them in queue\n\t\t\tif node.left != nil {\n\t\t\t\tqueue = append(queue, node.left)\n\t\t\t}\n\t\t\t// if there are right children then append them in queue\n\t\t\tif node.right != nil {\n\t\t\t\tqueue = append(queue, node.right)\n\t\t\t}\n\t\t}\n\t}\n\treturn result\n}\n"
  },
  {
    "path": "Trees/Binary Trees/node_depth.go",
    "content": "/*\n  The distance between a node in a Binary Tree and the tree's root is called the\n  node's depth.\n\n  Write a function that takes in a Binary Tree and returns the sum of its nodes'\n  depths.\n\n  Sample Input:\n          1\n       /     \\\n      2       3\n    /   \\   /   \\\n   4     5 6     7\n /   \\\n8     9\n  Output: 16\n*/\n\n/*\n\tThe depth of any node in the tree is equal to the depth of its parent node plus 1.\n\tBy starting at the root node whose depth is 0, you can pass down to every node in\n\tthe tree its respective depth, and you can implement the algorithm that does this\n\tand that sums up all of the depths either recursively or iteratively.\n\n\tTime and Space complexity\n\tAverage case: when the tree is balanced\n\tO(n) time | O(h) space - where n is the number of nodes in the Binary Tree and h is the height of the Binary Tree\n*/\npackage main\n\ntype BinaryTree struct {\n\tValue       int\n\tLeft, Right *BinaryTree\n}\n\nfunc NodeDepths(root *BinaryTree) int {\n\treturn nodeDepthHelper(root, 0)\n}\n\nfunc nodeDepthHelper(root *BinaryTree, depth int) int {\n    if root == nil {\n        return 0\n    }\n    return depth + nodeDepthHelper(root.Left, depth + 1) + nodeDepthHelper(root.Right, depth + 1)\n}"
  },
  {
    "path": "Trees/Binary Trees/postorder_traversal.cpp",
    "content": "// Post-Order Traversal of a Binary-Tree\n// Program Author : Abhisek Kumar Gupta\n/*\n          40\n        /   \\\n       10     30\n      / \\     /  \\\n     5   -1  -1  28\n    / \\         /  \\\n   1   -1      15    20\n  / \\          /\\    /\\\n -1 -1        -1 -1 -1 -1\n Input : 40 10 5 1 -1 -1 -1 -1 30 -1 28 15 -1 -1 20 -1 -1\n Output : 1->5->10->15->20->28->30->40\n*/\n#include<bits/stdc++.h>\nusing namespace std;\n\nclass Node{\n    public:\n        int data;\n        Node* left;\n        Node* right;\n\n        Node(int x){\n            data = x;\n            left = NULL;\n            right = NULL; \n        }\n};\n\nNode* build_binary_tree(){\n    int data;\n    cin >> data;\n    if(data == -1){\n        return NULL;\n    }\n    Node* root = new Node(data);\n    root->left = build_binary_tree();\n    root->right = build_binary_tree();\n    return root;\n}\nvoid print_binary_tree(Node* root){\n    if(root == NULL)\n        return;\n    print_binary_tree(root->left);\n    print_binary_tree(root->right);\n    cout << root->data << \"->\";    \n}\nint main(){\n    Node* root = build_binary_tree();\n    print_binary_tree(root);\n    return 0;\n}\n//40 10 5 1 -1 -1 -1 -1 30 -1 28 15 -1 -1 20 -1 -1\n"
  },
  {
    "path": "Trees/Binary Trees/preorder_traversal.cpp",
    "content": "// Pre-Order Traversal of a Binary-Tree\n// Program Author : Abhisek Kumar Gupta\n/*\n          40\n        /   \\\n       10     30\n      / \\     /  \\\n     5   -1  -1  28\n    / \\         /  \\\n   1   -1      15    20\n  / \\          /\\    /\\\n -1 -1        -1 -1 -1 -1\n Input : 40 10 5 1 -1 -1 -1 -1 30 -1 28 15 -1 -1 20 -1 -1\n Output : 40->10->5->1->30->28->15->20\n*/\n#include<bits/stdc++.h>\nusing namespace std;\nclass Node{\n    public: \n        int data;\n        Node *left;\n        Node *right;\n\n        Node(int x){\n            data = x;\n            left = NULL;\n            right = NULL;\n        }\n\n};\n\nNode* build_binary_tree(){\n    int data;\n    cin >> data;\n    if(data == -1)\n        return NULL;\n    Node* root = new Node(data);\n    root->left = build_binary_tree();\n    root->right = build_binary_tree();\n    return root;     \n}\n\nvoid print_binary_tree(Node* root){\n    if(root == NULL)\n        return;\n    cout << root->data << \"->\";\n    print_binary_tree(root->left);\n    print_binary_tree(root->right);    \n}\n\nint main(){\n    Node* root = build_binary_tree();\n    print_binary_tree(root);\n}"
  },
  {
    "path": "Trees/Binary Trees/remove_leaf_nodes.go",
    "content": "// Remove leaf nodes\npackage main\n\ntype BinaryTreeNode struct {\n\tleft  *BinaryTreeNode\n\tdata  int\n\tright *BinaryTreeNode\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: recurse both left and right subtree and check if the node doesn't have\n// left and right children\nfunc RemoveLeafNodes(root *BinaryTreeNode) *BinaryTreeNode {\n\tif root == nil {\n\t\treturn root\n\t}\n\t// if it doesnt have left and right children then delete it\n\tif root.left == nil && root.right == nil {\n\t\troot = nil\n\t\treturn root\n\t} else { // recurse to left and right subtree\n\t\troot.left = RemoveLeafNodes(root.left)\n\t\troot.right = RemoveLeafNodes(root.right)\n\t}\n\treturn root\n}"
  },
  {
    "path": "Trees/Binary Trees/search_an_element.go",
    "content": "// Search an element in Binary tree\npackage main\n\ntype BinaryTreeNode struct {\n\tleft  *BinaryTreeNode\n\tdata  int\n\tright *BinaryTreeNode\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: recurse down the tree choose left or right branch by comparing data with each node's data\nfunc SearchAnElement(root *BinaryTreeNode, data int) *BinaryTreeNode {\n\t// base case empty tree\n\tif root == nil {\n\t\treturn root\n\t} else {\n\t\t// if found return root\n\t\tif data == root.data {\n\t\t\treturn root\n\t\t} else {\n\t\t\t// recurse down correct subtree\n\t\t\ttemp := SearchAnElement(root.left, data)\n\t\t\tif temp != nil {\n\t\t\t\treturn temp\n\t\t\t} else {\n\t\t\t\treturn SearchAnElement(root.right, data)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Time Complexity: O(n). Space Complexity: O(n).\n// Approach: using level order traversal we can solve this problem, check whether\n// the root data is equal to the element we want to search\nfunc SearchAnElementWithoutRecursion(root *BinaryTreeNode, data int) *BinaryTreeNode {\n\tif root == nil {\n\t\treturn root\n\t}\n\tqueue := []*BinaryTreeNode{root}\n\tfor len(queue) > 0 {\n\t\tqlen := len(queue)\n\t\tfor i := 0; i < qlen; i++ {\n\t\t\tnode := queue[0]\n\t\t\tif data == node.data {\n\t\t\t\treturn node\n\t\t\t}\n\t\t\tqueue = queue[1:]\n\t\t\tif node.left != nil {\n\t\t\t\tqueue = append(queue, node.left)\n\t\t\t}\n\t\t\tif node.right != nil {\n\t\t\t\tqueue = append(queue, node.right)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}"
  },
  {
    "path": "Trees/Binary Trees/sum_of_all_nodes.cpp",
    "content": "// Binary Tree : Sum of all Nodes\n// Program Author : Abhisek Kumar Gupta\n/*\n            40\n            /   \\\n        10      30\n        / \\     /  \\\n       5  -1  -1  28\n      / \\        /  \\\n    1   -1      15    20\n   / \\          /\\    /\\\n   1 -1        -1 -1 -1 -1\n   /\\\n -1 -1\n    Input : 40 10 5 1 1 -1 -1 -1 -1 -1 30 -1 28 15 -1 -1 20 -1 -1\n    Output : 150  \n*/\n\n#include<bits/stdc++.h>\nusing namespace std;\nclass Node{\n    public:\n        int data;\n        Node* left;\n        Node* right;\n\n        Node(int d){\n            data = d;\n        }        \n};\nNode* build_binary_tree(){\n    int data;\n    cin >> data;\n    if(data == -1){\n        return NULL;\n    }\n    Node* root = new Node(data);\n    root->left = build_binary_tree();\n    root->right = build_binary_tree();\n    return root;\n}\n\nint sum_of_all_nodes(Node* root){\n    if(root == NULL){\n        return 0;\n    }\n    return root->data + sum_of_all_nodes(root->right) + sum_of_all_nodes(root->left);\n}\nint main(){\n    Node* root = build_binary_tree();\n    int sum_of_nodes = sum_of_all_nodes(root);\n    cout << sum_of_nodes;\n    return 0;\n}"
  },
  {
    "path": "Trees/Implement_Trie.cpp",
    "content": "/*\nApproach:\n- We define a Trie node structure that contains an array of child nodes and a flag to indicate the end of a word.\n- The Trie class provides methods to insert words into the Trie, search for words, and check if any word starts with a given prefix.\n- The insert operation involves traversing the Trie for each character of the word and creating a new node if the path doesn't exist. At the end, we mark the last node as the end of a word.\n- The search operation is similar to the insert operation, but it returns true only if the last node is marked as the end of a word.\n- The startsWith operation also involves traversing the Trie for each character of the prefix. It returns true regardless of whether the last node is marked as the end of a word or not.\n\nTime Complexity:\n- The time complexity of inserting a word into the Trie is O(m), where m is the length of the word.\n- The time complexity of searching for a word or checking for a prefix is O(m), where m is the length of the word or prefix.\n\nSpace Complexity:\n- The space complexity of the Trie is O(N * M), where N is the number of words and M is the average length of the words.\n\nSample Input / Output:\nint main() {\n    Trie trie;\n    \n    trie.insert(\"apple\");\n    trie.insert(\"banana\");\n    \n    cout << trie.search(\"apple\") << endl;   // Output: 1 (true)\n    cout << trie.search(\"banana\") << endl;  // Output: 1 (true)\n    cout << trie.search(\"car\") << endl;     // Output: 0 (false)\n    \n    cout << trie.startsWith(\"app\") << endl;     // Output: 1 (true)\n    cout << trie.startsWith(\"ban\") << endl;     // Output: 1 (true)\n    cout << trie.startsWith(\"cab\") << endl;     // Output: 0 (false)\n    \n    return 0;\n}\n\n*/\n\n//Here's the code for implementing a Trie (Prefix Tree) in C++:\n\n// Trie node structure\nstruct TrieNode {\n    struct TrieNode* children[26];    // Array to store child nodes\n    bool isEndOfWord;                 // Flag to indicate end of word\n    TrieNode() {\n        isEndOfWord = false;\n        for (int i = 0; i < 26; i++)\n            children[i] = nullptr;\n    }\n};\n\n// Trie class\nclass Trie {\nprivate:\n    TrieNode* root;   // Pointer to the root node\n\npublic:\n    Trie() {\n        root = new TrieNode();\n    }\n\n    // Insert a word into the Trie\n    void insert(string word) {\n        TrieNode* current = root;\n        \n        for (char ch : word) {\n            int index = ch - 'a';\n            \n            // Create a new node if the path doesn't exist\n            if (!current->children[index]) {\n                current->children[index] = new TrieNode();\n            }\n            \n            current = current->children[index];\n        }\n        \n        // Mark the end of a word\n        current->isEndOfWord = true;\n    }\n\n    // Search for a word in the Trie\n    bool search(string word) {\n        TrieNode* current = root;\n        \n        for (char ch : word) {\n            int index = ch - 'a';\n            \n            // Return false if the path doesn't exist\n            if (!current->children[index]) {\n                return false;\n            }\n            \n            current = current->children[index];\n        }\n        \n        // Return true only if the current node is the end of a word\n        return current->isEndOfWord;\n    }\n\n    // Check if any word in the Trie starts with the given prefix\n    bool startsWith(string prefix) {\n        TrieNode* current = root;\n        \n        for (char ch : prefix) {\n            int index = ch - 'a';\n            \n            // Return false if the path doesn't exist\n            if (!current->children[index]) {\n                return false;\n            }\n            \n            current = current->children[index];\n        }\n        \n        // Return true regardless of whether the current node is the end of a word or not\n        return true;\n    }\n};\n"
  },
  {
    "path": "Trees/Implement_Trie.py",
    "content": "'''\nApproach:\n1. We implement the TrieNode class with a dictionary of children nodes and a flag to indicate the end of a word.\n2. The Trie class is implemented with a root TrieNode as its member variable.\n3. The insert function traverses through each character of the input word and creates new TrieNode objects if necessary.\n4. The search function traverses through each character of the input word and returns True only if the last node is marked as the end of a word.\n5. The startsWith function is similar to the search function but returns True as long as the prefix exists in the Trie.\n\nTime Complexity:\n- Insertion: O(m), where m is the length of the word being inserted.\n- Search: O(m), where m is the length of the word being searched.\n- Starts With: O(m), where m is the length of the prefix being checked.\n\nSpace Complexity:\n- O(n*m), where n is the number of words inserted and m is the average length of the words.\n\nSample input and output:\n\ntrie = Trie()\ntrie.insert(\"apple\")\nprint(trie.search(\"apple\"))  # Output: True\nprint(trie.search(\"app\"))  # Output: False\nprint(trie.startsWith(\"app\"))  # Output: True\ntrie.insert(\"app\")\nprint(trie.search(\"app\"))  # Output: True\n\nHere's an implementation of the Trie data structure, also known as the Prefix Tree, in Python:\n'''\n\n# Trie node class\nclass TrieNode:\n    def __init__(self):\n        self.children = {}\n        self.is_end_of_word = False\n\n\n# Trie class\nclass Trie:\n    def __init__(self):\n        self.root = TrieNode()\n\n    # Function to insert a word into the Trie\n    def insert(self, word: str) -> None:\n        node = self.root\n        for char in word:\n            # If the current character doesn't exist in the Trie, create a new node\n            if char not in node.children:\n                node.children[char] = TrieNode()\n            # Move to next node\n            node = node.children[char]\n        # Mark the end of a word\n        node.is_end_of_word = True\n\n    # Function to search for a word in the Trie\n    def search(self, word: str) -> bool:\n        node = self.root\n        for char in word:\n            # If the current character doesn't exist, the word doesn't exist\n            if char not in node.children:\n                return False\n            # Move to next node\n            node = node.children[char]\n        # Return True only if the last node is marked as the end of a word\n        return node.is_end_of_word\n\n    # Function to check if a word is a prefix of any existing word in the Trie\n    def startsWith(self, prefix: str) -> bool:\n        node = self.root\n        for char in prefix:\n            # If the current character doesn't exist, the prefix doesn't exist\n            if char not in node.children:\n                return False\n            # Move to next node\n            node = node.children[char]\n        # The prefix exists if we reach this point\n        return True\n\n"
  },
  {
    "path": "Trees/MaxpathBinaryTree.cpp",
    "content": "#include <iostream>\n#include <algorithm> // For max function\n\nusing namespace std;\n\n// Definition for a binary tree node.\nstruct TreeNode {\n    int val;\n    TreeNode* left;\n    TreeNode* right;\n    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}\n};\n\nclass Solution {\npublic:\n    int maxPathSum(TreeNode* root) {\n        int maxSum = INT_MIN; // Initialize with the minimum possible value\n        findMaxPathSum(root, maxSum);\n        return maxSum;\n    }\n\nprivate:\n    int findMaxPathSum(TreeNode* node, int& maxSum) {\n        if (!node) {\n            return 0;\n        }\n        \n        // Calculate the maximum path sum for the left and right subtrees\n        int leftMax = max(0, findMaxPathSum(node->left, maxSum));\n        int rightMax = max(0, findMaxPathSum(node->right, maxSum));\n        \n        // Calculate the maximum path sum that includes the current node\n        int currentMax = node->val + leftMax + rightMax;\n        \n        // Update the overall maximum path sum\n        maxSum = max(maxSum, currentMax);\n        \n        // Return the maximum path sum that can be extended from this node\n        return node->val + max(leftMax, rightMax);\n    }\n};\n\nint main() {\n    // Create a sample binary tree\n    TreeNode* root = new TreeNode(10);\n    root->left = new TreeNode(2);\n    root->right = new TreeNode(10);\n    root->left->left = new TreeNode(20);\n    root->left->right = new TreeNode(1);\n    root->right->right = new TreeNode(-25);\n    root->right->right->left = new TreeNode(3);\n    root->right->right->right = new TreeNode(4);\n\n    Solution solution;\n    int maxSum = solution.maxPathSum(root);\n\n    cout << \"Maximum Path Sum: \" << maxSum << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "Trees/tree.go",
    "content": "// Represent simple HTML document using Tree Data Structure\n\npackage main\n\nimport \"strings\"\n\n/*\n\t<html>\n\t\t<body>\n\t\t\t<h1>This is a H1</h1>\n\t\t\t<h2>This is a H1</h2>\n\t\t\t<p>\n\t\t\tThis is paragraph.\n\t\t\t<img src=\"https://image.com/image.png\" alt=\"some logo\"/>\n\t\t\t</p>\n\t\t\t<div class='someClass'>\n\t\t\tThis is the footer of the page.\n\t\t\t<span id='spanId'>2022 &copy; AKGMAGE</span>\n\t\t\t</div>\n\t\t</body>\n\t</html>\n*/\n\ntype Node struct {\n\ttag string\n\ttext string\n\tsrc string\n\talt string\n\tclass string\n\tid string\n\tchildren []*Node\n}\n\nfunc FindByIDBFS(root *Node, id string) *Node {\n\t// make queue of type Node which will contain all the nodes \n\tqueue := make([]*Node, 0)\n\tqueue = append(queue, root)\n\tfor len(queue) > 0 {\n\t\tcurr := queue[0] // set curr as first node\n\t\tqueue = queue[1:] // remove first node from queue\n\t\t// return if match is found\n\t\tif curr.id == id {\n\t\t\treturn curr\n\t\t}\n\t\t// if it has any children then queue it up\n\t\tif len(curr.children) > 0 {\n\t\t\t// dont care about the index, only care about the value\n\t\t\tfor _, child := range curr.children {\n\t\t\t\t// add children in queue\n\t\t\t\tqueue = append(queue, child)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\nfunc FindByIDDFS(node *Node, id string) *Node {\n\t// return if match is found\n\tif node.id == id {\n\t\treturn node\n\t}\n\t// keep exploring children if it has any\n\tif len(node.children) > 0 {\n\t\tfor _, child := range node.children {\n\t\t\t// recursively call FindByIDBFS\n\t\t\tFindByIDBFS(child, id)\n\t\t}\n\t}\n\treturn nil\n}\n\n// hasClass returns true if given className is found in node class\nfunc (n *Node) hasClass(className string) bool {\n\t// Fields splits the string s around each instance of one or more consecutive white space characters\n\tclasses := strings.Fields(n.class)\n\t// range through slice of classes\n\tfor _, class := range classes {\n\t\t// return trupe if classname matches\n\t\tif class == className {\n\t\t\treturn true\n\t\t}\n\t}\n\t// No match found\n\treturn false\n}\n\nfunc findAllByClassName(root *Node, className string) []*Node {\n\t// make result of type Node which will contain all the resulting className nodes \n\tresult := make([]*Node, 0)\n\t// make queue of type Node which will contain all the nodes \n\tqueue := make([]*Node, 0)\n\tqueue = append(queue, root)\n\tfor len(queue) > 0 {\n\t\tcurr := queue[0] // set curr as first node\n\t\tqueue = queue[1:] // remove first node from queue\n\t\t// if match is found append it to result's slice\n\t\tif curr.hasClass(className) {\n\t\t\tresult = append(result, curr)\n\t\t}\n\t\t// keep exploring children if it has any\n\t\tif len(curr.children) > 0 {\n\t\t\tfor _, child := range curr.children {\n\t\t\t\t// add children to queue\n\t\t\t\tqueue = append(queue, child)\n\t\t\t}\n\t\t}\n\t}\n\treturn result\n}\n\nfunc main() {\n\tspan := Node {\n\t\ttag: \"span\",\n\t\tid: \"spanId\",\n\t\ttext: \"2022 &copy; AKGMAGE\",\n\t}\n\tdiv := Node {\n\t\ttag: \"div\",\n\t\tclass: \"someClass\",\n\t\tchildren: []*Node{&span},\n\t}\n\timage := Node{\n\t\ttag: \"image\",\n\t\tsrc: \"https://image.com/image.png\",\n\t\talt: \"some logo\",\n\t}\n\tp := Node {\n\t\ttag: \"p\",\n\t\ttext: \"This is para.\",\n\t\tchildren: []*Node{&image},\n\t}\n\th1:= Node {\n\t\ttag: \"h1\",\n\t\ttext: \"This is h1\",\n\t}\n\th2:= Node {\n\t\ttag: \"h2\",\n\t\ttext: \"This is h2\",\n\t}\n\tbody := Node {\n\t\ttag: \"body\",\n\t\tchildren: []*Node{&div, &p, &h2, &h1},\n\t}\n\thtml := Node {\n\t\ttag: \"html\",\n\t\tchildren: []*Node{&body},\n\t}\n}"
  },
  {
    "path": "Trees/trie.cpp",
    "content": "/*\n    https://leetcode.com/problems/implement-trie-prefix-tree/\n    \n    Implement Trie (also called 'prefix tree') which supports lowercase letters only,\n    a search tree with multiple childrens (26 in this case).\n    methods:    Insert - push new string into the tree.\n                Delete - remove string from the tree.\n                search - check if a string is already pushed into the tree.\n                StartWith - check if sum prefix is appear in the tree.\n\n    Example:\n\n    int main(){\n        Trie trie;\n\n        trie.Insert(\"abcd\");        \n        trie.Search(\"abcd\")          // return true;\n        trie.Search(\"ab\")            // return false;\n        trie.startWith(\"ab\")         // return true;\n\n        trie.Insert(\"ab\");        \n        trie.Search(\"ab\")            // return true;\n\n        trie.Delete(\"ab\")\n        trie.Search(\"ab\")            // return false;\n        trie.Search(\"abcd\")          // return true;\n    \n        return 0;\n    }\n\n    Time Complexity:\n        Insert() / Search() / startWith()  |  Average & Worst-case == O(m)  |  m == number of chars in string.\n\n    Space Complexity:\n        Space complexity for a trie: O(k * N)   |   k == size of the node, N == number of the different nodes.   \n\n*/\n\n\n#include <string>\n#include <vector>\n\nenum{CHARS_IN_ALPHABET = 26};\n\nclass TrieNode{\npublic:\n    TrieNode() : vec(CHARS_IN_ALPHABET, nullptr), end_of_str(false) {};\n\n// every node has a vector for his childrens and a flag to mark - end of word.\n    std::vector<TrieNode*> vec;\n    bool end_of_str;\n};\n/****************************************************************************/\nclass Trie {\npublic:\n    Trie();\n    ~Trie();\n    // non-copyable class\n    Trie(const Trie& other) = delete;\n    Trie& operator= (const Trie& other) = delete;\n\n    void Insert(std::string word);\n    bool Delete(std::string word);\n    bool Search(std::string word);\n    bool startWith(std::string prefix);\n    void Destroy(TrieNode* root);\n\nprivate:\n    enum RecDeleteStatus{NOT_FOUND = -1, DELETE = 0 , COMPLITE = 1};\n\n    RecDeleteStatus RecDelete(TrieNode* curr_node, const char* string_ptr);\n    bool IsLeaf(TrieNode* node);\n    TrieNode* CreatNodes(TrieNode* node_runner, const char* rest_letters);\n    TrieNode* FindLastChar(const char* first_char_string);\n\n    TrieNode* m_root;\n};\n/****************************************************************************/\nTrie::Trie() // Ctor\n{\n    m_root = new TrieNode();\n}\n/****************************************************************************/\nTrie::~Trie() // Dtor\n{\n    Destroy(m_root);\n    delete m_root;\n}\n/****************************************************************************/\n// function for push a word(string) inside the trie \nvoid Trie::Insert(std::string word)\n{\n    const char* string_ptr = word.data();\n    TrieNode* node_runner = m_root;\n\n    while(*string_ptr)\n    {\n        // if this node does not have this latter as a child yet.\n        if(!node_runner->vec[*string_ptr - 'a'])\n        {\n            node_runner = CreatNodes(node_runner, string_ptr);\n            break;\n        }\n        \n        node_runner = node_runner->vec[*string_ptr - 'a'];\n        ++string_ptr;\n    }\n    // mark node as end of word.\n    node_runner->end_of_str = true;\n}\n/****************************************************************************/\n// function for remove a word from the trie, if the word or part of her suffix\n// stand alone, the whole node will be removed.\nbool Trie::Delete(std::string word)\n{\n    if(RecDelete(m_root, word.data()) != NOT_FOUND)\n    {\n        return true;\n    }\n    return false;\n}\n/****************************************************************************/\n// function for check if a string is already pushed into the tree.\nbool Trie::Search(std::string word) \n{\n    TrieNode* node = FindLastChar(word.data());    \n    // if FindLastChar return nullptr the word isnt in the trie,\n    // if the word is found but it just a prefix of another word, return false\n    if(node == nullptr || node->end_of_str == false){\n        return false;\n    }\n    return true;   \n}\n/****************************************************************************/\n// function for check if sum prefix is appear in the tree.\nbool Trie::startWith(std::string prefix) \n{\n    TrieNode* node = FindLastChar(prefix.data());    \n    // if FindLastChar return nullptr the word isnt in the trie,\n    if(node == nullptr){\n        return false;\n    }\n    return true;\n}\n/****************************************************************************/\n// Recursive function for delete a word and the whole node if the word or part \n// of her suffix stand alone. if the word is prefix of another word, no nodes\n// will be removed\nTrie::RecDeleteStatus Trie::RecDelete(TrieNode* curr_node, const char* string_ptr)\n{\n    if(curr_node == nullptr)\n    {\n        return NOT_FOUND;\n    }\n    if(*string_ptr == '\\0')\n    {\n        return DELETE;\n    }\n\n    int char_idx = *string_ptr - 'a';\n    RecDeleteStatus status = RecDelete(curr_node->vec[char_idx], string_ptr + 1);\n\n    if(status == DELETE)\n    {\n        if(IsLeaf(curr_node->vec[char_idx]))\n        {\n            delete curr_node->vec[char_idx];\n            curr_node->vec[char_idx] = nullptr;\n            return DELETE;\n        }\n        else if(*(string_ptr + 1) == '\\0')\n        {\n            if(curr_node->vec[char_idx]->end_of_str)\n            {\n                curr_node->vec[char_idx]->end_of_str = false;\n                return DELETE;\n            }\n            else\n            {\n                return NOT_FOUND;\n            }\n        }\n    }\n    if(status == NOT_FOUND)\n    {\n        return NOT_FOUND;\n    }\n    return COMPLITE;\n}\n/****************************************************************************/\n// function to check if node does not have childrens\nbool Trie::IsLeaf(TrieNode* curr_node)\n{\n    for(auto it : curr_node->vec)\n    {\n        if(it != nullptr)\n        {\n            return false;\n        }\n    }\n    return true;\n}\n/****************************************************************************/\n// function for create and push new nodes ,from the input node(node_runner)\n// according to the string(string_ptr) that must have a null termination sign.\nTrieNode* Trie::CreatNodes(TrieNode* node_runner, const char* string_ptr) \n{\n    while(*string_ptr)\n    {\n        TrieNode* new_node = new TrieNode();\n        \n        node_runner->vec[*string_ptr - 'a'] = new_node;\n        node_runner = new_node;\n        ++string_ptr;\n    }\n\n    return node_runner;\n}\n/****************************************************************************/\n// function for search and return the node of the last character in a string\n// return nullptr if the word is not found.\nTrieNode* Trie::FindLastChar(const char* string_ptr)\n{\n    TrieNode* node_runner = m_root;\n\n    while(*string_ptr)\n    {\n        TrieNode* next_node = node_runner->vec[*string_ptr - 'a'];\n        if(nullptr == next_node)\n        {\n            return nullptr;\n        }\n        \n        node_runner = next_node;\n        ++string_ptr;\n    }\n    return node_runner;\n}\n/****************************************************************************/\n// destroy all nodes inside the trie except the root\nvoid Trie::Destroy(TrieNode* node)\n{\n    if(node == nullptr)\n    {\n        return;\n    }   \n    for(auto it : node->vec)\n    {\n        Destroy(it);\n        delete it;\n    }\n}\n"
  },
  {
    "path": "Trees/trie.go",
    "content": "/*\nApproach:\nIn this implementation, we define two struct types: `TrieNode` and `Trie`. `TrieNode` represents a single node in the Trie. It has two fields: `children` (a map of rune to `TrieNode`) to store the child nodes and `isWord` (a boolean) to indicate the end of a word.\n\n`Trie` represents the Trie data structure and has a single field `root` (a pointer to `TrieNode`), which is initialized with an empty `TrieNode` in the `NewTrie` function.\n\nThe Trie supports three operations:\n- `Insert` function is used to add a word to the Trie. It starts from the root node and traverses through each character of the word, creating new nodes as needed.\n- `Search` function is used to check if a given word exists in the Trie. It follows a similar approach to the `Insert` function but returns `true` if the final node marks the end of a word.\n- `StartsWith` function is used to check if there is any word in the Trie that starts with a given prefix. It works similar to the `Search` function but does not require the final node to mark the end of a word.\n\nSample Input:\nIn the `main` function demonstrates the usage of the Trie data structure. We insert words \"apple\", \"app\", \"application\", \"book\", and \"dog\" into the Trie. Then, we search for words \"app\", \"apple\", and \"banana\". Finally, we check if there are any words in the Trie that start with prefixes \"ap\", \"do\", and \"cat\".\n\nTime complexity of the `Insert`, `Search`, and `StartsWith` operations: O(m), where m is the length of the word or prefix being processed. \n\nSpace complexity: O(n), where n is the total number of characters in all the words inserted in the Trie.\n*/\n\n//Here's an implementation of the Trie data structure in Go:\n\npackage main\n\nimport \"fmt\"\n\n// TrieNode represents a single node in the Trie\ntype TrieNode struct {\n\tchildren map[rune]*TrieNode\n\tisWord   bool\n}\n\n// Trie represents the Trie data structure\ntype Trie struct {\n\troot *TrieNode\n}\n\n// NewTrie initializes a new Trie\nfunc NewTrie() *Trie {\n\treturn &Trie{\n\t\troot: &TrieNode{\n\t\t\tchildren: make(map[rune]*TrieNode),\n\t\t\tisWord:   false,\n\t\t},\n\t}\n}\n\n// Insert adds a word to the Trie\nfunc (t *Trie) Insert(word string) {\n\tnode := t.root\n\n\t// Traverse through each character of the word\n\tfor _, ch := range word {\n\t\tif node.children[ch] == nil {\n\t\t\tnode.children[ch] = &TrieNode{\n\t\t\t\tchildren: make(map[rune]*TrieNode),\n\t\t\t\tisWord:   false,\n\t\t\t}\n\t\t}\n\t\tnode = node.children[ch]\n\t}\n\n\t// Mark the end of the word\n\tnode.isWord = true\n}\n\n// Search returns true if the word exists in the Trie, otherwise false\nfunc (t *Trie) Search(word string) bool {\n\tnode := t.root\n\n\t// Traverse through each character of the word\n\tfor _, ch := range word {\n\t\tif node.children[ch] == nil {\n\t\t\treturn false\n\t\t}\n\t\tnode = node.children[ch]\n\t}\n\n\t// Check if the node marks the end of a word\n\treturn node.isWord\n}\n\n// StartsWith returns true if there is any word in the Trie that starts with the given prefix, otherwise false\nfunc (t *Trie) StartsWith(prefix string) bool {\n\tnode := t.root\n\n\t// Traverse through each character of the prefix\n\tfor _, ch := range prefix {\n\t\tif node.children[ch] == nil {\n\t\t\treturn false\n\t\t}\n\t\tnode = node.children[ch]\n\t}\n\n\treturn true\n}\n\nfunc main() {\n\ttrie := NewTrie()\n\n\t// Inserting words into the Trie\n\ttrie.Insert(\"apple\")\n\ttrie.Insert(\"app\")\n\ttrie.Insert(\"application\")\n\ttrie.Insert(\"book\")\n\ttrie.Insert(\"dog\")\n\n\t// Searching words in the Trie\n\tfmt.Println(trie.Search(\"app\"))    // Output: true\n\tfmt.Println(trie.Search(\"apple\"))  // Output: true\n\tfmt.Println(trie.Search(\"banana\")) // Output: false\n\n\t// Checking prefixes in the Trie\n\tfmt.Println(trie.StartsWith(\"ap\"))  // Output: true\n\tfmt.Println(trie.StartsWith(\"do\"))  // Output: true\n\tfmt.Println(trie.StartsWith(\"cat\")) // Output: false\n}\n\n"
  },
  {
    "path": "Trees/trie.java",
    "content": "/*\nDescription\nA trie (pronounced as \"try\") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.\n\nImplement the Trie class:\n\nTrie() Initializes the trie object.\nvoid insert(String word) Inserts the string word into the trie.\nboolean search(String word) Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.\nboolean startsWith(String prefix) Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise.\n\nInput\n[\"Trie\", \"insert\", \"search\", \"search\", \"startsWith\", \"insert\", \"search\"]\n[[], [\"apple\"], [\"apple\"], [\"app\"], [\"app\"], [\"app\"], [\"app\"]]\nOutput\n[null, null, true, false, true, null, true]\n\nExplanation\nTrie trie = new Trie();\ntrie.insert(\"apple\");\ntrie.search(\"apple\");   // return True\ntrie.search(\"app\");     // return False\ntrie.startsWith(\"app\"); // return True\ntrie.insert(\"app\");\ntrie.search(\"app\");     // return True\n\nTime Complexity for each operation is O(n)\nSpace Complexity O(n*m) where n is the number of words inserted and m is the average length of the words.\n\nExplanation:\ninsert() -> traverse through each character of the input word and initializes it if necessary. If the end of the word is reached set isEnd to true.\nsearch() -> Search In each child node until the end of the word is reached, then if end of the node is also reached return true else false.\nstartsWith() -> Similar to search method but we only check if end of the prefix is reached and we don't need to check if it is the end of the node.\n\n*/\n\nclass Trie {\n    Node root;\n\n    public Trie() {\n        root = new Node();\n    }\n    \n    public void insert(String word) {\n        root.insert(word, 0);\n    }\n    \n    public boolean search(String word) {\n        return root.search(word, 0);\n    }\n    \n    public boolean startsWith(String prefix) {\n        return root.startsWith(prefix, 0);\n    }\n\n    class Node {\n        Node[] nodes;\n        boolean isEnd;\n\n        Node() {\n            nodes = new Node[26];\n        }\n\n        // Function to insert the word in the tree\n        private void insert(String word, int idx) {\n            if (idx >= word.length()) return; // handle edge case\n            int i = word.charAt(idx) - 'a';\n            if (nodes[i] == null) {\n                nodes[i] = new Node(); // initialize the node[i] if the letter was not found before\n            }\n\n            if (idx == word.length()-1) nodes[i].isEnd = true; // signifies that this is the end of the word\n            nodes[i].insert(word, idx+1); // recursive call to populate the child node\n        }\n\n        // Function to search the word in the tree\n        private boolean search(String word, int idx) {\n            if (idx >= word.length()) return false;\n            Node node = nodes[word.charAt(idx) - 'a'];\n            if (node == null) return false; // if the node is null it means that it was not initialised hence the character was never found.\n            if (idx == word.length() - 1 && node.isEnd) return true; //if it is the last character and the end of the node then return true\n\n            return node.search(word, idx+1); // recursive call search in the child node\n\n        }\n\n        //Function to search the prefix in tree\n        private boolean startsWith(String prefix, int idx) {\n            if (idx >= prefix.length()) return false;\n            Node node = nodes[prefix.charAt(idx) - 'a'];\n            if (node == null) return false;\n            if (idx == prefix.length() - 1) return true; // Very similar to above method but here we don't need to check if it is the end of the node.\n\n            return node.startsWith(prefix, idx+1);\n        }\n    }\n}"
  },
  {
    "path": "Tries/pattern_matching.cpp",
    "content": "/*\nGiven a list of n words and a pattern p that we want to search. Check if the pattern p is present the given words or not. Return true if the pattern is present and false otherwise.\nInput Format :\n\nThe first line of input contains an integer, that denotes the value of n.\nThe following line contains n space separated words.\nThe following line contains a string, that denotes the value of the pattern p.\n\nOutput Format :\n\nThe first and only line of output contains true if the pattern is present and false otherwise.\n\nConstraints:\n\nTime Limit: 1 sec\n\nSample Input 1 :\n\n4\nabc def ghi cba\nde\n\nSample Output 2 :\n\ntrue\n\nSample Input 2 :\n\n4\nabc def ghi hg\nhi\n\nSample Output 2 :\n\ntrue\n\nSample Input 3 :\n\n4\nabc def ghi hg\nhif\n\nSample Output 3 :\n\nfalse\n\nExplaination :\n    The TrieNode class represents a single node in the Trie. Each node contains a character data, an array of pointers to its child nodes children, and a boolean flag isTerminal to indicate if a word ends at that node.\n\n    The Trie class serves as the main data structure and contains a pointer to the root node of the Trie, along with a count variable to keep track of the number of words inserted.\n\n    The insertWord function is used to insert a word into the Trie. It takes a root parameter representing the current node and a word parameter representing the word to be inserted. The function recursively traverses the Trie, creating new nodes as needed and marking the last node as terminal if the word does not already exist.\n\n    The search function is used to search for a word in the Trie. It takes a root parameter and a word parameter. The function recursively checks if each character in the word exists as a child node starting from the given root.\n\n    The patternMatching function takes a vector of strings vect and a pattern string. It iterates over each word in the vector and inserts all possible substrings of that word into the Trie. Finally, it performs a search operation on the pattern string in the Trie and returns the result.\n*/\n#include <iostream>\n#include <string>\n#include <vector>\nusing namespace std;\n\nclass TrieNode\n{\npublic:\n    char data;\n    TrieNode **children;\n    bool isTerminal;\n\n    TrieNode(char data)\n    {\n        this->data = data;\n        children = new TrieNode *[26];\n        for (int i = 0; i < 26; i++)\n        {\n            children[i] = NULL;\n        }\n        isTerminal = false;\n    }\n};\n\nclass Trie\n{\n    TrieNode *root;\n\npublic:\n    int count;\n\n    Trie()\n    {\n        this->count = 0;\n        root = new TrieNode('\\0');\n    }\n\n    bool insertWord(TrieNode *root, string word)\n    {\n        // Base case\n        if (word.size() == 0)\n        {\n            if (!root->isTerminal)\n            {\n                root->isTerminal = true;\n                return true;\n            }\n            else\n            {\n                return false;\n            }\n        }\n\n        // Small calculation\n        int index = word[0] - 'a';\n        TrieNode *child;\n        if (root->children[index] != NULL)\n        {\n            child = root->children[index];\n        }\n        else\n        {\n            child = new TrieNode(word[0]);\n            root->children[index] = child;\n        }\n\n        // Recursive call\n        return insertWord(child, word.substr(1));\n    }\n\n    void insertWord(string word)\n    {\n        if (insertWord(root, word))\n        {\n            this->count++;\n        }\n    }\n\n    bool search(TrieNode *root, string word)\n    {\n        if (word.length() == 0)\n        {\n            return true;\n        }\n        if (root->children[word[0] - 'a'] == NULL)\n        {\n            return false;\n        }\n        bool ans = search(root->children[word[0] - 'a'], word.substr(1));\n        return ans;\n    }\n\n    bool search(string word)\n    {\n        return search(root, word);\n    }\n\n    bool patternMatching(vector<string> vect, string pattern)\n    {\n        for (int i = 0; i < vect.size(); i++)\n        {\n            string word = vect[i];\n            for (int j = 0; j < word.size(); j++)\n            {\n                insertWord(word.substr(j));\n            }\n        }\n        return search(pattern);\n    }\n};\n\nint main()\n{\n    Trie t;\n    int n;\n    cin >> n;\n    string pattern;\n    vector<string> vect;\n\n    for (int i = 0; i < n; ++i)\n    {\n        string word;\n        cin >> word;\n        vect.push_back(word);\n    }\n    cin >> pattern;\n\n    cout << (t.patternMatching(vect, pattern) ? \"true\" : \"false\");\n}"
  },
  {
    "path": "Tries/search_in_tries.cpp",
    "content": "/*\nImplement the function SearchWord for the Trie class.\nFor a Trie, write the function for searching a word. Return true if the word is found successfully, otherwise return false.\nNote : main function is given for your reference which we are using internally to test the code.\n\nExplaination :\n    The given code implements a Trie data structure and focuses on implementing the search functionality. The TrieNode class represents a single node in the Trie, and the Trie class serves as the main data structure.\n\n    The insertWord function is used to insert a word into the Trie. It takes a root parameter representing the current node and a word parameter representing the word to be inserted. The function recursively traverses the Trie, creating new nodes as needed and marking the last node as terminal.\n\n    The search function is used to search for a word in the Trie. It takes a root parameter and a word parameter. The function recursively checks if each character in the word exists as a child node starting from the given root. It returns true if the word is found and the last node is marked as terminal, otherwise it returns false.\n\n    In the main function, an instance of the Trie class is created. The program then enters a loop where the user can input commands. The user is prompted to enter a choice: 1 for inserting a word or 2 for searching a word. If the choice is 1, the user can enter a word to be inserted into the Trie. If the choice is 2, the user can enter a word to search for in the Trie. The result of the search operation is printed as \"true\" or \"false\" accordingly.\n*/\n#include <iostream>\n#include <string>\nusing namespace std;\n\nclass TrieNode\n{\npublic:\n    char data;\n    TrieNode **children;\n    bool isTerminal;\n\n    TrieNode(char data)\n    {\n        this->data = data;\n        children = new TrieNode *[26];\n        for (int i = 0; i < 26; i++)\n        {\n            children[i] = NULL;\n        }\n        isTerminal = false;\n    }\n};\n\nclass Trie\n{\n    TrieNode *root;\n\npublic:\n    Trie()\n    {\n        root = new TrieNode('\\0');\n    }\n\n    void insertWord(TrieNode *root, string word)\n    {\n        // Base case\n        if (word.size() == 0)\n        {\n            root->isTerminal = true;\n            return;\n        }\n\n        // Small Calculation\n        int index = word[0] - 'a';\n        TrieNode *child;\n        if (root->children[index] != NULL)\n        {\n            child = root->children[index];\n        }\n        else\n        {\n            child = new TrieNode(word[0]);\n            root->children[index] = child;\n        }\n\n        // Recursive call\n        insertWord(child, word.substr(1));\n    }\n\n    void insertWord(string word)\n    {\n        insertWord(root, word);\n    }\n\n    bool search(TrieNode *root, string word)\n    {\n        if (word.length() == 0)\n        {\n            return root->isTerminal && true;\n        }\n        int index = word[0] - 'a';\n        TrieNode *child;\n        if (root->children[index] != NULL)\n        {\n            child = root->children[index];\n        }\n        else\n        {\n            return root->isTerminal && false;\n        }\n        bool ans = search(child, word.substr(1));\n        return ans;\n    }\n\n    bool search(string word)\n    {\n        return search(root, word);\n    }\n};\n\nint main()\n{\n    int choice;\n    cin >> choice;\n    Trie t;\n\n    while (choice != -1)\n    {\n        string word;\n        bool ans;\n        switch (choice)\n        {\n        case 1: // insert\n            cin >> word;\n            t.insertWord(word);\n            break;\n        case 2: // search\n            cin >> word;\n            cout << (t.search(word) ? \"true\\n\" : \"false\\n\");\n            break;\n        default:\n            return 0;\n        }\n        cin >> choice;\n    }\n\n    return 0;\n}"
  },
  {
    "path": "Tries/trie_node_class.cpp",
    "content": "/*\nExplaination :\n    The TrieNode class represents a single node in the Trie. Each node contains a character data, an array of pointers to its child nodes children, and a boolean flag isTerminal to indicate if a word ends at that node.\n\n    The Trie class serves as the main data structure and contains a pointer to the root node of the Trie. It provides public functions to insert a word into the Trie, search for a word in the Trie, and remove a word from the Trie.\n\n    The insertWord function is a private member function of the Trie class and is responsible for inserting a word into the Trie. It takes a root parameter representing the current node and a word parameter representing the word to be inserted. The function recursively traverses the Trie, creating new nodes as needed and marking the last node as terminal.\n\n    The search function is also a private member function of the Trie class and is used to search for a word in the Trie. It takes a root parameter and a word parameter. The function recursively checks if each character in the word exists as a child node starting from the given root and returns true if the entire word is found and marked as terminal.\n\n    The removeWord function is another private member function of the Trie class and is used to remove a word from the Trie. It takes a root parameter and a word parameter. The function recursively searches for the word in the Trie, marks the last node of the word as non-terminal, and removes any unnecessary child nodes that are not part of other words.\n\n    In the main function, an instance of the Trie class is created. Words \"and\", \"dot\", and \"double\" are inserted into the Trie using the insertWord function. The search function is then used to check if the word \"and\" exists in the Trie, and the result is printed. The removeWord function is called to remove the word \"and\" from the Trie, and again the search function is used to check if the word \"and\" exists in the Trie after removal, and the result is printed.\n*/\n#include <iostream>\n#include <vector>\nusing namespace std;\n\nclass TrieNode\n{\npublic:\n    char data;\n    TrieNode **children;\n    bool isTerminal;\n\n    TrieNode(char data)\n    {\n        this->data = data;\n        children = new TrieNode *[26];\n        for (int i = 0; i < 26; i++)\n        {\n            children[i] = NULL;\n        }\n        isTerminal = false;\n    }\n};\n\nclass Trie\n{\n    TrieNode *root;\n\npublic:\n    Trie()\n    {\n        root = new TrieNode('\\0');\n    }\n\nprivate:\n    void insertWord(TrieNode *root, string word)\n    {\n        // Base Case\n        if (word.length() == 0)\n        {\n            root->isTerminal = true;\n            return;\n        }\n        // Small Calculation\n        int index = word[0] - 'a';\n        TrieNode *child;\n        if (root->children[index] != NULL)\n        {\n            child = root->children[index];\n        }\n        else\n        {\n            child = new TrieNode(word[0]);\n            root->children[index] = child;\n        }\n        // Recursive Call\n        insertWord(child, word.substr(1));\n    }\n\n    bool search(TrieNode *root, string word)\n    {\n        if (word.length() == 0)\n        {\n            return root->isTerminal && true;\n        }\n        int index = word[0] - 'a';\n        TrieNode *child;\n        if (root->children[index] != NULL)\n        {\n            child = root->children[index];\n        }\n        else\n        {\n            return root->isTerminal && false;\n        }\n        bool ans = search(child, word.substr(1));\n        return ans;\n    }\n    void removeWord(TrieNode *root, string word)\n    {\n        if (word.size() == 0)\n        {\n            root->isTerminal = false;\n            return;\n        }\n        int index = word[0] - 'a';\n        TrieNode *child;\n        if (root->children[index] != NULL)\n        {\n            child = root->children[index];\n        }\n        else\n        {\n            // Word not found\n            return;\n        }\n        removeWord(child, word.substr(1));\n\n        // Remove Child Node if it is useless\n        if (child->isTerminal == false)\n        {\n            for (int i = 0; i < 26; i++)\n            {\n                if (child->children[i] != NULL)\n                {\n                    return;\n                }\n            }\n            delete child;\n            root->children[index] = NULL;\n        }\n    }\n\npublic:\n    void insertWord(string word)\n    {\n        insertWord(root, word);\n    }\n\n    bool search(string word)\n    {\n        return search(root, word);\n    }\n\n    void removeWord(string word)\n    {\n        removeWord(root, word);\n    }\n};\n\nint main()\n{\n    Trie t;\n    t.insertWord(\"and\");\n    t.insertWord(\"dot\");\n    t.insertWord(\"double\");\n    cout << t.search(\"and\") << endl;\n    t.removeWord(\"and\");\n    cout << t.search(\"and\") << endl;\n}"
  },
  {
    "path": "sorting/Cyclic_Sort.java",
    "content": "/* \nWhat is Cyclic Sort?\nThe basic idea behind cycle sort is to divide the input array into cycles, where each cycle consists of elements that belong to the same position in the sorted output array. The algorithm then performs a series of swaps to place each element in its correct position within its cycle, until all cycles are complete and the array is sorted.\nIt is usually used where elements are in the range of (1,n)\n\nNote : This Algorithm solution is for elements from 1-N , where N is the number of elements in the array.\nTime Complexity Analysis: \n    Worst Case: O(n) \n    Average Case: O(n)\n    Best Case: O(n)\nAuxiliary Space: O(1)\n*/\n\nimport java.util.Arrays;\n\npublic class Cyclic_Sort {\n    public static void main(String[] args) {\n        int[] arr={3, 5, 2, 1, 4};    //Sample Input\n        sort(arr);\n        System.out.println(Arrays.toString(arr));   //Printing the original array\n    }\n    \n  //Cyclic Sort Program\n    static void sort(int[] arr){\n        int i=0;    //Variable to iterate over each element of array\n        while(i<arr.length){\n            int correct=arr[i]-1;   //checking the correct position of the element \n            if(arr[i]!= arr[correct]){\n                swap(arr,i,correct);    //swaping the element with its correct position\n            }\n            else{      /* if element is already at correct position, incrementing the value of i by 1. \n                      To further the check the value of next element */\n                i++;    \n            }\n        }\n    }\n\n    static void swap(int[] arr,int one,int two){\n        int temp=arr[two];\n        arr[two]=arr[one];\n        arr[one]=temp;\n    }\n}\n"
  },
  {
    "path": "sorting/bubble_sort.cpp",
    "content": "/*\n    Here's how the Bubble Sort algorithm works:\n\n    1. We start by comparing the first two elements of the array. If the first element is greater than the second \n       element, we swap them.\n    2. We then compare the second and third elements. If the second element is greater than the third element, \n       we swap them.\n    3. We continue this process until we reach the end of the array. At this point, the largest element will \n       be at the end of the array.\n    4. We then repeat steps 1-3 for the remaining unsorted portion of the array until the entire array is sorted.\n    \n    The time complexity of Bubble Sort is O(n^2) in the worst and average case, and O(n) in the best case when \n    the input array is already sorted. \n    \n    The space complexity is O(1) as Bubble Sort operates on the input array in-place.\n\n    Bubble sort is O(n) on a list that is already sorted i.e. Best case\n\n    Sample Input : [2, 1, 9, 3, 5, 4, 0]\n    Output : [0 1 2 3 4 5 9]\n*/\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nvoid bubbleSort(vector<int>& arr) {\n    int n = arr.size();\n    // Traverse through all array elements\n    for (int i = 0; i < n - 1; i++) {\n        // Last i elements are already sorted\n        for (int j = 0; j < n - i - 1; j++) {\n            // Swap adjacent elements if they are in the wrong order\n            if (arr[j] > arr[j + 1]) {\n                swap(arr[j], arr[j + 1]);\n            }\n        }\n    }\n}\n\nint main() {\n    vector<int> arr = {64, 25, 12, 22, 11};\n    bubbleSort(arr);\n    cout << \"Sorted array: \";\n    for (auto i : arr) {\n        cout << i << \" \";\n    }\n    return 0;\n}\n"
  },
  {
    "path": "sorting/bubble_sort.go",
    "content": "/*\n    Here's how the Bubble Sort algorithm works:\n\n    1. We start by comparing the first two elements of the array. If the first element is greater than the second \n       element, we swap them.\n    2. We then compare the second and third elements. If the second element is greater than the third element, \n       we swap them.\n    3. We continue this process until we reach the end of the array. At this point, the largest element will \n       be at the end of the array.\n    4. We then repeat steps 1-3 for the remaining unsorted portion of the array until the entire array is sorted.\n    \n    The time complexity of Bubble Sort is O(n^2) in the worst and average case, and O(n) in the best case when \n    the input array is already sorted. \n    \n    The space complexity is O(1) as Bubble Sort operates on the input array in-place.\n\n    Bubble sort is O(n) on a list that is already sorted i.e. Best case\n\n    Sample Input : [2, 1, 9, 3, 5, 4, 0]\n    Output : [0 1 2 3 4 5 9]\n*/\n\npackage main\n\nimport \"fmt\"\n\nfunc bubbleSort(arr []int) {\n    n := len(arr)\n\tflag := true\n    // Traverse through all array elements\n    for i := 0; i < n-1; i++ {\n        // Last i elements are already sorted\n        for j := 0; j < n-i-1; j++ {\n            // Swap adjacent elements if they are in the wrong order\n            if arr[j] > arr[j+1] {\n                arr[j], arr[j+1] = arr[j+1], arr[j]\n\t\t\t\tflag = false\n            }\n        }\n\t\tif flag {\n\t\t\tfmt.Println(\"Already sorted so no further redundant passes best case O(n)\")\n\t\t\tbreak\n\t\t}\n    }\n}\n\nfunc main() {\n    arr := []int{64, 25, 12, 22, 11}\n    bubbleSort(arr)\n    fmt.Println(\"Sorted array:\", arr)\n}\n"
  },
  {
    "path": "sorting/bubble_sort.java",
    "content": "/*\n    Here's how the Bubble Sort algorithm works:\n\n    1. We start by comparing the first two elements of the array. If the first element is greater than the second \n       element, we swap them.\n    2. We then compare the second and third elements. If the second element is greater than the third element, \n       we swap them.\n    3. We continue this process until we reach the end of the array. At this point, the largest element will \n       be at the end of the array.\n    4. We then repeat steps 1-3 for the remaining unsorted portion of the array until the entire array is sorted.\n    \n    The time complexity of Bubble Sort is O(n^2) in the worst and average case, and O(n) in the best case when \n    the input array is already sorted. \n    \n    The space complexity is O(1) as Bubble Sort operates on the input array in-place.\n\n    Bubble sort is O(n) on a list that is already sorted i.e. Best case\n\n    Sample Input : [2, 1, 9, 3, 5, 4, 0]\n    Output : [0 1 2 3 4 5 9]\n*/\n\nimport java.util.Arrays;\n\npublic class bubble_sort {\n    public static void bubbleSort(int[] arr) {\n        int n = arr.length;\n        // Traverse through all array elements\n        for (int i = 0; i < n - 1; i++) {\n            // Last i elements are already in place\n            for (int j = 0; j < n - i - 1; j++) {\n                // Swap adjacent elements if they are in the wrong order\n                if (arr[j] > arr[j + 1]) {\n                    int temp = arr[j];\n                    arr[j] = arr[j + 1];\n                    arr[j + 1] = temp;\n                }\n            }\n        }\n    }\n\n    public static void main(String[] args) {\n        int[] arr = {64, 34, 25, 12, 22, 11, 90};\n        bubbleSort(arr);\n        System.out.println(Arrays.toString(arr));\n    }\n}\n"
  },
  {
    "path": "sorting/bubble_sort.js",
    "content": "/*\n    Here's how the Bubble Sort algorithm works:\n\n    1. We start by comparing the first two elements of the array. If the first element is greater than the second \n       element, we swap them.\n    2. We then compare the second and third elements. If the second element is greater than the third element, \n       we swap them.\n    3. We continue this process until we reach the end of the array. At this point, the largest element will \n       be at the end of the array.\n    4. We then repeat steps 1-3 for the remaining unsorted portion of the array until the entire array is sorted.\n    \n    The time complexity of Bubble Sort is O(n^2) in the worst and average case, and O(n) in the best case when \n    the input array is already sorted. \n    \n    The space complexity is O(1) as Bubble Sort operates on the input array in-place.\n\n    Bubble sort is O(n) on a list that is already sorted i.e. Best case\n\n    Sample Input : [2, 1, 9, 3, 5, 4, 0]\n    Output : [0 1 2 3 4 5 9]\n*/\n\nfunction bubbleSort(arr) {\n  var n = arr.length;\n  // Traverse through all array elements\n  for (var i = 0; i < n - 1; i++) {\n    // Last i elements are already sorted\n    for (var j = 0; j < n - i - 1; j++) {\n      // Swap adjacent elements if they are in the wrong order\n      if (arr[j] > arr[j + 1]) {\n        var temp = arr[j];\n        arr[j] = arr[j + 1];\n        arr[j + 1] = temp;\n      }\n    }\n  }\n}\n\nvar arr = [64, 25, 12, 22, 11];\nbubbleSort(arr);\nconsole.log(\"Sorted array: \" + arr);\n"
  },
  {
    "path": "sorting/bubble_sort.py",
    "content": "'''\n    Here's how the Bubble Sort algorithm works:\n\n    1. We start by comparing the first two elements of the array. If the first element is greater than the second \n       element, we swap them.\n    2. We then compare the second and third elements. If the second element is greater than the third element, \n       we swap them.\n    3. We continue this process until we reach the end of the array. At this point, the largest element will \n       be at the end of the array.\n    4. We then repeat steps 1-3 for the remaining unsorted portion of the array until the entire array is sorted.\n    \n    The time complexity of Bubble Sort is O(n^2) in the worst and average case, and O(n) in the best case when \n    the input array is already sorted. \n    \n    The space complexity is O(1) as Bubble Sort operates on the input array in-place.\n\n    Bubble sort is O(n) on a list that is already sorted i.e. Best case\n\n    Sample Input : [2, 1, 9, 3, 5, 4, 0]\n    Output : [0 1 2 3 4 5 9]\n'''\n\ndef bubbleSort(arr):\n    n = len(arr)\n    # Traverse through all array elements\n    for i in range(n - 1):\n        # Last i elements are already sorted\n        for j in range(0, n - i - 1):\n            # Swap adjacent elements if they are in the wrong order\n            if arr[j] > arr[j + 1]:\n                arr[j], arr[j + 1] = arr[j + 1], arr[j]\n\narr = [64, 25, 12, 22, 11]\nbubbleSort(arr)\nprint(\"Sorted array:\", arr)\n"
  },
  {
    "path": "sorting/bucket-sort.js",
    "content": "function bucketSort(arr, bucketSize = 5) {\n    if (arr.length === 0) {\n        return arr;\n    }\n\n    // Determine minimum and maximum values in the array\n    let minValue = arr[0];\n    let maxValue = arr[0];\n    for (let i = 1; i < arr.length; i++) {\n        if (arr[i] < minValue) {\n            minValue = arr[i];\n        } else if (arr[i] > maxValue) {\n            maxValue = arr[i];\n        }\n    }\n\n    // Determine number of buckets needed and initialize empty buckets\n    const bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;\n    const buckets = new Array(bucketCount);\n    for (let i = 0; i < bucketCount; i++) {\n        buckets[i] = [];\n    }\n\n    // Assign array elements to buckets based on their value\n    for (let i = 0; i < arr.length; i++) {\n        const bucketIndex = Math.floor((arr[i] - minValue) / bucketSize);\n        buckets[bucketIndex].push(arr[i]);\n    }\n\n    // Sort each bucket using another sorting algorithm (here, insertion sort)\n    const sortedArray = [];\n    for (let i = 0; i < buckets.length; i++) {\n        const bucket = buckets[i];\n        insertionSort(bucket);\n        sortedArray.push(...bucket);\n    }\n\n    return sortedArray;\n}\n\nfunction insertionSort(arr) {\n    for (let i = 1; i < arr.length; i++) {\n        const currentValue = arr[i];\n        let j = i - 1;\n        while (j >= 0 && arr[j] > currentValue) {\n            arr[j + 1] = arr[j];\n            j--;\n        }\n        arr[j + 1] = currentValue;\n    }\n}\n"
  },
  {
    "path": "sorting/bucket_sort.cpp",
    "content": "/*The code implements the bucket sort algorithm in C++. It defines a bucketSort function that takes a vector of integers as input and sorts it using the bucket sort technique. The algorithm distributes the elements into separate buckets based on their values, sorts each bucket individually, and then concatenates the sorted buckets to obtain the final sorted array.*/\n/*Time Complexity: O(n + k) for best case and average case and O(n^2) for the worst case.\nThe space complexity of bucket sort is O(n + k)*/\n#include <iostream>\n#include <vector>\n#include <algorithm>\n\nusing namespace std;\n\nvoid bucketSort(vector<int>& arr) {\n    // Find the maximum value in the array to determine the range of buckets\n    int max_value = *max_element(arr.begin(), arr.end());\n\n    // Calculate the number of buckets needed\n    int num_buckets = max_value + 1;\n\n    // Create empty buckets\n    vector<vector<int>> buckets(num_buckets);\n\n    // Distribute the elements into buckets\n    for (int num : arr) {\n        buckets[num].push_back(num);\n    }\n\n    // Sort each bucket individually\n    for (auto& bucket : buckets) {\n        sort(bucket.begin(), bucket.end());\n    }\n\n    // Concatenate the sorted buckets to get the sorted array\n    int index = 0;\n    for (const auto& bucket : buckets) {\n        for (int num : bucket) {\n            arr[index++] = num;\n        }\n    }\n}\n\nint main() {\n    // Create an array of integers\n    vector<int> array = {5, 3, 9, 1, 8, 2, 7, 4, 6};\n\n    // Sort the array using bucket sort\n    bucketSort(array);\n\n    // Print the sorted array\n    for (int num : array) {\n        cout << num << \" \";\n    }\n    cout << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "sorting/bucket_sort.go",
    "content": "/*\n\tBucket sort, or bin sort, is a sorting algorithm that works by distributing\n\tthe elements of an array into a number of buckets. Each bucket is then\n\tsorted individually, either using a different sorting algorithm,\n\tor by recursively applying the bucket sorting algorithm.\n\tIt is a distribution sort, a generalization of pigeonhole sort that\n\tallows multiple keys per bucket, and is a cousin of\n\tradix sort in the most-to-least significant digit flavor.\n\tBucket sort can be implemented with comparisons and therefore can also\n\tbe considered a comparison sort algorithm.\n\tThe computational complexity depends on the algorithm used to sort\n\teach bucket, the number of buckets to use,\n\tand whether the input is uniformly distributed.\n\n\tBucket sort works as follows:\n\n\tSet up an array of initially empty \"buckets\".\n\tScatter: Go over the original array, putting each object in its bucket.\n\tSort each non-empty bucket.\n\tGather: Visit the buckets in order and put all elements back into the original array.\n\n\tSource(https://en.wikipedia.org/wiki/Bucket_sort)\n*/\n// The average time complexity for Bucket Sort is O(n + k).\n// The worst time complexity is O(n²).\n// The space complexity for Bucket Sort is O(n+k).\npackage main\n\nimport (\n\t\"fmt\"\n)\n\nfunc InsertionSort(Array []int) {\n\tfor i := 0; i < len(Array); i++ {\n\t\ttemp := Array[i]\n\t\tj := i - 1\n\t\tfor ; j >= 0 && Array[j] > temp; j-- {\n\t\t\tArray[j+1] = Array[j]\n\t\t}\n\t\tArray[j+1] = temp\n\t}\n}\n\nfunc BucketSort(Array []int, bucketSize int) []int {\n\tvar max, min int\n\tfor _, n := range Array {\n\t\tif n < min {\n\t\t\tmin = n\n\t\t}\n\t\tif n > max {\n\t\t\tmax = n\n\t\t}\n\t}\n\tnBuckets := int(max-min)/bucketSize + 1\n\tbuckets := make([][]int, nBuckets)\n\tfor i := 0; i < nBuckets; i++ {\n\t\tbuckets[i] = make([]int, 0)\n\t}\n\n\tfor _, n := range Array {\n\t\tidx := int(n-min) / bucketSize\n\t\tbuckets[idx] = append(buckets[idx], n)\n\t}\n\n\tsorted := make([]int, 0)\n\tfor _, bucket := range buckets {\n\t\tif len(bucket) > 0 {\n\t\t\tInsertionSort(bucket)\n\t\t\tsorted = append(sorted, bucket...)\n\t\t}\n\t}\n\n\treturn sorted\n}\n\nfunc main() {\n\tArray := []int{3, 4, 5, 2, 1}\n\tArray = BucketSort(Array, 2)\n\tfor _, val := range Array {\n\t\tfmt.Println(val)\n\t}\n}"
  },
  {
    "path": "sorting/bucket_sort.java",
    "content": "/*\n\nHere is a step by step process :\nSet up an array of initially empty \"buckets\".\nScatter: Go over the original array, putting each object in its bucket.\nSort each non-empty bucket.\nGather: Visit the buckets in order and put all elements back into the original array.\n\nBucket Sort time complexity\nBest Case Time Complexity: O(n+k)\nAverage Case Time Complexity: O(n)\nWorst Case Time Complexity: O(n^2^)\nBest Case Time Complexity:\nIf the array elements are uniformly distributed, bucket size will almost be the same for all the buckets. Hence, this will be the best case which will take up the least amount of time.\nSorting time complexity will reduce even further if all the elements inside each bucket are already sorted.\nTo create n buckets and scatter each element from the array, time complexity = O(n). If we use Insertion sort to sort each bucket, time complexity = O(k). Hence, best case time complexity for bucket sort = O(n+k), where n = number of elements, and k = number of buckets\nWorst Case Time Complexity\nIf the array elements are not uniformly distributed, i.e., elements are concentrated within specific ranges.\nThis will result in one or more buckets having more elements than other buckets, making bucket sort like any other sorting technique, where every element is compared to the other. Time complexity increases even further if the elements in the array are present in the reverse order. If insertion sort is used, the worst-case time complexity can go up to O(n^2^).\n\n\nBucket Sort Space Complexity\nSpace Complexity : O(n+k)\nSpace Complexity for bucket sort is O(n+k), where n = number of elements in the array, and k = number of buckets formed Space taken by each bucket is O(k), and inside each bucket, we have n elements scattered. Hence, the space complexity becomes O(n+k).\n\n*/\n\npackage util;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\n\npublic class BucketSort {\n\nstatic void bucketSort(int[] arr, int noOfBuckets) {\n\nboolean isNegativePresent = false;\nint offset = Integer.MAX_VALUE;\nfor (int i : arr) {\n  if (i < offset) offset = i;\n  if (i < 0) isNegativePresent = true;\n}\n\nint globalMax = Integer.MIN_VALUE;\nint globalMin = Integer.MAX_VALUE;\nfor (int i = 0; i < arr.length; i++) {\n  arr[i] -= offset;\n  globalMin = Math.min(arr[i], globalMin);\n  globalMax = Math.max(arr[i], globalMax);\n}\n\nint range = globalMax - globalMin;\nint bucketRange = (int) Math.ceil((double) range / noOfBuckets);\n\n// Create bucket array\nList<Integer>[] buckets = new List[noOfBuckets];\n\n// Associate a list with each index in the bucket array\nfor (int i = 0; i < noOfBuckets; i++) {\n  buckets[i] = new LinkedList<>();\n}\n\n// Assign numbers from array to the proper bucket\n// by using hashing function\nfor (int num : arr) {\n  buckets[hash(num, bucketRange, noOfBuckets)].add(num);\n}\n\n// sort buckets\nfor (List<Integer> bucket : buckets) Collections.sort(bucket);\n\nint idx = 0;\n// Merge buckets to get sorted array\nfor (List<Integer> bucket : buckets) {\n  for (int num : bucket) {\n    arr[idx++] = num;\n  }\n}\n\nif (isNegativePresent) {\n  for (int i = 0; i < arr.length; i++) {\n    arr[i] += offset;\n  }\n}\n}\n\nprivate static int hash(int num, int hashValue, int numberOfBuckets) {\nint bucketNumber = num / hashValue;\nif (bucketNumber == numberOfBuckets)\nbucketNumber--;\nreturn bucketNumber;\n}\n}"
  },
  {
    "path": "sorting/bucket_sort.js",
    "content": "Here's an implementation of bucket sort in JavaScript:\n\nfunction bucketSort(arr, numBuckets = 10) {\n  const n = arr.length;\n  const buckets = new Array(numBuckets);\n  \n  // Initialize the buckets\n  for (let i = 0; i < numBuckets; i++) {\n    buckets[i] = [];\n  }\n  \n  // Distribute the elements into the buckets\n  for (let i = 0; i < n; i++) {\n    const bucketIndex = Math.floor(arr[i] * numBuckets);\n    buckets[bucketIndex].push(arr[i]);\n  }\n  \n  // Sort the elements within each bucket\n  for (let i = 0; i < numBuckets; i++) {\n    buckets[i].sort((a, b) => a - b);\n  }\n  \n  // Concatenate the sorted buckets\n  let sortedArr = [];\n  for (let i = 0; i < numBuckets; i++) {\n    sortedArr = sortedArr.concat(buckets[i]);\n  }\n  \n  return sortedArr;\n}\n\n\nThe bucketSort function takes an array arr of numbers and an optional parameter numBuckets that specifies the number of buckets to use (default is 10).\nThe algorithm works by distributing the elements of arr into numBuckets buckets based on their value. Each bucket contains elements within a range of values,\nand since the buckets are sorted, the elements within each bucket are sorted as well. Finally, the sorted buckets are concatenated to obtain the final sorted\narray.\n\nNote that the performance of bucket sort depends on the distribution of the elements in the input array. If the elements are evenly distributed, bucket sort can achieve a time complexity of O(n), which is faster than many other sorting algorithms. However, if the elements are concentrated in a small range of values, the buckets may become unbalanced and the performance may degrade. Therefore, bucket sort is often used as a sub-routine in other sorting algorithms, or when the distribution of the input is known to be relatively even.\n"
  },
  {
    "path": "sorting/count_sort.cpp",
    "content": "/*\n                                        Count Sort\nThe Counting Sort algorithm is a non-comparative sorting algorithm that works by counting the occurrences of each distinct element in the input \nlist. It then uses this information to determine the correct position of each element in the sorted output.\n\nHere are the steps involved in the Counting Sort algorithm:\n\n1. Find the range: Determine the range of values in the input list. This range is necessary to create an array with the appropriate size to store the counts.\n\n2. Count the occurrences: Create a count array of size equal to the range determined in the previous step. Iterate through the input list and count \nthe occurrences of each element by incrementing the corresponding count in the count array.\n\n3. Calculate cumulative counts: Modify the count array such that each element represents the cumulative count of elements up to that index. This step \nensures that the count array contains the correct positions for each element in the sorted order.\n\n4. Generate the sorted output: Create an output array of the same size as the input list. Iterate through the input list and use the count array to \ndetermine the correct position of each element in the output array. Place each element in its corresponding position and decrement the count \nin the count array.\n\n5. Return the sorted list: The output array now contains the elements in sorted order. Return this sorted list as the result of the Counting Sort algorithm.\n\nHere's an example to illustrate the process:\n\nSample Input: [4, 2, 9, 4, 6, 1]\n\n1. Find the range: The range of values in the input list is from 1 to 9.\n2. Count the occurrences: Create the count array [0, 1, 1, 0, 2, 0, 1, 0, 0, 1], where the index represents the element and the value represents the count.\n3. Calculate cumulative counts: Modify the count array to [0, 1, 2, 2, 4, 4, 5, 5, 5, 6]. Each element represents the cumulative count of elements up to that index.\n4. Generate the sorted output: Create the output array [1, 2, 4, 4, 6, 9]. Iterate through the input list, use the count array to determine the correct \nposition of each element, place it in the output array, and decrement the count in the count array.\n5. Return the sorted list: The sorted list is [1, 2, 4, 4, 6, 9].\n\nCounting Sort is an efficient algorithm when the range of values in the input list is relatively small. It has a time complexity of O(n + k), where n is \nthe number of elements in the input list and k is the range of values.\n*/\n\n#include <iostream>\nusing namespace std;\n\nint getMax(int a[], int n)\n{\n    int max = a[0];\n    for (int i = 1; i < n; i++)\n    {\n        if (a[i] > max)\n            max = a[i];\n    }\n    return max; // maximum element from the array\n}\n\nvoid countSort(int a[], int n) // function to perform counting sort\n{\n    int output[n + 1];\n    int max = getMax(a, n);\n    int count[max + 1]; // create count array with size [max+1]\n\n    for (int i = 0; i <= max; ++i)\n    {\n        count[i] = 0; // Initialize count array with all zeros\n    }\n\n    for (int i = 0; i < n; i++) // Store the count of each element\n    {\n        count[a[i]]++;\n    }\n\n    for (int i = 1; i <= max; i++)\n        count[i] += count[i - 1]; // find cumulative frequency\n\n    /* This loop will find the index of each element of the original array in count array, and\n     place the elements in output array*/\n    for (int i = n - 1; i >= 0; i--)\n    {\n        output[count[a[i]] - 1] = a[i];\n        count[a[i]]--; // decrease count for same numbers\n    }\n\n    for (int i = 0; i < n; i++)\n    {\n        a[i] = output[i]; // store the sorted elements into main array\n    }\n}\n\nvoid printArr(int a[], int n) /* function to print the array */\n{\n    int i;\n    for (i = 0; i < n; i++)\n        cout << a[i] << \" \";\n}\n\nint main()\n{\n    int a[] = {31, 11, 42, 7, 30, 11};\n    int n = sizeof(a) / sizeof(a[0]);\n    cout << \"Before sorting array elements are - \\n\";\n    printArr(a, n);\n    countSort(a, n);\n    cout << \"\\nAfter sorting array elements are - \\n\";\n    printArr(a, n);\n    return 0;\n}"
  },
  {
    "path": "sorting/count_sort.java",
    "content": "/*\n                                        Count Sort\nThe Counting Sort algorithm is a non-comparative sorting algorithm that works by counting the occurrences of each distinct element in the input \nlist. It then uses this information to determine the correct position of each element in the sorted output.\n\nHere are the steps involved in the Counting Sort algorithm:\n\n1. Find the range: Determine the range of values in the input list. This range is necessary to create an array with the appropriate size to store the counts.\n\n2. Count the occurrences: Create a count array of size equal to the range determined in the previous step. Iterate through the input list and count \nthe occurrences of each element by incrementing the corresponding count in the count array.\n\n3. Calculate cumulative counts: Modify the count array such that each element represents the cumulative count of elements up to that index. This step \nensures that the count array contains the correct positions for each element in the sorted order.\n\n4. Generate the sorted output: Create an output array of the same size as the input list. Iterate through the input list and use the count array to \ndetermine the correct position of each element in the output array. Place each element in its corresponding position and decrement the count \nin the count array.\n\n5. Return the sorted list: The output array now contains the elements in sorted order. Return this sorted list as the result of the Counting Sort algorithm.\n\nHere's an example to illustrate the process:\n\nSample Input: [4, 2, 9, 4, 6, 1]\n\n1. Find the range: The range of values in the input list is from 1 to 9.\n2. Count the occurrences: Create the count array [0, 1, 1, 0, 2, 0, 1, 0, 0, 1], where the index represents the element and the value represents the count.\n3. Calculate cumulative counts: Modify the count array to [0, 1, 2, 2, 4, 4, 5, 5, 5, 6]. Each element represents the cumulative count of elements up to that index.\n4. Generate the sorted output: Create the output array [1, 2, 4, 4, 6, 9]. Iterate through the input list, use the count array to determine the correct \nposition of each element, place it in the output array, and decrement the count in the count array.\n5. Return the sorted list: The sorted list is [1, 2, 4, 4, 6, 9].\n\nCounting Sort is an efficient algorithm when the range of values in the input list is relatively small. It has a time complexity of O(n + k), where n is \nthe number of elements in the input list and k is the range of values.\n*/\n\nclass CountingSort {  \n  \nint getMax(int[] a, int n) {  \n  int max = a[0];  \n  for(int i = 1; i<n; i++) {  \n      if(a[i] > max)  \n         max = a[i];  \n  }  \n  return max; //maximum element from the array  \n}  \n  \nvoid countSort(int[] a, int n) // function to perform counting sort  \n{  \n   int[] output = new int [n+1];  \n   int max = getMax(a, n);  \n   //int max = 42;  \n   int[] count = new int [max+1]; //create count array with size [max+1]  \n  \n    for (int i = 0; i <= max; ++i)   \n    {  \n        count[i] = 0; // Initialize count array with all zeros  \n    }  \n        \n    for (int i = 0; i < n; i++) // Store the count of each element  \n    {  \n        count[a[i]]++;  \n    }  \n    \n    for(int i = 1; i<=max; i++)   \n        count[i] += count[i-1]; //find cumulative frequency  \n    \n    /* This loop will find the index of each element of the original array in  \n    \n    count array, and \n    place the elements in output array*/  \n    for (int i = n - 1; i >= 0; i--) {  \n        output[count[a[i]] - 1] = a[i];  \n        count[a[i]]--; // decrease count for same numbers  \n    }  \n    \n    for(int i = 0; i<n; i++) {  \n        a[i] = output[i]; //store the sorted elements into main array  \n    }  \n    }  \n    \n    /* Function to print the array elements */  \n    void printArray(int a[], int n)  \n    {  \n        int i;  \n        for (i = 0; i < n; i++)  \n            System.out.print(a[i] + \" \");  \n    }  \n  \n    public static void main(String args[])  \n    {  \n        int a[] = { 11, 30, 24, 7, 31, 16, 39, 41 };  \n        int n = a.length;  \n        CountingSort c1 = new CountingSort();  \n        System.out.println(\"\\nBefore sorting array elements are - \");  \n        c1.printArray(a, n);  \n        c1.countSort(a,n);  \n        System.out.println(\"\\nAfter sorting array elements are - \");  \n        c1.printArray(a, n);  \n        System.out.println();  \n    }  \n}  "
  },
  {
    "path": "sorting/count_sort.js",
    "content": "/*\n                                        Count Sort\nThe Counting Sort algorithm is a non-comparative sorting algorithm that works by counting the occurrences of each distinct element in the input \nlist. It then uses this information to determine the correct position of each element in the sorted output.\n\nHere are the steps involved in the Counting Sort algorithm:\n\n1. Find the range: Determine the range of values in the input list. This range is necessary to create an array with the appropriate size to store the counts.\n\n2. Count the occurrences: Create a count array of size equal to the range determined in the previous step. Iterate through the input list and count \nthe occurrences of each element by incrementing the corresponding count in the count array.\n\n3. Calculate cumulative counts: Modify the count array such that each element represents the cumulative count of elements up to that index. This step \nensures that the count array contains the correct positions for each element in the sorted order.\n\n4. Generate the sorted output: Create an output array of the same size as the input list. Iterate through the input list and use the count array to \ndetermine the correct position of each element in the output array. Place each element in its corresponding position and decrement the count \nin the count array.\n\n5. Return the sorted list: The output array now contains the elements in sorted order. Return this sorted list as the result of the Counting Sort algorithm.\n\nHere's an example to illustrate the process:\n\nSample Input: [4, 2, 9, 4, 6, 1]\n\n1. Find the range: The range of values in the input list is from 1 to 9.\n2. Count the occurrences: Create the count array [0, 1, 1, 0, 2, 0, 1, 0, 0, 1], where the index represents the element and the value represents the count.\n3. Calculate cumulative counts: Modify the count array to [0, 1, 2, 2, 4, 4, 5, 5, 5, 6]. Each element represents the cumulative count of elements up to that index.\n4. Generate the sorted output: Create the output array [1, 2, 4, 4, 6, 9]. Iterate through the input list, use the count array to determine the correct \nposition of each element, place it in the output array, and decrement the count in the count array.\n5. Return the sorted list: The sorted list is [1, 2, 4, 4, 6, 9].\n\nCounting Sort is an efficient algorithm when the range of values in the input list is relatively small. It has a time complexity of O(n + k), where n is \nthe number of elements in the input list and k is the range of values.\n*/\n\nfunction sort(arr)\n{\n    var n = arr.length;\n \n    // The output character array that will have sorted arr\n    var output = Array.from({length: n}, (_, i) => 0);\n \n    // Create a count array to store count of individual\n    // characters and initialize count array as 0\n    var count = Array.from({length: 256}, (_, i) => 0);\n \n \n    // store count of each character\n    for (var i = 0; i < n; ++i)\n        ++count[arr[i].charCodeAt(0)];\n    // Change count[i] so that count[i] now contains actual\n    // position of this character in output array\n    for (var i = 1; i <= 255; ++i)\n        count[i] += count[i - 1];\n \n    // Build the output character array\n    // To make it stable we are operating in reverse order.\n    for (var i = n - 1; i >= 0; i--) {\n        output[count[arr[i].charCodeAt(0)] - 1] = arr[i];\n        --count[arr[i].charCodeAt(0)];\n    }\n \n    // Copy the output array to arr, so that arr now\n    // contains sorted characters\n    for (var i = 0; i < n; ++i)\n        arr[i] = output[i];\n     return arr;\n}\n \n// Driver method\n    var arr = [ 'g', 'e', 'e', 'k', 's', 'f', 'o',\n                   'r', 'g', 'e', 'e', 'k', 's' ];\n \n    arr = sort(arr);\n    document.write(\"Sorted character array is \");\n    for (var i = 0; i < arr.length; ++i)\n        document.write(arr[i]);"
  },
  {
    "path": "sorting/count_sort.py",
    "content": "#                                         Count Sort\n# The Counting Sort algorithm is a non-comparative sorting algorithm that works by counting the occurrences of each distinct element in the input \n# list. It then uses this information to determine the correct position of each element in the sorted output.\n\n# Here are the steps involved in the Counting Sort algorithm:\n\n# 1. Find the range: Determine the range of values in the input list. This range is necessary to create an array with the appropriate size to store the counts.\n\n# 2. Count the occurrences: Create a count array of size equal to the range determined in the previous step. Iterate through the input list and count \n# the occurrences of each element by incrementing the corresponding count in the count array.\n\n# 3. Calculate cumulative counts: Modify the count array such that each element represents the cumulative count of elements up to that index. This step \n# ensures that the count array contains the correct positions for each element in the sorted order.\n\n# 4. Generate the sorted output: Create an output array of the same size as the input list. Iterate through the input list and use the count array to \n# determine the correct position of each element in the output array. Place each element in its corresponding position and decrement the count \n# in the count array.\n\n# 5. Return the sorted list: The output array now contains the elements in sorted order. Return this sorted list as the result of the Counting Sort algorithm.\n\n# Here's an example to illustrate the process:\n\n# Sample Input: [4, 2, 9, 4, 6, 1]\n\n# 1. Find the range: The range of values in the input list is from 1 to 9.\n# 2. Count the occurrences: Create the count array [0, 1, 1, 0, 2, 0, 1, 0, 0, 1], where the index represents the element and the value represents the count.\n# 3. Calculate cumulative counts: Modify the count array to [0, 1, 2, 2, 4, 4, 5, 5, 5, 6]. Each element represents the cumulative count of elements up to that index.\n# 4. Generate the sorted output: Create the output array [1, 2, 4, 4, 6, 9]. Iterate through the input list, use the count array to determine the correct \n# position of each element, place it in the output array, and decrement the count in the count array.\n# 5. Return the sorted list: The sorted list is [1, 2, 4, 4, 6, 9].\n\n# Counting Sort is an efficient algorithm when the range of values in the input list is relatively small. It has a time complexity of O(n + k), where n is \n# the number of elements in the input list and k is the range of values.\n\n# The main function that sort the given string arr[] inalphabetical order \ndef countSort(arr):\n \n    # The output character array that will have sorted arr\n    output = [0 for i in range(len(arr))]\n \n    # Create a count array to store count of individual\n    # characters and initialize count array as 0\n    count = [0 for i in range(256)]\n \n    # For storing the resulting answer since the\n    # string is immutable\n    ans = [\"\" for _ in arr]\n \n    # Store count of each character\n    for i in arr:\n        count[ord(i)] += 1\n \n    # Change count[i] so that count[i] now contains actual\n    # position of this character in output array\n    for i in range(256):\n        count[i] += count[i-1]\n \n    # Build the output character array\n    for i in range(len(arr)):\n        output[count[ord(arr[i])]-1] = arr[i]\n        count[ord(arr[i])] -= 1\n \n    # Copy the output array to arr, so that arr now\n    # contains sorted characters\n    for i in range(len(arr)):\n        ans[i] = output[i]\n    return ans\n \n \n# Driver code\nif __name__ == '__main__':\n    arr = \"geeksforgeeks\"\n    ans = countSort(arr)\n    print(\"Sorted character array is % s\" % (\"\".join(ans)))"
  },
  {
    "path": "sorting/dnf.cpp",
    "content": "/*\n\nThe Dutch National Flag algorithm is used to sort an array containing elements with values of 0, 1, and 2. The goal is to rearrange the elements in-place so that all the 0s are grouped at the beginning, followed by all the 1s, and finally all the 2s.\n\nThe algorithm uses three pointers: low, mid, and high. The low pointer represents the boundary of the 0s section, the mid pointer scans the array, and the high pointer represents the boundary of the 2s section.\n\nThe algorithm iterates through the array and performs the following operations:\n\n    1. If the element at the mid pointer is 0, it is swapped with the element at the low pointer, and both pointers are incremented.\n    2. If the element at the mid pointer is 1, it is already in the correct section, so the mid pointer is simply incremented.\n    3. If the element at the mid pointer is 2, it is swapped with the element at the high pointer, and the high pointer is decremented.\n\nThe iteration continues until the mid pointer crosses the high pointer, indicating that all elements have been processed.\n\nAfter the algorithm finishes, the array will be sorted according to the Dutch National Flag problem requirements, with all 0s at the beginning, followed by 1s, and finally 2s. The sorting is done in-place, meaning it does not require any additional space.\n\nThe time complexity of the Dutch National Flag algorithm is O(n), where n is the length of the array, as we only need to iterate through the array once. The space complexity is O(1) since no extra space is used apart from the input array.\n\nConsider an array: [1, 2, 0, 2, 1, 0].\n\nThe algorithm uses three pointers: low, mid, and high. Initially, low = 0, mid = 0, and high = 5.\n\n    Iterate while mid <= high:\n        If the element at mid is 0, swap it with the element at low, increment both low and mid.\n        If the element at mid is 1, increment mid.\n        If the element at mid is 2, swap it with the element at high, decrement high.\n\nAfter applying the algorithm, the sorted array will be: [0, 0, 1, 1, 2, 2].\n\nIn this example, the algorithm moves all the 0s to the beginning, followed by the 1s, and finally the 2s, achieving the desired sorting according to the Dutch National Flag problem requirements.\n*/\n\n#include <iostream>\n#include <vector>\n\nstd::vector<int64_t> DutchNationalFlag(std::vector<int64_t>& array) {\n    int low = 0;        // Initialize the low pointer to the beginning of the array\n    int mid = 0;        // Initialize the mid pointer to the beginning of the array\n    int high = array.size() - 1;  // Initialize the high pointer to the end of the array\n\n    while (mid <= high) {\n        switch (array[mid]) {\n            case 0:\n                // If the value at mid is 0, swap it with the value at low\n                std::swap(array[low], array[mid]);\n                low++;  // Increment low to move forward\n                mid++;  // Increment mid to move forward\n                break;\n            case 1:\n                // If the value at mid is 1, no swapping needed, just move mid forward\n                mid++;\n                break;\n            case 2:\n                // If the value at mid is 2, swap it with the value at high\n                std::swap(array[mid], array[high]);\n                high--;  // Decrement high to move backward\n                break;\n        }\n    }\n\n    return array;\n}\n\nint main() {\n    std::vector<int64_t> array = {2, 0, 1, 1, 0, 2, 2, 1, 0};\n    std::vector<int64_t> sortedArray = DutchNationalFlag(array);\n\n    std::cout << \"Sorted Array: \";\n    for (int64_t num : sortedArray) {\n        std::cout << num << \" \";\n    }\n    std::cout << std::endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "sorting/dnf.go",
    "content": "/*\n\nThe Dutch National Flag algorithm is used to sort an array containing elements with values of 0, 1, and 2. The goal is to rearrange the elements in-place so that all the 0s are grouped at the beginning, followed by all the 1s, and finally all the 2s.\n\nThe algorithm uses three pointers: low, mid, and high. The low pointer represents the boundary of the 0s section, the mid pointer scans the array, and the high pointer represents the boundary of the 2s section.\n\nThe algorithm iterates through the array and performs the following operations:\n\n    1. If the element at the mid pointer is 0, it is swapped with the element at the low pointer, and both pointers are incremented.\n    2. If the element at the mid pointer is 1, it is already in the correct section, so the mid pointer is simply incremented.\n    3. If the element at the mid pointer is 2, it is swapped with the element at the high pointer, and the high pointer is decremented.\n\nThe iteration continues until the mid pointer crosses the high pointer, indicating that all elements have been processed.\n\nAfter the algorithm finishes, the array will be sorted according to the Dutch National Flag problem requirements, with all 0s at the beginning, followed by 1s, and finally 2s. The sorting is done in-place, meaning it does not require any additional space.\n\nThe time complexity of the Dutch National Flag algorithm is O(n), where n is the length of the array, as we only need to iterate through the array once. The space complexity is O(1) since no extra space is used apart from the input array.\n\nConsider an array: [1, 2, 0, 2, 1, 0].\n\nThe algorithm uses three pointers: low, mid, and high. Initially, low = 0, mid = 0, and high = 5.\n\n    Iterate while mid <= high:\n        If the element at mid is 0, swap it with the element at low, increment both low and mid.\n        If the element at mid is 1, increment mid.\n        If the element at mid is 2, swap it with the element at high, decrement high.\n\nAfter applying the algorithm, the sorted array will be: [0, 0, 1, 1, 2, 2].\n\nIn this example, the algorithm moves all the 0s to the beginning, followed by the 1s, and finally the 2s, achieving the desired sorting according to the Dutch National Flag problem requirements.\n*/\npackage main\n\nimport \"fmt\"\n\nfunc DutchNationalFlag(array []int64) []int64 {\n\n\t// Initialize Low, Mid, and High pointers\n\tvar (\n\t\tLow  = 0\n\t\tMid  = 0\n\t\tHigh = len(array) - 1\n\t)\n\n\t// Iterate while Mid pointer is less than or equal to High pointer\n\tfor Mid <= High {\n\n\t\t// Check the value at Mid pointer\n\t\tswitch array[Mid] {\n\n\t\t// Case 0: Value is 0, so swap it with the value at Low pointer\n\t\t// Increment both Low and Mid pointers to move forward\n\t\tcase 0:\n\t\t\tarray[Low], array[Mid] = array[Mid], array[Low]\n\t\t\tLow++\n\t\t\tMid++\n\n\t\t// Case 1: Value is 1, no swapping needed\n\t\t// Increment Mid pointer to move forward\n\t\tcase 1:\n\t\t\tMid++\n\n\t\t// Case 2: Value is 2, so swap it with the value at High pointer\n\t\t// Decrement High pointer to move backward\n\t\tcase 2:\n\t\t\tarray[Mid], array[High] = array[High], array[Mid]\n\t\t\tHigh--\n\t\t}\n\t}\n\n\t// Return the sorted array\n\treturn array\n}\n\n"
  },
  {
    "path": "sorting/dnf.java",
    "content": "package sorting;\n\n/*\n *Explanation:\nThe code above solves the Dutch National Flag problem. It takes an array of integers and a pivot element as input, and sorts the array in the Dutch National Flag order. The Dutch National Flag problem involves partitioning the array into three sections based on the pivot element.\n\nThe dutchNationalFlagSort method uses three pointers: low, mid, and high. The low pointer represents the boundary for elements less than the pivot, the mid pointer represents the boundary for elements equal to the pivot, and the high pointer represents the boundary for elements greater than the pivot.\n\nThe method uses a while loop that continues until the mid pointer surpasses the high pointer. Inside the loop, it compares the element at the mid index with the pivot. If the element is less than the pivot, it swaps it with the element at the low index and increments both low and mid. If the element is greater than the pivot, it swaps it with the element at the high index and decrements high. If the element is equal to the pivot, it increments mid.\n\nThe swap method is a helper function that swaps two elements in the array.\n\nIn the main method, an example array and pivot value are provided. The dutchNationalFlagSort method is called with these values, and the sorted array is printed.\n\nTime Complexity: The time complexity of the Dutch National Flag algorithm is O(n), where n is the length of the input array.\n\nSpace Complexity: The space complexity is O(1) as the algorithm sorts the array in-place without using any additional data structures. \n**/\nimport java.util.Arrays;\n\npublic class DutchNationalFlag {\n\n    /**\n     * Sorts an array of integers in the Dutch National Flag order.\n     * The Dutch National Flag problem partitions the array into three sections:\n     * - All elements less than the pivot are placed before it.\n     * - All elements greater than the pivot are placed after it.\n     * - All elements equal to the pivot are placed in the middle.\n     *\n     * @param array the array of integers to be sorted\n     * @param pivot the pivot element\n     */\n    public static void main(String[] args) {\n        int[] array = {2, 2, 1, 1, 0, 0, 2, 1, 0};\n        int pivot = 1;\n\n        dutchNationalFlagSort(array, pivot);\n\n        System.out.println(\"Sorted Array: \" + Arrays.toString(array));\n    }\n    \n    public static void dutchNationalFlagSort(int[] array, int pivot) {\n        int low = 0; // Pointer for elements less than the pivot\n        int mid = 0; // Pointer for elements equal to the pivot\n        int high = array.length - 1; // Pointer for elements greater than the pivot\n\n        while (mid <= high) {\n            if (array[mid] < pivot) { // Current element is less than the pivot\n                swap(array, low, mid); // Swap current element with element at the low index\n                low++; // Increment low pointer\n                mid++; // Increment mid pointer\n            } else if (array[mid] > pivot) { // Current element is greater than the pivot\n                swap(array, mid, high); // Swap current element with element at the high index\n                high--; // Decrement high pointer\n            } else { // Current element is equal to the pivot\n                mid++; // Increment mid pointer\n            }\n        }\n    }\n\n    /**\n     * Swaps two elements in an array.\n     *\n     * @param array the array\n     * @param i     the index of the first element\n     * @param j     the index of the second element\n     */\n    private static void swap(int[] array, int i, int j) {\n        int temp = array[i];\n        array[i] = array[j];\n        array[j] = temp;\n    }\n}\n\n"
  },
  {
    "path": "sorting/dnf.js",
    "content": "/*\n    Dutch National Flag Problem\n\n    Given an array containing only 0s, 1s, and 2s, sort the array in a single traversal.\n\n    Sample Input: [0, 2, 1, 2, 0]\n    Sample Output: [0, 0, 1, 2, 2]\n\n    Approach:\n    - We can use three pointers, low, mid, and high, to divide the array into three regions:\n      1. 0s region: elements before the low pointer (excluding low) are 0s\n      2. 1s region: elements between the low and mid pointers (excluding mid) are 1s\n      3. 2s region: elements after the high pointer (excluding high) are 2s\n    - Initialize low and mid pointers to the start of the array (0 index) and high pointer to the end of the array (array.length - 1).\n    - Iterate while the mid pointer is less than or equal to the high pointer:\n      - If the current element at mid is 0, swap it with the element at low and increment both low and mid pointers.\n      - If the current element at mid is 1, it is already in the correct region, so we just increment the mid pointer.\n      - If the current element at mid is 2, swap it with the element at high and decrement the high pointer.\n    - Repeat the above steps until the mid pointer crosses the high pointer.\n    - At the end, the array will be sorted in place.\n\n    Time Complexity: O(n), where n is the length of the array.\n    Space Complexity: O(1), no additional space is used.\n\n    Further Reading: https://en.wikipedia.org/wiki/Dutch_national_flag_problem\n*/\n\nfunction dutchNationalFlagProblem(arr) {\n  let low = 0;\n  let mid = 0;\n  let high = arr.length - 1;\n\n  while (mid <= high) {\n    if (arr[mid] === 0) {\n      // Swap current element at mid with element at low\n      [arr[mid], arr[low]] = [arr[low], arr[mid]];\n      // Increment both low and mid pointers\n      low++;\n      mid++;\n    } else if (arr[mid] === 1) {\n      // Move to the next element in the 1s region\n      mid++;\n    } else {\n      // Swap current element at mid with element at high\n      [arr[mid], arr[high]] = [arr[high], arr[mid]];\n      // Decrement the high pointer\n      high--;\n    }\n  }\n\n  return arr;\n}\n\n// Test the function\nconst input = [0, 2, 1, 2, 0];\nconst output = dutchNationalFlagProblem(input);\nconsole.log(output);\n"
  },
  {
    "path": "sorting/dnf.py",
    "content": "# Approach Explanation:\n# The code implements the Dutch National Flag problem, which is a sorting problem where we need to sort an array consisting of 0s, 1s, and 2s in ascending order. The approach used is called the \"Three Pointers\" approach.\n\n# We initialize three pointers, low, mid, and high, which represent the boundaries of three sections in the array:\n\n# All elements before low are 0s (left section).\n# All elements between low and mid are 1s (middle section).\n# All elements after high are 2s (right section).\n# We iterate through the array using the mid pointer:\n\n# If the element at mid is 0, we swap it with the element at low and increment both low and mid pointers.\n# If the element at mid is 1, we increment the mid pointer.\n# If the element at mid is 2, we swap it with the element at high and decrement the high pointer.\n# By doing this, we move all the 0s to the left section, 1s to the middle section, and 2s to the right section, effectively sorting the array.\n\n# Time Complexity: O(n), where n is the length of the input array.\n# Space Complexity: O(1) (constant space), as we are sorting the array in-place\n\n# Sample Input:\n# arr = [2, 0, 1, 2, 1, 0]\n\n# Sample Output:\n# Input Array: [2, 0, 1, 2, 1, 0]\n# Output Array: [0, 0, 1, 1, 2, 2]\n\n\ndef dutch_national_flag_problem(arr):\n    # Initialize variables for the three pointers\n    low = 0\n    mid = 0\n    high = len(arr) - 1\n\n    # Loop through the array until mid and high pointers meet\n    while mid <= high:\n        if arr[mid] == 0:\n            # Swap the element at mid with the element at low\n            arr[mid], arr[low] = arr[low], arr[mid]\n            # Move the low and mid pointers to the right\n            low += 1\n            mid += 1\n        elif arr[mid] == 1:\n            # Increment the mid pointer\n            mid += 1\n        else:\n            # Swap the element at mid with the element at high\n            arr[mid], arr[high] = arr[high], arr[mid]\n            # Move the high pointer to the left\n            high -= 1\n\n    return arr\n\n\n# Test the function\narr = [2, 0, 1, 2, 1, 0]\nresult = dutch_national_flag_problem(arr)\nprint(\"Input Array:\", arr)\nprint(\"Output Array:\", result)"
  },
  {
    "path": "sorting/heap_sort.cpp",
    "content": "/*\nHeap sort is a sorting technique based on comparison based on binary heap data.\nSimilar to sorting, it finds the largest number first and then puts the largest number last.\n\n\nThis sorting algorithm uses a tree structure called the stack, where the stack is a kind of binary tree. \nA binary decision tree in which the value of the root of a tree is less than or equal to the value of one of its roots is called a min-heap. \nA decision binary tree is called maximum heap when the value of the root of a tree is greater than or equal to the value of one of its trees. \nIn this post, we'll learn more about C++ Stack Sorting.\n\nWorking of heap sort in C++\nTo sort any list into a logical order following steps are followed:-\n\nConvert the list into a heap.\nNow convert this heap into a max heap.\nAs the heap is converted to max heap largest element in the list is stored in the root of the heap, replace it with the last item of the heap.\nNow delete this node and reduce the size of the heap by 1.\nFollow these steps until the list is sorted.  \n*/\n\n#include<iostream>\nusing namespace std;\nvoid heapify(int arr[], int n, int i){\n    int largest = i;\n    int l = 2*i + 1;\n    int r = 2*i + 2;\n \n    //If left child is larger than root\n    if (l < n && arr[l] > arr[largest])\n        largest = l;\n    //If right child largest \n    if (r < n && arr[r] > arr[largest])\n        largest = r;\n  //If root is nor largest\n    if (largest != i){\n        swap(arr[i], arr[largest]);\n      //Recursively heapifying the sub-tree\n        heapify(arr, n, largest);\n    }\n}\n\nvoid heapSort(int arr[], int n){\n    for (int i = n / 2 - 1; i >= 0; i--)\n        heapify(arr, n, i);\n  //One by one extract an element from heap\n    for (int i=n-1; i>=0; i--){\n        //Moving current root to end\n        swap(arr[0], arr[i]);\n      //Calling max heapify on the reduced heap\n        heapify(arr, i, 0);\n    }\n}\n //Function to print array\nvoid display(int arr[], int n){\n    for (int i = 0; i < n; i++){\n        cout << arr[i] << \"\\t\";\n    }\n    cout << \"\\n\";\n}\nint main(){\n    int arr[] = {1, 14, 3, 7, 0};\n    int n = sizeof(arr)/sizeof(arr[0]);\n    cout << \"Unsorted array  \\n\";\n    display(arr, n);\n    heapSort(arr, n);\n cout << \"Sorted array  \\n\";\n    display(arr, n);\n}\n\n/*Time Complexcity\nBest\nO(nlog n)\n\nAverage\nO(nlog n)\n\nWorst\nO(nlog n)\n*/\n"
  },
  {
    "path": "sorting/heap_sort.java",
    "content": "/*Since the tree satisfies Max-Heap property, then the largest item is stored at the root node.\n\nSwap: Remove the root element and put at the end of the array (nth position) Put the last item of the tree (heap) at the vacant place.\n\nRemove: Reduce the size of the heap by 1.\n\nHeapify: Heapify the root element again so that we have the highest element at root.\n\nThe process is repeated until all the items of the list are sorted.*/\n\n// Heap Sort in Java language\n  \npublic class heap_sort {\n  \n    public void sort(int arr[]) {\n      int n = arr.length;\n  \n      // Build max heap\n      for (int i = n / 2 - 1; i >= 0; i--) {\n        heapify(arr, n, i);\n      }\n  \n      // Heap sort\n      for (int i = n - 1; i >= 0; i--) {\n        int temp = arr[0];\n        arr[0] = arr[i];\n        arr[i] = temp;\n  \n        // Heapify root element\n        heapify(arr, i, 0);\n      }\n    }\n  \n    void heapify(int arr[], int n, int i) {\n      // Find largest among root, left child and right child\n      int largest = i;\n      int l = 2 * i + 1;\n      int r = 2 * i + 2;\n  \n      if (l < n && arr[l] > arr[largest])\n        largest = l;\n  \n      if (r < n && arr[r] > arr[largest])\n        largest = r;\n  \n      // Swap and continue heapifying if root is not largest\n      if (largest != i) {\n        int swap = arr[i];\n        arr[i] = arr[largest];\n        arr[largest] = swap;\n  \n        heapify(arr, n, largest);\n      }\n    }\n  \n    // Function to print an array\n    static void printArray(int arr[]) {\n      int n = arr.length;\n      for (int i = 0; i < n; ++i)\n        System.out.print(arr[i] + \" \");\n      System.out.println();\n    }\n  \n    // Driver code\n    public static void main(String args[]) {\n      int arr[] = { 1, 12, 9, 5, 6, 10 };\n  \n      heap_sort hs = new heap_sort();\n      hs.sort(arr);\n  \n      System.out.println(\"Sorted array is\");\n      printArray(arr);\n    }\n  }\n"
  },
  {
    "path": "sorting/heap_sort.js",
    "content": "/**\nHeap Sort is a sorting algorithm that works by building a binary heap out of the input array and then repeatedly extracting the maximum element and restoring the heap property. The time complexity of Heap Sort is O(n log n) in the worst, average, and best cases, making it an efficient algorithm for sorting large data sets. The space complexity of the implementation is O(1) because the algorithm sorts the input array in place and does not use any additional data structures other than a few variables used for index tracking and swapping. Therefore, the space used by the algorithm does not depend on the size of the input array.\n*/\n\n/**\n * The heapSort function takes an array as input and returns a sorted array using the Heap Sort algorithm. The function first builds a max heap from the input array using the buildMaxHeap function. It then repeatedly extracts the maximum element from the heap and restores the heap property using the siftDown function\n * @param {Array} array The array to be sorted.\n * @returns {Array} The sorted array.\n * time complexity is O(n log n) because it calls buildMaxHeap function once and then the siftDown function n times in the worst case, where n is the length of the input array.\n */\n function heapSort(array) {\n    // Build a max heap from the input array\n    buildMaxHeap(array);\n  \n    // Extract the max element from the heap and restore the heap property\n    for (let i = array.length - 1; i > 0; i--) {\n      // Move the root element to the end of the array\n      swap(array, 0, i);\n  \n      // Restore the heap property by sifting down the root element\n      siftDown(array, 0, i);\n    }\n  \n    return array;\n  }\n  \n  /**\n   * The buildMaxHeap function takes an array as input and transforms it into a max heap by calling siftDown on each non-leaf node in the tree.\n   * @param {Array} array The array to be transformed into a max heap.\n   * time complexity is O(n) because it calls the siftDown function on each non-leaf node in the tree\n   */\n  function buildMaxHeap(array) {\n    const startIndex = Math.floor((array.length - 1) / 2);\n  \n    for (let i = startIndex; i >= 0; i--) {\n      siftDown(array, i, array.length);\n    }\n  }\n  \n  /**\n   * The siftDown function takes an array, an index, and an endIndex as input. It sifts down the element at the given index in the heap until it reaches its correct position.\n   * @param {Array} array The array representing the heap.\n   * @param {number} index The index of the element to be sifted down.\n   * @param {number} endIndex The index at which to stop sifting down.\n   * time complexity is O(log n) because it repeatedly swaps the element at the given index with its child elements until it reaches its correct position in the heap.\n   */\n  function siftDown(array, index, endIndex) {\n    let childIndex1 = index * 2 + 1;\n    while (childIndex1 < endIndex) {\n      const childIndex2 = index * 2 + 2 < endIndex ? index * 2 + 2 : null;\n      const swapIndex =\n        childIndex2 !== null && array[childIndex2] > array[childIndex1]\n          ? childIndex2\n          : childIndex1;\n  \n      if (array[swapIndex] > array[index]) {\n        swap(array, index, swapIndex);\n        index = swapIndex;\n        childIndex1 = index * 2 + 1;\n      } else {\n        return;\n      }\n    }\n  }\n  \n  /**\n   * The swap function takes an array and two indices as input and swaps the elements at those indices. It is used in the heapSort function to move the root element of the heap to the end of the array during each iteration of the main loop. This function is also used within the siftDown function to swap the parent element with its child element when restoring the heap property.\n   * @param {Array} array The array containing the elements to be swapped.\n   * @param {number} i The index of the first element.\n   * @param {number} j The index of the second element.\n   */\n  function swap(array, i, j) {\n    const temp = array[i];\n    array[i] = array[j];\n    array[j] = temp;\n  }\n  "
  },
  {
    "path": "sorting/heap_sort.py",
    "content": "  \n'''\n    Heap sort is a sorting algorithm that works by transforming an unsorted list into a heap data structure, \n    which is a binary tree where each parent node is greater than or equal to its children if any.\n    then it repeatedly extracts the maximum element from the heap and puts it into its correct sorted position until the whole list is sorted.\n\n    Sample_input : [5,16,8,14,20,1,26]\n    Sample_output : [1,5,8,14,16,20,26]\n\n    Here's how the algorithm works:\n\n    The heap_sort function takes an unsorted list arr as input.\n    It starts by building the initial heap by calling the heapify function on each parent node in the tree. \n    It does this by iterating over the parent nodes in reverse order starting from the last parent node,\n    and calling heapify on each of them. This builds a heap where each parent node is greater than or equal to its children.\n    It then repeatedly extracts the maximum element from the heap and puts it into its correct sorted position. \n    It does this by swapping the maximum element which is always at the root of the heap with the last element in the heap, \n    and then calling heapify on the root node to restore the heap property.\n    Finally, it returns the sorted list.\n\n  '''\ndef heap_sort(arr):\n    # Build the initial heap\n    n = len(arr)\n    for i in range(n // 2 - 1, -1, -1):\n        heapify(arr, n, i)\n    \n    # Extract the maximum element repeatedly\n    for i in range(n - 1, 0, -1):\n        arr[0], arr[i] = arr[i], arr[0] # Swap\n        heapify(arr, i, 0)\n    \n    return arr\n\ndef heapify(arr, n, i):\n    largest = i\n    left = 2 * i + 1\n    right = 2 * i + 2\n    \n    # Check if left child is larger than root\n    if left < n and arr[left] > arr[largest]:\n        largest = left\n    \n    # Check if right child is larger than root\n    if right < n and arr[right] > arr[largest]:\n        largest = right\n    \n    # Swap if necessary and heapify the affected subtree\n    if largest != i:\n        arr[i], arr[largest] = arr[largest], arr[i]\n        heapify(arr, n, largest)\n"
  },
  {
    "path": "sorting/insertion_sort.cpp",
    "content": "/*\n    Insertion sort is a simple sorting algorithm that builds the final sorted array one item at a time. \n    It starts with the second element of the array, compares it with the first element, and swaps them \n    if necessary. It then continues to the third element, compares it with the first and second elements, \n    and swaps it into the correct position. This process continues until the last element is compared and \n    sorted into its correct position in the sorted array.\n\n    At each iteration, the algorithm assumes that the subarray to the left of the current element is already \n    sorted, and it searches for the correct position of the current element within that subarray by comparing \n    it to each element from right to left until it finds the correct position. Once it finds the correct \n    position, it shifts all the larger elements to the right to make space for the current element and \n    inserts it in its correct position.\n\n    Insertion sort has an average-case time complexity of O(n^2) but can perform better than other O(n^2) \n    algorithms, such as bubble sort or selection sort, in certain cases. It is also an efficient algorithm \n    for small data sets or partially sorted data sets.\n\t\n    In this implementation, we define a function called InsertionSort that takes an array of integers and sorts\n\tit in ascending order using the Insertion Sort algorithm.\n\n\tThe algorithm works by iterating over the array from the second element to the end.\n\n\tFor each element, it compares it with the previous elements in the array and inserts it in the correct position.\n\n\tThe current variable holds the value of the current element being compared.\n\n\tThe j variable holds the index of the previous element being compared.\n\n\tThe loop compares the current value with the previous values in the array and shifts the values to the right to make space for the current value.\n\n\tOnce the correct position is found, the current value is inserted into the array.\n\n\tFinally, the sorted array is returned. In the main function, we define an array of integers, sort it using the InsertionSort function, and print the sorted array.\n\n\tSample input: [0, 2, 1,-1, 10, 3, 4]\n\tOutput: [-1 0 1 2 3 4 10]\n*/\n\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\n\n// InsertionSort is a function that takes an array of integers and sorts it in\n// ascending order using the Insertion Sort algorithm.\nvoid insertionSort(vector<int>& arr) {\n    int n = arr.size();\n    for(int i=1; i<n; i++) { // i starts from 1 as we assume 1st element is already sorted\n        int key = arr[i]; // assign key with current element which needs to be compared and sorted\n        int j = i-1; // set the index j to previous element\n        \n        /* Move elements of arr[0..i-1], that are greater than key, to one position ahead \n        of their current position */\n        while(j>=0 && arr[j]>key) {\n            arr[j+1] = arr[j];\n            j--;\n        }\n        arr[j+1] = key; // insert the key at its sorted position\n    }\n}\n\nint main() {\n    vector<int> arr = {3, 5, 1, 4, 2};\n    insertionSort(arr);\n\n    cout << \"Sorted Array: \";\n    for(int num: arr) {\n        cout << num << \" \";\n    }\n    cout << endl;\n    return 0;\n}\n"
  },
  {
    "path": "sorting/insertion_sort.go",
    "content": "/*\n    Insertion sort is a simple sorting algorithm that builds the final sorted array one item at a time. \n    It starts with the second element of the array, compares it with the first element, and swaps them \n    if necessary. It then continues to the third element, compares it with the first and second elements, \n    and swaps it into the correct position. This process continues until the last element is compared and \n    sorted into its correct position in the sorted array.\n\n    At each iteration, the algorithm assumes that the subarray to the left of the current element is already \n    sorted, and it searches for the correct position of the current element within that subarray by comparing \n    it to each element from right to left until it finds the correct position. Once it finds the correct \n    position, it shifts all the larger elements to the right to make space for the current element and \n    inserts it in its correct position.\n\n    Insertion sort has an average-case time complexity of O(n^2) but can perform better than other O(n^2) \n    algorithms, such as bubble sort or selection sort, in certain cases. It is also an efficient algorithm \n    for small data sets or partially sorted data sets.\n    \n\tIn this implementation, we define a function called InsertionSort that takes an array of integers and sorts\n\tit in ascending order using the Insertion Sort algorithm.\n\n\tThe algorithm works by iterating over the array from the second element to the end.\n\n\tFor each element, it compares it with the previous elements in the array and inserts it in the correct position.\n\n\tThe current variable holds the value of the current element being compared.\n\n\tThe j variable holds the index of the previous element being compared.\n\n\tThe loop compares the current value with the previous values in the array and shifts the values to the right to make space for the current value.\n\n\tOnce the correct position is found, the current value is inserted into the array.\n\n\tFinally, the sorted array is returned. In the main function, we define an array of integers, sort it using the InsertionSort function, and print the sorted array.\n\n\tSample input: [0, 2, 1,-1, 10, 3, 4]\n\tOutput: [-1 0 1 2 3 4 10]\n*/\n\npackage main\n\nimport \"fmt\"\n\n// InsertionSort is a function that takes an array of integers and sorts it in\n// ascending order using the Insertion Sort algorithm.\nfunc InsertionSort(arr []int) []int {\n    // Iterate over the array from the second element to the end\n    for i := 1; i < len(arr); i++ {\n        // Set the current value and the previous index\n        current := arr[i]\n        j := i - 1\n\n        // Compare the current value with the previous values in the array\n        for j >= 0 && arr[j] > current {\n            // Shift the values to the right to make space for the current value\n            arr[j+1] = arr[j]\n            j--\n        }\n\n        // Insert the current value in the correct position\n        arr[j+1] = current\n    }\n\n    // Return the sorted array\n    return arr\n}\n\nfunc main() {\n    arr := []int{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5}\n    sortedArr := InsertionSort(arr)\n    fmt.Println(sortedArr)\n}\n"
  },
  {
    "path": "sorting/insertion_sort.java",
    "content": "/*\n    Insertion sort is a simple sorting algorithm that builds the final sorted array one item at a time. \n    It starts with the second element of the array, compares it with the first element, and swaps them \n    if necessary. It then continues to the third element, compares it with the first and second elements, \n    and swaps it into the correct position. This process continues until the last element is compared and \n    sorted into its correct position in the sorted array.\n\n    At each iteration, the algorithm assumes that the subarray to the left of the current element is already \n    sorted, and it searches for the correct position of the current element within that subarray by comparing \n    it to each element from right to left until it finds the correct position. Once it finds the correct \n    position, it shifts all the larger elements to the right to make space for the current element and \n    inserts it in its correct position.\n\n    Insertion sort has an average-case time complexity of O(n^2) but can perform better than other O(n^2) \n    algorithms, such as bubble sort or selection sort, in certain cases. It is also an efficient algorithm \n    for small data sets or partially sorted data sets.\n    \n\tIn this implementation, we define a function called InsertionSort that takes an array of integers and sorts\n\tit in ascending order using the Insertion Sort algorithm.\n\n\tThe algorithm works by iterating over the array from the second element to the end.\n\n\tFor each element, it compares it with the previous elements in the array and inserts it in the correct position.\n\n\tThe current variable holds the value of the current element being compared.\n\n\tThe j variable holds the index of the previous element being compared.\n\n\tThe loop compares the current value with the previous values in the array and shifts the values to the right to make space for the current value.\n\n\tOnce the correct position is found, the current value is inserted into the array.\n\n\tFinally, the sorted array is returned. In the main function, we define an array of integers, sort it using the InsertionSort function, and print the sorted array.\n\n\tSample input: [0, 2, 1,-1, 10, 3, 4]\n\tOutput: [-1 0 1 2 3 4 10]\n*/\n\n// InsertionSort is a function that takes an array of integers and sorts it in\n// ascending order using the Insertion Sort algorithm.\npublic class InsertionSort {\n    public static void insertionSort(int[] arr) {\n        int n = arr.length;\n        for (int i = 1; i < n; ++i) {\n            int key = arr[i];\n            int j = i - 1;\n\n            /* Move elements of arr[0..i-1], that are greater than key, to one\n            position ahead of their current position */\n            while (j >= 0 && arr[j] > key) {\n                arr[j + 1] = arr[j];\n                j = j - 1;\n            }\n            arr[j + 1] = key;\n        }\n    }\n\n    public static void main(String[] args) {\n        int[] arr = { 12, 11, 13, 5, 6 };\n        insertionSort(arr);\n        System.out.println(Arrays.toString(arr));\n    }\n}\n"
  },
  {
    "path": "sorting/insertion_sort.js",
    "content": "/*\n    Insertion sort is a simple sorting algorithm that builds the final sorted array one item at a time. \n    It starts with the second element of the array, compares it with the first element, and swaps them \n    if necessary. It then continues to the third element, compares it with the first and second elements, \n    and swaps it into the correct position. This process continues until the last element is compared and \n    sorted into its correct position in the sorted array.\n\n    At each iteration, the algorithm assumes that the subarray to the left of the current element is already \n    sorted, and it searches for the correct position of the current element within that subarray by comparing \n    it to each element from right to left until it finds the correct position. Once it finds the correct \n    position, it shifts all the larger elements to the right to make space for the current element and \n    inserts it in its correct position.\n\n    Insertion sort has an average-case time complexity of O(n^2) but can perform better than other O(n^2) \n    algorithms, such as bubble sort or selection sort, in certain cases. It is also an efficient algorithm \n    for small data sets or partially sorted data sets.\n    \n\tIn this implementation, we define a function called InsertionSort that takes an array of integers and sorts\n\tit in ascending order using the Insertion Sort algorithm.\n\n\tThe algorithm works by iterating over the array from the second element to the end.\n\n\tFor each element, it compares it with the previous elements in the array and inserts it in the correct position.\n\n\tThe current variable holds the value of the current element being compared.\n\n\tThe j variable holds the index of the previous element being compared.\n\n\tThe loop compares the current value with the previous values in the array and shifts the values to the right to make space for the current value.\n\n\tOnce the correct position is found, the current value is inserted into the array.\n\n\tFinally, the sorted array is returned. In the main function, we define an array of integers, sort it using the InsertionSort function, and print the sorted array.\n\n\tSample input: [0, 2, 1,-1, 10, 3, 4]\n\tOutput: [-1 0 1 2 3 4 10]\n*/\n\n/**\n * Perform insertion sort on an array of integers in non-decreasing order.\n * @param {number[]} arr - The input array to sort.\n * @returns {number[]} The sorted array in non-decreasing order.\n */\nfunction insertionSort(arr) {\n  // Loop through each element of the array, starting with the second.\n  for (let i = 1; i < arr.length; i++) {\n    // Save the current element to be inserted later.\n    let current = arr[i];\n    // Loop through the sorted portion of the array backwards.\n    for (let j = i - 1; j >= 0 && arr[j] > current; j--) {\n      // Shift each element that is greater than the current element up one position.\n      arr[j + 1] = arr[j];\n    }\n    // Insert the current element in its proper place.\n    arr[j + 1] = current;\n  }\n  // Return the sorted array.\n  return arr;\n}\n\nconst inputArr = [4, 5, 67, 56, 3, 35, 45];\nconsole.log(insertionSort(inputArr));\n"
  },
  {
    "path": "sorting/insertion_sort.py",
    "content": "\"\"\"\n    Insertion sort is a simple sorting algorithm that builds the final sorted array one item at a time. \n    It starts with the second element of the array, compares it with the first element, and swaps them \n    if necessary. It then continues to the third element, compares it with the first and second elements, \n    and swaps it into the correct position. This process continues until the last element is compared and \n    sorted into its correct position in the sorted array.\n\n    At each iteration, the algorithm assumes that the subarray to the left of the current element is already \n    sorted, and it searches for the correct position of the current element within that subarray by comparing \n    it to each element from right to left until it finds the correct position. Once it finds the correct \n    position, it shifts all the larger elements to the right to make space for the current element and \n    inserts it in its correct position.\n\n    Insertion sort has an average-case time complexity of O(n^2) but can perform better than other O(n^2) \n    algorithms, such as bubble sort or selection sort, in certain cases. It is also an efficient algorithm \n    for small data sets or partially sorted data sets.\n    \n\tIn this implementation, we define a function called InsertionSort that takes an array of integers and sorts\n\tit in ascending order using the Insertion Sort algorithm.\n\n\tThe algorithm works by iterating over the array from the second element to the end.\n\n\tFor each element, it compares it with the previous elements in the array and inserts it in the correct position.\n\n\tThe current variable holds the value of the current element being compared.\n\n\tThe j variable holds the index of the previous element being compared.\n\n\tThe loop compares the current value with the previous values in the array and shifts the values to the right to make space for the current value.\n\n\tOnce the correct position is found, the current value is inserted into the array.\n\n\tFinally, the sorted array is returned. In the main function, we define an array of integers, sort it using the InsertionSort function, and print the sorted array.\n\n\tSample input: [0, 2, 1,-1, 10, 3, 4]\n\tOutput: [-1 0 1 2 3 4 10]\n\"\"\"\n\ndef insertion_sort(arr):\n    \"\"\"\n        Sorts an array in ascending order using the insertion sort algorithm.\n        \n        @param arr: list of integers to be sorted\n        @return: sorted list of integers\n    \"\"\"\n    # iterate through every element of the array\n    for i in range(1, len(arr)):\n        # store the current element and its index\n        current = arr[i]\n        j = i - 1\n        \n        # move all elements greater than the current element to the right\n        while j >= 0 and arr[j] > current:\n            arr[j + 1] = arr[j]\n            j -= 1\n        \n        # insert the current element in its correct position\n        arr[j + 1] = current\n    \n    # return the sorted array\n    return arr\n"
  },
  {
    "path": "sorting/merge_sort.cpp",
    "content": "// Merge Sort\n/*\n\tHere's how the merge sort algorithm works:\n\n\t1. It divides the input array into two halves, recursively sorts them, and then merges the sorted halves.\n\t2. To merge two sorted sub-arrays, we need to create a temporary array and then compare the elements of the two sub-arrays, \n\t   one by one, and add the smaller element to the temporary array.\n\t3. After we have exhausted one of the sub-arrays, we simply copy the remaining elements of the other sub-array to the temporary array.\n\t4. Finally, we copy the elements of the temporary array back to the original array.\n\n\tThe time complexity of merge sort is O(n log n), where n is the number of elements in the array. \n\tThe space complexity is O(n), because we create a temporary array of size n during the merging process.\n*/\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\nvoid merge(vector<int>& arr, int start, int mid, int end) {\n    vector<int> temp(end - start + 1);\n    int i = start, j = mid + 1, k = 0;\n\n    while (i <= mid && j <= end) {\n        if (arr[i] <= arr[j]) {\n            temp[k] = arr[i];\n            ++i;\n        } else {\n            temp[k] = arr[j];\n            ++j;\n        }\n        ++k;\n    }\n\n    while (i <= mid) {\n        temp[k] = arr[i];\n        ++i;\n        ++k;\n    }\n\n    while (j <= end) {\n        temp[k] = arr[j];\n        ++j;\n        ++k;\n    }\n\n    for (int l = start; l <= end; ++l) {\n        arr[l] = temp[l - start];\n    }\n}\n\nvoid merge_sort(vector<int>& arr, int start, int end) {\n    if (start < end) {\n        int mid = (start + end) / 2;\n        merge_sort(arr, start, mid);\n        merge_sort(arr, mid + 1, end);\n        merge(arr, start, mid, end);\n    }\n}\n\nint main() {\n    vector<int> arr = {5, 2, 8, 1, 9, 4};\n    merge_sort(arr, 0, arr.size() - 1);\n    for (int num : arr) {\n        cout << num << \" \";\n    }\n    cout << endl;\n    return 0;\n}"
  },
  {
    "path": "sorting/merge_sort.go",
    "content": "// Merge Sort\n/*\n\tThe MergeSort function is the main function that takes an integer array as input and sorts it using the Merge Sort algorithm.\n\n\tIn the MergeSort function, if the length of the input array is only one element, it is already sorted, so we return it as is.\n\tOtherwise, we find the middle point of the array and split it into two halves. We then recursively call the MergeSort\n\tfunction on the left half and the right half of the array. Finally, we merge the two sorted halves using the merge function.\n\n\tThe merge function takes two sorted arrays as input and merges them into one sorted array. We initialize a new array to hold\n\tthe merged result and three index variables for the left, right, and result arrays. We then iterate over the left and right\n\tarrays and compare their elements. We add the smaller element to the result array and move the corresponding index variable.\n\tFinally, we append the remaining elements of the left or right array to the result array and return it.\n\n\tThe time complexity of Merge Sort is O(n*log n), where n is the number of elements in the array,\n\tand the space complexity is O(n) due to the use of the temporary arrays during the merging phase.\n\n*/\npackage main\n\nimport \"fmt\"\n\n// MergeSort is the main function that takes an integer array as input\n// and sorts it using the Merge Sort algorithm.\nfunc MergeSort(arr []int) []int {\n\t// If the array has only one element, return it.\n\tif len(arr) == 1 {\n\t\treturn arr\n\t}\n\n\t// Find the middle point to divide the array into two halves.\n\tmid := len(arr) / 2\n\n\t// Split the array into two halves.\n\tleft := arr[:mid]\n\tright := arr[mid:]\n\n\t// Recursively sort the left half of the array.\n\tleft = MergeSort(left)\n\n\t// Recursively sort the right half of the array.\n\tright = MergeSort(right)\n\n\t// Merge the two sorted halves.\n\treturn merge(left, right)\n}\n\n// Merge is a helper function that takes two sorted arrays and merges them into one sorted array.\nfunc merge(left, right []int) []int {\n\t// Initialize a new array to hold the merged result.\n\tresult := make([]int, len(left)+len(right))\n\n\t// Initialize the index variables for the left, right, and result arrays.\n\ti := 0 // Index for left array\n\tj := 0 // Index for right array\n\tk := 0 // Index for result array\n\n\t// Iterate over the left and right arrays and compare their elements.\n\t// Add the smaller element to the result array and move the corresponding index variable.\n\tfor i < len(left) && j < len(right) {\n\t\tif left[i] < right[j] {\n\t\t\tresult[k] = left[i]\n\t\t\ti++\n\t\t} else {\n\t\t\tresult[k] = right[j]\n\t\t\tj++\n\t\t}\n\t\tk++\n\t}\n\n\t// Append the remaining elements of the left or right array to the result array.\n\tfor i < len(left) {\n\t\tresult[k] = left[i]\n\t\ti++\n\t\tk++\n\t}\n\n\tfor j < len(right) {\n\t\tresult[k] = right[j]\n\t\tj++\n\t\tk++\n\t}\n\n\t// Return the merged and sorted result array.\n\treturn result\n}\n\nfunc main() {\n\t// Example usage\n\tarr := []int{3, 2, 1, 5, 4}\n\tfmt.Println(\"Unsorted array:\", arr)\n\tarr = MergeSort(arr)\n\tfmt.Println(\"Sorted array:\", arr)\n}"
  },
  {
    "path": "sorting/merge_sort.java",
    "content": "// In computer science, merge sort (also commonly spelled as mergesort) is an efficient, general-purpose,\n// and comparison-based sorting algorithm. Most implementations produce a stable sort,\n// which means that the order of equal elements is the same in the input and output.\n// Merge sort is a divide-and-conquer algorithm that was invented by John von Neumann in 1945.\n// A detailed description and analysis of bottom-up merge sort appeared in a report by Goldstine and von Neumann as early as 1948.\n// Conceptually, a merge sort works as follows:\n\n// Divide the unsorted list into n sublists, each containing one element (a list of one element is considered sorted).\n// Repeatedly merge sublists to produce new sorted sublists until there is only one sublist remaining. This will be the sorted list\n// Source(https://en.wikipedia.org/wiki/Merge_sort)\n\n// Approach: Divide by finding the number mid of the position midway between left and right. Do this step the same\n// way we found the midpoint in binary search\n// Conquer by recursively sorting the subarrays in each of the two subproblems created by the divide step.\n// That is, recursively sort the subarray Arr[left. . mid] and recursively sort the subarray Arr[mid + 1. . right].\n// Combine by merging the two sorted subarrays back into the single sorted subarray Arr[left. . right].\n\nclass MergeSort {\n\n     void mergeSort(int ar[], int p,int r){\n        if(p<r){\n            int mid = (p+(r-1))/2;\n            mergeSort(ar,p,mid);\n            mergeSort(ar,mid+1,r);\n            merge(ar,p,mid,r);\n        }\n    }\n\n    void merge(int ar[],int p,int mid,int r){\n\n        int n1 = mid-p+1;\n        int n2 = r - mid;\n        int l1[] = new int[n1];\n        int l2[] = new int[n2];\n        for(int i=0;i<n1;i++){\n            l1[i] = ar[i + p];\n        }\n        for(int j=0;j<n2;j++){\n            l2[j] = ar[mid + 1 + j];\n        }\n        int i=0, j=0;\n        int k=p;\n        while(i<n1 && j < n2){\n            if(l1[i] <= l2[j]){\n                ar[k] = l1[i];\n                i++; k++;\n            } else {\n                ar[k] = l2[j];\n                j++; k++;\n            }\n        }\n        while(i<n1){\n            ar[k] = l1[i];\n            i++; k++;\n        }\n        while(j < n2){\n            ar[k] = l2[j];\n            j++; k++;\n        }\n    }\n    public static void main(String args[]) {\n        int ar[] = {4, 6, 2, 1, 3, 5};\n        MergeSort ms = new MergeSort();\n        ms.mergeSort(ar,0,ar.length-1);\n        for(int x : ar){\n            System.out.print(x + \" \");\n        }\n    }\n}\n"
  },
  {
    "path": "sorting/merge_sort.js",
    "content": "// Merge Sort\n/*\n\tHere's how the merge sort algorithm works:\n\n\t1. It divides the input array into two halves, recursively sorts them, and then merges the sorted halves.\n\t2. To merge two sorted sub-arrays, we need to create a temporary array and then compare the elements of the two sub-arrays, \n\t   one by one, and add the smaller element to the temporary array.\n\t3. After we have exhausted one of the sub-arrays, we simply copy the remaining elements of the other sub-array to the temporary array.\n\t4. Finally, we copy the elements of the temporary array back to the original array.\n\n\tThe time complexity of merge sort is O(n log n), where n is the number of elements in the array. \n\tThe space complexity is O(n), because we create a temporary array of size n during the merging process.\n*/\n\n/**\n * Merge sort algorithm to sort an array of integers in ascending order.\n * @param {Array} arr - The array of integers to be sorted\n * @return {Array} - The sorted array\n */\nfunction mergeSort(arr) {\n  if (arr.length <= 1) {\n    return arr;\n  }\n\n  // Split the array into two halves\n  const middleIndex = Math.floor(arr.length / 2);\n  const leftArr = arr.slice(0, middleIndex);\n  const rightArr = arr.slice(middleIndex);\n\n  // Recursively call mergeSort on each half\n  const sortedLeftArr = mergeSort(leftArr);\n  const sortedRightArr = mergeSort(rightArr);\n\n  // Merge the two sorted halves into a single sorted array\n  return merge(sortedLeftArr, sortedRightArr);\n}\n\n/**\n * Merge two sorted arrays into a single sorted array\n * @param {Array} leftArr - The first sorted array\n * @param {Array} rightArr - The second sorted array\n * @return {Array} - The merged sorted array\n */\nfunction merge(leftArr, rightArr) {\n  let i = 0;\n  let j = 0;\n  const mergedArr = [];\n\n  // Compare the elements of the two arrays and add the smallest to the merged array\n  while (i < leftArr.length && j < rightArr.length) {\n    if (leftArr[i] <= rightArr[j]) {\n      mergedArr.push(leftArr[i]);\n      i++;\n    } else {\n      mergedArr.push(rightArr[j]);\n      j++;\n    }\n  }\n\n  // Add any remaining elements from the left or right array to the merged array\n  while (i < leftArr.length) {\n    mergedArr.push(leftArr[i]);\n    i++;\n  }\n\n  while (j < rightArr.length) {\n    mergedArr.push(rightArr[j]);\n    j++;\n  }\n\n  return mergedArr;\n}\n\nconst unsortedArr = [5, 2, 9, 1, 5, 6];\nconst sortedArr = mergeSort(unsortedArr);\n\nconsole.log(sortedArr); // Output: [1, 2, 5, 5, 6, 9]\n"
  },
  {
    "path": "sorting/merge_sort.py",
    "content": "#  In computer science, merge sort (also commonly spelled as mergesort) is an efficient, general-purpose,\n#  and comparison-based sorting algorithm. Most implementations produce a stable sort,\n#  which means that the order of equal elements is the same in the input and output.\n#  Merge sort is a divide-and-conquer algorithm that was invented by John von Neumann in 1945.\n#  A detailed description and analysis of bottom-up merge sort appeared in a report by Goldstine and von Neumann as early as 1948.\n#  Conceptually, a merge sort works as follows:\n\n#  Divide the unsorted list into n sublists, each containing one element (a list of one element is considered sorted).\n#  Repeatedly merge sublists to produce new sorted sublists until there is only one sublist remaining. This will be the sorted list\n#  Source(https://en.wikipedia.org/wiki/Merge_sort)\n\n#  Approach: Divide by finding the number mid of the position midway between left and right. Do this step the same\n#  way we found the midpoint in binary search\n#  Conquer by recursively sorting the subarrays in each of the two subproblems created by the divide step.\n#  That is, recursively sort the subarray Arr[left. . mid] and recursively sort the subarray Arr[mid + 1. . right].\n#  Combine by merging the two sorted subarrays back into the single sorted subarray Arr[left. . right].\n\ndef main():\n    # test for merge sort\n    a_lst = [3,2,-1,9,0,7,-3,-4,10,9]\n    merge_sort(a_lst, 0, 9)\n    print(a_lst)\n\ndef merge_sort(a_lst: list[int], start: int, n: int) -> None:\n    if start < n:\n        mid: int = (start + n) // 2\n        merge_sort(a_lst, start, mid)\n        merge_sort(a_lst, mid + 1, n)\n        merge(a_lst, start, mid, n)\n\n\ndef merge(a_lst: list[int], start: int, mid: int, n: int):\n    n_left: int = mid - start + 1 # length of left array\n    n_right: int = n - mid      # length of right array\n    \n    left: list[int] = [0] * n_left         # Initialize left and right arrays\n    right: list[int] = [0] * n_right\n\n    for idx in range(n_left):   # Fill left and right arrays\n        left[idx] = a_lst[start + idx]\n    for idx in range(n_right):\n        right[idx] = a_lst[mid + idx + 1]\n\n    # Fill the orignal array with the smallest element from either\n    # left or right until left or right is empty\n    l_idx: int = 0\n    r_idx: int = 0\n    idx: int = start\n    while l_idx < len(left) and r_idx < len(right):\n        if left[l_idx] < right[r_idx]:\n            a_lst[idx] = left[l_idx]\n            l_idx += 1\n        else:\n            a_lst[idx] = right[r_idx]\n            r_idx += 1\n        idx += 1\n\n    # Fill the original array with the rest of the elements\n    # from the half array that is nonempty\n\n    while l_idx < len(left):\n        a_lst[idx] = left[l_idx]\n        l_idx += 1\n        idx += 1\n    while r_idx < len(right):\n        a_lst[idx] = right[r_idx]\n        r_idx += 1\n        idx += 1\n\nif __name__ == \"__main__\":\n    main()  \n"
  },
  {
    "path": "sorting/quick_sort.cpp",
    "content": "#include<bits/stdc++.h>\nusing namespace std;\n\nint Hoare_partition(int arr[],int l,int h)\n{\n\t// Here p is the Index of pivot element\n\t// Here We consider first element as pivot, \n\t// But if we Want to consider any element as pivot then just swap that index with the first element\n\tint pivot=arr[l];\n    int i=l-1,j=h+1;\n    \n    while(true)\n    {\n    \tdo{\n    \t\ti++;\n\t\t}while(arr[i]<pivot);\n\t\t\n\t\tdo{\n\t\t\tj--;\n\t\t}while(arr[j]>pivot);\n\t\t\n\t\tif(i>=j)\n\t\t  return j;\n\t\tswap(arr[i],arr[j]);\n\t}\n}\n\nvoid Quick_Sort(int arr[],int low,int high)\n{\n\t\n    if(low<high)// If there is single element then no need to sort it\n    {\n    \tint p=Hoare_partition(arr,low,high);\n    \t\n    \tQuick_Sort(arr,low,p);\n    \tQuick_Sort(arr,p+1,high);\n\t}\n}\n\nvoid Display(int arr[],int n)\n{\n    for(int i=0;i<n;i++)\n      cout<<arr[i]<<\" \";\n    cout<<endl;\n}\nint main()\n{\n    int arr[]={150,400,300,20,-1,100,60,9,100,300};\n    int n=sizeof(arr)/sizeof(arr[0]);\n    Quick_Sort(arr,0,n-1);\n    Display(arr,n);\n    return 0;\n}"
  },
  {
    "path": "sorting/quick_sort.go",
    "content": "// Quicksort\n/*\n\tIn this implementation, we use the standard algorithm for quicksort:\n\n\t1. Choose a pivot element (we choose the middle element in this case)\n\t2. Partition the array into two subarrays: elements less than the pivot go to the left subarray,\n\t   and elements greater than the pivot go to the right subarray\n\t3. Recursively sort the left and right subarrays using the same algorithm\n\n\tThe quicksort function takes three arguments: the array to be sorted, the left index of the subarray,\n\tand the right index of the subarray. We start by choosing the pivot element (in this case, the middle element),\n\tinitializing two pointers to the left and right ends of the subarray, and then partitioning the array into two\n\tsubarrays by moving elements less than the pivot to the left subarray and elements greater than the pivot to\n\tthe right subarray. We repeat this process until the subarrays have length 0 or 1.\n\n\tOnce the subarrays are partitioned, we recursively sort the left and right subarrays using the quicksort function.\n\tWe use two conditional statements to check if the left or right subarray has length greater than 1 and call quicksort\n\ton that subarray if it does. Finally, the sorted array is returned.\n*/\npackage main\n\nimport \"fmt\"\n\n// Quicksort function to sort an array of integers in ascending order\nfunc quicksort(arr []int, left, right int) {\n\t// Choose pivot element (middle element in this case)\n\tpivot := arr[(left+right)/2]\n\n\t// Initialize two pointers to left and right ends of subarray\n\ti := left\n\tj := right\n\n\t// Partition array into two subarrays: elements less than pivot\n\t// go to the left subarray and elements greater than pivot go to\n\t// the right subarray. Repeat until subarrays have length 0 or 1.\n\tfor i <= j {\n\t\t// Find first element in left subarray greater than pivot\n\t\tfor arr[i] < pivot {\n\t\t\ti++\n\t\t}\n\t\t// Find first element in right subarray less than pivot\n\t\tfor arr[j] > pivot {\n\t\t\tj--\n\t\t}\n\t\t// Swap elements at i and j if they are in the wrong subarray\n\t\tif i <= j {\n\t\t\tarr[i], arr[j] = arr[j], arr[i]\n\t\t\ti++\n\t\t\tj--\n\t\t}\n\t}\n\n\t// Recursively sort left and right subarrays\n\tif left < j {\n\t\tquicksort(arr, left, j)\n\t}\n\tif i < right {\n\t\tquicksort(arr, i, right)\n\t}\n}\n\nfunc main() {\n\t// Example usage\n\tarr := []int{3, 7, 1, 8, 4, 2, 9, 5, 6}\n\tquicksort(arr, 0, len(arr)-1)\n\tfmt.Println(arr) // Output: [1 2 3 4 5 6 7 8 9]\n}\n"
  },
  {
    "path": "sorting/quick_sort.java",
    "content": "/*\nQuick sort:\nQuicksort picks an element as pivot, and then it partitions the given array around the picked pivot element.\nIn quick sort, a large array is divided into two arrays in which one holds values that are smaller than the\nspecified value (Pivot), and another array holds the values that are greater than the pivot.\n\nAfter that, left and right sub-arrays are also partitioned using the same approach.\nIt will continue until the single element remains in the sub-array.\n\nFor more information:\n--> https://www.geeksforgeeks.org/java-program-for-quicksort/\n--> https://www.javatpoint.com/quick-sort\n */\n\npackage sorting;\n\npublic class quick_sort {\n    public static void main(String[] args) {\n        int[] a = {15,4,3,7,13,2,6,7,3,2,1,5,6,3,2};\n        int n = a.length;\n\n        sort(a, 0, n-1);\n\n        System.out.println(\"sorted array\");\n        for (int j : a) System.out.print(j + \" \");\n        System.out.println();\n    }\n\n    /**\n     *\n     * @param a to be sorted\n     * @param start starting index\n     * @param end ending index\n     */\n    private static void sort(int[] a, int start, int end){\n        if (start < end) {\n            int p = partition(a, start, end);\n            sort(a, start, p-1);\n            sort(a, p+1, end);\n        }\n    }\n\n    /**\n     * smaller elements to the left of the pivot, greater elements to the right\n     * @param a to be sorted\n     * @param start starting index\n     * @param end ending index\n     * @return index\n     */\n    private static int partition(int[] a, int start, int end) {\n        int pivot = a[end];\n        int i = (start-1); // index of smaller element\n        for (int j=start; j<end; j++) {\n            if (a[j] <= pivot) {\n                i++;\n                int temp = a[i];\n                a[i] = a[j];\n                a[j] = temp;\n            }\n        }\n        int temp = a[i+1];\n        a[i+1] = a[end];\n        a[end] = temp;\n\n        return i+1;\n    }\n\n}\n\n"
  },
  {
    "path": "sorting/quick_sort.js",
    "content": "/*\n    The quickSort function implements the quicksort algorithm, which takes an array arr and the indices low and high \n    of the subarray to be sorted. If low is less than high, the array is partitioned around a pivot element using the \n    partition function, and the subarrays on either side of the pivot are recursively sorted using the quickSort function.\n\n    The partition function takes an array arr and the indices low and high of the subarray to be partitioned. \n    It chooses the rightmost element as the pivot, initializes the index of the smaller element to low - 1, and \n    iterates over the subarray. If an element arr[j] is less than the pivot, it is swapped with the element arr[i+1] \n    and the index i is incremented. Finally, the pivot element is swapped with the element arr[i+1], \n    and the index i+1 is returned as the index of the pivot.\n\n    The time complexity of quicksort is O(n log n) on average, and O(n^2) in the worst case. The space complexity \n    is O(log n) on average, and O(n) in the worst case.\n*/\n/**\n * This function implements the quicksort algorithm to sort an array in place.\n * @param {Array} arr - The array to be sorted.\n * @param {number} low - The lower index of the subarray to be sorted.\n * @param {number} high - The higher index of the subarray to be sorted.\n * @returns {void}\n */\nfunction quickSort(arr, low, high) {\n  if (low < high) {\n    // Partition the array around the pivot element and get the index of the pivot.\n    const pivotIndex = partition(arr, low, high);\n\n    // Recursively sort the subarrays on either side of the pivot.\n    quickSort(arr, low, pivotIndex - 1);\n    quickSort(arr, pivotIndex + 1, high);\n  }\n}\n\n/**\n * This function partitions an array around a pivot element and returns the index of the pivot.\n * @param {Array} arr - The array to be partitioned.\n * @param {number} low - The lower index of the subarray to be partitioned.\n * @param {number} high - The higher index of the subarray to be partitioned.\n * @returns {number} - The index of the pivot element.\n */\nfunction partition(arr, low, high) {\n  // Choose the rightmost element as the pivot.\n  const pivot = arr[high];\n\n  // Initialize the index of the smaller element.\n  let i = low - 1;\n\n  // Iterate over the subarray and partition it.\n  for (let j = low; j < high; j++) {\n    if (arr[j] < pivot) {\n      i++;\n\n      // Swap arr[i] and arr[j].\n      const temp = arr[i];\n      arr[i] = arr[j];\n      arr[j] = temp;\n    }\n  }\n\n  // Swap arr[i+1] and arr[high] (or the pivot).\n  const temp = arr[i + 1];\n  arr[i + 1] = arr[high];\n  arr[high] = temp;\n\n  // Return the index of the pivot.\n  return i + 1;\n}\n"
  },
  {
    "path": "sorting/quick_sort.py",
    "content": "'''\n    The basic idea of quicksort is to divide the input array into two partitions, with one partition \n    consisting of all elements smaller than a chosen pivot element, and the other partition consisting \n    of all elements larger than the pivot. This process is then recursively applied to the smaller\n    partitions until the entire array is sorted.\n\n    In this implementation, we first handle the base case where the array has 0 or 1 element, \n    which is already sorted. Then, we choose the pivot element as the middle element of the array, \n    and partition the array into two subarrays based on whether each element is less than or greater \n    than the pivot. We then recursively sort the left and right subarrays using the same quicksort \n    function, and concatenate the results together along with the pivot element to get the final sorted array.\n'''\n''' Time and Space complexity\n    The time complexity of quicksort is O(n log n) on average and O(n^2) in the worst case. \n    The space complexity of quicksort is O(log n) on average and O(n) in the worst case. \n    The worst case occurs when the partition process divides the input array into two subarrays of unequal size.\n'''\ndef quicksort(arr):\n    \"\"\"\n    Sorts an array using quicksort algorithm.\n\n    Args:\n    arr: A list of comparable elements to be sorted.\n\n    Returns:\n    The sorted list.\n    \"\"\"\n    # Base case: an empty or single-element list is already sorted.\n    if len(arr) < 2:\n        return arr\n\n    # Choose a pivot element and partition the list around it.\n    pivot_index = len(arr) // 2\n    pivot = arr[pivot_index]\n    left, right = [], []\n    for i in range(len(arr)):\n        if i != pivot_index:\n            if arr[i] < pivot:\n                left.append(arr[i])\n            else:\n                right.append(arr[i])\n\n    # Recursively sort the left and right partitions.\n    return quicksort(left) + [pivot] + quicksort(right)\n"
  },
  {
    "path": "sorting/radix_sort.cpp",
    "content": "/*\n                            Radix Sort\n1. Identify the maximum number: Find the maximum number in the given list. This is necessary to determine the number of digits we need to consider \nduring the sorting process.\n\n2. Perform counting sort for each digit position: Starting from the least significant digit (rightmost digit), perform the following steps for each \ndigit position, moving towards the most significant digit (leftmost digit):\na. Create a count array: Create a count array of size 10 (to represent digits 0-9) and initialize all elements to 0. This count array will be used \nto store the frequency of each digit at the current position.\nb. Count the frequencies: Iterate through the list of numbers and count the frequency of each digit at the current position. For example, if the \ncurrent digit position is the units place, count the frequency of each digit from 0 to 9.\nc. Update the count array: Modify the count array such that each element represents the cumulative count of digits up to that index. This step \nensures that the count array contains the correct positions for each digit in the sorted order.\nd. Distribute the numbers: Iterate through the list of numbers again, and for each number, find its digit at the current position. Use the count \narray to determine the correct position of the number in the output array and place it there. After placing the number, decrement the count for \nthat digit in the count array.\ne. Collect the numbers: After distributing all the numbers, collect them back into the original array. The array will now be partially sorted \nbased on the current digit position.\n\n3. Repeat the counting sort for the next digit position: After collecting the numbers based on the least significant digit, move to the next digit \nposition (towards the left) and repeat steps 2a to 2e for that digit. Continue this process until all the digits have been processed, from the least \nsignificant digit to the most significant digit.\n\n4. Final sorted list: After completing the counting sort process for all digit positions, you will have a fully sorted list of numbers.\n\nHere's an example to illustrate the process:\n\nSample Input: [170, 45, 75, 90, 802, 24, 2, 66]\nMaximum number: 802\n\n# 1. First iteration (Least significant digit - rightmost digit):\n    # Create the count array: [0, 2, 1, 1, 0, 1, 0, 0, 0, 1]\n    # Update the count array: [0, 2, 3, 4, 4, 5, 5, 5, 5, 6]\n    # Distribute the numbers: [802, 2, 24, 45, 75, 170, 90, 66]\n    # Collect the numbers: [802, 2, 24, 45, 75, 170, 90, 66]\n\n# 2. Second iteration (Next least significant digit):\n    # Create the count array: [1, 2, 1, 1, 1, 1, 0, 0, 0, 1]\n    # Update the count array: [1, 3, 4, 5, 6, 7, 7, 7, 7, 8]\n    # Distribute the numbers: [802, 2, 24, 45, 66, 75, 90, 170]\n    # Collect the numbers: [802, 2, 24, 45, 66, 75, 90, 170]\n\n# 3. Third iteration (Most significant digit):\n    # Create the count array: [1, 1, 1, 1, 2, 2, 1, 0, 0, 0]\n    # Update the count array: [1, 2, 3, 4, 6, 8, 9, 9, 9, 9]\n    # Distribute the numbers: [2, 24, 45, 66, 75, 90, 170, 802]\n    # Collect the numbers: [2, 24, 45, 66, 75, 90, 170, 802]\n\n# The final sorted list is [2, 24, 45, 66, 75, 90, 170, 802].\n\n# Radix sort using counting sort works by sorting the numbers digit by digit, from the least significant digit to the most significant digit. \n# The counting sort process distributes and collects the numbers based on each digit position, ensuring that the numbers are correctly ordered at \n# each iteration. By repeating this process for each digit, the algorithm achieves a fully sorted list without the need for explicit element comparisons.\n\n*/\n\n#include <iostream>\nusing namespace std;\n\n// Function to get maximum value in arr[]\nint getMax(int arr[], int n)\n{\n\tint mx = arr[0];\n\tfor (int i = 1; i < n; i++)\n\t\tif (arr[i] > mx)\n\t\t\tmx = arr[i];\n\treturn mx;\n}\n\n// A function to do counting sort of arr[] according to\n// the digit represented by exp.\nvoid countSort(int arr[], int n, int exp)\n{\n\tint output[n]; // output array\n\tint i, count[10] = { 0 };\n\n\t// Store count of occurrences in count[]\n\tfor (i = 0; i < n; i++)\n\t\tcount[(arr[i] / exp) % 10]++;\n\n\t// Change count[i] so that count[i] now contains actual\n\t// position of this digit in output[]\n\tfor (i = 1; i < 10; i++)\n\t\tcount[i] += count[i - 1];\n\n\t// Build the output array\n\tfor (i = n - 1; i >= 0; i--) {\n\t\toutput[count[(arr[i] / exp) % 10] - 1] = arr[i];\n\t\tcount[(arr[i] / exp) % 10]--;\n\t}\n\n\t// Copy the output array to arr[], so that arr[] now\n\t// contains sorted numbers according to current digit\n\tfor (i = 0; i < n; i++)\n\t\tarr[i] = output[i];\n}\n\n// The main function to that sorts arr[] of size n using\n// Radix Sort\nvoid radixsort(int arr[], int n)\n{\n\t// Find the maximum number to know number of digits\n\tint m = getMax(arr, n);\n\n\t// Do counting sort for every digit. Note that instead\n\t// of passing digit number, exp is passed. exp is 10^i\n\t// where i is current digit number\n\tfor (int exp = 1; m / exp > 0; exp *= 10)\n\t\tcountSort(arr, n, exp);\n}\n\n// Function to print an array\nvoid print(int arr[], int n)\n{\n\tfor (int i = 0; i < n; i++)\n\t\tcout << arr[i] << \" \";\n}\n\n\nint main()\n{\n\tint arr[] = { 170, 45, 75, 90, 802, 24, 2, 66 };\n\tint n = sizeof(arr) / sizeof(arr[0]);\n\t\n\t// Function Call\n\tradixsort(arr, n);\n\tprint(arr, n);\n\treturn 0;\n}\n\n// Time Compexity -> O((n+k)*d)\n// Space Complexity -> O(n+k)"
  },
  {
    "path": "sorting/radix_sort.go",
    "content": "/*\nRadix sort is a sorting Algorithm that sorts elements by grouping them based on their individual digits or by the position of their digits. \nIt is a linear time sorting Algorithm that has a time complexity of O(nk).\n\nUsing the Least Significant Bit\nIn this method, we will write a go language program to implement the radix sort by using the least significant bit. LSD sorts the elements \nfrom right to left by comparing their individual digits.\n\nAlgorithm\nStep 1 − First, we need to import the fmt package. Then create a function named radixSortMSD() to sort the array.\n\nStep 2 − Inside the function create a new array. Use the for loop to iterate over the array and store the maximum element of the array in a variable.\n\nStep 3 − Now, initialize a count array to keep track of the number of elements that have a particular digit.\n\nStep 4 − Traverse the array and increment the count for the corresponding digit for each element.\n\nStep 5 − Modify the count array to store the actual position of each element in the Output array. Copy the elements from the input array to the \nOutput array in the order specified by the count array.\n\nStep 6 − Update the input array to the sorted Output array and return the sorted array.\n\nStep 7 − Start the main() function. Inside the main() initialize an array and store value to it. further, call the radixSort() function and pass \nthe array as an argument to the function.\n\nStep 8 − Store the result obtained by the function in a variable and print It on the screen.\n\nThe code implements Radix Sort using the LSD (Least Significant Digit) approach to sort an array of integers. It iterates through each digit from \nthe least significant to the most significant, performing counting sort for each digit. Counting sort is used to determine the correct positions \nof elements based on the current digit. The sorted elements are then copied back to the original array. This process is repeated until all digits \nhave been processed, resulting in a sorted array.\n*/\n\npackage main\n\nimport \"fmt\"\n\n// radixSortLSD performs Radix Sort using the LSD (Least Significant Digit) algorithm\nfunc radixSortLSD(arr []int) []int {\n   // Find the maximum element in the array\n   max := arr[0]\n   for i := 1; i < len(arr); i++ {\n      if arr[i] > max {\n         max = arr[i]\n      }\n   }\n   \n   exp := 1\n   // Perform counting sort for each digit from LSD to MSD\n   for max/exp > 0 {\n      // Create a count array to store the frequency of each digit (0-9)\n      count := make([]int, 10)\n      \n      // Count the frequency of each digit at the current exponent\n      for i := 0; i < len(arr); i++ {\n         count[(arr[i]/exp)%10]++\n      }\n      \n      // Calculate the cumulative sum of count array to determine the correct positions of each digit\n      for i := 1; i < 10; i++ {\n         count[i] += count[i-1]\n      }\n      \n      // Create an output array to store the sorted elements based on the current digit\n      output := make([]int, len(arr))\n      \n      // Build the output array by placing each element in its correct position based on the current digit\n      for i := len(arr) - 1; i >= 0; i-- {\n         output[count[(arr[i]/exp)%10]-1] = arr[i]\n         count[(arr[i]/exp)%10]--\n      }\n      \n      // Copy the sorted elements from the output array back to the original array\n      for i := 0; i < len(arr); i++ {\n         arr[i] = output[i]\n      }\n      \n      // Move to the next digit by multiplying the exponent by 10\n      exp *= 10\n   }\n   \n   // Return the sorted array\n   return arr\n}\n\nfunc main() {\n   // Test the radixSortLSD function\n   arr := []int{15, 31, 42, 20, 9}\n   fmt.Println(\"The unsorted array is:\", arr)\n   result := radixSortLSD(arr)\n   fmt.Println(\"The sorted array is:\", result)\n}\n\n// Output\n// The unsorted array is: [15 31 42 20 9]\n// The sorted array is: [9 15 20 31 42]\n\n// Time Compexity -> O((n+k)*d)\n// Space Complexity -> O(n+k)"
  },
  {
    "path": "sorting/radix_sort.java",
    "content": "/*\n                            Radix Sort\n1. Identify the maximum number: Find the maximum number in the given list. This is necessary to determine the number of digits we need to consider \nduring the sorting process.\n\n2. Perform counting sort for each digit position: Starting from the least significant digit (rightmost digit), perform the following steps for each \ndigit position, moving towards the most significant digit (leftmost digit):\na. Create a count array: Create a count array of size 10 (to represent digits 0-9) and initialize all elements to 0. This count array will be used \nto store the frequency of each digit at the current position.\nb. Count the frequencies: Iterate through the list of numbers and count the frequency of each digit at the current position. For example, if the \ncurrent digit position is the units place, count the frequency of each digit from 0 to 9.\nc. Update the count array: Modify the count array such that each element represents the cumulative count of digits up to that index. This step \nensures that the count array contains the correct positions for each digit in the sorted order.\nd. Distribute the numbers: Iterate through the list of numbers again, and for each number, find its digit at the current position. Use the count \narray to determine the correct position of the number in the output array and place it there. After placing the number, decrement the count for \nthat digit in the count array.\ne. Collect the numbers: After distributing all the numbers, collect them back into the original array. The array will now be partially sorted \nbased on the current digit position.\n\n3. Repeat the counting sort for the next digit position: After collecting the numbers based on the least significant digit, move to the next digit \nposition (towards the left) and repeat steps 2a to 2e for that digit. Continue this process until all the digits have been processed, from the least \nsignificant digit to the most significant digit.\n\n4. Final sorted list: After completing the counting sort process for all digit positions, you will have a fully sorted list of numbers.\n\nHere's an example to illustrate the process:\n\nSample Input: [170, 45, 75, 90, 802, 24, 2, 66]\nMaximum number: 802\n\n# 1. First iteration (Least significant digit - rightmost digit):\n    # Create the count array: [0, 2, 1, 1, 0, 1, 0, 0, 0, 1]\n    # Update the count array: [0, 2, 3, 4, 4, 5, 5, 5, 5, 6]\n    # Distribute the numbers: [802, 2, 24, 45, 75, 170, 90, 66]\n    # Collect the numbers: [802, 2, 24, 45, 75, 170, 90, 66]\n\n# 2. Second iteration (Next least significant digit):\n    # Create the count array: [1, 2, 1, 1, 1, 1, 0, 0, 0, 1]\n    # Update the count array: [1, 3, 4, 5, 6, 7, 7, 7, 7, 8]\n    # Distribute the numbers: [802, 2, 24, 45, 66, 75, 90, 170]\n    # Collect the numbers: [802, 2, 24, 45, 66, 75, 90, 170]\n\n# 3. Third iteration (Most significant digit):\n    # Create the count array: [1, 1, 1, 1, 2, 2, 1, 0, 0, 0]\n    # Update the count array: [1, 2, 3, 4, 6, 8, 9, 9, 9, 9]\n    # Distribute the numbers: [2, 24, 45, 66, 75, 90, 170, 802]\n    # Collect the numbers: [2, 24, 45, 66, 75, 90, 170, 802]\n\n# The final sorted list is [2, 24, 45, 66, 75, 90, 170, 802].\n\n# Radix sort using counting sort works by sorting the numbers digit by digit, from the least significant digit to the most significant digit. \n# The counting sort process distributes and collects the numbers based on each digit position, ensuring that the numbers are correctly ordered at \n# each iteration. By repeating this process for each digit, the algorithm achieves a fully sorted list without the need for explicit element comparisons.\n\n*/\n\nimport java.io.*;\nimport java.util.*;\n\nclass Radix {\n\n\t// A utility function to get maximum value in arr[]\n\tstatic int getMax(int arr[], int n)\n\t{\n\t\tint mx = arr[0];\n\t\tfor (int i = 1; i < n; i++)\n\t\t\tif (arr[i] > mx)\n\t\t\t\tmx = arr[i];\n\t\treturn mx;\n\t}\n\n\t// A function to do counting sort of arr[] according to\n\t// the digit represented by exp.\n\tstatic void countSort(int arr[], int n, int exp)\n\t{\n\t\tint output[] = new int[n]; // output array\n\t\tint i;\n\t\tint count[] = new int[10];\n\t\tArrays.fill(count, 0);\n\n\t\t// Store count of occurrences in count[]\n\t\tfor (i = 0; i < n; i++)\n\t\t\tcount[(arr[i] / exp) % 10]++;\n\n\t\t// Change count[i] so that count[i] now contains\n\t\t// actual position of this digit in output[]\n\t\tfor (i = 1; i < 10; i++)\n\t\t\tcount[i] += count[i - 1];\n\n\t\t// Build the output array\n\t\tfor (i = n - 1; i >= 0; i--) {\n\t\t\toutput[count[(arr[i] / exp) % 10] - 1] = arr[i];\n\t\t\tcount[(arr[i] / exp) % 10]--;\n\t\t}\n\n\t\t// Copy the output array to arr[], so that arr[] now\n\t\t// contains sorted numbers according to current\n\t\t// digit\n\t\tfor (i = 0; i < n; i++)\n\t\t\tarr[i] = output[i];\n\t}\n\n\t// The main function to that sorts arr[] of\n\t// size n using Radix Sort\n\tstatic void radixsort(int arr[], int n)\n\t{\n\t\t// Find the maximum number to know number of digits\n\t\tint m = getMax(arr, n);\n\n\t\t// Do counting sort for every digit. Note that\n\t\t// instead of passing digit number, exp is passed.\n\t\t// exp is 10^i where i is current digit number\n\t\tfor (int exp = 1; m / exp > 0; exp *= 10)\n\t\t\tcountSort(arr, n, exp);\n\t}\n\n\t// A utility function to print an array\n\tstatic void print(int arr[], int n)\n\t{\n\t\tfor (int i = 0; i < n; i++)\n\t\t\tSystem.out.print(arr[i] + \" \");\n\t}\n\n\t// Main driver method\n\tpublic static void main(String[] args)\n\t{\n\t\tint arr[] = { 170, 45, 75, 90, 802, 24, 2, 66 };\n\t\tint n = arr.length;\n\n\t\t// Function Call\n\t\tradixsort(arr, n);\n\t\tprint(arr, n);\n\t}\n}\n\n// Time Compexity -> O((n+k)*d)\n// Space Complexity -> O(n+k)"
  },
  {
    "path": "sorting/radix_sort.js",
    "content": "/*\n                            Radix Sort\n1. Identify the maximum number: Find the maximum number in the given list. This is necessary to determine the number of digits we need to consider \nduring the sorting process.\n\n2. Perform counting sort for each digit position: Starting from the least significant digit (rightmost digit), perform the following steps for each \ndigit position, moving towards the most significant digit (leftmost digit):\na. Create a count array: Create a count array of size 10 (to represent digits 0-9) and initialize all elements to 0. This count array will be used \nto store the frequency of each digit at the current position.\nb. Count the frequencies: Iterate through the list of numbers and count the frequency of each digit at the current position. For example, if the \ncurrent digit position is the units place, count the frequency of each digit from 0 to 9.\nc. Update the count array: Modify the count array such that each element represents the cumulative count of digits up to that index. This step \nensures that the count array contains the correct positions for each digit in the sorted order.\nd. Distribute the numbers: Iterate through the list of numbers again, and for each number, find its digit at the current position. Use the count \narray to determine the correct position of the number in the output array and place it there. After placing the number, decrement the count for \nthat digit in the count array.\ne. Collect the numbers: After distributing all the numbers, collect them back into the original array. The array will now be partially sorted \nbased on the current digit position.\n\n3. Repeat the counting sort for the next digit position: After collecting the numbers based on the least significant digit, move to the next digit \nposition (towards the left) and repeat steps 2a to 2e for that digit. Continue this process until all the digits have been processed, from the least \nsignificant digit to the most significant digit.\n\n4. Final sorted list: After completing the counting sort process for all digit positions, you will have a fully sorted list of numbers.\n\nHere's an example to illustrate the process:\n\nSample Input: [170, 45, 75, 90, 802, 24, 2, 66]\nMaximum number: 802\n\n# 1. First iteration (Least significant digit - rightmost digit):\n    # Create the count array: [0, 2, 1, 1, 0, 1, 0, 0, 0, 1]\n    # Update the count array: [0, 2, 3, 4, 4, 5, 5, 5, 5, 6]\n    # Distribute the numbers: [802, 2, 24, 45, 75, 170, 90, 66]\n    # Collect the numbers: [802, 2, 24, 45, 75, 170, 90, 66]\n\n# 2. Second iteration (Next least significant digit):\n    # Create the count array: [1, 2, 1, 1, 1, 1, 0, 0, 0, 1]\n    # Update the count array: [1, 3, 4, 5, 6, 7, 7, 7, 7, 8]\n    # Distribute the numbers: [802, 2, 24, 45, 66, 75, 90, 170]\n    # Collect the numbers: [802, 2, 24, 45, 66, 75, 90, 170]\n\n# 3. Third iteration (Most significant digit):\n    # Create the count array: [1, 1, 1, 1, 2, 2, 1, 0, 0, 0]\n    # Update the count array: [1, 2, 3, 4, 6, 8, 9, 9, 9, 9]\n    # Distribute the numbers: [2, 24, 45, 66, 75, 90, 170, 802]\n    # Collect the numbers: [2, 24, 45, 66, 75, 90, 170, 802]\n\n# The final sorted list is [2, 24, 45, 66, 75, 90, 170, 802].\n\n# Radix sort using counting sort works by sorting the numbers digit by digit, from the least significant digit to the most significant digit. \n# The counting sort process distributes and collects the numbers based on each digit position, ensuring that the numbers are correctly ordered at \n# each iteration. By repeating this process for each digit, the algorithm achieves a fully sorted list without the need for explicit element comparisons.\n\n*/\n\n// A utility function to get maximum value in arr[]\nfunction getMax(arr,n)\n{\n    let mx = arr[0];\n        for (let i = 1; i < n; i++)\n            if (arr[i] > mx)\n                mx = arr[i];\n        return mx;\n}\n \n// A function to do counting sort of arr[] according to\n    // the digit represented by exp.\nfunction countSort(arr,n,exp)\n{\n    let output = new Array(n); // output array\n        let i;\n        let count = new Array(10);\n        for(let i=0;i<10;i++)\n            count[i]=0;\n  \n        // Store count of occurrences in count[]\n        for (i = 0; i < n; i++) {\n            let x = Math.floor(arr[i] / exp) % 10;\n            count[x]++;\n        }\n  \n        // Change count[i] so that count[i] now contains\n        // actual position of this digit in output[]\n        for (i = 1; i < 10; i++)\n            count[i] += count[i - 1];\n  \n        // Build the output array\n        for (i = n - 1; i >= 0; i--) {\n            output[count[x] - 1] = arr[i];\n            count[x]--;\n        }\n  \n        // Copy the output array to arr[], so that arr[] now\n        // contains sorted numbers according to current digit\n        for (i = 0; i < n; i++)\n            arr[i] = output[i];\n}\n \n// The main function to that sorts arr[] of size n using\n    // Radix Sort\nfunction radixsort(arr,n)\n{\n    // Find the maximum number to know number of digits\n        let m = getMax(arr, n);\n  \n        // Do counting sort for every digit. Note that\n        // instead of passing digit number, exp is passed.\n        // exp is 10^i where i is current digit number\n        for (let exp = 1; Math.floor(m / exp) > 0; exp *= 10)\n            countSort(arr, n, exp);\n}\n \n// A utility function to print an array\nfunction print(arr,n)\n{\n    for (let i = 0; i < n; i++)\n            document.write(arr[i] + \" \");\n}\n \n/*Driver Code*/\nlet arr=[170, 45, 75, 90, 802, 24, 2, 66];\nlet n = arr.length;\n \n// Function Call\nradixsort(arr, n);\nprint(arr, n);\n\n// Time Compexity -> O((n+k)*d)\n// Space Complexity -> O(n+k)"
  },
  {
    "path": "sorting/radix_sort.py",
    "content": "\n#                             Radix Sort\n# 1. Identify the maximum number: Find the maximum number in the given list. This is necessary to determine the number of digits we need to consider \n# during the sorting process.\n\n# 2. Perform counting sort for each digit position: Starting from the least significant digit (rightmost digit), perform the following steps for each \n# digit position, moving towards the most significant digit (leftmost digit):\n# a. Create a count array: Create a count array of size 10 (to represent digits 0-9) and initialize all elements to 0. This count array will be used \n# to store the frequency of each digit at the current position.\n# b. Count the frequencies: Iterate through the list of numbers and count the frequency of each digit at the current position. For example, if the \n# current digit position is the units place, count the frequency of each digit from 0 to 9.\n# c. Update the count array: Modify the count array such that each element represents the cumulative count of digits up to that index. This step \n# ensures that the count array contains the correct positions for each digit in the sorted order.\n# d. Distribute the numbers: Iterate through the list of numbers again, and for each number, find its digit at the current position. Use the count \n# array to determine the correct position of the number in the output array and place it there. After placing the number, decrement the count for \n# that digit in the count array.\n# e. Collect the numbers: After distributing all the numbers, collect them back into the original array. The array will now be partially sorted \n# based on the current digit position.\n\n# 3. Repeat the counting sort for the next digit position: After collecting the numbers based on the least significant digit, move to the next digit \n# position (towards the left) and repeat steps 2a to 2e for that digit. Continue this process until all the digits have been processed, from the least \n# significant digit to the most significant digit.\n\n# 4. Final sorted list: After completing the counting sort process for all digit positions, you will have a fully sorted list of numbers.\n\n# Here's an example to illustrate the process:\n\n# Sample Input: [170, 45, 75, 90, 802, 24, 2, 66]\n# Maximum number: 802\n\n# 1. First iteration (Least significant digit - rightmost digit):\n    # Create the count array: [0, 2, 1, 1, 0, 1, 0, 0, 0, 1]\n    # Update the count array: [0, 2, 3, 4, 4, 5, 5, 5, 5, 6]\n    # Distribute the numbers: [802, 2, 24, 45, 75, 170, 90, 66]\n    # Collect the numbers: [802, 2, 24, 45, 75, 170, 90, 66]\n\n# 2. Second iteration (Next least significant digit):\n    # Create the count array: [1, 2, 1, 1, 1, 1, 0, 0, 0, 1]\n    # Update the count array: [1, 3, 4, 5, 6, 7, 7, 7, 7, 8]\n    # Distribute the numbers: [802, 2, 24, 45, 66, 75, 90, 170]\n    # Collect the numbers: [802, 2, 24, 45, 66, 75, 90, 170]\n\n# 3. Third iteration (Most significant digit):\n    # Create the count array: [1, 1, 1, 1, 2, 2, 1, 0, 0, 0]\n    # Update the count array: [1, 2, 3, 4, 6, 8, 9, 9, 9, 9]\n    # Distribute the numbers: [2, 24, 45, 66, 75, 90, 170, 802]\n    # Collect the numbers: [2, 24, 45, 66, 75, 90, 170, 802]\n\n# The final sorted list is [2, 24, 45, 66, 75, 90, 170, 802].\n\n# Radix sort using counting sort works by sorting the numbers digit by digit, from the least significant digit to the most significant digit. \n# The counting sort process distributes and collects the numbers based on each digit position, ensuring that the numbers are correctly ordered at \n# each iteration. By repeating this process for each digit, the algorithm achieves a fully sorted list without the need for explicit element comparisons.\n\n# Method to do Radix Sort\ndef countingSort(arr, exp1):\n\n\tn = len(arr)\n\n\t# The output array elements that will have sorted arr\n\toutput = [0] * (n)\n\n\t# initialize count array as 0\n\tcount = [0] * (10)\n\n\t# Store count of occurrences in count[]\n\tfor i in range(0, n):\n\t\tindex = arr[i] // exp1\n\t\tcount[index % 10] += 1\n\n\t# Change count[i] so that count[i] now contains actual\n\t# position of this digit in output array\n\tfor i in range(1, 10):\n\t\tcount[i] += count[i - 1]\n\n\t# Build the output array\n\ti = n - 1\n\twhile i >= 0:\n\t\tindex = arr[i] // exp1\n\t\toutput[count[index % 10] - 1] = arr[i]\n\t\tcount[index % 10] -= 1\n\t\ti -= 1\n\n\t# Copying the output array to arr[],\n\t# so that arr now contains sorted numbers\n\ti = 0\n\tfor i in range(0, len(arr)):\n\t\tarr[i] = output[i]\n\n# Method to do Radix Sort\ndef radixSort(arr):\n\n\t# Find the maximum number to know number of digits\n\tmax1 = max(arr)\n\n\t# Do counting sort for every digit. Note that instead\n\t# of passing digit number, exp is passed. exp is 10^i\n\t# where i is current digit number\n\texp = 1\n\twhile max1 / exp >= 1:\n\t\tcountingSort(arr, exp)\n\t\texp *= 10\n\n\n# Driver code\narr = [170, 45, 75, 90, 802, 24, 2, 66]\n\n# Function Call\nradixSort(arr)\n\nfor i in range(len(arr)):\n\tprint(arr[i],end=\" \")\n\n# Time Compexity -> O((n+k)*d)\n# Space Complexity -> O(n+k)"
  },
  {
    "path": "sorting/selection_sort.cpp",
    "content": "/*\n\tSelection sort is a simple sorting algorithm that works by repeatedly finding the minimum element from an \n\tunsorted part of the array and putting it at the beginning of the array. \n    \n    In each iteration, the minimum element is found by comparing each element of the unsorted part of the array with the current minimum \n\telement, and if a smaller element is found, it becomes the new minimum element. \n    \n    Once the minimum element is found, it is swapped with the first element of the unsorted part of the array. \n\n\tThis process is repeated until the entire array is sorted. The main idea behind selection sort is to divide \n\tthe array into two parts: a sorted part and an unsorted part. \n    \n    Initially, the sorted part is empty, and the unsorted part is the entire array. In each iteration, the minimum element is selected from \n\tthe unsorted part and added to the end of the sorted part.\n\n\tThe time complexity of selection sort is O(n^2) in both the best and worst cases, where n is the number \n\tof elements in the array. This is because for each element in the array, it needs to compare it with \n\tevery other element to find the smallest one, which takes O(n) time. Since this process needs to be \n\trepeated for each element, the overall time complexity becomes O(n^2).\n\n\tThe space complexity of selection sort is O(1) because it does not require any extra space other than \n\tthe input array itself. It performs the sorting in place by swapping the elements within the array.\n*/\n// Sample Input : [2, 1, 9, 3, 5, 4, 0]\n// Output : [0 1 2 3 4 5 9]\n#include <iostream>\n#include <vector>\n\nusing namespace std;\n\n// Function to perform selection sort on a vector\nvoid selectionSort(vector<int>& arr) {\n    int n = arr.size();\n\n    // Iterate through the array\n    for (int i = 0; i < n - 1; i++) {\n        int minIdx = i;\n\n        // Find the index of the minimum element in the unsorted part of the array\n        for (int j = i + 1; j < n; j++) {\n            if (arr[j] < arr[minIdx]) {\n                minIdx = j;\n            }\n        }\n\n        // Swap the minimum element with the first element of the unsorted part of the array\n        swap(arr[i], arr[minIdx]);\n    }\n}\n\nint main() {\n    // Example usage\n    vector<int> arr = {64, 25, 12, 22, 11};\n    selectionSort(arr);\n    for (int i = 0; i < arr.size(); i++) {\n        cout << arr[i] << \" \";\n    }\n    return 0;\n}\n"
  },
  {
    "path": "sorting/selection_sort.go",
    "content": "/*\n\tSelection sort is a simple sorting algorithm that works by repeatedly finding the minimum element from an \n\tunsorted part of the array and putting it at the beginning of the array. \n    \n    In each iteration, the minimum element is found by comparing each element of the unsorted part of the array with the current minimum \n\telement, and if a smaller element is found, it becomes the new minimum element. \n    \n    Once the minimum element is found, it is swapped with the first element of the unsorted part of the array. \n\n\tThis process is repeated until the entire array is sorted. The main idea behind selection sort is to divide \n\tthe array into two parts: a sorted part and an unsorted part. \n    \n    Initially, the sorted part is empty, and the unsorted part is the entire array. In each iteration, the minimum element is selected from \n\tthe unsorted part and added to the end of the sorted part.\n\n\tThe time complexity of selection sort is O(n^2) in both the best and worst cases, where n is the number \n\tof elements in the array. This is because for each element in the array, it needs to compare it with \n\tevery other element to find the smallest one, which takes O(n) time. Since this process needs to be \n\trepeated for each element, the overall time complexity becomes O(n^2).\n\n\tThe space complexity of selection sort is O(1) because it does not require any extra space other than \n\tthe input array itself. It performs the sorting in place by swapping the elements within the array.\n*/\n// Sample Input : [2, 1, 9, 3, 5, 4, 0]\n// Output : [0 1 2 3 4 5 9]\npackage main\n\nimport \"fmt\"\n\n// selectionSort sorts an array of integers in ascending order\n// using the selection sort algorithm.\nfunc selectionSort(arr []int) {\n\t// Loop over the array from start to end\n\tfor i := 0; i < len(arr); i++ {\n\t\t// Assume the current index contains the minimum value\n\t\tminIdx := i\n\t\t// Loop over the rest of the array to find the minimum value\n\t\tfor j := i + 1; j < len(arr); j++ {\n\t\t\t// If a value is found that is smaller than the current minimum,\n\t\t\t// update the minimum index\n\t\t\tif arr[j] < arr[minIdx] {\n\t\t\t\tminIdx = j\n\t\t\t}\n\t\t}\n\t\t// Swap the minimum value with the current index\n\t\tarr[i], arr[minIdx] = arr[minIdx], arr[i]\n\t}\n}\n\nfunc main() {\n\t// Example usage\n\tarr := []int{5, 3, 6, 2, 10}\n\tfmt.Println(\"Before sorting:\", arr)\n\tselectionSort(arr)\n\tfmt.Println(\"After sorting:\", arr)\n}\n"
  },
  {
    "path": "sorting/selection_sort.java",
    "content": "/*\n\tSelection sort is a simple sorting algorithm that works by repeatedly finding the minimum element from an \n\tunsorted part of the array and putting it at the beginning of the array. \n    \n  In each iteration, the minimum element is found by comparing each element of the unsorted part of the array with the current minimum \n\telement, and if a smaller element is found, it becomes the new minimum element. \n    \n  Once the minimum element is found, it is swapped with the first element of the unsorted part of the array. \n\n\tThis process is repeated until the entire array is sorted. The main idea behind selection sort is to divide \n\tthe array into two parts: a sorted part and an unsorted part. \n    \n  Initially, the sorted part is empty, and the unsorted part is the entire array. In each iteration, the minimum element is selected from \n\tthe unsorted part and added to the end of the sorted part.\n\n\tThe time complexity of selection sort is O(n^2) in both the best and worst cases, where n is the number \n\tof elements in the array. This is because for each element in the array, it needs to compare it with \n\tevery other element to find the smallest one, which takes O(n) time. Since this process needs to be \n\trepeated for each element, the overall time complexity becomes O(n^2).\n\n\tThe space complexity of selection sort is O(1) because it does not require any extra space other than \n\tthe input array itself. It performs the sorting in place by swapping the elements within the array.\n*/\n// Sample Input : [2, 1, 9, 3, 5, 4, 0]\n// Output : [0 1 2 3 4 5 9]\n\n/**\n * Sorts an array of integers in ascending order using the Selection Sort algorithm.\n * \n * @param arr the array to be sorted\n * @return the sorted array\n */\npublic static int[] selectionSort(int[] arr) {\n    // iterate through the array\n    for (int i = 0; i < arr.length - 1; i++) {\n        int minIdx = i;\n        // find the index of the smallest element in the unsorted portion of the array\n        for (int j = i + 1; j < arr.length; j++) {\n            if (arr[j] < arr[minIdx]) {\n                minIdx = j;\n            }\n        }\n        // swap the smallest element with the first unsorted element\n        int temp = arr[minIdx];\n        arr[minIdx] = arr[i];\n        arr[i] = temp;\n    }\n    return arr;\n}\n"
  },
  {
    "path": "sorting/selection_sort.js",
    "content": "/*\n\tSelection sort is a simple sorting algorithm that works by repeatedly finding the minimum element from an \n\tunsorted part of the array and putting it at the beginning of the array. \n    \n  In each iteration, the minimum element is found by comparing each element of the unsorted part of the array with the current minimum \n\telement, and if a smaller element is found, it becomes the new minimum element. \n    \n  Once the minimum element is found, it is swapped with the first element of the unsorted part of the array. \n\n\tThis process is repeated until the entire array is sorted. The main idea behind selection sort is to divide \n\tthe array into two parts: a sorted part and an unsorted part. \n    \n  Initially, the sorted part is empty, and the unsorted part is the entire array. In each iteration, the minimum element is selected from \n\tthe unsorted part and added to the end of the sorted part.\n\n\tThe time complexity of selection sort is O(n^2) in both the best and worst cases, where n is the number \n\tof elements in the array. This is because for each element in the array, it needs to compare it with \n\tevery other element to find the smallest one, which takes O(n) time. Since this process needs to be \n\trepeated for each element, the overall time complexity becomes O(n^2).\n\n\tThe space complexity of selection sort is O(1) because it does not require any extra space other than \n\tthe input array itself. It performs the sorting in place by swapping the elements within the array.\n*/\n// Sample Input : [2, 1, 9, 3, 5, 4, 0]\n// Output : [0 1 2 3 4 5 9]\nconst inputArr = [4, 5, 67, 56, 3, 35, 45];\n/**\n * Sorts an array using selection sort algorithm.\n * @param {number[]} array - The array to be sorted.\n * @returns {number[]} - The sorted array.\n */\nfunction selectionSort(array) {\n  // Loop through the array from the start to the second last element\n  for (let i = 0; i < array.length - 1; i++) {\n    // Assume that the current element is the minimum\n    let minIndex = i;\n    // Loop through the rest of the array to find the minimum element\n    for (let j = i + 1; j < array.length; j++) {\n      if (array[j] < array[minIndex]) {\n        // If we find a smaller element, update the minimum index\n        minIndex = j;\n      }\n    }\n    // Swap the current element with the minimum element\n    let temp = array[i];\n    array[i] = array[minIndex];\n    array[minIndex] = temp;\n  }\n  // Return the sorted array\n  return array;\n}\n\nconsole.log(selectionSort(inputArr));\n"
  },
  {
    "path": "sorting/selection_sort.py",
    "content": "'''\n\tSelection sort is a simple sorting algorithm that works by repeatedly finding the minimum element from an \n\tunsorted part of the array and putting it at the beginning of the array. \n    \n    In each iteration, the minimum element is found by comparing each element of the unsorted part of the array with the current minimum \n\telement, and if a smaller element is found, it becomes the new minimum element. \n    \n    Once the minimum element is found, it is swapped with the first element of the unsorted part of the array. \n\n\tThis process is repeated until the entire array is sorted. The main idea behind selection sort is to divide \n\tthe array into two parts: a sorted part and an unsorted part. \n    \n    Initially, the sorted part is empty, and the unsorted part is the entire array. In each iteration, the minimum element is selected from \n\tthe unsorted part and added to the end of the sorted part.\n\n\tThe time complexity of selection sort is O(n^2) in both the best and worst cases, where n is the number \n\tof elements in the array. This is because for each element in the array, it needs to compare it with \n\tevery other element to find the smallest one, which takes O(n) time. Since this process needs to be \n\trepeated for each element, the overall time complexity becomes O(n^2).\n\n\tThe space complexity of selection sort is O(1) because it does not require any extra space other than \n\tthe input array itself. It performs the sorting in place by swapping the elements within the array.\n'''\n#  Sample Input : [2, 1, 9, 3, 5, 4, 0]\n#  Output : [0 1 2 3 4 5 9]\n\ndef selection_sort(arr):\n    \"\"\"\n    Sorts an array in ascending order using the selection sort algorithm.\n\n    Args:\n        arr (list): An array of integers.\n\n    Returns:\n        list: The sorted array in ascending order.\n    \"\"\"\n    # Loop through the array\n    for i in range(len(arr)):\n        # Find the minimum element in the unsorted portion of the array\n        min_idx = i\n        for j in range(i+1, len(arr)):\n            if arr[j] < arr[min_idx]:\n                min_idx = j\n        \n        # Swap the minimum element with the first element in the unsorted portion of the array\n        arr[i], arr[min_idx] = arr[min_idx], arr[i]\n    \n    return arr\n\ndata = [-2, 45, 0, 11, -9]\nsize = len(data)\nselection_sort(data, size)\nprint('Sorted Array in Ascending Order:')\nprint(data)"
  },
  {
    "path": "sorting/tim_sort.cpp",
    "content": "//Implementation of Tim Sort\n//Tim Sort makes use of insertionSort and Merge function of MergeSort\n//The basic idea is to divide the input array into blocks called as runs\n//The size of runs varies from 32 to 64, and perform insertion sort on the runs\n//Then, The runs(blocks) are merged to form the final sorted array\n//\n//Time Complexity of this algorithm in Best case is O(n),Average case is O(n*log(n))\n//Time Complexity in Worst case is O(n*log(n)).\n//This is a stable sorting algorithm\n//This algorithm uses Space of O(n)\n//This algorithm is used in languages like Java and Python for sorting.\n\n#include<bits/stdc++.h>\nusing namespace std;\nconst int run=32;\nvoid insertionSort(vector<int>&array,int l,int r)\n{\n\tfor(int i = l + 1; i <= r; i++){\n\t\tint temp = array[i];\n\t\tint j = i - 1;\n\t\twhile(j >= l and array[j] > temp) {\n\t\t\tarray[j + 1] = array[j];\n\t\t\tj--;\n\t\t}\n\t\tarray[j + 1] = temp;\n\t}\n}\nvoid merge(vector<int>&array,int l,int m,int r) {\n\tint len1 = m - l + 1, len2 = r - m;\n\tvector<int>left(len1), right(len2);\n\t\n\tfor(int i = 0; i < len1; i++){\n\t\tleft[i] = array[l + i];\n\t}\n\tfor(int i = 0; i < len2; i++){\n\t\tright[i] = array[m + 1 + i];\n\t}\n\n\tint i = 0, j = 0, k = l;\n\n\twhile(i < len1 and j < len2) {\n\t\tif(left[i] <= right[j])\n\t\t\tarray[k] = left[i++];\n\t\telse array[k] = right[j++];\n\t\tk++;\n\t}\n\n\twhile(i<len1) {\n\t\tarray[k++]=left[i++];\n\t}\n\n\twhile(j < len2) {\n\t\tarray[k++] = right[j++];\n\t}\n}\n\nvoid timSort(vector<int>&array, int n) {\n\t// calling insertion sort on blocks of size equal to run=32\n\t// if the size of array is less than defined run size, then the insertion sort would have sorted the array and there is no need of merging.\n\tfor(int i = 0; i < n; i += run) {\n\t\tinsertionSort(array, i, min((i + run - 1), n - 1));\n\t}\t\n\t//we merge from size run,the array merges to form sizes 64,128,...\n\tfor(int size = run; size < n; size = 2 * size) {\n\t\t//we merge from array[left,left+size-1]\n\t\t//and array[left+size,left+2*size]\n\t\t//after every merge,we increase left by 2*size\n\t\tfor(int left = 0; left < n; left += 2 * size) {\n\t\t\tint mid = left + size - 1;//ending point of left subarray\n\t\t\tint right = min((left + 2 * size - 1), n - 1);//ending point of right subarray\n\t\t\tif(mid < right)\n\t\t\t\tmerge(array, left, mid, right); //calling the merge function\n\t\t}\n\t}\n\tfor(int i: array)//printing the sorted array\n\t\tcout << i <<\" \";\n\t//sample output 1,2,3,4,5,6,7,8,9\n}\nint main()\n{\n\tvector<int> array = {9,8,7,6,5,4,3,2,1};\n\tint n = array.size();\n\ttimSort(array, n);//call to TimSort function\n\treturn 0;\n}\n"
  },
  {
    "path": "sorting/tim_sort.go",
    "content": "// File: tim_sort.go\n//Implementation of Tim Sort\n//Tim Sort makes use of insertionSort and Merge function of MergeSort\n//The basic idea is to divide the input array into blocks called as runs\n//The size of runs varies from 32 to 64, and perform insertion sort on the runs\n//Then, The runs(blocks) are merged to form the final sorted array\n//\n//Time Complexity of this algorithm in Best case is O(n),Average case is O(n*log(n))\n//Time Complexity in Worst case is O(n*log(n)).\n//This is a stable sorting algorithm\n//This algorithm uses Space of O(n)\n//This algorithm is used in languages like Java and Python for sorting.\n\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math\"\n)\n\nfunc\tmain() {\n\n\tarr := []int{43, 56, 2, 99, 1, 64, 23, 78, 34, 11, 90, 45, 32, 67, 88, 12, 9, 10, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}\n\tn := len(arr)\n\tfmt.Printf(\"Before Sorting\\n\")\n\tprintArray(arr, n)\n\ttimSort(arr, n)\n\tfmt.Printf(\"Sorted Array is\\n\")\n\tprintArray(arr, n)\n}\n\nfunc\ttimSort(arr []int, n int) {\n\n\trun := 32\n\t// you can take any value between 32 to 64, it actually is some empirical result from insertion s \n\tfor i := 0; i < n; i += run {\n\t\tinsertionSort(arr, i, int(math.Min(float64(i + 31), float64(n - 1))))\n\t}\n\n\tfor size := run; size < n; size = 2 * size {\n\t\tfor left := 0; left < n; left += 2 * size {\n\t\t\tmid := left + size - 1\n\t\t\tright := int(math.Min(float64(left + 2 * size - 1), float64(n - 1)))\n\t\t\tmerge(arr, left, mid, right)\n\t\t}\n\t}\n}\n\nfunc\tinsertionSort(arr []int, left int, right int) {\n\tfor i := left + 1; i <= right; i++ {\n\t\tj := i\n\t\tfor j > left && arr[j] < arr[j - 1] {\n\t\t\tarr[j], arr[j - 1] = arr[j - 1], arr[j]\n\t\t\tj--\n\t\t}\n\t}\n}\n\nfunc\tmerge(arr []int, left int, mid int, right int) {\n\n\t// function to merge the two sorted arrays\n\tlen1 := mid - left + 1\n\tlen2 := right - mid\n\tleftArr := make([]int, len1)\n\trightArr := make([]int, len2)\n\n\tfor i := 0; i < len1; i++ {\n\t\tleftArr[i] = arr[left + i]\n\t}\n\tfor j := 0; j < len2; j++ {\n\t\trightArr[j] = arr[mid + 1 + j]\n\t}\n\n\ti := 0\n\tj := 0\n\tk := left\n\n\tfor i < len1 && j < len2 {\n\t\tif leftArr[i] <= rightArr[j] {\n\t\t\tarr[k] = leftArr[i]\n\t\t\ti++\n\t\t} else {\n\t\t\tarr[k] = rightArr[j]\n\t\t\tj++\n\t\t}\n\t\tk++\n\t}\n\n\tfor i < len1 {\n\t\tarr[k] = leftArr[i]\n\t\ti++\n\t\tk++\n\t}\n\n\tfor j < len2 {\n\t\tarr[k] = rightArr[j]\n\t\tj++\n\t\tk++\n\t}\n}\n\n\n// Function to print the array\nfunc\tprintArray(arr []int, n int) {\n\tfor i := 0; i < n; i++ {\n\t\tfmt.Printf(\"%d \", arr[i])\n\t}\n\tfmt.Printf(\"\\n\")\n}\n\n// to run in terminal\n// $ go run tim_sort.go\n\n// Output\n// Before Sorting\n// 43 56 2 99 1 64 23 78 34 11 90 45 32 67 88 12 9 10 3 4 5 6 7 8 9 10 11 12 13 14 15\n// Sorted Array is\n// 1 2 3 4 5 6 7 8 9 9 10 10 11 11 12 12 13 14 15 23 32 34 43 45 56 64 67 78 88 90 99\n"
  },
  {
    "path": "sorting/tim_sort.java",
    "content": "//Implementation of Tim Sort\n//Tim Sort makes use of insertionSort and Merge function of MergeSort\n//The basic idea is to divide the input array into blocks called as runs\n//The size of runs varies from 32 to 64, and perform insertion sort on the runs\n//Then, The runs(blocks) are merged to form the final sorted array\n//\n//Time Complexity of this algorithm in Best case is O(n),Average case is O(n*log(n))\n//Time Complexity in Worst case is O(n*log(n)).\n//This is a stable sorting algorithm\n//This algorithm uses Space of O(n)\n//This algorithm is used in languages like Java and Python for sorting.\n\nimport java.util.Arrays;\nclass tim_sort\n{\n   static int run=32;  // you can take any value between 32 to 64, it actually is some empirical result from insertion sort\n    public static void main(String[] args)\n    {\n        int[] arr={43,56,2,99,1,64,23,78,34,11,90,45,32,67,88,12,9,10,3,4,5,6,7,8,9,10,11,12,13,14,15};\n        System.out.println(\"Before Sorting: \"+Arrays.toString(arr));\n        timSort(arr,arr.length);\n        System.out.println(\"After Sorting: \"+Arrays.toString(arr));\n    }\n    public static void timSort(int[] arr,int n)\n    {\n        for(int i=0;i<n;i+=run)\n        {   \n            insertionSort(arr,i,Math.min((i+31),(n-1)));\n        }\n        \n        for(int size=run;size<n;size=2*size)\n        {\n            for(int left=0;left<n;left+=2*size)\n            {\n                int mid=left+size-1;\n                int right=Math.min((left+2*size-1),(n-1));\n                merge(arr,left,mid,right);\n            }\n        }\n    }\n    public static void insertionSort(int[] arr,int left,int right)\n    {// simple insertion sort on array from left to right\n        for(int i=left+1;i<=right;i++)\n        {\n            int temp=arr[i];\n            int j=i-1;\n            while(j>=left && arr[j]>temp)\n            {\n                arr[j+1]=arr[j];\n                j--;\n            }\n            arr[j+1]=temp;\n        }\n    }\n    public static void merge(int[] arr,int left,int mid,int right)\n    {\n        int len1=mid-left+1;\n        int len2=right-mid;\n        int[] leftArr=new int[len1];\n        int[] rightArr=new int[len2];\n        for(int i=0;i<len1;i++)\n        {\n            leftArr[i]=arr[left+i];\n        }\n        for(int i=0;i<len2;i++)\n        {\n            rightArr[i]=arr[mid+1+i];\n        }\n        int i=0,j=0,k=left;\n        while(i<len1 && j<len2)\n        {\n            if(leftArr[i]<=rightArr[j])\n            {\n                arr[k]=leftArr[i];\n                i++;\n            }\n            else\n            {\n                arr[k]=rightArr[j];\n                j++;\n            }\n            k++;\n        }\n        while(i<len1)\n        {\n            arr[k]=leftArr[i];\n            i++;\n            k++;\n        }\n        while(j<len2)\n        {\n            arr[k]=rightArr[j];\n            j++;\n            k++;\n        }\n    }\n}\n\n//to run this code in terminal\n// javac tim_sort.java\n// java tim_sort\n\n//Output:\n// Before Sorting: [43, 56, 2, 99, 1, 64, 23, 78, 34, 11, 90, 45, 32, 67, 88, 12, 9, 10, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,\n// 14, 15]\n// After Sorting: [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 14, 15, 23, 32, 34, 43, 45, 56, 64, 67, 78, 88, 90, 99]"
  },
  {
    "path": "sorting/tim_sort.py",
    "content": "\"\"\"\nImplementation of Tim Sort in Python \n\nTim Sort is based on Insertion and Merge Sort. \n\nThe steps of the algorithm are: \n\n1. Divide the input array into blocks called runs\n2. The size of a run can either be 32 or 64\n3. Sort the elements of every run with insertion sort\n4. Merge the sorted runs using with merge sort\n5. After every iteration double the size of the merged array \n\n\"\"\"\n\nMINIMUM = 32\n\n# Returns the minrun = the minimum length of a run \ndef find_minrun(n):\n\n    r = 0\n    while n >= MINIMUM:\n        r |= n & 1\n        n >>= 1\n\n    return n + r\n \n \n# Sorts an array from left to right index (Insertion Sort)\ndef insertion_sort(array, left, right):\n    for i in range(left + 1, right + 1):\n        j = i\n        while j > left and array[j] < array[j - 1]:\n            array[j], array[j - 1] = array[j - 1], array[j]\n            j -= 1\n \n \n# Merges the sorted runs\ndef merge(array, l, m, r):\n \n    # original array is broken in two parts: left - right \n    \n    array_len1 = m - l + 1\n    array_len2 = r - m\n\n    left = []\n    right = []\n\n    for i in range(0, array_len1):\n        left.append(array[l + i])\n\n    for i in range(0, array_len2):\n        right.append(array[m + 1 + i])\n \n    i = 0\n    j = 0\n    k = l\n \n    # merge the two arrays in a larger sub array\n    while i < array_len1 and j < array_len2:\n        if left[i] <= right[j]:\n            array[k] = left[i]\n            i += 1\n \n        else:\n            array[k] = right[j]\n            j += 1\n \n        k += 1\n \n    # Copy remaining elements of the left part, if any\n    while i < array_len1:\n        array[k] = left[i]\n        k += 1\n        i += 1\n \n    # Copy remaining element of the right part, if any\n    while j <array_len2:\n        array[k] = right[j]\n        k += 1\n        j += 1\n \n \n# Timsort algorithm\ndef tim_sort(array):\n    n = len(array)\n    minrun = find_minrun(n)\n \n    # Sort individual subarrays of size RUN\n    for start in range(0, n, minrun):\n        end = min(start + minrun - 1, n - 1)\n        insertion_sort(array, start, end)\n \n    # Start merging from size RUN (or 32), then 128, 256, ... etc.\n    size = minrun\n    while size < n:\n \n        # Choose the starting point of the left sub array\n        # Merge array[left ... left + size - 1]\n        # and array[left+size ... left + 2 * size - 1]\n        # After every merge, the size is increased by 2 * size.\n        for left in range(0, n, 2 * size):\n \n            # Find end point of the left sub array.\n            # The mid + 1 is the starting point of the right sub array.\n            mid = min(n - 1, left + size - 1)\n            right = min((left + 2 * size - 1), (n - 1))\n \n            # Merge array[left ... mid] and array[mid + 1 ... right]\n            if mid < right:\n                merge(array, left, mid, right)\n \n        size = 2 * size\n \n \n\nif __name__ == \"__main__\":\n \n    array = [-1, 5, 0, -3, 11, 9, -2, 7, -15, 22, 4, -10]\n \n    print(\"Array to sort:\")\n    print(array)\n \n    # Function Call\n    tim_sort(array)\n \n    print(\"The sorted array using TimSort is\")\n    print(array)"
  },
  {
    "path": "sorting/wave_sort.cpp",
    "content": "#include <bits/stdc++.h>\r\n\r\n/*\r\nWave sort, also known as \"odd-even sort,\" is a simple sorting algorithm that works by repeatedly \r\ncomparing and swapping adjacent elements in an array until the array is sorted. \r\nThe algorithm gets its name from the pattern of element swaps, which resembles a wave-like motion.\r\nIn this sorting method we arrange array in\r\nArr[0] >=arr[1]<=arr[2]>=arr[3]<=arr[4]……….   Like a wave\r\n*/\r\n\r\nusing namespace std;\r\n\r\nvoid wavesort(int arr[], int n)\r\n{\r\n    for (int i = 1; i < n; i += 2)\r\n    {\r\n        if (arr[i] > arr[i - 1])\r\n        {\r\n            swap(arr[i], arr[i - 1]);\r\n        }\r\n        if (arr[i] > arr[i + 1] && i <= n - 2)\r\n        {\r\n            swap(arr[i], arr[i + 1]);\r\n        }\r\n    }\r\n}\r\n\r\nint main()\r\n{\r\n    int arr[9] = {1, 3, 4, 7, 5, 6, 2};\r\n    wavesort(arr, 7);\r\n    for (int i = 0; i < 7; i++)\r\n    {\r\n        cout << arr[i] << \" \";\r\n    }\r\n    return 0;\r\n}\r\n\r\n/*\r\nTime Complexity: O(N)\r\nAuxiliary Space: O(1)\r\n*/\r\n\r\n/*\r\nThe idea is based on the fact that if we make sure that all even positioned (at index 0, 2, 4, ..) \r\nelements are greater than their adjacent odd elements, we don’t need to worry about oddly positioned elements.\r\n\r\n- Traverse all even positioned elements of the input array, and do the following.\r\n    - If the current element is smaller than the previous odd element, swap the previous and current.\r\n    - If the current element is smaller than the next odd element, swap next and current.\r\n*/\r\n\r\n/*\r\nDry-Run\r\nConsider the array: [7, 2, 5, 1, 8, 3]\r\n\r\nStep 1:\r\n\r\nStart with the initial array: [7, 2, 5, 1, 8, 3]\r\nIn the first iteration, we compare and swap adjacent elements at even indices (0, 2, 4).\r\nCompare 7 and 2: 7 > 2, so we swap them. Array becomes: [2, 7, 5, 1, 8, 3]\r\nCompare 7 and 8: 7 < 8, so no swap is needed.\r\nAfter the first phase, the array becomes: [2, 7, 5, 1, 8, 3]\r\nStep 2:\r\n\r\nIn the second iteration, we compare and swap adjacent elements at odd indices (1, 3, 5).\r\nCompare 7 and 5: 7 > 5, so we swap them. Array becomes: [2, 5, 7, 1, 8, 3]\r\nCompare 7 and 1: 7 > 1, so we swap them. Array becomes: [2, 5, 1, 7, 8, 3]\r\nCompare 7 and 3: 7 > 3, so we swap them. Array becomes: [2, 5, 1, 3, 8, 7]\r\nAfter the second phase, the array becomes: [2, 5, 1, 3, 8, 7]\r\nStep 3:\r\n\r\nIn the third iteration, we again compare and swap adjacent elements at even indices (0, 2, 4).\r\nCompare 2 and 5: 2 < 5, so no swap is needed.\r\nCompare 5 and 1: 5 > 1, so we swap them. Array becomes: [1, 5, 2, 3, 8, 7]\r\nCompare 5 and 3: 5 > 3, so we swap them. Array becomes: [1, 3, 2, 5, 8, 7]\r\nAfter the third phase, the array becomes: [1, 3, 2, 5, 8, 7]\r\nStep 4:\r\n\r\nIn the fourth iteration, we compare and swap adjacent elements at odd indices (1, 3, 5).\r\nCompare 3 and 2: 3 > 2, so we swap them. Array becomes: [1, 2, 3, 5, 8, 7]\r\nCompare 3 and 5: 3 < 5, so no swap is needed.\r\nCompare 5 and 8: 5 < 8, so no swap is needed.\r\nAfter the fourth phase, the array remains the same: [1, 2, 3, 5, 8, 7]\r\nStep 5:\r\n\r\nIn the fifth iteration, we again compare and swap adjacent elements at even indices (0, 2, 4).\r\nCompare 1 and 2: 1 < 2, so no swap is needed.\r\nCompare 2 and 3: 2 < 3, so no swap is needed.\r\nCompare 3 and 5: 3 < 5, so no swap is needed.\r\nAfter the fifth phase, the array remains the same: [1, 2, 3, 5, 8, 7]\r\nStep 6:\r\n\r\nIn the sixth iteration, we compare and swap adjacent elements at odd indices (1, 3, 5).\r\nCompare 2 and 3: 2 < 3, so no swap is needed.\r\nCompare 3 and 5: 3 < 5, so no swap is needed.\r\nCompare 5 and 7: 5 < 7, so no swap is needed.\r\nAfter the sixth phase, the array remains the same: [1, 2, 3, 5, 8, 7]\r\nSince no more swaps occur in the array, the algorithm terminates, and the array is considered sorted.\r\n\r\nFinal sorted array: [1, 2, 3, 5, 7, 8]\r\n*/"
  }
]