diff --git a/java/find-building-where-alice-and-bob-can-meet.java b/java/find-building-where-alice-and-bob-can-meet.java new file mode 100644 index 0000000..f9b40fb --- /dev/null +++ b/java/find-building-where-alice-and-bob-can-meet.java @@ -0,0 +1,71 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +class Solution { + private record Query(int height, int index) {} + + private static List> process(int[] heights, int[][] originalQueries, int[] result) { + List> queries = new ArrayList<>(heights.length); + for (var i = 0; i < heights.length; ++i) { + queries.add(new ArrayList<>()); + } + + for (var i = 0; i < originalQueries.length; ++i) { + int a = Math.min(originalQueries[i][0], originalQueries[i][1]); + int b = Math.max(originalQueries[i][0], originalQueries[i][1]); + + if (heights[b] > heights[a] || a == b) { + result[i] = b; + } else { + queries.get(b).add(new Query(heights[a], i)); + } + } + + return queries; + } + + private int search(List stack, int height) { + int l = 0; + int r = stack.size() - 1; + + var index = -1; + while (l <= r) { + var mid = (l + r) / 2; + if (stack.get(mid).height > height) { + index = Math.max(index, mid); + l = mid + 1; + } else { + r = mid - 1; + } + } + + return index; + } + + public int[] leftmostBuildingQueries(int[] heights, int[][] originalQueries) { + var result = new int[originalQueries.length]; + Arrays.fill(result, -1); + + var queries = process(heights, originalQueries, result); + + List stack = new ArrayList<>(); + for (var i = heights.length - 1; i >= 0; --i) { + var size = stack.size(); + for (var q : queries.get(i)) { + var pos = search(stack, q.height); + if (pos < size && pos >= 0) { + result[q.index] = stack.get(pos).index; + } + } + + while (!stack.isEmpty() && stack.get(stack.size() - 1).height <= heights[i]) { + stack.remove(stack.size() - 1); + } + + stack.add(new Query(heights[i], i)); + } + + return result; + } +}