给一个N元数组A[0..N-1],设计一个数据结构,支持查询操作Query(L,R),计算min{A[L]...A[R]};RMQ问题可以做到O(n)的预处理,O(1)的查询复杂度;以下JAVA代码是O(nlogn)的预处理,O(1)的查询复杂度;
参考文献:《算法竞赛入门经典训练指南》P197,刘汝佳,陈锋
package ProgrammingContest;
public class RMQProblem {
private int LEN = 0;
private int EXP = 0;
private int[] A = null;
private int[][] D = null;
public RMQProblem(int[] a) {
LEN = a.length;
EXP = minExp(LEN);
A = a;
D = new int[a.length][EXP];
for ( int i=0; i<A.length; i++ ) D[i][0] = A[i];
for ( int j=1; j<=EXP; j++ ) {
for ( int i=0; (i+(1<<j)-1)<LEN; i++ ) {
D[i][j] = min(D[i][j-1],D[i+(1<<(j-1))][j-1]);
}
}
}
public int query(int L, int R) {
int k = 0;
while ( ( 1 << k ) <= (R-L+1) ) {
k++;
}
k--;
return min(D[L][k],D[R-(1<<k)+1][k]);
}
private int minExp(int x) {
int exp = 0;
int test = 1;
while ( test < x ) {
test <<= 1;
exp++;
}
return exp;
}
private int min(int x, int y) {
return (x<y)?x:y;
}
/**
* @param args
*/
public static void main(String[] args) {
int[] v = {0, 1, 2, 3, 4, 5};
RMQProblem inst = new RMQProblem(v);
for ( int i=0; i<v.length; i++) {
int r = inst.query(i,v.length-1);
System.out.println(r);
}
}
}