给定一个 N×3 的矩阵 matrix,对于每一个长度为 3 的小数组 arr,都表示一个大楼的三个数 据。arr[0]表示大楼的左边界,arr[1]表示大楼的右边界,arr[2]表示大楼的高度(一定大于 0)。 每座大楼的地基都在 X 轴上,大楼之间可能会有重叠,请返回整体的轮廓线数组。
【举例】 matrix ={{2,5,6}, {1,7,4}, {4,6,7}, {3,6,5}, {10,13,2}, {9,11,3}, {12,14,4},{10,12,5} }
返回: {{1,2,4},{2,4,6}, {4,6,7}, {6,7,4}, {9,10,3}, {10,12,5}, {12,14,4}}
- //描述高度变化的对象
- public static class Op {
- public int x;//x轴上的值
- public boolean isAdd;//true为加入,false为删除
- public int h;//高度
-
- public Op(int x, boolean isAdd, int h) {
- this.x = x;
- this.isAdd = isAdd;
- this.h = h;
- }
- }
-
- /**
- * 排序的比较策略
- * 1.第一个维度的X值从小到大。
- * 2.如果第一个维度的值相同,看第二个维度的值,“加入”排在前,“删除”排在后
- * 3.如果两个对象第一维度和第二个维度的值都相同,则认为两个对象相同,谁在前都行
- */
- public static class OpComparator implements Comparator
{ -
- @Override
- public int compare(Op o1, Op o2) {
- if (o1.x != o2.x) {
- return o1.x - o2.x;
- }
- if (o1.isAdd != o2.isAdd) {
- return o1.isAdd ? -1 : 1;
- }
- return 0;
- }
- }
-
- public static List
> buildingOutline(int[][] matrix) {
- int N = matrix.length;
- Op[] ops = new Op[N << 1];
- for (int i = 0; i < matrix.length; i++) {
- ops[i * 2] = new Op(matrix[i][0], true, matrix[i][2]);
- ops[i * 2 + 1] = new Op(matrix[i][1], false, matrix[i][2]);
- }
-
- //把描述高度变化的对象数组,按照规定的排序策略排序
- Arrays.sort(ops, new OpComparator());
-
- // key : 某个高度 value : 次数
- TreeMap
mapHeightTimes = new TreeMap<>(); - // key : x点 value : 最大高度
- TreeMap
mapXHeight = new TreeMap<>(); -
- for (int i = 0; i < ops.length; i++) {
- //如果当前是加入操作
- if (ops[i].isAdd) {
- //没有出现的高度
- if (!mapHeightTimes.containsKey(ops[i].h)) {
- mapHeightTimes.put(ops[i].h, 1);
- } else {//之前出现的高度,次数加一即可
- mapHeightTimes.put(ops[i].h, mapHeightTimes.get(ops[i].h) + 1);
- }
- } else {//如果当前是删除操作
- //如果当前的高度出现的次数为1,直接删除
- if (mapHeightTimes.get(ops[i].h) == 1) {
- mapHeightTimes.remove(ops[i].h);
- } else {//如果当前高度出现的次数大于1,次数减1即可
- mapHeightTimes.put(ops[i].h, mapHeightTimes.get(ops[i].h) - 1);
- }
- }
- //根据mapHeightTimes中的最大高度,设置mapXHeight
- //mapHeightTimes为空,说明最大高度为0
- if (mapHeightTimes.isEmpty()) {
- mapXHeight.put(ops[i].x, 0);
- } else {
- //mapHeightTimes不为空,获取最大高度
- mapXHeight.put(ops[i].x, mapHeightTimes.lastKey());
- }
-
- }
- //res为结果数组,每一个List
代表一个轮廓线,有开始位置,结束位置,高度一共三个信息 - List
> res = new ArrayList<>();
- //一个新轮廓线的开始位置
- int start = 0;
- //之前的最大高度
- int preHeight = 0;
-
- for (Map.Entry
entry : mapXHeight.entrySet()) { - //当前位置
- int curX = entry.getKey();
- //当前最大高度
- int curMaxHeight = entry.getValue();
- //之前最大高度和当前最大高度不一样时
- if (preHeight != curMaxHeight) {
- if (preHeight != 0) {
- res.add(new ArrayList<>(Arrays.asList(start, curX, preHeight)));
- }
- start = curX;
- preHeight = curMaxHeight;
- }
- }
- return res;
- }
-
- public static void main(String[] args) {
- int[][] matrix = {
- {2, 5, 6},
- {1, 7, 4},
- {4, 6, 7},
- {3, 6, 5},
- {10, 13, 2},
- {9, 11, 3},
- {12, 14, 4},
- {10, 12, 5}
- };
- List
> res = buildingOutline(matrix);
- System.out.println(res);
- }