Skip to content

Commit a7eb41f

Browse files
William FisetWilliam Fiset
William Fiset
authored and
William Fiset
committed
Update ST
1 parent bcd35af commit a7eb41f

File tree

2 files changed

+112
-3
lines changed

2 files changed

+112
-3
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,112 @@
11

22

3+
Hello everyone, my name is William, today we're taking a look at some source
4+
code on how to implement a SparseTable. In the last video we looked at what a
5+
sparse table is, how it can be used to do fast range queries and how to build
6+
one. This video is a follow up to that video, so make sure to give that video
7+
a watch, I'll make sure to put a link in the description below.
8+
9+
Awesome, so here we are in the source code written in Java. In this header I put
10+
some instructions on how you can download this code and run it yourself.
11+
12+
This particular implementation I'm about to show you is for a min sparse table
13+
that can do minimum range queries. If you want to do any other type of range
14+
query such as a max range query or a product range query you will need to modify
15+
this code. I also have another more generic sparse table on github which support
16+
different query operations if you're interested in that.
17+
18+
Alright, let's dig into the details. The sparse table class has a few instance
19+
variables you'll want to know about.
20+
21+
The first is 'n', the number of elements in the input array.
22+
23+
Then there's capital P, the floor of the base 2 logarithm of n, this is
24+
effectively the number of rows in the sparse table.
25+
26+
After there's the log2 array, this array is simply used to do fast lookups for
27+
the floor of the base 2 logarithm so that we don't need to do any calculations
28+
when we need the value. We could technically since the value of capital P using
29+
this array if we wanted to.
30+
31+
Then dp is just the sparse table with P plus 1 rows and n columns.
32+
33+
Following this is the variable 'it', short for index table. This is the table
34+
that keeps track of the index of the selected minimum or maximum element in the
35+
range we're querying. I briefly mentioned this in the last video, but this table
36+
is super handy to have around as we'll hopefully see in a future video ;P
37+
38+
So when you want to create a MinSparseTable, you need to provide the input
39+
values to do range queries on. However, remember that this input array can only
40+
contain immutable values, if the data changes after the sparse table is built
41+
then the queries on the sparse table will be wrong.
42+
43+
The MinSparseTable constructor calls the init method which actually builds the
44+
sparse table. Doing work in the constructor isn't considered a best practice,
45+
but this is just a simple proof of concept example.
46+
47+
Inside the init method we start by getting the value of 'n', the number of
48+
elements in the values array. Then we compute capitol P from the value of 'n'.
49+
After we know those values, we can go ahead and allocate memory for our sparse
50+
table and our index table which are both have P+1 rows and 'n' columns.
51+
52+
Then the next thing we want to do is simply populate the first row of both the
53+
sparse table with the input values, and the index table with the indeces 0 to N
54+
55+
After that, populate the log2 array with all the values for the floor of the
56+
base 2 logarithm between 1 and N inclusive.
57+
58+
Next, we build the sparse table and its associated index table. These two for
59+
loops iterate over all the cells of the table while making
60+
sure not to consider intervals which would go outside the bounds of the table.
61+
62+
Inside the two loops, we can find the values of the left and the right cells
63+
and take the minimum.
64+
65+
Lastly, we want to save and propagate the index of the smallest element inside
66+
the index table so that we don’t lose track of it. You can think of the index
67+
table as an identical sparse table that tracks of index values instead of
68+
minimum values.
69+
70+
If we scroll further below you see that we have two more methods to look at.
71+
Once we have finished building the sparse table we can start calling the two
72+
methods below to query the minimum value in the given range, and the query
73+
the index of the minimum value in a given range.
74+
75+
This first method 'queryMin' calculates the value of the smallest element in the
76+
range l to r inclusive in constant time. This method works by finding two
77+
overlapping ranges which cover the entire between l and r and taking the minimum
78+
of both intervals.
79+
80+
The first thing we do is calculate p, the floor of the base 2 log corresponding
81+
row in the sparse table.
82+
83+
Then, simply do a lookup to get the left and the right cell values and take the
84+
minimum. The left cell is found at row `p`, column `l`, and the right cell at
85+
row `p` and column `r - k plus 1`. Here, `k` is just calculated dynamically as
86+
1 shifted `p` times for simplicity.
87+
88+
89+
The last method 'queryMinIndex' is used to find the index of the minium element
90+
in the range `l` to `r` inclusive.
91+
92+
If there are multiple smallest elements, the index of leftmost one is returned.
93+
94+
To do this we’re basically going to do the same thing as when we were finding
95+
the minimum query value; we’re going to find the values of the left and the
96+
right cell, but rather than returning the minimum of the two, we’re going to
97+
compare them and find the smaller one and return the index stored in the
98+
Index Table.
99+
100+
101+
And that's all I have on sparse tables for now, folks thank you very much for
102+
watching and please subscribe for more content.
103+
104+
105+
106+
107+
108+
109+
3110

4111

5112

src/main/java/com/williamfiset/algorithms/datastructures/sparsetable/examples/MinSparseTable.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Min sparse table example
33
*
44
* <p>Download the code: <br>
5-
* $ git clone https://github.com/williamfiset/Algorithms
5+
* $ git clone https://github.com/williamfiset/algorithms
66
*
77
* <p>Run: <br>
88
* $ ./gradlew run -Palgorithm=datastructures.sparsetable.examples.MinSparseTable
@@ -28,7 +28,10 @@ public class MinSparseTable {
2828
// The sparse table values.
2929
private long[][] dp;
3030

31-
// Index Table (IT) associated with the values in the sparse table.
31+
// Index Table (IT) associated with the values in the sparse table. This table
32+
// is only useful when we want to query the index of the min (or max) element
33+
// in the range [l, r] rather than the value itself. The index table doesn’t
34+
// make sense for most other range query types like gcd or sum.
3235
private int[][] it;
3336

3437
public MinSparseTable(long[] values) {
@@ -85,7 +88,6 @@ private long queryMin(int l, int r) {
8588

8689
// Returns the index of the minimum element in the range [l, r].
8790
public int queryMinIndex(int l, int r) {
88-
int len = r - l + 1;
8991
int p = log2[r - l + 1];
9092
long leftInterval = dp[p][l];
9193
long rightInterval = dp[p][r - (1 << p) + 1];

0 commit comments

Comments
 (0)