From a55e362ee182643a8983244b06179ed022574b9a Mon Sep 17 00:00:00 2001 From: Arpan Mukherjee Date: Fri, 16 Oct 2020 22:08:00 +0530 Subject: [PATCH] Added Sparse Table for range query (#996) * Added Sparse Table for range query * Fixed Lint Warnings * Fixed comments and Lint warnings * Fixed comments * Fixed comments and Lint warnings * Fixed comments and Lint warnings * Fixed variable reference Lint warnings * Added documentation for functions parameters and return statements * updating DIRECTORY.md * Added documentation * Applied namespace range_queries Co-authored-by: David Leal * Updated wikipedia documentation link * Resolved comments * Fixed typo Co-authored-by: David Leal * Resolved comments * Added tests * Cleaned up debugging statements * Resolved comments * Resolved Comments * Update sparse_table.cpp * Resolved comments Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> * Fixed comments * Update sparse_table.cpp Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal Co-authored-by: Krishna Vedala <7001608+kvedala@users.noreply.github.com> --- DIRECTORY.md | 1 + range_queries/sparse_table.cpp | 101 +++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100755 range_queries/sparse_table.cpp diff --git a/DIRECTORY.md b/DIRECTORY.md index c431979aa..471980365 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -213,6 +213,7 @@ * [Heavy Light Decomposition](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/range_queries/heavy_light_decomposition.cpp) * [Mo](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/range_queries/mo.cpp) * [Segtree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/range_queries/segtree.cpp) + * [Sparse Table](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/range_queries/sparse_table.cpp) ## Search * [Binary Search](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/search/binary_search.cpp) diff --git a/range_queries/sparse_table.cpp b/range_queries/sparse_table.cpp new file mode 100755 index 000000000..465532f3b --- /dev/null +++ b/range_queries/sparse_table.cpp @@ -0,0 +1,101 @@ +/** + * @file sparse_table.cpp + * @brief Implementation of [Sparse Table](https://en.wikipedia.org/wiki/Range_minimum_query) data structure + * + * @details + * Sparse Table is a data structure, that allows answering range queries. + * It can answer most range queries in O(logn), but its true power is answering range minimum queries + * or equivalent range maximum queries). For those queries it can compute the answer in O(1) time. + * + * * Running Time Complexity \n + * * Build : O(NlogN) \n + * * Range Query : O(1) \n +*/ + +#include +#include +#include +#include + +/** + * @namespace range_queries + * @brief Range Queries algorithms + */ +namespace range_queries { +/** + * @namespace sparse_table + * @brief Range queries using sparse-tables + */ + namespace sparse_table { +/** + * This function precomputes intial log table for further use. + * @param n value of the size of the input array + * @return corresponding vector of the log table + */ +template +std::vector computeLogs(const std::vector& A) { + int n = A.size(); + std::vector logs(n); + logs[1] = 0; + for (int i = 2 ; i < n ; i++) { + logs[i] = logs[i/2] + 1; + } + return logs; +} + +/** + * This functions builds the primary data structure sparse table + * @param n value of the size of the input array + * @param A array of the input integers + * @param logs array of the log table + * @return created sparse table data structure + */ +template +std::vector > buildTable(const std::vector& A, const std::vector& logs) { + int n = A.size(); + std::vector > table(20, std::vector(n+5, 0)); + int curLen = 0; + for (int i = 0 ; i <= logs[n] ; i++) { + curLen = 1 << i; + for (int j = 0 ; j + curLen < n ; j++) { + if (curLen == 1) { + table[i][j] = A[j]; + } + else { + table[i][j] = std::min(table[i-1][j], table[i-1][j + curLen/2]); + } + } + } + return table; +} + +/** + * This function is the query function to get the range minimum value + * @param beg beginning index of the query range + * @param end ending index of the query range + * @param logs array of the log table + * @param table sparse table data structure for the input array + * @return minimum value for the [beg, end] range for the input array + */ +template +int getMinimum(int beg, int end, const std::vector& logs, const std::vector >& table) { + int p = logs[end - beg + 1]; + int pLen = 1 << p; + return std::min(table[p][beg], table[p][end - pLen + 1]); +} +} +} // namespace range_queries + +/** + * Main function + */ +int main() { + std::vector A{1, 2, 0, 3, 9}; + std::vector logs = range_queries::sparse_table::computeLogs(A); + std::vector > table = range_queries::sparse_table::buildTable(A, logs); + assert(range_queries::sparse_table::getMinimum(0, 0, logs, table) == 1); + assert(range_queries::sparse_table::getMinimum(0, 4, logs, table) == 0); + assert(range_queries::sparse_table::getMinimum(2, 4, logs, table) == 0); + return 0; +} +