Sign in to import from GitHub:
Line Sweep顧名思義,就是針對x或是y軸依序掃描過去。
例如下圖,針對不同的interval,對x軸掃描。從最左邊掃到最右邊。
因為,需要從最小掃到最大。所以interval必須要拆成起點和終點,分別給不同的flag,放進一個vector之後遞增排序。
給你一個vector<vector<int>> intervals來代表區間,vector<int> queries來查詢在x = queries[i] 的時候有多少個重複interval,使用interval和queries來建立line sweep的準備資料。
enum state{start, end};
vector<vector<int>> intervals;
vector<vector<int>> db;
for(auto& itv : intervals) {
db.push_back({itv[0], start});
db.push_back({itv[1], end, itv[0]});
}
for(int i = 0; i < queries.size(); ++i)
db.push_back({queries[i], query, i});
sort(db.begin(), db.end());
建立好準備資料,就可以根據題目依序拿出item來做處理。
vector<int> ans(queries.size());
unordered_multiset<int> ms;
for(auto& item : db) {
switch(item[1]) {
case start:
ms.insert(item[0]);
break;
case query:
ans[item[2]] = ms.empty() ? -1 : ms.size();
break;
case end :
ms.erase(ms.find(item[2]));
break;
}
}
return ans;
給定vector<vector<int>> interval,找出每個query的x值,長度最小的interval。如果沒有則回傳-1。
- 因為是interval可以使用line sweep。
- 將query當成第二個,因為這邊的interval定義是前後都有包含。所以先查詢之後再刪除。
- 第三個欄位放每個interval的size。
- 因為要找出最小的interval所以使用multiset來對遇到的interval進行排序。
class Solution {
enum state {start, query, end};
public:
vector<int> minInterval(vector<vector<int>>& intervals, vector<int>& queries) {
vector<vector<int>> db;
for(auto& itv : intervals) {
int sz = itv[1] - itv[0] + 1;
db.push_back({itv[0], start, sz});
db.push_back({itv[1], end, sz});
}
for(int i = 0; i < queries.size(); ++i) {
db.push_back({queries[i], query, i});
}
sort(db.begin(), db.end());
vector<int> ans(queries.size());
multiset<int> ms;
for(auto& item : db) {
if(item[1] == start) ms.insert(item[2]);
else if(item[1] == query) {
if(ms.empty()) ans[item[2]] = -1;
else ans[item[2]] = *ms.begin();
} else
ms.erase(ms.find(item[2]));
}
return ans;
}
};
- 2023/07/18 重做一次還是沒想到使用line sweep。
- line sweep可以想成是走訪整個時間軸。或是依序走訪x軸。
- 先建立掃描的順序。
- interval的起始點 (把length放進multiset)
- query點 (從multiset拿出最小值)
- interval的終點 (把length從multiset移除)
- 依序走訪得出答案。
找出重疊矩形的邊緣。如下圖所示。
一開始對這種題目完全沒想法。如果是面試應該當場傻掉。
不過後來看答案之後,原來是使用Line Sweep。另外當沒有想法的時候,如果不擠點東西出來,在面試場合應該也不好看。
- 先觀察給的example的答案。
- 解答都是出現在高度有變化的地方 ==> 判斷高度改變就儲存答案。
- 判斷的地方都是每個方塊的x起點和x終點。 ==> line sweep
- 重點 因為我們必須排列x從小到大,如果x一樣則y從大到小。 ==> 所以start-point {b[0], -b[2]}, end-point {b[1], b[2]},因為當x一樣,最大的y就會排在前面。
為什麼要這樣排列?
當矩形重疊時,{1, 2, 1}, {1, 2, 2}, {1, 2, 3}
存入height之後
這邊也是個重點,把成對的vector排列成像竹筍的樣子。
class Solution {
public:
vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
vector<pair<int, int>> height; // x, y
multiset<int> hlist;
for(auto& b : buildings) {
height.emplace_back(b[0], -b[2]); // start
height.emplace_back(b[1], b[2]); // end
}
sort(begin(height), end(height));
hlist.insert(0); // 從高度0開始
int cur{0}, prev{0};
vector<vector<int>> ans;
for(auto& [x, y] : height) {
if(y < 0) hlist.insert(-y); // 矩形起點,儲存高度。
else hlist.erase(hlist.find(y)); // 矩形終點,所以把這個矩形的高度刪掉
cur = *hlist.rbegin(); // 取最高的高度
if(cur != prev) { // 高度改變
ans.push_back({x, cur});
prev = cur;
}
}
return ans;
}
};
leetcode
刷題
or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing