Skip to content

Commit 06601e1

Browse files
authored
update: 添加问题“1840.最高建筑高度”的代码和题解 (#1648)
* 1840: tmp.cpp (#1647) * docs: better (1647) * 1840: tmp.cpp (#1647) - 忽然想起来a和b的高度不仅仅受限于a和b,还有可能受限于其左右 * 1840: tmp.cpp (#1647) - 不对,还有从右往左的限制 * 1840: WA.cpp (#1647) - 38 / 50 - 给n忘了 input: 6 [] output: 0 should: 5 * 1840: WA.cpp (#1647) - 47 / 50 input: 10 [[5,3],[2,5],[7,4],[10,3]] output: 4 should: 5 * 1840: dbg.cpp (#1647) - swap时候只交换高度就好了,下标不要交换 * 1840: AC.cpp (#1647) - AC,76.74%,76.74% * update: 添加问题“1840.最高建筑高度”的代码和题解 (#1648) Signed-off-by: LetMeFly666 <Tisfy@qq.com> * fix: hb-ha (#1647) #1648 (comment) --------- Signed-off-by: LetMeFly666 <Tisfy@qq.com>
1 parent 9dda2cd commit 06601e1

6 files changed

Lines changed: 220 additions & 13 deletions

.commitmsg

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2026-06-20 10:09:03
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2026-06-20 11:17:44
6+
*/
7+
#ifdef _DEBUG
8+
#include "_[1,2]toVector.h"
9+
#endif
10+
11+
/*
12+
从左到右限制一遍再从右到左限制一遍是不是就可以了呢?是不是不需要由较低的高度往两边限制呢?
13+
*/
14+
class Solution {
15+
private:
16+
int cal(int a, int ha, int b, int hb) {
17+
if (ha > hb) {
18+
swap(ha, hb);
19+
}
20+
return hb + (b - a - (hb - ha)) / 2;
21+
}
22+
public:
23+
int maxBuilding(int n, vector<vector<int>>& restrictions) {
24+
restrictions.push_back({1, 0});
25+
restrictions.push_back({n, INT_MAX});
26+
sort(restrictions.begin(), restrictions.end());
27+
for (int i = 1; i < restrictions.size(); i++) {
28+
restrictions[i][1] = min(restrictions[i][1], restrictions[i - 1][1] + restrictions[i][0] - restrictions[i - 1][0]);
29+
}
30+
for (int i = restrictions.size() - 2; i >= 0; i--) {
31+
restrictions[i][1] = min(restrictions[i][1], restrictions[i + 1][1] + restrictions[i + 1][0] - restrictions[i][0]);
32+
}
33+
34+
int ans = 0;
35+
for (int i = 1; i < restrictions.size(); i++) {
36+
ans = max(ans, cal(restrictions[i - 1][0], restrictions[i - 1][1], restrictions[i][0], restrictions[i][1]));
37+
}
38+
return ans;
39+
}
40+
41+
void testCal() {
42+
assert(cal(7, 3, 10, 4) == 5);
43+
assert(cal(7, 4, 10, 3) == 5);
44+
}
45+
};
46+
47+
#ifdef _DEBUG
48+
/*
49+
10
50+
[[5,3],[2,5],[7,4],[10,3]]
51+
52+
5
53+
*/
54+
int main() {
55+
int a;
56+
string s;
57+
Solution sol;
58+
sol.testCal();
59+
while (cin >> a >> s) {
60+
vector<vector<int>> v = stringToVectorVector(s);
61+
Solution sol;
62+
cout << sol.maxBuilding(a, v) << endl;
63+
}
64+
return 0;
65+
}
66+
#endif

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,7 @@
709709
|1824.最少侧跳次数|中等|<a href="https://leetcode.cn/problems/minimum-sideway-jumps/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/01/21/LeetCode%201824.%E6%9C%80%E5%B0%91%E4%BE%A7%E8%B7%B3%E6%AC%A1%E6%95%B0/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/128745707" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/minimum-sideway-jumps/solutions/2071687/letmefly-1824zui-shao-ce-tiao-ci-shu-by-00cbq/" target="_blank">LeetCode题解</a>|
710710
|1827.最少操作使数组递增|简单|<a href="https://leetcode.cn/problems/minimum-operations-to-make-the-array-increasing/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2022/12/11/LeetCode%201827.%E6%9C%80%E5%B0%91%E6%93%8D%E4%BD%9C%E4%BD%BF%E6%95%B0%E7%BB%84%E9%80%92%E5%A2%9E/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/128273168" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/minimum-operations-to-make-the-array-increasing/solutions/2015884/letmefly-1827zui-shao-cao-zuo-shi-shu-zu-nso0/" target="_blank">LeetCode题解</a>|
711711
|1832.判断句子是否为全字母句|简单|<a href="https://leetcode.cn/problems/check-if-the-sentence-is-pangram/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2022/12/13/LeetCode%201832.%E5%88%A4%E6%96%AD%E5%8F%A5%E5%AD%90%E6%98%AF%E5%90%A6%E4%B8%BA%E5%85%A8%E5%AD%97%E6%AF%8D%E5%8F%A5/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/128304160" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/check-if-the-sentence-is-pangram/solutions/2018952/letmefly-1832pan-duan-ju-zi-shi-fou-wei-fd4l0/" target="_blank">LeetCode题解</a>|
712+
|1840.最高建筑高度|困难|<a href="https://leetcode.cn/problems/maximum-building-height/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2026/06/20/LeetCode%201840.%E6%9C%80%E9%AB%98%E5%BB%BA%E7%AD%91%E9%AB%98%E5%BA%A6/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/162142809" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/maximum-building-height/solutions/3985807/letmefly-1840zui-gao-jian-zhu-gao-du-zuo-n22n/" target="_blank">LeetCode题解</a>|
712713
|1845.座位预约管理系统|中等|<a href="https://leetcode.cn/problems/seat-reservation-manager/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/10/02/LeetCode%201845.%E5%BA%A7%E4%BD%8D%E9%A2%84%E7%BA%A6%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/142686842" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/seat-reservation-manager/solutions/2937537/letmefly-1845zuo-wei-yu-yue-guan-li-xi-t-qqxe/" target="_blank">LeetCode题解</a>|
713714
|1847.最近的房间|困难|<a href="https://leetcode.cn/problems/closest-room/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/12/17/LeetCode%201847.%E6%9C%80%E8%BF%91%E7%9A%84%E6%88%BF%E9%97%B4/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/144524587" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/closest-room/solutions/3022258/letmefly-1847zui-jin-de-fang-jian-you-xu-9aeg/" target="_blank">LeetCode题解</a>|
714715
|1848.到目标元素的最小距离|简单|<a href="https://leetcode.cn/problems/minimum-distance-to-the-target-element/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2026/04/13/LeetCode%201848.%E5%88%B0%E7%9B%AE%E6%A0%87%E5%85%83%E7%B4%A0%E7%9A%84%E6%9C%80%E5%B0%8F%E8%B7%9D%E7%A6%BB/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/160123059" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/minimum-distance-to-the-target-element/solutions/3951021/letmefly-1848dao-mu-biao-yuan-su-de-zui-q8qsh/" target="_blank">LeetCode题解</a>|

Solutions/LeetCode 1732.找到最高海拔.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,5 +149,6 @@ impl Solution {
149149
}
150150
```
151151

152-
> 同步发文于CSDN,原创不易,转载请附上[原文链接](https://blog.letmefly.xyz/2022/11/19/LeetCode%201732.%E6%89%BE%E5%88%B0%E6%9C%80%E9%AB%98%E6%B5%B7%E6%8B%94/)哦~
153-
> Tisfy:[https://letmefly.blog.csdn.net/article/details/127932334](https://letmefly.blog.csdn.net/article/details/127932334)
152+
> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/127932334)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2022/11/19/LeetCode%201732.%E6%89%BE%E5%88%B0%E6%9C%80%E9%AB%98%E6%B5%B7%E6%8B%94/)哦~
153+
>
154+
> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode)
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
---
2+
title: 1840.最高建筑高度:左右两次扫描,传递限制约束(没有很多头痛公式版)
3+
date: 2026-06-20 11:18:57
4+
tags: [题解, LeetCode, 困难, 数组, 数学, 排序]
5+
categories: [题解, LeetCode]
6+
index_img: https://assets.leetcode.cn/aliyun-lc-upload/uploads/2021/04/25/ic236-q4-ex2.png
7+
---
8+
9+
# 【LetMeFly】1840.最高建筑高度:左右两次扫描,传递限制约束(没有很多头痛公式版)
10+
11+
力扣题目链接:[https://leetcode.cn/problems/maximum-building-height/](https://leetcode.cn/problems/maximum-building-height/)
12+
13+
<p>在一座城市里,你需要建 <code>n</code> 栋新的建筑。这些新的建筑会从 <code>1</code> 到 <code>n</code> 编号排成一列。</p>
14+
15+
<p>这座城市对这些新建筑有一些规定:</p>
16+
17+
<ul>
18+
<li>每栋建筑的高度必须是一个非负整数。</li>
19+
<li>第一栋建筑的高度 <strong>必须</strong> 是 <code>0</code> 。</li>
20+
<li>任意两栋相邻建筑的高度差 <strong>不能超过</strong>  <code>1</code> 。</li>
21+
</ul>
22+
23+
<p>除此以外,某些建筑还有额外的最高高度限制。这些限制会以二维整数数组 <code>restrictions</code> 的形式给出,其中 <code>restrictions[i] = [id<sub>i</sub>, maxHeight<sub>i</sub>]</code> ,表示建筑 <code>id<sub>i</sub></code> 的高度 <strong>不能超过</strong> <code>maxHeight<sub>i</sub></code> 。</p>
24+
25+
<p>题目保证每栋建筑在 <code>restrictions</code> 中<strong> 至多出现一次</strong> ,同时建筑 <code>1</code> <strong>不会</strong> 出现在 <code>restrictions</code> 中。</p>
26+
27+
<p>请你返回 <strong>最高</strong> 建筑能达到的 <strong>最高高度</strong> 。</p>
28+
29+
<p> </p>
30+
31+
<p><strong>示例 1:</strong></p>
32+
<img alt="" src="https://assets.leetcode.cn/aliyun-lc-upload/uploads/2021/04/25/ic236-q4-ex1-1.png" style="width: 400px; height: 253px;" />
33+
<pre>
34+
<b>输入:</b>n = 5, restrictions = [[2,1],[4,1]]
35+
<b>输出:</b>2
36+
<b>解释:</b>上图中的绿色区域为每栋建筑被允许的最高高度。
37+
我们可以使建筑高度分别为 [0,1,2,1,2] ,最高建筑的高度为 2 。</pre>
38+
39+
<p><strong>示例 2:</strong></p>
40+
<img alt="" src="https://assets.leetcode.cn/aliyun-lc-upload/uploads/2021/04/25/ic236-q4-ex2.png" style="width: 500px; height: 269px;" />
41+
<pre>
42+
<b>输入:</b>n = 6, restrictions = []
43+
<b>输出:</b>5
44+
<b>解释:</b>上图中的绿色区域为每栋建筑被允许的最高高度。
45+
我们可以使建筑高度分别为 [0,1,2,3,4,5] ,最高建筑的高度为 5 。
46+
</pre>
47+
48+
<p><strong>示例 3:</strong></p>
49+
<img alt="" src="https://assets.leetcode.cn/aliyun-lc-upload/uploads/2021/04/25/ic236-q4-ex3.png" style="width: 500px; height: 187px;" />
50+
<pre>
51+
<b>输入:</b>n = 10, restrictions = [[5,3],[2,5],[7,4],[10,3]]
52+
<b>输出:</b>5
53+
<b>解释:</b>上图中的绿色区域为每栋建筑被允许的最高高度。
54+
我们可以使建筑高度分别为 [0,1,2,3,3,4,4,5,4,3] ,最高建筑的高度为 5 。
55+
</pre>
56+
57+
<p> </p>
58+
59+
<p><strong>提示:</strong></p>
60+
61+
<ul>
62+
<li><code>2 <= n <= 10<sup>9</sup></code></li>
63+
<li><code>0 <= restrictions.length <= min(n - 1, 10<sup>5</sup>)</code></li>
64+
<li><code>2 <= id<sub>i</sub> <= n</code></li>
65+
<li><code>id<sub>i</sub></code> 是 <strong>唯一的</strong> 。</li>
66+
<li><code>0 <= maxHeight<sub>i</sub> <= 10<sup>9</sup></code></li>
67+
</ul>
68+
69+
70+
71+
## 解题方法:从左到右限制一次 + 从右到左限制一次
72+
73+
假设能确定坐标$a$的楼**可以**达到$ha$这么高,其右边坐标$b$的楼**可以**达到$hb$这么高,那么从$a$到$b$这段区间的楼最多能有多高呢?
74+
75+
> 不妨假设$ha\leq hb$,那么楼高总体上呈现先上升后下降的趋势。$a$处楼高$ha$,$a+1$处楼高$ha+1$,...,$a + (hb-ha)$处楼高$hb$(和$b$处等高)。
76+
>
77+
> $a + (hb-ha)$处和$b$处楼都高$hb$,如果二者之间有一栋或两栋楼则最高高度可达$hb+1$,如果二者之间有三栋或四栋楼则最高高度可达$hb+2$,...,如果二者之间有$n$栋楼则最高高度可达$hb+\lfloor\frac{n+1}{2}\rfloor$。由于二者之间有$b-a-(hb-ha)-1$栋楼所以二者之间最高高度可达$hb+\lfloor\frac{b-a-(hb-ha)}{2}\rfloor$,即为从$a$到$b$这段范围的最大楼高。
78+
>
79+
> 如果$ha\gt hb$同理,不妨直接交换$ha$和$hb$使得$ha\lt hb$,这样并不影响这段区间的最大楼高计算结果。
80+
81+
现在问题是每个关键坐标的最大楼高确定了吗?还没有。
82+
83+
> 前面讨论的前提是坐标$a$的楼**可以**达到$ha$这么高,而题目中给的$maxHeight$限制不一定能达到!
84+
>
85+
> 例如假设坐标$5$的楼最高为$3$,那么坐标$7$的楼最高为$5$,即使题目中给$restrictions[i]=[7, 99999]$的限制也达不到。
86+
87+
最终剩下了如何确定每个关键点的最大高度这一个关键问题了,很简单:
88+
89+
> 一个楼的最大高度限制除了题目给定的自身限制以外,还有来自其左右楼高的限制。
90+
>
91+
> 我们从左到右遍历一遍关键坐标的楼高并传递更新最大楼高限制,再从右往左遍历一遍传递更新最大楼高限制,不就ok了吗?
92+
>
93+
> 假设坐标$a$的楼高限制是$ha$,那么其右边坐标$b$的楼高最多为$ha+b-a$。
94+
>
95+
> 注意题目中还有两个初始情况下的额外限制:坐标$1$最大高度$0$,坐标$n$最大高度$+\infty$。
96+
97+
时空复杂度分析:
98+
99+
+ 时间复杂度$O(m\log m)$,其中$m=len(restrictions)$,$\log m$的时间复杂度来自排序;
100+
+ 空间复杂度$O(\log m)$。
101+
102+
### AC代码
103+
104+
#### C++
105+
106+
```cpp
107+
/*
108+
* @LastEditTime: 2026-06-20 11:17:44
109+
*/
110+
/*
111+
从左到右限制一遍再从右到左限制一遍是不是就可以了呢?是不是不需要由较低的高度往两边限制呢?
112+
*/
113+
class Solution {
114+
private:
115+
int cal(int a, int ha, int b, int hb) {
116+
if (ha > hb) {
117+
swap(ha, hb);
118+
}
119+
return hb + (b - a - (hb - ha)) / 2;
120+
}
121+
public:
122+
int maxBuilding(int n, vector<vector<int>>& restrictions) {
123+
restrictions.push_back({1, 0});
124+
restrictions.push_back({n, INT_MAX});
125+
sort(restrictions.begin(), restrictions.end());
126+
for (int i = 1; i < restrictions.size(); i++) {
127+
restrictions[i][1] = min(restrictions[i][1], restrictions[i - 1][1] + restrictions[i][0] - restrictions[i - 1][0]);
128+
}
129+
for (int i = restrictions.size() - 2; i >= 0; i--) {
130+
restrictions[i][1] = min(restrictions[i][1], restrictions[i + 1][1] + restrictions[i + 1][0] - restrictions[i][0]);
131+
}
132+
133+
int ans = 0;
134+
for (int i = 1; i < restrictions.size(); i++) {
135+
ans = max(ans, cal(restrictions[i - 1][0], restrictions[i - 1][1], restrictions[i][0], restrictions[i][1]));
136+
}
137+
return ans;
138+
}
139+
140+
void testCal() {
141+
assert(cal(7, 3, 10, 4) == 5);
142+
assert(cal(7, 4, 10, 3) == 5);
143+
}
144+
};
145+
```
146+
147+
> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/162142809)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2026/06/20/LeetCode%201840.%E6%9C%80%E9%AB%98%E5%BB%BA%E7%AD%91%E9%AB%98%E5%BA%A6/)~
148+
>
149+
> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode)

Solutions/Other-AI-LLM_Maintained_TechNotes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,6 @@ git fetch --prune origin # 4. 清理已失效的 remote-trac
350350

351351
*本文由AI大模型维护,持续更新中。最近更新时间:2026-04-25*
352352

353-
> 同步发文于我的[个人博客](https://blog.letmefly.xyz/),(AI)创作不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2026/04/16/Other-AI-LLM_Maintained_TechNotes/)~
353+
> 发文于我的[个人博客](https://blog.letmefly.xyz/),(AI)创作不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2026/04/16/Other-AI-LLM_Maintained_TechNotes/)~
354354
>
355355
> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode)

0 commit comments

Comments
 (0)