I experimented with some tree structures, but ended up returning to a simple binary search, so now it is O (nlogn):
static int getAnswerV2a(int[] A, int[] B, int[] C) { int len = A.length; ArrayList<Interval> intervals = new ArrayList<Interval>(len); for (int i=0; i<len; i++) { intervals.add(new Interval(A[i], B[i])); } for (int i = 0; i < C.length; i++) { int c = C[i]; binarySearch(intervals, 0, intervals.size(), c); if (intervals.isEmpty()) return i+1; } return -1; } static class Interval { int start, end; Interval(int start, int end) { this.start = start; this.end = end; } boolean matches(int c) { return start <= c && c <= end; } } // Find an interval (between indices i and j) that matches c // When found, remove it from the List and adjust indices accordingly static void binarySearch(ArrayList<Interval> intervals, int i, int j, int c) { if (i==j) return; else if (i+1==j) { if (intervals.get(i).matches(c)) intervals.remove(i); } else { int mid = (int) Math.floor((i+j) / 2); Interval interval = intervals.get(mid); if (interval.start > c) binarySearch(intervals, i, mid, c); else if (interval.end < c) binarySearch(intervals, mid+1, j, c); else { intervals.remove(mid); binarySearch(intervals, i, j-1, c); } } }
source share