时间复杂度 $O(n^2)$
注意:线段列表在合并后需要更新,不然会导致判断横纵线段交点时多判
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
ArrayList<Seg> rows = new ArrayList<>();
ArrayList<Seg> cols = new ArrayList<>();
for (int i = 0; i < n; ++i) {
int x1 = scanner.nextInt();
int y1 = scanner.nextInt();
int x2 = scanner.nextInt();
int y2 = scanner.nextInt();
if (x1 == x2) {
cols.add(new Seg(x1, Math.min(y1, y2), Math.max(y1, y2)));
} else {
rows.add(new Seg(y1, Math.min(x1, x2), Math.max(x1, x2)));
}
}
long res = merge(rows) + merge(cols);
for (Seg row : rows) {
for (Seg col : cols) {
if (row.k >= col.l && row.k <= col.r && col.k >= row.l && col.k <= row.r) {
--res;
}
}
}
System.out.println(res);
}
public static long merge(ArrayList<Seg> list) {
long res = 0;
ArrayList<Seg> temp = new ArrayList<>();
list.sort((s1, s2) -> {
if (s1.k != s2.k) {
return s1.k - s2.k;
} else if (s1.l != s2.l) {
return s1.l - s2.l;
} else {
return s1.r - s2.r;
}
});
for (int i = 0; i < list.size(); ) {
int j = i;
int l = Integer.MIN_VALUE + 1;
int r = Integer.MIN_VALUE;
while (j < list.size() && list.get(j).k == list.get(i).k) {
++j;
}
for (int k = i; k < j; ++k) {
if (r < list.get(k).l) {
res += r - l + 1;
if (l != Integer.MIN_VALUE + 1) {
temp.add(new Seg(list.get(i).k, l, r));
}
r = list.get(k).r;
l = list.get(k).l;
} else {
r = Math.max(r, list.get(k).r);
}
}
res += r - l + 1;
if (l != Integer.MIN_VALUE + 1) {
temp.add(new Seg(list.get(i).k, l, r));
}
i = j;
}
list.clear();
list.addAll(temp);
return res;
}
static class Seg {
int k;
int l;
int r;
Seg(int k, int l, int r) {
this.k = k;
this.l = l;
this.r = r;
}
}
}
请问,这是考察的什么知识点?
考察的合并区间算法。只是要先对k(k表示纵向线段的行号或横向线段的列号)排个序,对于k相同的线段,再合并区间并保存。最后去除重复的交点即可
谢啦,前几天看完第一章基础课打算去做(题的序号存着的),然后忘了,今天来做,结果想不起考察的知识点了。老哥也在看基础课吗?
没有,我是前几天参加美团笔试,想做做2019的,所以才做了这题的
那问问,美团笔试算法题咋样?
2小时5道题。2道简单,2道中等难度,一道困难吧我觉得
那还可以,希望我到时候能AC3道就行。hh