| 每日一题做题记录,参考官方和三叶的题解 |
题目要求
思路一:排序+二分
【是我没想到的思路】
- 要比较的对象是左端点,那就把左端点抽出来排个序形成数组;
- 遍历右端点:
- 对每个右端点,用二分在里找第一个大于等于它的数。
- 数组要记录在的下标。
Java
class Solution {
public int[] findRightInterval(int[][] intervals) {
int n = intervals.length;
int[][] left = new int[n][2]; //(left, idx)
for(int i = 0; i < n; i++)
left[i] = new int[]{intervals[i][0], i};
Arrays.sort(left, (a,b) -> a[0] - b[0]);
int[] res = new int[n];
// 二分找第一个大于等于目标
for(int i = 0; i < n; i++) {
int l = 0, r = n - 1;
while(l < r) {
int mid = l + r >> 1;
if(left[mid][0] >= intervals[i][1])
r = mid;
else
l = mid + 1;
}
res[i] = left[r][0] >= intervals[i][1] ? left[r][1] : -1;
}
return res;
}
}
- 时间复杂度:,次遍历,每次
- 空间复杂度:
C++
class Solution {
public:
vector<int> findRightInterval(vector<vector<int>>& intervals) {
int n = intervals.size();
vector<vector<int>> left(n, vector<int>(2)); //(left, idx)
for(int i = 0; i < n; i++)
left[i] = {intervals[i][0], i};
sort(left.begin(), left.end());
vector<int> res(n);
// 二分找第一个大于等于目标
for(int i = 0; i < n; i++) {
int l = 0, r = n - 1;
while(l < r) {
int mid = l + r >> 1;
if(left[mid][0] >= intervals[i][1])
r = mid;
else
l = mid + 1;
}
res[i] = left[r][0] >= intervals[i][1] ? left[r][1] : -1;
}
return res;
}
};
- 时间复杂度:,次遍历,每次二分
- 空间复杂度:
思路二:双指针
- 把左端点和右端点都排个序,两个指针分别从两个数组头开始;
- 遍历右端点的时候就不用每次都从整个里面找了,只需要从上一次结束的地方开始。
Java
class Solution {
public int[] findRightInterval(int[][] intervals) {
int n = intervals.length;
int[][] left = new int[n][2], right = new int[n][2];
for(int i = 0; i < n; i++) {
left[i] = new int[]{intervals[i][0], i};
right[i] = new int[]{intervals[i][1], i};
}
Arrays.sort(left, (a,b) -> a[0] - b[0]);
Arrays.sort(right, (a,b) -> a[0] - b[0]);
int[] res = new int[n];
for(int l = 0, r = 0; r < n; r++) {
int cur = right[r][0], idx = right[r][1];
while(l < n && left[l][0] < cur)
l++;
res[idx] = l == n ? -1 : left[l][1];
}
return res;
}
}
- 时间复杂度:,看起来和之前一样是因为排序复杂度高,其实构造答案的复杂度只有
- 空间复杂度:
C++
class Solution {
public:
vector<int> findRightInterval(vector<vector<int>>& intervals) {
int n = intervals.size();
vector<vector<int>> left(n, vector<int>(2)), right(n, vector<int>(2));
for(int i = 0; i < n; i++) {
left[i] = {intervals[i][0], i};
right[i] = {intervals[i][1], i};
}
sort(left.begin(), left.end());
sort(right.begin(), right.end());
vector<int> res(n);
for(int l = 0, r = 0; r < n; r++) {
int cur = right[r][0], idx = right[r][1];
while(l < n && left[l][0] < cur)
l++;
res[idx] = l == n ? -1 : left[l][1];
}
return res;
}
};
- 时间复杂度:
- 空间复杂度:
总结
热爱双指针的我一下就想到了第二种,轻松搞定~
【和自己去过了520、还有周董看、很快乐了】
| 欢迎指正与讨论! |