diff --git a/solution/0400-0499/0436.Find Right Interval/README.md b/solution/0400-0499/0436.Find Right Interval/README.md index 880cdf33da7a9..35d3948ef0e58 100644 --- a/solution/0400-0499/0436.Find Right Interval/README.md +++ b/solution/0400-0499/0436.Find Right Interval/README.md @@ -69,7 +69,11 @@ tags: -### 方法一:二分查找 +### 方法一:排序 + 二分查找 + +我们可以将区间的起点和下标存入数组 `arr` 中,并按照起点进行排序。然后遍历区间数组,对于每个区间 `[_, ed]`,我们可以使用二分查找找到第一个起点大于等于 `ed` 的区间,即为其右侧区间,如果找到了,我们就将其下标存入答案数组中,否则存入 `-1`。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为区间的长度。 @@ -78,15 +82,13 @@ tags: ```python class Solution: def findRightInterval(self, intervals: List[List[int]]) -> List[int]: - for i, v in enumerate(intervals): - v.append(i) - intervals.sort() n = len(intervals) ans = [-1] * n - for _, e, i in intervals: - j = bisect_left(intervals, [e]) + arr = sorted((st, i) for i, (st, _) in enumerate(intervals)) + for i, (_, ed) in enumerate(intervals): + j = bisect_left(arr, (ed, -inf)) if j < n: - ans[i] = intervals[j][2] + ans[i] = arr[j][1] return ans ``` @@ -96,27 +98,30 @@ class Solution: class Solution { public int[] findRightInterval(int[][] intervals) { int n = intervals.length; - List starts = new ArrayList<>(); + int[][] arr = new int[n][0]; + for (int i = 0; i < n; ++i) { + arr[i] = new int[] {intervals[i][0], i}; + } + Arrays.sort(arr, (a, b) -> a[0] - b[0]); + int[] ans = new int[n]; for (int i = 0; i < n; ++i) { - starts.add(new int[] {intervals[i][0], i}); + int j = search(arr, intervals[i][1]); + ans[i] = j < n ? arr[j][1] : -1; } - starts.sort(Comparator.comparingInt(a -> a[0])); - int[] res = new int[n]; - int i = 0; - for (int[] interval : intervals) { - int left = 0, right = n - 1; - int end = interval[1]; - while (left < right) { - int mid = (left + right) >> 1; - if (starts.get(mid)[0] >= end) { - right = mid; - } else { - left = mid + 1; - } + return ans; + } + + private int search(int[][] arr, int x) { + int l = 0, r = arr.length; + while (l < r) { + int mid = (l + r) >> 1; + if (arr[mid][0] >= x) { + r = mid; + } else { + l = mid + 1; } - res[i++] = starts.get(left)[0] < end ? -1 : starts.get(left)[1]; } - return res; + return l; } } ``` @@ -128,25 +133,17 @@ class Solution { public: vector findRightInterval(vector>& intervals) { int n = intervals.size(); - vector> starts; + vector> arr; for (int i = 0; i < n; ++i) { - starts.emplace_back(make_pair(intervals[i][0], i)); + arr.emplace_back(intervals[i][0], i); } - sort(starts.begin(), starts.end()); - vector res; - for (auto interval : intervals) { - int left = 0, right = n - 1; - int end = interval[1]; - while (left < right) { - int mid = left + right >> 1; - if (starts[mid].first >= end) - right = mid; - else - left = mid + 1; - } - res.push_back(starts[left].first < end ? -1 : starts[left].second); + sort(arr.begin(), arr.end()); + vector ans; + for (auto& e : intervals) { + int j = lower_bound(arr.begin(), arr.end(), make_pair(e[1], -1)) - arr.begin(); + ans.push_back(j == n ? -1 : arr[j].second); } - return res; + return ans; } }; ``` @@ -154,35 +151,21 @@ public: #### Go ```go -func findRightInterval(intervals [][]int) []int { - n := len(intervals) - starts := make([][]int, n) - for i := 0; i < n; i++ { - starts[i] = make([]int, 2) - starts[i][0] = intervals[i][0] - starts[i][1] = i +func findRightInterval(intervals [][]int) (ans []int) { + arr := make([][2]int, len(intervals)) + for i, v := range intervals { + arr[i] = [2]int{v[0], i} } - sort.Slice(starts, func(i, j int) bool { - return starts[i][0] < starts[j][0] - }) - var res []int - for _, interval := range intervals { - left, right, end := 0, n-1, interval[1] - for left < right { - mid := (left + right) >> 1 - if starts[mid][0] >= end { - right = mid - } else { - left = mid + 1 - } - } - val := -1 - if starts[left][0] >= end { - val = starts[left][1] + sort.Slice(arr, func(i, j int) bool { return arr[i][0] < arr[j][0] }) + for _, e := range intervals { + j := sort.Search(len(arr), func(i int) bool { return arr[i][0] >= e[1] }) + if j < len(arr) { + ans = append(ans, arr[j][1]) + } else { + ans = append(ans, -1) } - res = append(res, val) } - return res + return } ``` @@ -191,28 +174,19 @@ func findRightInterval(intervals [][]int) []int { ```ts function findRightInterval(intervals: number[][]): number[] { const n = intervals.length; - const starts = Array.from({ length: n }).map(() => new Array(2)); - for (let i = 0; i < n; i++) { - starts[i][0] = intervals[i][0]; - starts[i][1] = i; - } - starts.sort((a, b) => a[0] - b[0]); - - return intervals.map(([_, target]) => { - let left = 0; - let right = n; - while (left < right) { - const mid = (left + right) >>> 1; - if (starts[mid][0] < target) { - left = mid + 1; + const arr: number[][] = Array.from({ length: n }, (_, i) => [intervals[i][0], i]); + arr.sort((a, b) => a[0] - b[0]); + return intervals.map(([_, ed]) => { + let [l, r] = [0, n]; + while (l < r) { + const mid = (l + r) >> 1; + if (arr[mid][0] >= ed) { + r = mid; } else { - right = mid; + l = mid + 1; } } - if (left >= n) { - return -1; - } - return starts[left][1]; + return l < n ? arr[l][1] : -1; }); } ``` diff --git a/solution/0400-0499/0436.Find Right Interval/README_EN.md b/solution/0400-0499/0436.Find Right Interval/README_EN.md index ffed5e3affe65..cd998e67c4bf7 100644 --- a/solution/0400-0499/0436.Find Right Interval/README_EN.md +++ b/solution/0400-0499/0436.Find Right Interval/README_EN.md @@ -68,7 +68,11 @@ The right interval for [2,3] is [3,4] since start2 = 3 is the smalles -### Solution 1 +### Solution 1: Sorting + Binary Search + +We can store the start point and index of each interval into an array `arr`, and sort it by the start point. Then we iterate through the interval array, for each interval `[_, ed]`, we can use binary search to find the first interval whose start point is greater than or equal to `ed`, which is its right-side interval. If found, we store its index into the answer array, otherwise, we store `-1`. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$. Where $n$ is the length of the intervals. @@ -77,15 +81,13 @@ The right interval for [2,3] is [3,4] since start2 = 3 is the smalles ```python class Solution: def findRightInterval(self, intervals: List[List[int]]) -> List[int]: - for i, v in enumerate(intervals): - v.append(i) - intervals.sort() n = len(intervals) ans = [-1] * n - for _, e, i in intervals: - j = bisect_left(intervals, [e]) + arr = sorted((st, i) for i, (st, _) in enumerate(intervals)) + for i, (_, ed) in enumerate(intervals): + j = bisect_left(arr, (ed, -inf)) if j < n: - ans[i] = intervals[j][2] + ans[i] = arr[j][1] return ans ``` @@ -95,27 +97,30 @@ class Solution: class Solution { public int[] findRightInterval(int[][] intervals) { int n = intervals.length; - List starts = new ArrayList<>(); + int[][] arr = new int[n][0]; + for (int i = 0; i < n; ++i) { + arr[i] = new int[] {intervals[i][0], i}; + } + Arrays.sort(arr, (a, b) -> a[0] - b[0]); + int[] ans = new int[n]; for (int i = 0; i < n; ++i) { - starts.add(new int[] {intervals[i][0], i}); + int j = search(arr, intervals[i][1]); + ans[i] = j < n ? arr[j][1] : -1; } - starts.sort(Comparator.comparingInt(a -> a[0])); - int[] res = new int[n]; - int i = 0; - for (int[] interval : intervals) { - int left = 0, right = n - 1; - int end = interval[1]; - while (left < right) { - int mid = (left + right) >> 1; - if (starts.get(mid)[0] >= end) { - right = mid; - } else { - left = mid + 1; - } + return ans; + } + + private int search(int[][] arr, int x) { + int l = 0, r = arr.length; + while (l < r) { + int mid = (l + r) >> 1; + if (arr[mid][0] >= x) { + r = mid; + } else { + l = mid + 1; } - res[i++] = starts.get(left)[0] < end ? -1 : starts.get(left)[1]; } - return res; + return l; } } ``` @@ -127,25 +132,17 @@ class Solution { public: vector findRightInterval(vector>& intervals) { int n = intervals.size(); - vector> starts; + vector> arr; for (int i = 0; i < n; ++i) { - starts.emplace_back(make_pair(intervals[i][0], i)); + arr.emplace_back(intervals[i][0], i); } - sort(starts.begin(), starts.end()); - vector res; - for (auto interval : intervals) { - int left = 0, right = n - 1; - int end = interval[1]; - while (left < right) { - int mid = left + right >> 1; - if (starts[mid].first >= end) - right = mid; - else - left = mid + 1; - } - res.push_back(starts[left].first < end ? -1 : starts[left].second); + sort(arr.begin(), arr.end()); + vector ans; + for (auto& e : intervals) { + int j = lower_bound(arr.begin(), arr.end(), make_pair(e[1], -1)) - arr.begin(); + ans.push_back(j == n ? -1 : arr[j].second); } - return res; + return ans; } }; ``` @@ -153,35 +150,21 @@ public: #### Go ```go -func findRightInterval(intervals [][]int) []int { - n := len(intervals) - starts := make([][]int, n) - for i := 0; i < n; i++ { - starts[i] = make([]int, 2) - starts[i][0] = intervals[i][0] - starts[i][1] = i +func findRightInterval(intervals [][]int) (ans []int) { + arr := make([][2]int, len(intervals)) + for i, v := range intervals { + arr[i] = [2]int{v[0], i} } - sort.Slice(starts, func(i, j int) bool { - return starts[i][0] < starts[j][0] - }) - var res []int - for _, interval := range intervals { - left, right, end := 0, n-1, interval[1] - for left < right { - mid := (left + right) >> 1 - if starts[mid][0] >= end { - right = mid - } else { - left = mid + 1 - } - } - val := -1 - if starts[left][0] >= end { - val = starts[left][1] + sort.Slice(arr, func(i, j int) bool { return arr[i][0] < arr[j][0] }) + for _, e := range intervals { + j := sort.Search(len(arr), func(i int) bool { return arr[i][0] >= e[1] }) + if j < len(arr) { + ans = append(ans, arr[j][1]) + } else { + ans = append(ans, -1) } - res = append(res, val) } - return res + return } ``` @@ -190,28 +173,19 @@ func findRightInterval(intervals [][]int) []int { ```ts function findRightInterval(intervals: number[][]): number[] { const n = intervals.length; - const starts = Array.from({ length: n }).map(() => new Array(2)); - for (let i = 0; i < n; i++) { - starts[i][0] = intervals[i][0]; - starts[i][1] = i; - } - starts.sort((a, b) => a[0] - b[0]); - - return intervals.map(([_, target]) => { - let left = 0; - let right = n; - while (left < right) { - const mid = (left + right) >>> 1; - if (starts[mid][0] < target) { - left = mid + 1; + const arr: number[][] = Array.from({ length: n }, (_, i) => [intervals[i][0], i]); + arr.sort((a, b) => a[0] - b[0]); + return intervals.map(([_, ed]) => { + let [l, r] = [0, n]; + while (l < r) { + const mid = (l + r) >> 1; + if (arr[mid][0] >= ed) { + r = mid; } else { - right = mid; + l = mid + 1; } } - if (left >= n) { - return -1; - } - return starts[left][1]; + return l < n ? arr[l][1] : -1; }); } ``` diff --git a/solution/0400-0499/0436.Find Right Interval/Solution.cpp b/solution/0400-0499/0436.Find Right Interval/Solution.cpp index 28acbe2ec7db9..9def4c71a6a99 100644 --- a/solution/0400-0499/0436.Find Right Interval/Solution.cpp +++ b/solution/0400-0499/0436.Find Right Interval/Solution.cpp @@ -2,24 +2,16 @@ class Solution { public: vector findRightInterval(vector>& intervals) { int n = intervals.size(); - vector> starts; + vector> arr; for (int i = 0; i < n; ++i) { - starts.emplace_back(make_pair(intervals[i][0], i)); + arr.emplace_back(intervals[i][0], i); } - sort(starts.begin(), starts.end()); - vector res; - for (auto interval : intervals) { - int left = 0, right = n - 1; - int end = interval[1]; - while (left < right) { - int mid = left + right >> 1; - if (starts[mid].first >= end) - right = mid; - else - left = mid + 1; - } - res.push_back(starts[left].first < end ? -1 : starts[left].second); + sort(arr.begin(), arr.end()); + vector ans; + for (auto& e : intervals) { + int j = lower_bound(arr.begin(), arr.end(), make_pair(e[1], -1)) - arr.begin(); + ans.push_back(j == n ? -1 : arr[j].second); } - return res; + return ans; } }; \ No newline at end of file diff --git a/solution/0400-0499/0436.Find Right Interval/Solution.go b/solution/0400-0499/0436.Find Right Interval/Solution.go index 773c2988423f1..93a7403d1c347 100644 --- a/solution/0400-0499/0436.Find Right Interval/Solution.go +++ b/solution/0400-0499/0436.Find Right Interval/Solution.go @@ -1,30 +1,16 @@ -func findRightInterval(intervals [][]int) []int { - n := len(intervals) - starts := make([][]int, n) - for i := 0; i < n; i++ { - starts[i] = make([]int, 2) - starts[i][0] = intervals[i][0] - starts[i][1] = i +func findRightInterval(intervals [][]int) (ans []int) { + arr := make([][2]int, len(intervals)) + for i, v := range intervals { + arr[i] = [2]int{v[0], i} } - sort.Slice(starts, func(i, j int) bool { - return starts[i][0] < starts[j][0] - }) - var res []int - for _, interval := range intervals { - left, right, end := 0, n-1, interval[1] - for left < right { - mid := (left + right) >> 1 - if starts[mid][0] >= end { - right = mid - } else { - left = mid + 1 - } + sort.Slice(arr, func(i, j int) bool { return arr[i][0] < arr[j][0] }) + for _, e := range intervals { + j := sort.Search(len(arr), func(i int) bool { return arr[i][0] >= e[1] }) + if j < len(arr) { + ans = append(ans, arr[j][1]) + } else { + ans = append(ans, -1) } - val := -1 - if starts[left][0] >= end { - val = starts[left][1] - } - res = append(res, val) } - return res + return } \ No newline at end of file diff --git a/solution/0400-0499/0436.Find Right Interval/Solution.java b/solution/0400-0499/0436.Find Right Interval/Solution.java index b4b633115c544..0a94c209dbc18 100644 --- a/solution/0400-0499/0436.Find Right Interval/Solution.java +++ b/solution/0400-0499/0436.Find Right Interval/Solution.java @@ -1,26 +1,29 @@ class Solution { public int[] findRightInterval(int[][] intervals) { int n = intervals.length; - List starts = new ArrayList<>(); + int[][] arr = new int[n][0]; for (int i = 0; i < n; ++i) { - starts.add(new int[] {intervals[i][0], i}); + arr[i] = new int[] {intervals[i][0], i}; } - starts.sort(Comparator.comparingInt(a -> a[0])); - int[] res = new int[n]; - int i = 0; - for (int[] interval : intervals) { - int left = 0, right = n - 1; - int end = interval[1]; - while (left < right) { - int mid = (left + right) >> 1; - if (starts.get(mid)[0] >= end) { - right = mid; - } else { - left = mid + 1; - } + Arrays.sort(arr, (a, b) -> a[0] - b[0]); + int[] ans = new int[n]; + for (int i = 0; i < n; ++i) { + int j = search(arr, intervals[i][1]); + ans[i] = j < n ? arr[j][1] : -1; + } + return ans; + } + + private int search(int[][] arr, int x) { + int l = 0, r = arr.length; + while (l < r) { + int mid = (l + r) >> 1; + if (arr[mid][0] >= x) { + r = mid; + } else { + l = mid + 1; } - res[i++] = starts.get(left)[0] < end ? -1 : starts.get(left)[1]; } - return res; + return l; } } \ No newline at end of file diff --git a/solution/0400-0499/0436.Find Right Interval/Solution.py b/solution/0400-0499/0436.Find Right Interval/Solution.py index 234154cc733d0..d934606579f1e 100644 --- a/solution/0400-0499/0436.Find Right Interval/Solution.py +++ b/solution/0400-0499/0436.Find Right Interval/Solution.py @@ -1,12 +1,10 @@ class Solution: def findRightInterval(self, intervals: List[List[int]]) -> List[int]: - for i, v in enumerate(intervals): - v.append(i) - intervals.sort() n = len(intervals) ans = [-1] * n - for _, e, i in intervals: - j = bisect_left(intervals, [e]) + arr = sorted((st, i) for i, (st, _) in enumerate(intervals)) + for i, (_, ed) in enumerate(intervals): + j = bisect_left(arr, (ed, -inf)) if j < n: - ans[i] = intervals[j][2] + ans[i] = arr[j][1] return ans diff --git a/solution/0400-0499/0436.Find Right Interval/Solution.ts b/solution/0400-0499/0436.Find Right Interval/Solution.ts index b6744a5ba33c4..30363455989a0 100644 --- a/solution/0400-0499/0436.Find Right Interval/Solution.ts +++ b/solution/0400-0499/0436.Find Right Interval/Solution.ts @@ -1,26 +1,17 @@ function findRightInterval(intervals: number[][]): number[] { const n = intervals.length; - const starts = Array.from({ length: n }).map(() => new Array(2)); - for (let i = 0; i < n; i++) { - starts[i][0] = intervals[i][0]; - starts[i][1] = i; - } - starts.sort((a, b) => a[0] - b[0]); - - return intervals.map(([_, target]) => { - let left = 0; - let right = n; - while (left < right) { - const mid = (left + right) >>> 1; - if (starts[mid][0] < target) { - left = mid + 1; + const arr: number[][] = Array.from({ length: n }, (_, i) => [intervals[i][0], i]); + arr.sort((a, b) => a[0] - b[0]); + return intervals.map(([_, ed]) => { + let [l, r] = [0, n]; + while (l < r) { + const mid = (l + r) >> 1; + if (arr[mid][0] >= ed) { + r = mid; } else { - right = mid; + l = mid + 1; } } - if (left >= n) { - return -1; - } - return starts[left][1]; + return l < n ? arr[l][1] : -1; }); }