Range Minimum Query(RMQ) 是一个用O(N*logN)进行预处理,用O(1)时间在数组的一段区间中查找最小元素的值的算法

Lowest Common Ancestor(LCA) 是寻找树中两个节点最近祖先的算法,LCA可以在O(N)时间内归约为RMQ

参考文章:RangeMinimumQueryAndLowestCommonAncestor

我写的RMQ类:RMQ

 

package SDJL;

public class RMQ
{
    
private int[] datas;
    
private int[][] m;//m[i][j]保存了从第i个位置开始长度为2^j区间中的最小值
    private int n, log_n;//n表示数组长度,log_n表示2为底n的对数

    
public RMQ(int[] datas)
    
{
        
this.datas = datas;
        
this.n = datas.length;
        
for (this.log_n = 01 << this.log_n <= n; this.log_n++) ;//计算log_n

        
//以下部分为计算m,用时O(N*logN)
        this.m = new int[this.n][this . log_n];
        
for (int i = 0; i < this.n; i++)
        
{
            m[i][
0= this.datas[i];
        }

        
for (int j = 1; j < this.log_n; j++)
        
{
            
int power_j = 1 << j;
            
int power_jMinus1 = 1 << (j - 1);
            
for (int i = 0; i + power_j - 1 < this.n; i++)
            
{                
                
if (this.m[i][j - 1< this.m[i + power_jMinus1][j - 1])
                
{
                    
this.m[i][j] = this.m[i][j - 1];
                }

                
else
                
{
                    
this.m[i][j] = this.m[i + power_jMinus1][j - 1];
                }

            }

        }

    }


    
//获得两个区间中的最小值,用时O(1)
    public int getMinimum(int stratIndex, int endIndex)
    
{
        
/*
        *把区间分为左、右两部分,每个部分有2^k长,一般情况下中间部分有重叠
        
*/

        
int k = (int)(Math.log(endIndex - stratIndex + 1/ Math.log(2));

        
//在左、右两部分中选择一个最小值
        if (this.m[stratIndex][k] <= this.m[endIndex - (1 << k) + 1][k])
        
{
            
return this.m[stratIndex][k];
        }

        
else
        
{
            
return this.m[endIndex - (1 << k) + 1][k];
        }

    }


    
public int getData(int index)
    
{
        
return this.datas[index];
    }


    
public int length()
    
{
        
return this.datas.length;
    }

}
posted on 2008-10-11 11:31  刘永辉  阅读(810)  评论(0编辑  收藏  举报