1. 程式人生 > 其它 >天際線問題

天際線問題

連結

城市的天際線是從遠處觀看該城市中所有建築物形成的輪廓的外部輪廓。給你所有建築物的位置和高度,請返回由這些建築物形成的 天際線 。

每個建築物的幾何資訊由陣列 buildings 表示,其中三元組 buildings[i] = [lefti, righti, heighti] 表示:

lefti 是第 i 座建築物左邊緣的 x 座標。
righti 是第 i 座建築物右邊緣的 x 座標。
heighti 是第 i 座建築物的高度。
天際線 應該表示為由 “關鍵點” 組成的列表,格式 [[x1,y1],[x2,y2],...] ,並按 x 座標 進行 排序 。關鍵點是水平線段的左端點。列表中最後一個點是最右側建築物的終點,y 座標始終為 0 ,僅用於標記天際線的終點。此外,任何兩個相鄰建築物之間的地面都應被視為天際線輪廓的一部分。

注意:輸出天際線中不得有連續的相同高度的水平線。例如 [...[2 3], [4 5], [7 5], [11 5], [12 7]...] 是不正確的答案;三條高度為 5 的線應該在最終輸出中合併為一個:[...[2 3], [4 5], [12 7], ...]

import java.util.*;

class Solution {
    public static List<List<Integer>> getSkyline(int[][] buildings) {
        if (buildings == null || buildings.length == 0 || buildings[0].length == 0) {
            return new ArrayList<>(0);
        }

        int n = buildings.length;

        Operation[] operations = new Operation[n << 1];

        for (int i = 0; i < n; ++i) {
            operations[i << 1] = new Operation(buildings[i][0], true, buildings[i][2]);
            operations[i << 1 | 1] = new Operation(buildings[i][1], false, buildings[i][2]);
        }


        Arrays.sort(operations, new Comparator<Operation>() {
            @Override
            public int compare(Operation o1, Operation o2) {
                return Integer.compare(o1.x, o2.x);
            }
        });

        TreeMap<Integer, Integer> heightTimesMap = new TreeMap<>();
        TreeMap<Integer, Integer> heightMap = new TreeMap<>();

        for (Operation operation : operations) {
            if (operation.add) {
                heightTimesMap.put(operation.height, heightTimesMap.getOrDefault(operation.height, 0) + 1);
            } else {
                if (heightTimesMap.get(operation.height) == 1) {
                    heightTimesMap.remove(operation.height);
                } else {
                    heightTimesMap.put(operation.height, heightTimesMap.get(operation.height) - 1);
                }
            }
            heightMap.put(operation.x, heightTimesMap.isEmpty() ? 0 : heightTimesMap.lastKey());
        }

        int preHeight = 0;
        List<List<Integer>> ret = new ArrayList<>();

        for (Map.Entry<Integer, Integer> entry : heightMap.entrySet()) {
            if (preHeight != entry.getValue()) {
                ret.add(Arrays.asList(entry.getKey(), entry.getValue()));
            }
            preHeight = entry.getValue();
        }


        return ret;
    }
}

class Operation {
    int x;
    boolean add;
    int height;

    public Operation(int x, boolean add, int height) {
        this.x = x;
        this.add = add;
        this.height = height;
    }
}
心之所向,素履以往 生如逆旅,一葦以航