LeetCode解析------218.天際線問題-樹狀數組

題目:

城市的天際線是從遠處觀看該城市中所有建築物形成的輪廓的外部輪廓。現在,假設您獲得了城市風光照片(圖A)上顯示的所有建築物的位置和高度,請編寫一個程序以輸出由這些建築物形成的天際線(圖B)。
在這裏插入圖片描述
在這裏插入圖片描述

每個建築物的幾何信息用三元組 [Li,Ri,Hi] 表示,其中 Li 和 Ri 分別是第 i 座建築物左右邊緣的 x 座標,Hi 是其高度。可以保證 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX 和 Ri - Li > 0。您可以假設所有建築物都是在絕對平坦且高度爲 0 的表面上的完美矩形。

示例 1:

例如,圖A中所有建築物的尺寸記錄爲:[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] 。
輸出是以 [ [x1,y1], [x2, y2], [x3, y3], … ]格式的“關鍵點”(圖B中的紅點)的列表,它們唯一地定義了天際線。關鍵點是水平線段的左端點。請注意,最右側建築物的最後一個關鍵點僅用於標記天際線的終點,並始終爲零高度。此外,任何兩個相鄰建築物之間的地面都應被視爲天際線輪廓的一部分。
例如,圖B中的天際線應該表示爲:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8],[24, 0] ]。

說明:

任何輸入列表中的建築物數量保證在 [0, 10000] 範圍內。 輸入列表已經按左 x 座標 Li 進行升序排列。 輸出列表必須按 x 位排序。 輸出天際線中不得有連續的相同高度的水平線。例如 […[2 3], [4 5], [7 5], [11 5], [12 7]…] 是不正確的答案;三條高度爲 5 的線應該在最終輸出中合併爲一個:[…[2 3], [4 5], [12 7], …]

簡單介紹:
題目:天際線問題
題目難度:困難
使用語言:JAVA。
這道題來自leetcode題庫的樹狀數組標籤。

解題思路:
首先看題、分析題意,我們可以明確1個關鍵點:
1.記錄拐點,保存當前區間最高建築物的左邊座標。
既然,我們已經分析出來題目的關鍵任務了,下面我們就可以開始思考實現了。
我們採用算法與數據結構的思路來剖析一下這題,

數據結構:
要實現對數據的操作,我們要先明確存儲數據的數據結構。
該題的數據結構的作用:
1.points:調整順序後的建築物座標,按x座標從小到大。
-----x相同的情況:------
a.左座標在右座標前面
b.同爲左座標,高的在前
c.同爲右座標,高的在後
2.results:保存結果

算法:
既然明確了我們的數據結構,我們就可以開始我們的算法分析了。
1.自定義排序規則,如上面數據結構所描述的
2.自定義一個TreeMap,從大到小排序
3.遍歷points,左邊座標出現則相應高度加1,右邊座標出現則相應高度減1。
高度變化,則加入results。

代碼部分:

import java.util.*;

public class Solution {
    public List<List<Integer>> getSkyline(int [][]buildings){
        List<List<Integer>> points=new ArrayList<>();//參與運算
        List<List<Integer>> results=new ArrayList<>();//結果
       // int n=buildings.length;
        //查找左上角右上角座標,左上角座標保存爲負數
        for(int []b:buildings){
            List<Integer> p1=new ArrayList<>();
            p1.add(b[0]);
            p1.add(-b[2]);
            points.add(p1);

            List<Integer> p2=new ArrayList<>();
            p2.add(b[1]);
            p2.add(b[2]);
            points.add(p2);
        }
         //對座標排序,利用自定義比較規則
        Collections.sort(points, new Comparator<List<Integer>>() {
            @Override
            public int compare(List<Integer> p1, List<Integer> p2) {
                int x1=p1.get(0);
                int y1=p1.get(1);
                int x2=p2.get(0);
                int y2=p2.get(1);
                if(x1!=x2){
                    return x1-x2;//從小到大排序
                } else {
                    return y1-y2;//左座標從大到小,右座標從小到大
                }
            }
        });

        TreeMap<Integer,Integer> treeMap=new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;//依次找到最大的
            }
        });
        treeMap.put(0,1);//初始設置最大堆
        int preMax=0;//目前最大高度

        for(List<Integer> p:points){//逐個查找拐點
            int x=p.get(0);
            int y=p.get(1);
            if(y<0){
                Integer v=treeMap.get(-y);//高度調整
                if(v==null){
                    treeMap.put(-y,1);
                } else {
                    treeMap.put(-y,v+1);
                }
            }else {
                Integer v= treeMap.get(y);
                if(v==1){
                    treeMap.remove(y);
                }else{
                    treeMap.put(y,v-1);
                }
            }

            int curMax=treeMap.firstKey();
            if(curMax!=preMax){//高度變化,則添加拐點
                List<Integer> temp=new ArrayList<>();
                temp.add(x);
                temp.add(curMax);
                results.add(temp);
                preMax=curMax;
            }
        }

        return results;


    }
}

在這裏插入圖片描述

結語:
晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章