2021-04-25 16:44:31 +08:00

189 lines
7.0 KiB
C++

// Source : https://leetcode.com/problems/maximum-building-height/
// Author : Hao Chen
// Date : 2021-04-25
/*****************************************************************************************************
*
* You want to build n new buildings in a city. The new buildings will be built in a line and are
* labeled from 1 to n.
*
* However, there are city restrictions on the heights of the new buildings:
*
* The height of each building must be a non-negative integer.
* The height of the first building must be 0.
* The height difference between any two adjacent buildings cannot exceed 1.
*
* Additionally, there are city restrictions on the maximum height of specific buildings. These
* restrictions are given as a 2D integer array restrictions where restrictions[i] = [idi, maxHeighti]
* indicates that building idi must have a height less than or equal to maxHeighti.
*
* It is guaranteed that each building will appear at most once in restrictions, and building 1 will
* not be in restrictions.
*
* Return the maximum possible height of the tallest building.
*
* Example 1:
*
* Input: n = 5, restrictions = [[2,1],[4,1]]
* Output: 2
* Explanation: The green area in the image indicates the maximum allowed height for each building.
* We can build the buildings with heights [0,1,2,1,2], and the tallest building has a height of 2.
*
* Example 2:
*
* Input: n = 6, restrictions = []
* Output: 5
* Explanation: The green area in the image indicates the maximum allowed height for each building.
* We can build the buildings with heights [0,1,2,3,4,5], and the tallest building has a height of 5.
*
* Example 3:
*
* Input: n = 10, restrictions = [[5,3],[2,5],[7,4],[10,3]]
* Output: 5
* Explanation: The green area in the image indicates the maximum allowed height for each building.
* We can build the buildings with heights [0,1,2,3,3,4,4,5,4,3], and the tallest building has a
* height of 5.
*
* Constraints:
*
* 2 <= n <= 10^9
* 0 <= restrictions.length <= min(n - 1, 10^5)
* 2 <= idi <= n
* idi is unique.
* 0 <= maxHeighti <= 10^9
******************************************************************************************************/
/*
At first , it's not difficult to work out the max height between two buildings.
**Case study**
considering the following restractions:
1) Building #1 `max-height = 1`, Building #5 `max-height = 1`
then we can have the building height list - `[1,2,3,2,1] `
2) Building #1 `max-height = 3`, Building #5 `max-height = 1`
then we can have the building height list - `[3,4,3,2,1]`
3) Building #1 `max-height = 1`, Building #5 `max-height = 9`
then we can have the building height list - `[1,2,3,4,5]`
So, we can figure out the following rules :
1) if two restraction has same limited height, suppose we have `[n ......... n]`,
then we can have the building height list `[n, n+1, n+2, ... n+m-1, n+m, n+m-1 ..., n+2, n+1, n]`
So, **`m = width /2`** - the `width` is the number of buildings.
2) if two restraction has different limited height, suppose we have `[n ...... n+x]`
then we still can have the building height list like 1) - we just add some buildings behind `[n .... n+x, (n+x-1... n) ]`
So, **`m = (width+x)/2`** - we need to extend x buildings
3) if there hasn't enough buildings between two restractions. then, the max height we can make is **`width`**. For examples:
- Building#1 max-height = 2, building#3 max-height = 5 : then, we only can make `[2,3,4]`
- Building#1 max-height = 2, building#2 max-height = 9 : then, we only can make `[2,3]`
So, we can have the following source code to calculate the max height between two restractions.
```
int getMaxHeight(vector<int>& left, vector<int>& right) {
int width = right[0] - left[0];
int height_delta = abs(right[1] - left[1]);
int min_height = min (left[1], right[1]);
//if the `width` is enough to have `height_delta`
if (width >= height_delta) return min_height + (width + height_delta) / 2;
// if the `width` is not enought have `height_delta`
// then, the `width` is the max height we can make
int max_height = min_height + width;
return max_height;
}
```
BUT, we still have a case need to deal with, considering we have the following restractions:
`[1,1], [2,2] ,[3,3], [4,0]`
we can process them couple by couple.
- step 1: `[1,1], [2,2]` : max-height = 2
- step 2: `[2,2] ,[3,3]` : max-height = 3
- step 3: `[3,3], [4,0]` : max-height = 1
for the last couple of restractions, we can see the building#3 max-height is 1, so we have go backwards to recaluate the building#2 and building#1.
- step 3: `[3,1], [4,0]` : max-height = 1 (change the `[3,3]` to `[3,1]` )
- step:4: `[2,2] ,[3,1]` : max-height = 2
- step 5: `[1,1], [2,2]` : max-height = 2
So, the correct answer of max height is `2`
finally, we have the whole source code with debug code inside.
*/
class Solution {
private:
void print(vector<vector<int>>& vv){
cout << "[" ;
for(int i = 0; i < vv.size()-1; i++) {
cout << "[" <<vv[i][0] << "," << vv[i][1] << "],";
}
int i = vv.size() - 1;
cout << "[" << vv[i][0] << "," << vv[i][1] << "]]" << endl;
}
public:
int getMaxHeight(vector<int>& left, vector<int>& right) {
int width = right[0] - left[0];
int height_delta = abs(right[1] - left[1]);
int min_height = min (left[1], right[1]);
//if the `width` is enough to have `height_delta`
if (width >= height_delta) return min_height + (width + height_delta) / 2;
// if the `width` is not enought have `height_delta`
// then, the `width` is the max height we can make
int max_height = min_height + width;
// if the restriction is higher then make it to right limitation.
left[1] = min (left[1], max_height);
right[1] = min (right[1], max_height);
return max_height;
}
int maxBuilding(int n, vector<vector<int>>& restrictions) {
restrictions.push_back({1,0});
restrictions.push_back({n, n-1});
sort(restrictions.begin(), restrictions.end());
//print(restrictions);
for(int i=0; i<restrictions.size()-1; i++){
int height = getMaxHeight(restrictions[i], restrictions[i+1]);
//cout << "[" << restrictions[i][0] << "," << restrictions[i][1]<< "] - "
// << "[" << restrictions[i+1][0] << "," << restrictions[i+1][1]<< "] = "
// << height << endl;
}
cout << endl;
int maxHeight = 0;
for(int i= restrictions.size()-1; i>0; i--){
int height = getMaxHeight(restrictions[i-1], restrictions[i]);
//cout << "[" << restrictions[i-1][0] << "," << restrictions[i-1][1]<< "] - "
// << "[" << restrictions[i][0] << "," << restrictions[i][1]<< "] = "
// << height << endl;
maxHeight = max(maxHeight, height);
}
// cout << endl;
return maxHeight;
}
};