如何确定位置Z是否在起始X和结束Y的区域内

时间:2014-03-24 10:48:05

标签: java algorithm set jtextarea

我有一个JTextArea,用户可以使用特殊语法创建区域。我正在寻找一些最佳方式的帮助(使用线性时间算法最有效)来确定当前位置是否在非重叠区域之一。

假设我有以下内容来确定用户定义的区域(我在开始时使用正则表达式扫描文档以确定区域):

REGION START = 0, END = 20
REGION START = 21, END = 24
REGION START = 34, END = 40

我不关心用户所在的区域,我只需要确定它们是否位于某个区域内,给定位置X.我可以将这些区域存储为数组并遍历条目,直到找到一个匹配的,但这不是线性时间,如果它与一个区域不匹配则需要更长的时间。

使用算法或以某种方式存储数据有更简单的方法吗?

3 个答案:

答案 0 :(得分:1)

  

我可以将区域存储为数组并遍历条目   直到找到匹配的,但这不是线性时间

It is linear.

假设区域已排序,您可以使用Binary Search

答案 1 :(得分:1)

实际上你提议的算法确实是线性的。这是另一个,有点复杂,但更快:

  • 您需要使用累积表数据结构,如二进制索引树(BIT)。 BIT允许您以对数复杂度实现以下操作:
    • 更新lo,hi,val:在index [lo,hi]处添加值val
    • 查询x:返回索引x的总和
  • 对于每个区域[lo,hi],您调用Update(lo,hi,1),将1添加到BIT中的相应位置
  • 对于每个查询,只需检查Query(x)是否为零。如果是,那么x,不与区域重叠

关于二进制索引树:http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees

还有一些代码:

public class BIT {

  // AddAtPosition: adds at binary indexed tree [bit] the value [v]
  // exactly at position [i]. The binary indexed tree has size [size]

  public static void AddAtPosition(int [] bit, int size, int i, int v) {
    while(i < size) {
      bit[i] += v;
      i += (i & -i);
    }
  }

  // AddAtInterval: adds at binary indexed tree [bit] the value [v]
  // to all position from [lo] to [hi]. The binary indexed tree has size [size]

  public static void AddAtInterval(int [] bit, int size, int lo, int hi, int v) {
    AddAtPosition(bit, size, lo+1, v);
    AddAtPosition(bit, size, hi+2, -v);
  }

  // QueryAtPosition: returns the value of index [i] at binary indexed tree [bit]

  public static int QueryAtPosition(int [] bit, int i) {
    int ans = 0;
    i++;
    while(i > 0) {
      ans += bit[i];
      i -= (i & -i);
    }
    return ans;
  }

  public static void main(String [] args) {
    int [] bit = new int[10+1]; // for values from 0-9
    AddAtInterval(bit, 11, 0, 5, 1);
    AddAtInterval(bit, 11, 4, 7, 1);
    for(int i=0; i<=9; ++i) {
      System.out.print("Query At position " + i + ": ");
      System.out.println(QueryAtPosition(bit, i));
    }
  }
}

答案 2 :(得分:0)

虽然我喜欢BIT示例,但我想我可能会使用一个更简单的解决方案,我希望与BIT相比没有巨大的性能影响 - 是否存在,考虑到我需要相同长度的数组开始?我已经根据我的JText区域的长度以相同的方式定义了一个数组:

int[] pC = new int[myArea.getText().length()];

然后我搜索我的区域,每当我找到一个区域时,我在数组中将适当的位置设置为1:

for (int i = m.start(); i < m.end(); i++) {
  pC[i] = 1;
}

然后我可以使用以下语法对位置Z进行简单检查:

if (pC[Z] == 0) {
  // OUTSIDE REGION
}
else {
  // INSIDE REGION
}