Skip to content

Commit b4ddf1e

Browse files
committed
refactor: edit 2D ORS following comments
1 parent 25301d4 commit b4ddf1e

File tree

2 files changed

+34
-45
lines changed

2 files changed

+34
-45
lines changed

src/main/java/algorithms/orthogonalRangeSearching/twoDim/OrthogonalRangeSearching.java

Lines changed: 28 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,13 @@ public static RangeTreeNode<Integer[]> buildXTree(List<Integer[]> inputs, int st
2424

2525
if (start > end) {
2626
return null;
27-
} else if (end - start + 1 > 3) {
28-
RangeTreeNode<Integer[]> node = new RangeTreeNode<>(inputs.get(mid), buildXTree(inputs, start, mid),
29-
buildXTree(inputs, mid + 1, end));
30-
node.setYTree(buildYTree(inputs, start, end));
31-
return node;
32-
} else if (end - start + 1 == 3) {
33-
RangeTreeNode<Integer[]> node = new RangeTreeNode<>(inputs.get(mid), buildXTree(inputs, start, mid),
34-
buildXTree(inputs, end, end));
35-
node.setYTree(buildYTree(inputs, start, end));
36-
return node;
37-
} else if (end - start + 1 == 2) {
38-
RangeTreeNode<Integer[]> node = new RangeTreeNode<>(inputs.get(mid),
39-
buildXTree(inputs, start, start),
40-
buildXTree(inputs, end, end));
27+
} else if (start == end) {
28+
RangeTreeNode<Integer[]> node = new RangeTreeNode<>(inputs.get(mid));
4129
node.setYTree(buildYTree(inputs, start, end));
4230
return node;
4331
} else {
44-
RangeTreeNode<Integer[]> node = new RangeTreeNode<>(inputs.get(mid));
32+
RangeTreeNode<Integer[]> node = new RangeTreeNode<>(inputs.get(mid), buildXTree(inputs, start, mid),
33+
buildXTree(inputs, mid + 1, end));
4534
node.setYTree(buildYTree(inputs, start, end));
4635
return node;
4736
}
@@ -58,7 +47,6 @@ public static RangeTreeNode<Integer[]> buildXTree(List<Integer[]> inputs, int st
5847
*/
5948
private static RangeTreeNode<Integer[]> buildYTree(List<Integer[]> inputs, int start, int end) {
6049

61-
int mid = (end + start) / 2;
6250
List<Integer[]> ySortedSublist = inputs.subList(start, end + 1);
6351
ySortedSublist.sort(Comparator.comparingInt(a -> a[1])); //sort by y-coordinate
6452

@@ -80,17 +68,11 @@ private static RangeTreeNode<Integer[]> buildYTreeHelper(List<Integer[]> inputs,
8068

8169
if (start > end) {
8270
return null;
83-
} else if (end - start + 1 > 3) {
71+
} else if (start == end) {
72+
return new RangeTreeNode<>(inputs.get(start));
73+
} else {
8474
return new RangeTreeNode<>(inputs.get(mid), buildYTree(inputs, start, mid),
8575
buildYTree(inputs, mid + 1, end));
86-
} else if (end - start + 1 == 3) {
87-
return new RangeTreeNode<>(inputs.get(mid), buildYTree(inputs, start, mid),
88-
buildYTree(inputs, end, end));
89-
} else if (end - start + 1 == 2) {
90-
return new RangeTreeNode<>(inputs.get(mid), buildYTree(inputs, start, start),
91-
buildYTree(inputs, end, end));
92-
} else {
93-
return new RangeTreeNode<>(inputs.get(mid));
9476
}
9577
}
9678

@@ -133,7 +115,7 @@ public static RangeTreeNode<Integer[]> findXSplit(RangeTreeNode<Integer[]> root,
133115
public static void XLeftTraversal(RangeTreeNode<Integer[]> v, int xLow, int xHigh, int yLow, int yHigh,
134116
ArrayList<Integer[]> result) {
135117
if (v != null) {
136-
if (v.getLeft() == null && v.getRight() == null && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf
118+
if (isLeaf(v) && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf
137119
YSearch(v, yLow, yHigh, result);
138120
} else {
139121
if (xLow <= v.getVal()[0]) {
@@ -158,7 +140,7 @@ public static void XLeftTraversal(RangeTreeNode<Integer[]> v, int xLow, int xHig
158140
public static void XRightTraversal(RangeTreeNode<Integer[]> v, int xLow, int xHigh, int yLow, int yHigh,
159141
ArrayList<Integer[]> result) {
160142
if (v != null) {
161-
if (v.getLeft() == null && v.getRight() == null && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf
143+
if (isLeaf(v) && v.getVal()[0] >= xLow && v.getVal()[0] <= xHigh) { //leaf
162144
YSearch(v, yLow, yHigh, result);
163145
} else {
164146
if (xHigh >= v.getVal()[0]) {
@@ -186,7 +168,7 @@ public static RangeTreeNode<Integer[]> findYSplit(RangeTreeNode<Integer[]> root,
186168
return null;
187169
} else {
188170
if (yHigh <= v.getVal()[1]) {
189-
if (v.getLeft() == null && v.getRight() == null) { // extra check since ysplit might be leaf node
171+
if (isLeaf(v)) { // extra check since ysplit might be leaf node
190172
break;
191173
} else {
192174
v = v.getLeft();
@@ -212,7 +194,7 @@ public static void allLeafTraversal(RangeTreeNode<Integer[]> v, List<Integer[]>
212194
if (v.getLeft() != null) {
213195
allLeafTraversal(v.getLeft(), result);
214196
}
215-
if (v.getLeft() == null && v.getRight() == null) { // leaf
197+
if (isLeaf(v)) {
216198
result.add(v.getVal());
217199
}
218200
if (v.getRight() != null) {
@@ -228,16 +210,16 @@ public static void allLeafTraversal(RangeTreeNode<Integer[]> v, List<Integer[]>
228210
* @param low The lower bound of the Y-coordinate range.
229211
* @param result A list to store the results.
230212
*/
231-
public static void leftTraversal(RangeTreeNode<Integer[]> v, int low, List<Integer[]> result) {
213+
public static void YLeftTraversal(RangeTreeNode<Integer[]> v, int low, List<Integer[]> result) {
232214
if (v != null) {
233-
if (v.getLeft() == null && v.getRight() == null) { // leaf
215+
if (isLeaf(v)) {
234216
result.add(v.getVal());
235217
} else {
236218
if (low <= v.getVal()[1]) {
237-
leftTraversal(v.getLeft(), low, result);
219+
YLeftTraversal(v.getLeft(), low, result);
238220
allLeafTraversal(v.getRight(), result);
239221
} else { // definitely a qualifying leaf has to exist
240-
leftTraversal(v.getRight(), low, result);
222+
YLeftTraversal(v.getRight(), low, result);
241223
}
242224
}
243225
}
@@ -250,16 +232,16 @@ public static void leftTraversal(RangeTreeNode<Integer[]> v, int low, List<Integ
250232
* @param high The upper bound of the Y-coordinate range.
251233
* @param result A list to store the results.
252234
*/
253-
public static void rightTraversal(RangeTreeNode<Integer[]> v, int high, List<Integer[]> result) {
235+
public static void YRightTraversal(RangeTreeNode<Integer[]> v, int high, List<Integer[]> result) {
254236
if (v != null) {
255-
if (v.getLeft() == null && v.getRight() == null && v.getVal()[1] <= high) { // leaf, need extra check
237+
if (isLeaf(v) && v.getVal()[1] <= high) { // leaf, need extra check
256238
result.add(v.getVal());
257239
} else {
258240
if (high > v.getVal()[1]) {
259241
allLeafTraversal(v.getLeft(), result);
260-
rightTraversal(v.getRight(), high, result);
242+
YRightTraversal(v.getRight(), high, result);
261243
} else { // a qualifying leaf might or might not exist, we are just exploring
262-
rightTraversal(v.getLeft(), high, result);
244+
YRightTraversal(v.getLeft(), high, result);
263245
}
264246
}
265247
}
@@ -275,15 +257,14 @@ public static void rightTraversal(RangeTreeNode<Integer[]> v, int high, List<Int
275257
*/
276258
public static void YSearch(RangeTreeNode<Integer[]> v, int yLow, int yHigh, ArrayList<Integer[]> result) {
277259
if (v != null) {
278-
System.out.println(v.getVal()[0]);
279260
RangeTreeNode<Integer[]> splitNodeY = findYSplit(v.getYTree(), yLow, yHigh);
280261
if (splitNodeY != null) {
281-
if (splitNodeY.getLeft() == null && splitNodeY.getRight() == null
262+
if (isLeaf(splitNodeY)
282263
&& splitNodeY.getVal()[1] >= yLow && splitNodeY.getVal()[1] <= yHigh) { // if split node is leaf
283264
result.add(splitNodeY.getVal());
284265
}
285-
leftTraversal(splitNodeY.getLeft(), yLow, result);
286-
rightTraversal(splitNodeY.getRight(), yHigh, result);
266+
YLeftTraversal(splitNodeY.getLeft(), yLow, result);
267+
YRightTraversal(splitNodeY.getRight(), yHigh, result);
287268
}
288269
}
289270
}
@@ -302,7 +283,7 @@ public static List<Integer[]> search(RangeTreeNode<Integer[]> tree, int xLow, in
302283
RangeTreeNode<Integer[]> splitNodeX = findXSplit(tree, xLow, xHigh);
303284
ArrayList<Integer[]> result = new ArrayList<>();
304285
if (splitNodeX != null) {
305-
if (splitNodeX.getLeft() == null && splitNodeX.getRight() == null
286+
if (isLeaf(splitNodeX)
306287
&& splitNodeX.getVal()[0] >= xLow && splitNodeX.getVal()[0] <= xHigh) { // if split node is leaf
307288
YSearch(splitNodeX, yLow, yHigh, result);
308289
}
@@ -311,4 +292,9 @@ public static List<Integer[]> search(RangeTreeNode<Integer[]> tree, int xLow, in
311292
}
312293
return result;
313294
}
295+
296+
private static <T> boolean isLeaf(RangeTreeNode<T> node) {
297+
return node.getLeft() == null && node.getRight() == null;
298+
}
299+
314300
}

src/main/java/algorithms/orthogonalRangeSearching/twoDim/README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ Given the 2D range tree, we now want to query the points in a given rectangle
2222
i.e. search(tree, xLow, xHigh, yLow, yHigh).
2323

2424
We first want to find the points that will satisfy the x-condition i.e. find me all points whose x-coordinates are
25-
between xLow and xHigh. To do so, we first need to find our split node in the x-tree, by performing binary search while
26-
traversing the x-tree - similar to how we found the split node in a 1D range tree. This will give us our X-split.
25+
between xLow and xHigh. To do so, we first need to find our split node in the x-tree, by performing binary search[^1]
26+
while traversing the x-tree - similar to how we found the split node in a 1D range tree. This will give us our X-split.
2727

2828
Now given our X-split, we want to find points that satisfy both our x-condition and y-condition.
2929

@@ -65,4 +65,7 @@ entirely rebuilding the y-trees for the rotated notes. Therefore, 2D ORS is main
6565
### d-dimensional Range Trees
6666
- Query cost: O(k + log^dn)
6767
- Build tree cost: O(nlog^(d-1)n)
68-
- Space: O(nlog^(d-1)n)
68+
- Space: O(nlog^(d-1)n)
69+
70+
[^1] This reference to binary search differs from our typical binary search formulation, but essentially refers
71+
to the findSplit function where you walk down the balanced tree and remove roughly half of the nodes each time.

0 commit comments

Comments
 (0)