当青训营遇上码上掘金 题目重述:
- 现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。
这题与力扣中的一道算法题很像,本题解也是参考了其数雨水的官方题解思路和算法。
动态规划
所能承接的青豆数取决于柱子两端相邻的柱子最大值与当前高度的差值,也就是说对于一个长度n的数组第i个柱子能收集到的青豆为i点能到达的最高点与本位置的高度之差。本题使用了vector容器,但考虑到vector不能直接键盘输入则,创建数组先接收柱子高度值,再利用pushback()将数据压入容器。做法通过对数组中的每个数据进行从左往右的扫描,记录左侧最高值lheight和rheight,lMax[i] = max(lMax[i - 1], height[i]);然后计算每根柱子能够接收的青豆数。但动态规划时间复杂度高因此引入另一种做法单调栈。
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n;i++)
height.pushback(a[i]);
}
单调栈
除了计算并存储每个位置两边的最大高度以外,也可以用单调栈计算能接的雨水总量。 维护一个单调栈,单调栈存储的是下标,满足从栈底到栈顶的下标对应的数组中的元素递减。 从左到右遍历数组,遍历到下标 iii 时,如果栈内至少有两个元素,记栈顶元素为top的下面一个元素是 left,则一定有 height[left]≥height[top]。如果i柱子高度大于top,则得到一个可以接雨水的区域,根据高度即可计算得到该区域能接的青豆数。