Given a set of intervals, for each of the interval i, check if there exists an interval j whose start point is bigger than or equal to the end point of the interval i, which can be called that j is on the "right" of i. For any interval i, you need to store the minimum interval j's index, which means that the interval j has the minimum start point to build the "right" relationship for interval i. If the interval j doesn't exist, store -1 for the interval i. Finally, you need output the stored value of each interval as an array. Note: You may assume the interval's end point is always bigger than its start point. You may assume none of these intervals have the same start point. Example 1: Input: [ [1,2] ] Output: [-1] Explanation: There is only one interval in the collection, so it outputs -1. Example 2: Input: [ [3,4], [2,3], [1,2] ] Output: [-1, 0, 1] Explanation: There is no satisfied "right" interval for [3,4]. For [2,3], the interval [3,4] has minimum-"right" start point; For [1,2], the interval [2,3] has minimum-"right" start point. Example 3: Input: [ [1,4], [2,3], [3,4] ] Output: [-1, 2, -1] Explanation: There is no satisfied "right" interval for [1,4] and [3,4]. For [2,3], the interval [3,4] has minimum-"right" start point. NOTE: input types have been changed on April 15, 2019. Please reset to default code definition to get new method signature.
假設一個二維的整數數組中每一行表示一個區間,每一行的第一個值表示區間的左邊界,第二個值表示區間的右邊界。如今要求返回一個整數數組,用來記錄每個邊界右側最鄰近的區間。java
如[ [1,4], [2,3], [3,4] ]
表示三個區間,[1,4]不存在最鄰近右區間,所以[1,4]的最鄰近右區間的位置爲-1。[2,3]最鄰近右區間爲[3,4],所以返回2,[3,4]也不存在最臨近右區間,所以也返回-1。最終函數返回數組[-1,2,-1]。數組
若是咱們將區間按照左邊界進行排序,則針對每個區間的右邊界,只要找到左邊界比這個值大的最小左邊界所在的區間便可。這裏不可以直接對原來的二維數組進行排序,由於會丟失每個區間的原始下標位置。代碼中採用了內部類Node來記錄每個區間的左邊界以及每個區間的原始下標,並對Node進行排序和二分法查找。代碼以下:ide
public int[] findRightInterval(int[][] intervals) { int[] result = new int[intervals.length]; Arrays.fill(result, -1); Node[] leftIndex = new Node[intervals.length]; for(int i = 0 ; i<intervals.length ; i++) { Node n = new Node(); n.index = i; n.value = intervals[i][0]; leftIndex[i] = n; } Arrays.sort(leftIndex); for(int i = 0 ; i<intervals.length ; i++) { int rightIndex = intervals[i][1]; int left = 0, right = intervals.length-1; while(left <=right) { int mid = (left + right) / 2; Node tmp = leftIndex[mid]; if(tmp.value > rightIndex) { right = mid - 1; }else { left = mid + 1; } } if(leftIndex[right].value == rightIndex) { result[i] = leftIndex[right].index; }else if(right<intervals.length-1) { result[i] = leftIndex[right+1].index; } } return result; } public static class Node implements Comparable<Node>{ int value; int index; @Override public int compareTo(Node o) { // TODO Auto-generated method stub return this.value - o.value; } }
換一種思路,有沒有辦法將全部的區間用一維數組的方式展開,一維數組的每個下標上的值,都記錄了該位置所在的右側第一個區間。具體流程以下:函數
[3,4], [2,3], [1,2]
的三個區間,展開來後咱們知道這裏的三個區間橫跨了[1,4]這麼一個區間代碼以下:ui
public int[] findRightInterval(int[][] intervals) { int[] result = new int[intervals.length]; int min = intervals[0][0], max = intervals[0][1]; for(int i = 1 ; i<intervals.length ; i++) { min = Math.min(min, intervals[i][0]); max = Math.max(max, intervals[i][1]); } int[] buckets = new int[max - min + 1]; Arrays.fill(buckets, -1); for(int i = 0 ; i<intervals.length ; i++) { buckets[intervals[i][0] - min] = i; } for(int i = buckets.length-2 ; i>=0 ; i--) { if(buckets[i] == -1) buckets[i] = buckets[i+1]; } for(int i = 0 ; i<intervals.length ; i++) { result[i] = buckets[intervals[i][1] - min]; } return result; }
這裏的核心思路在於,如何理解bucket數組,這個bucket數組本質上是將全部的區間以最左邊界和最右邊界展開,數組的每個下標對應着區間中的相對位置,並記錄了這個下標右側的第一個區間的位置。this