当青训营遇上码上掘金
题目
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
以下为上图例子的解析: 输入:height = [5,0,2,1,4,0,1,0,3] 输出:17 解析:上面是由数组 [5,0,2,1,4,0,1,0,3] 表示的柱子高度,在这种情况下,可以接 17 个单位的青豆。
思路分析
刚开始看到这个题,是没什么思路,在网上学习后,发现可以用分行法,动态规划法和双指针法三种方法去解析。第一个时间复杂度较高,后两者时间复杂度相同O(n) ,但是双指针法的空间复杂度很低O(1)。
分行法
此方法的基本思想是按行去遍历,从高度为1开始,一直到数组中最大数的高度,一行一行的去计算。比方说求第
i层,遍历所有元素,如果>=i则舍去;如果<i则保留。但是需要注意的是要用一个temp变量去存储每一行中每一小段雨水,还有通过一个flag变量判断是否开始(因为题目要求不考虑边角堆积)。
代码如下:
#include<iostream>
#include<vector>
using namespace std;
int main(){
vector<int> height {5,0,2,1,4,0,1,0,3};
int max = *max_element(height.begin(),height.end());
int ans = 0;
int temp = 0;
int flag = -1;
for(int i=1;i<=max;i++){
temp = 0;
flag = -1;
for(int j=0;j<height.size();j++){
if (height[j] < i && flag == 1){
temp++;
}else if(height[j] >= i){
flag = 1;
ans+=temp;
temp = 0;
}
}
}
cout<<"Answer is : "<<ans<<endl;
return 0;
}
动态规划法
此方法的思想是分别建立两个数组
left和right,分别从左和右开始遍历,对数据进行预处理,然后再通过两个数组的值进行组合求解。
代码如下:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
vector<int> height {5,0,2,1,4,0,1,0,3};
int length = height.size();
vector<int> left; vector<int> right; int sum = 0;
left.push_back(height[0]);
right.push_back(height[length-1]);
for(int i=1;i<length;i++){
left.push_back(max(left[i-1],height[i]));
}
for(int i=length-2;i>=0;i--){
right.insert(right.begin(),max(height[i],right[0]));
}
for(int i=0;i<length;i++){
sum += (min(left[i],right[i])-height[i]);
}
cout<<"Answer is = "<<sum<<endl;
return 0;
}
双指针法
此方法的思想是基于动态规划之上,动态规划是分别建立两个数组从两端进行遍历,而双指针法则是通过
left和right两个指针从两端同时开始遍历,进行累加。
代码如下:
#include<iostream>
#include<vector>
using namespace std;
int main(){
vector<int> height {5,0,2,1,4,0,1,0,3};
int left=0,leftMax=height[0],right=height.size()-1,rightMax=height[right];
int sum = 0;
while(left<right){
if(height[left]>leftMax){
leftMax = height[left];
}
if(height[right]>rightMax){
rightMax = height[right];
}
if(height[left]<height[right]){
sum+=leftMax-height[left];
left++;
}else{
sum+=rightMax-height[right];
right--;
}
}
cout<<"Answer is = "<<sum<<endl;
return 0;
}
顺便附上我的码上掘金链接 攒青豆项目代码