摘要:
1,ST表的介绍
2,ST表的构建
3,区间查询
1,ST表的介绍
稀疏表(Sparse Table)又称ST表,它不是一种数据结构,它是基于倍增的思想,解决静态的RMQ(Range Maximum/Minimum Query区间最值)问题。
倍增就是成倍增加,如果问题的状态空间特别大,一步步的计算时间复杂度太高,可以通过倍增的思想,只考虑 2 的整数次幂,快速缩小求解范围直到找到解。
比如对于长度为 n 的数组 nums ,每次查询区间 [i,j] 内的最小值,如果是线性查找的话,查找的时间复杂度是O(n),做 m 次查询总的时间复杂度就是 O(m*n) 。
我们可以对数组进行预处理,用 dp[i][j] 表示区间 [i,j] 内的最小值,这样每次查询的时候直接从数组 dp 中取即可,时间复杂度是O(1),m 次查询总的时间复杂度就是O(m)。虽然查询的时间复杂度降低了,但由于需要提前计算 dp 数组,而计算 dp 数组的时间复杂度是 O(n*n)。
所以这里只需要降低计算 dp 数组的时间复杂度即可,在计算的时候如果知道区间 [i,k] 和区间 [k+1,j] 的最小值,我们就可以直接计算出区间 [i,j] 之间的最小值,不需要在一个个遍历区间的所有元素。
我们可以这样来做,对于数组的每个元素,把从它开始的数列按照长度划分为1,2,4,8,……这样的区间,如下图所示。
我们可以发现长度为 i 的区间可以通过长度为 i/2 的区间直接计算,计算总的时间复杂度是 O(n*logn) ,这个就是ST表。
ST表的创建是基于动态规划的思想,我们定义 dp[i][j] 表示查询从 i 开始连续的 2^j 个数的最小值,也就是查询区间 [i , i+2^j-1] 内的最小值,状态转移方程如下:
dp[i][j] = min(dp[i][j-1],dp[i + 2^(j-1)][j-1])
这里实际上是把区间 [i,i+2^j-1] 分成了 [i,i+2^(j-1)-1] 和 [i+2^(j-1),i+2^j-1] 两部分,这两部分区间长度是相等的,都是 2^(j-1),整个区间的最小值也就是这两个区间的最小值,如下图所示:
2,ST表的构建