-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathIntervalTree.java
108 lines (85 loc) · 2.57 KB
/
IntervalTree.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package gfg.ds.advanced;
import utils.Pair;
import java.util.Optional;
/** @noinspection WeakerAccess */
public class IntervalTree {
private IntervalTreeNode root;
public IntervalTreeNode getRoot() {
return root;
}
/** t=O(log n) */
public IntervalTree insert(Pair<Integer, Integer> interval) {
assert !isInvalid(interval) : String.format("Interval not valid:%s", interval);
IntervalTreeNode newNode = new IntervalTreeNode(interval, interval.value);
if (isEmpty()) {
root = newNode;
return this;
}
IntervalTreeNode prev = null;
IntervalTreeNode curr = root;
for (; curr != null; ) {
assert !curr.interval.equals(interval) : String.format("Duplicate data: %s", interval);
curr.maxInTree = Math.max(curr.maxInTree, newNode.maxInTree);
prev = curr;
curr = interval.key < curr.interval.key ? curr.left : curr.right;
}
assert prev != null;
if (interval.key < prev.interval.key) {
prev.left = newNode;
} else {
prev.right = newNode;
}
return this;
}
public boolean isEmpty() {
return root == null;
}
private boolean isInvalid(Pair<Integer, Integer> interval) {
return interval == null || interval.key > interval.value;
}
/** t=O(log n) */
public Optional<Pair<Integer, Integer>> overlapSearch(Pair<Integer, Integer> interval) {
if (isEmpty()) {
return Optional.empty();
}
IntervalTreeNode curr = root;
for (; curr != null; ) {
if (isOverlapping(curr.interval, interval)) {
return Optional.of(curr.interval);
}
if (curr.left != null && curr.maxInTree >= interval.key) {
curr = curr.left;
} else {
curr = curr.right;
}
}
return Optional.empty();
}
private boolean isOverlapping(
Pair<Integer, Integer> interval1, Pair<Integer, Integer> interval2) {
boolean notOverlapping = interval1.value < interval2.key || interval1.key > interval2.value;
return !notOverlapping;
}
public static class IntervalTreeNode {
private Pair<Integer, Integer> interval;
private int maxInTree;
private IntervalTreeNode left;
private IntervalTreeNode right;
public IntervalTreeNode(Pair<Integer, Integer> interval, int maxInTree) {
this.interval = interval;
this.maxInTree = maxInTree;
}
public Pair<Integer, Integer> getInterval() {
return interval;
}
public int getMaxInTree() {
return maxInTree;
}
public IntervalTreeNode getLeft() {
return left;
}
public IntervalTreeNode getRight() {
return right;
}
}
}