RMQ问题的ST算法读书笔记

原创作品,出自 “晓风残月xj” 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj)。

由于各种原因,可能存在诸多不足,欢迎斧正!

首先介绍一下我对RMQ问题的理解

           RMQ问题,全名为range minimun/maximun query,即区间最值查询问题。

此问题可以由三种想法:

         1.朴素算法,即在给定的查询区间内逐个比较,每次查询的时间复杂度为O(N),在查询次数Q和总序列长度N都很大的情况下 ,总的时间复杂度为O(N*Q),效率很大,一般不可取。

         2.线段树算法。首先预处理建立线段树,每个节点存放该区间的最值,此过程的时间复杂度为O(N);然后在每次查询时的时间复杂度为O(log(N)),总的时间复杂度为O(Q*(N)),此算法效率足够高,但代码量较大,编程难度不小。

         3.ST算法。ST算法也需要与处理,此过程的时间复杂度为O(N*log(N));然后每次查询的时间复杂度为O(1).总的时间复杂度为O(N*log(N)).代码量较少,编程难度小,只是牺牲了一定的空间。

 

下面介绍一下我对ST算法的理解

          ST算法,全名为Sparse_Table 算法,采用的是动态规划的思想。要求区间[l,r]的最值,我们将其区间细分成两个长度相近的小区间[l,k],[k,r],然后合并。

dp[i][j]表示区间[i,i+2^j-1]的最值,该区间长度为2^j。dp[i][j]可以由dp[i][j-1]和dp[i+2^(j-1)][j-1]导出,而后两者的区间长度是2^(j-1),在之前已经求出了。下面证明 

                                              dp[i][j]=Max/Min(dp[i][j-1],dp[i+2^(j-1)][j-1])

        dp[i][j]表示区间[i,i+2^j-1]的最值,dp[i][j-1]表示区间[i,i+2^(j-1)-1]的最值,dp[i+2^(j-1)][j-1]表示区间[i+2^(j-1),i+2^(j-1)+2^(j-1)-1]即区间[i+2^(j-1),i+2^(j-1]的最值;

[i,i+2^j-1]=[i,i+2^(j-1)-1]+[i+2^(j-1),i+2^(j-1],从而证明后两个区间可以覆盖前一个,证明是对的。

ST算法可以递归实现,也可以非递归现实。下面说说非递归实现的一般步骤:

两层for循环

for l   1->M                     //2^M尽量取大于n,枚举区间长度2^l

    for   s->n                   //枚举起点

       begin

               if(s+(1<<l)-1<=n)

                     dp[i][j]=Max/Min(dp[i][j-1],dp[i+2^(j-1)][j-1]);

       end

上述过程为预处理,时间复杂度为O()N*log(N),求好区间最值为下面的查询做准备.

          对于RMQ问题,接下来要做的就是查询了。

对于某次区间为[l,r]的最值查询,我们要做的就是将该区间分解成两个小的在ST算法中已经处理过的区间,然后合并。此过程是有公式可套的。

先求一个最大的k,使其满足2^k<=(r-l+1),在C/C++中k=(int)(log(1.0*r-l+1)/log(2.0)),于是可以将区间[l,r]分成长度为2^k的两个小区间:[l,l+2^k-1],[r-2^k+1,r]

[l,l+2^k-1]对应dp[l][k];[r-2^k+1,r]对应dp[r-2^k+1][k],于是区间为[l,r]的最值=Max/Min(dp[l][k],dp[r-2^k+1][k]),下面证明该式子的正确性:

           首先上面已经说明dp[l][k],dp[r-2^k+1][k]合起来可以覆盖住整个查询区间,下面只需说明没有超出查询区间(否则会出错),由k=(int)(log(1.0*r-l+1)/log(2.0)),可知

l+2^k-1<=r,且r-2^k+1>=l,r-2^k+1+2^k-1=r,从而证明没有超出,刚好完全覆盖(至于有无重复覆盖是不影响最值的),足够说明区间为[l,r]的最值=Max/Min(dp[l][k],dp[r-2^k+1][k])的正确性。

每次查询的时间复杂度为O(1),查询总的时间复杂度为(Q)。

          从上所述,整个RMQ问题的时间复杂度为O(N*log(N)),空间复杂度为O(N*log(N)),且ST算法的效率很高,编程实现较为简单,解题时是个不错的选择。

 

参考文献http://wenku.baidu.com/view/83cf4b0f4a7302768e99393e.html,在此表示感谢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值