Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fc4d94f

Browse files
Merge pull request #12 from borrelunde/problem_0436_find_right_interval
LeetCode problem: 436. Find Right Interval
2 parents 26a0855 + 7cd3cc9 commit fc4d94f

File tree

3 files changed

+299
-0
lines changed

3 files changed

+299
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# 436. Find Right Interval
2+
3+
Difficulty: `Medium`
4+
Topics: `Array`, `Binary Search`, `Sorting`
5+
6+
You are given an array of `intervals`, where `intervals[i] = [start_i, end_i]` and each `start_i` is **unique**.
7+
8+
The **right interval** for an interval `i` is an interval `j` such that `start_j >= end_i` and `start_j` is
9+
**minimized**. Note that `i` may equal `j`.
10+
11+
Return *an array of **right interval** indices for each interval `i`*. If no **right interval** exists for interval `i`,
12+
then put `-1` at index `i`.
13+
14+
**Example 1:**
15+
16+
```text
17+
Input: intervals = [[1,2]]
18+
Output: [-1]
19+
Explanation: There is only one interval in the collection, so it outputs -1.
20+
```
21+
22+
**Example 2:**
23+
24+
```text
25+
Input: intervals = [[3,4],[2,3],[1,2]]
26+
Output: [-1,0,1]
27+
Explanation: There is no right interval for [3,4].
28+
The right interval for [2,3] is [3,4] since start_0 = 3 is the smallest start that is >= end_1 = 3.
29+
The right interval for [1,2] is [2,3] since start_1 = 2 is the smallest start that is >= end_2 = 2.
30+
```
31+
32+
**Example 3:**
33+
34+
```text
35+
Input: intervals = [[1,4],[2,3],[3,4]]
36+
Output: [-1,2,-1]
37+
Explanation: There is no right interval for [1,4] and [3,4].
38+
The right interval for [2,3] is [3,4] since start_2 = 3 is the smallest start that is >= end_1 = 3.
39+
```
40+
41+
**Constraints:**
42+
43+
- `1 <= intervals.length <= 2 * 10^4`
44+
- `intervals[i].length == 2`
45+
- `-10^6 <= start_i <= end_i <= 10^6`
46+
- The start point of each interval is **unique**.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package com.borrelunde.leetcodesolutions.problem0436.findrightinterval;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* This is the solution to the LeetCode problem: 436. Find Right Interval
8+
*
9+
* @author Børre A. Opedal Lunde
10+
* @since 2024年02月09日
11+
*/
12+
public class Solution {
13+
14+
private static final int INVALID_INDEX = - 1;
15+
16+
public int[] findRightInterval(int[][] intervals) {
17+
18+
// Map to store the start value and index of each interval.
19+
Map<Integer, Integer> intervalStartValueByIndex = new HashMap<>();
20+
for (int i = 0; i < intervals.length; i++) {
21+
intervalStartValueByIndex.put(intervals[i][0], i);
22+
}
23+
24+
// Sort the intervals so that a binary search can be used on it.
25+
sort(intervals);
26+
27+
// The array to store the right interval indices.
28+
int[] result = new int[intervals.length];
29+
30+
// Find the right interval for each interval.
31+
for (int[] interval : intervals) {
32+
int intervalIndex = intervalStartValueByIndex.get(interval[0]);
33+
int rightIntervalIndex = binarySearch(intervals, interval[1]);
34+
result[intervalIndex] = rightIntervalIndex == INVALID_INDEX
35+
? INVALID_INDEX
36+
: intervalStartValueByIndex.get(intervals[rightIntervalIndex][0]);
37+
}
38+
39+
// Return the right interval indices array.
40+
return result;
41+
}
42+
43+
private static int binarySearch(int[][] intervals, int target) {
44+
45+
int low = 0;
46+
int high = intervals.length - 1;
47+
48+
while (low <= high) {
49+
// Calculate the middle index of the array. Bitwise shift to the
50+
// right is the same as dividing by 2, but faster.
51+
int middle = low + ((high - low) >> 1);
52+
53+
if (intervals[middle][0] >= target) {
54+
high = middle - 1;
55+
} else {
56+
low = middle + 1;
57+
}
58+
}
59+
60+
// After the loop, low is the smallest index of the interval whose start
61+
// value is greater than or equal to the target. However, we need to
62+
// check if it is within the bounds of the array. If it is not, then
63+
// the target was not found.
64+
65+
return low < intervals.length ? low : INVALID_INDEX;
66+
}
67+
68+
private static void sort(int[][] matrix) {
69+
70+
// A temporary matrix is used in the sorting algorithm to store sorted
71+
// elements before it is copied to the original matrix.
72+
int[][] tempMatrix = new int[matrix.length][2];
73+
74+
// Start the recursive merge-sorting process.
75+
mergeSort(matrix, tempMatrix, 0, matrix.length - 1);
76+
}
77+
78+
private static void mergeSort(int[][] matrix, int[][] tempMatrix, int low, int high) {
79+
80+
// If the matrix has 0 or 1 elements, it's already sorted.
81+
if (low >= high) {
82+
return; // Break out of recursion.
83+
}
84+
85+
// Calculate the middle index of the array. Bitwise shift to the right
86+
// is the same as dividing by 2, but faster.
87+
int middle = low + ((high - low) >> 1);
88+
mergeSort(matrix, tempMatrix, low, middle); // Sort the left half.
89+
mergeSort(matrix, tempMatrix, middle + 1, high); // Sort the right half.
90+
merge(matrix, tempMatrix, low, middle, high); // Merge the two sorted halves.
91+
}
92+
93+
private static void merge(int[][] matrix, int[][] tempMatrix, int low, int middle, int high) {
94+
95+
// Indices for left and right halves, and the temporary helper matrix.
96+
int left = low;
97+
int right = middle + 1;
98+
int temp = 0;
99+
100+
// Merge left and right halves into the temporary matrix.
101+
while (left <= middle && right <= high) {
102+
if (matrix[left][0] <= matrix[right][0]) {
103+
tempMatrix[temp++] = matrix[left++];
104+
} else {
105+
tempMatrix[temp++] = matrix[right++];
106+
}
107+
}
108+
109+
// If there are remaining elements in the left half, copy them into the
110+
// temporary matrix.
111+
while (left <= middle) {
112+
tempMatrix[temp++] = matrix[left++];
113+
}
114+
115+
// The same goes for the right half.
116+
while (right <= high) {
117+
tempMatrix[temp++] = matrix[right++];
118+
}
119+
120+
// Finally, copy the sorted elements from the temporary matrix to the
121+
// original matrix.
122+
for (int i = 0; i < temp; i++) {
123+
matrix[low + i] = tempMatrix[i];
124+
}
125+
}
126+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package com.borrelunde.leetcodesolutions.problem0436.findrightinterval;
2+
3+
import org.junit.jupiter.api.DisplayName;
4+
import org.junit.jupiter.api.Test;
5+
6+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
7+
8+
/**
9+
* This is the test to the LeetCode problem: 463. Find Right Interval
10+
*
11+
* @author Børre A. Opedal Lunde
12+
* @since 2024年02月09日
13+
*/
14+
@DisplayName("Find Right Interval")
15+
class SolutionTest {
16+
17+
private final Solution solution = new Solution();
18+
19+
@Test
20+
@DisplayName("Example one")
21+
void exampleOne() {
22+
int[][] intervals = new int[][]{
23+
{1, 2}
24+
};
25+
26+
int[] expected = new int[]{- 1};
27+
int[] actual = solution.findRightInterval(intervals);
28+
29+
assertArrayEquals(expected, actual);
30+
}
31+
32+
@Test
33+
@DisplayName("Example two")
34+
void exampleTwo() {
35+
int[][] intervals = new int[][]{
36+
{3, 4},
37+
{2, 3},
38+
{1, 2}
39+
};
40+
41+
int[] expected = new int[]{- 1, 0, 1};
42+
int[] actual = solution.findRightInterval(intervals);
43+
44+
assertArrayEquals(expected, actual);
45+
}
46+
47+
@Test
48+
@DisplayName("Example three")
49+
void exampleThree() {
50+
int[][] intervals = new int[][]{
51+
{1, 4},
52+
{2, 3},
53+
{3, 4}
54+
};
55+
56+
int[] expected = new int[]{- 1, 2, - 1};
57+
int[] actual = solution.findRightInterval(intervals);
58+
59+
assertArrayEquals(expected, actual);
60+
}
61+
62+
@Test
63+
@DisplayName("Empty matrix")
64+
void emptyMatrix() {
65+
int[][] intervals = new int[][]{
66+
// Empty.
67+
};
68+
69+
int[] expected = new int[]{};
70+
int[] actual = solution.findRightInterval(intervals);
71+
72+
assertArrayEquals(expected, actual);
73+
}
74+
75+
@Test
76+
@DisplayName("Large interval that encompasses others")
77+
void largeIntervalEncompassesOthers() {
78+
int[][] intervals = {
79+
{1, 100},
80+
{2, 3},
81+
{4, 5},
82+
{6, 7}
83+
};
84+
int[] expected = {- 1, 2, 3, - 1};
85+
int[] actual = solution.findRightInterval(intervals);
86+
assertArrayEquals(expected, actual);
87+
}
88+
89+
@Test
90+
@DisplayName("Non-overlapping, consecutive intervals")
91+
void nonOverlappingConsecutiveIntervals() {
92+
int[][] intervals = {
93+
{1, 2},
94+
{2, 3},
95+
{3, 4}
96+
};
97+
int[] expected = {1, 2, - 1};
98+
int[] actual = solution.findRightInterval(intervals);
99+
assertArrayEquals(expected, actual);
100+
}
101+
102+
@Test
103+
@DisplayName("Reverse ordered intervals")
104+
void reverseOrderedIntervals() {
105+
int[][] intervals = {
106+
{3, 4},
107+
{2, 3},
108+
{1, 2}
109+
};
110+
int[] expected = {- 1, 0, 1};
111+
int[] actual = solution.findRightInterval(intervals);
112+
assertArrayEquals(expected, actual);
113+
}
114+
115+
@Test
116+
@DisplayName("Intervals with large numbers")
117+
void intervalsWithLargeNumbers() {
118+
int[][] intervals = {
119+
{1000000, 2000000},
120+
{2000000, 3000000},
121+
{3000000, 4000000}
122+
};
123+
int[] expected = {1, 2, - 1};
124+
int[] actual = solution.findRightInterval(intervals);
125+
assertArrayEquals(expected, actual);
126+
}
127+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /