406. 根据身高重建队列
难度中等442
假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)
表示,其中h
是这个人的身高,k
是排在这个人前面且身高大于或等于h
的人数。 编写一个算法来重建这个队列。
注意:
总人数少于1100人。
示例
输入:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
输出:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
📖 文字题解
方法 1:暴力
直观想法
直接按问题描述进行。对于数组中的每个元素,我们找出下雨后水能达到的最高位置,等于两边最大高度的较小值减去当前高度的值。
算法
- 初始化 ans=0
- 从左向右扫描数组:
- 初始化max_left=0 和 max_right=0
- 从当前元素向左扫描并更新:
- max_left=max(max_left,height[j])
- 从当前元素向右扫描并更新:
- max_right=max(max_right,height[j])
- 将min(max_left,max_right)−height[i] 累加到ans
int trap(vector<int>& height)
{
int ans = 0;
int size = height.size();
for (int i = 1; i < size - 1; i++) {
int max_left = 0, max_right = 0;
for (int j = i; j >= 0; j--) {
//Search the left part for max bar size
max_left = max(max_left, height[j]);
}
for (int j = i; j < size; j++) {
//Search the right part for max bar size
max_right = max(max_right, height[j]);
}
ans += min(max_left, max_right) - height[i];
}
return ans;
}
复杂性分析
-
时间复杂度: O ( n 2 ) O(n^2) O(n2)。数组中的每个元素都需要向左向右扫描。
-
空间复杂度 O(1)的额外空间。
方法 2:动态编程
直观想法
在暴力方法中,我们仅仅为了找到最大值每次都要向左和向右扫描一次。但是我们可以提前存储这个值。因此,可以通过动态编程解决。
这个概念可以见下图解释:
算法
- 找到数组中从下标 i 到最左端最高的条形块高度 left_max。
- 找到数组中从下标 i 到最右端最高的条形块高度right_max。
- 扫描数组height并更新答案:
- 累加 KaTeX parse error: Expected '}', got '_' at position 15: \min(\text{max_̲left}[i],\text{… 到 ans 上
int trap(vector<int>& height)
{
if(height == null)
return 0;
int ans = 0;
int size = height.size();
vector<int> left_max(size), right_max(size);
left_max[0] = height[0];
for (int i = 1; i < size