如何在java中验证重叠否

时间:2010-04-15 13:44:20

标签: java

我有动态渲染行。我们有像FROM TO这样的领域。

For eg: From     TO
        2        10,
        2        3,
        8        12

它不能接受这个组合行..这意味着没有数字应该重叠。

For eg: From     TO
        2        10,
        0        1,
        11       12

允许这种组合。行也可能增加。

我需要为此重叠编写验证。 任何1都可以帮助解决这个问题。

这是代码,我试过,

List<AppHrVacationAccrualRuleDefinition> a = new ArrayList<AppHrVacationAccrualRuleDefinition>();
List<AppHrVacationAccrualRuleDefinition> b = new ArrayList<AppHrVacationAccrualRuleDefinition>();

a=ruleDefinition;
b=ruleDefinition;

int count = 0;
int k = 1;

for (int l = 0; l < a.size(); l++)
{
    for (int j = k; j < b.size(); j++)
    {
        if (((a.get(l).getStartValue().equals(b.get(j).getEndValue()) || 
                a.get(l).getStartValue() < b.get(j).getEndValue())) && 
                ((b.get(j).getStartValue().equals(a.get(l).getEndValue())
                || b.get(j).getStartValue() < a.get(l).getEndValue())))
        {
            System.out.println("INNN*************");
            count++;
        }
    }
}
System.out.println("count********" + count);

7 个答案:

答案 0 :(得分:7)

您的算法为O(N^2);事实上,您可以在O(N log N)中轻松完成此操作,如下所示。

  • 按时间间隔对上限进行排序:O(N log N)
  • For-each interval:O(N)
    • 如果此区间的下限低于前一区间的上限,则重叠
  • 如果你没有在for-each中找到任何重叠,那么就没有重叠。

因此,对于您给出的两个测试用例,这就是它的工作方式:

Input:
  (2, 10), (2, 3), (8, 12)

Sorted by upper bound:
  (2, 3), (2, 10), (8, 12)
      |____|
      FOUND OVERLAP!

Input:
  (2, 10), (0, 1), (11, 12)

Sorted by upper bound:
  (0, 1), (2, 10), (11, 12)
      |____|   |____|
        OK!      OK!        NO OVERLAP!

要在Java中执行此操作,您需要使用:

答案 1 :(得分:2)

这是一个小测试案例:

package playground.tests;

import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;
import playground.Range;

public class NonoverlappingRangeListsTest extends TestCase {
    public void testOverlap() throws Exception {
        assertFalse(new Range(0, 5).overlaps(new Range(6, 7)));
        assertTrue(new Range(0, 5).overlaps(new Range(3, 7)));
        assertTrue(new Range(0, 5).overlaps(new Range(7, 3)));
        assertTrue(new Range(0, 5).overlaps(new Range(-1, 0)));
        assertTrue(new Range(0, 5).overlaps(new Range(5, 6)));
        assertTrue(new Range(0, 5).overlaps(new Range(2, 3)));
    }

    public void testIsNonoverlappingList() throws Exception {
        List<Range> list = new ArrayList<Range>();
        assertTrue(Range.isNonoverlapping(list));
        list.add(new Range(0, 5));
        list.add(new Range(6, 7));
        assertTrue(Range.isNonoverlapping(list));
        list.add(new Range(2, 3));
        assertFalse(Range.isNonoverlapping(list));

    }
}

通过测试的课程:

package playground;

import java.util.List;

public class Range {

    private final int from;

    private final int to;

    public Range(int from, int to) {
        this.from = Math.min(from, to);
        this.to = Math.max(from, to);
    }

    public boolean overlaps(Range that) {
        return this.from <= that.to && that.from <= this.to;
    }

    public static boolean isNonoverlapping(List<Range> ranges) {
        for (int i = 0; i < ranges.size(); i++)
            for (int j = i + 1; j < ranges.size(); j++)
                if (ranges.get(i).overlaps(ranges.get(j)))
                    return false;
        return true;
    }

}

答案 2 :(得分:1)

伪代码:

foreach i1 in interval
   foreach i2 in interval
      if (i1 != i2)
         if (overlap(i1, i2))
            return true;

清楚?

答案 3 :(得分:1)

您可以使用您可以获得的最大数量的大小来创建和布尔数组,例如bool mem[MAX_SIZE],然后对于每个行,您将在该布尔数组中将相应的TO-FROM范围设置为{{ 1}},true表示此位置已被占用。

这样的事情:

true

然后,当您想要处理行时,如您的示例所述,发出非法操作信号的充分条件是TO或FROM与已处理的时间间隔重叠

void mark(int to, int from){
  for(int i=to; i<= from; i++)
     mem[i] = true; //falls into an already-existing interval
}

如果你的MAX_SIZE相对较大,那么数组会变得更大,但它会比一些嵌套的for循环节省你的处理时间。

答案 4 :(得分:1)

我会这样做:

public boolean overlap(List<Interval> intervals) {
    int countMinusOne = intervals.size() - 1;

    for (int i = 0; i < countMinusOne; i++) {
        Interval first = intervals.get(i);

        for (int j = i + 1; j <= countMinusOne; j++) {
            Interval second = intervals.get(j);

            if (second.getStart() <= first.getEnd() &&
                second.getEnd() >= first.getStart()) return true;
        }
    }

    return false;
}

这假定间隔的开始始终小于间隔的结束。它尽可能少地进行检查。

答案 5 :(得分:1)

看起来这里的很多答案都非常适合。但是,对此有一个很好理解的数据结构可能对您有用:Interval Tree

答案 6 :(得分:0)

设置数字=新的HashSet()

虽然有更多数字 {    读下一个号码;如果不存在数字继续其他失败验证; }

(或者我完全误解了这个问题......)