《征服数据结构》稀疏表(Sparse Table)

摘要:

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,……这样的区间,如下图所示。

e6040774e02eabaa9ac50bf5edf51c3e.png

我们可以发现长度为 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),整个区间的最小值也就是这两个区间的最小值,如下图所示:

d01141b16660f6bd37cc9bb22ccd7e74.png

2,ST表的构建

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
稀疏矩阵乘法可以使用链数据结构进行实现,以减少存储空间和计算时间。在链实现中,每个节点示非零元素,并记录其行、列和值。 以下是一个用链实现稀疏矩阵的示例代码: ```python class Node: def __init__(self, row, col, value): self.row = row self.col = col self.value = value self.next = None class SparseMatrix: def __init__(self, rows, cols): self.rows = rows self.cols = cols self.head = None def add_element(self, row, col, value): new_node = Node(row, col, value) if self.head is None: self.head = new_node else: current = self.head while current.next: current = current.next current.next = new_node def multiply(self, other): # 创建结果矩阵 result = SparseMatrix(self.rows, other.cols) # 转置other矩阵,以便快速查找列 transpose_other = {} current = other.head while current: if current.col not in transpose_other: transpose_other[current.col] = [] transpose_other[current.col].append((current.row, current.value)) current = current.next # 遍历self矩阵的行 current_self = self.head while current_self: result_row = [0] * result.cols # 遍历self矩阵的行中的非零元素 current_other = current_self while current_other: # 查找对应的列 if current_other.col in transpose_other: for other_row, other_value in transpose_other[current_other.col]: result_row[other_row] += current_other.value * other_value current_other = current_other.next # 将结果矩阵的行添加到结果中 for col, value in enumerate(result_row): if value != 0: result.add_element(current_self.row, col, value) current_self = current_self.next return result ``` 在上述代码中,`SparseMatrix` 类稀疏矩阵,`Node` 类示链中的节点。`add_element` 方法用于向稀疏矩阵中添加非零元素。`multiply` 方法实现稀疏矩阵的乘法运算。它遍历第一个矩阵的每一行,并在转置的第二个矩阵中查找对应的列,然后计算乘积并将结果保存在 `result` 矩阵中。 请注意,上述代码只是一个简单的示例,实际的实现可能需要更多的边界条件和错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据结构和算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值