题目描述
知识点
思维+动态规划
结果
实现
码前思考
- 之前我使用了一种错误的思想去思考这个问题。。。
- 后来看了LeetCode官方题解才发现,原来一个点的积水量,就是取决于它左边最高高度和右边最高高度的最小值。。。
- 这样的话,就很好写代码了。
代码实现
//动态规划,类似于合唱队形,只不过是凹陷的,求面积
class Solution {
public:
int trap(vector<int>& height) {
int size = height.size();
if(size==1||size==0){
return 0;
}
vector<int> left(size,0);
vector<int> right(size,0);
//从左往右,找递减
left[0]=height[0];
for(int i=1;i<height.size();i++){
if(height[i]<left[i-1]){//必须是严格小于不能等于
left[i]=left[i-1];
}else{
left[i]=height[i];
}
}
//从右到左,找递减
right[size-1]=height[size-1];
for(int i=size-2;i>=0;i--){
if(height[i]<right[i+1]){
right[i]=right[i+1];
}else{
right[i]=height[i];
}
}
//遍历两个数组,找到最低点
int res=0;
for(int i=0;i<size;i++){
int minHeight = min(left[i],right[i]);
res+=minHeight-height[i];
}
return res;
}
};
码后反思
- 我还是太天真了。。。
错误代码,考虑以区域为单位就算,忽视了高高低低的情况
//动态规划,类似于合唱队形,只不过是凹陷的,求面积
class Solution {
public:
int trap(vector<int>& height) {
int size = height.size();
if(size==1||size==0){
return 0;
}
vector<int> left(size,0);
vector<int> right(size,0);
//从左往右,找递减
left[0]=0;
for(int i=1;i<height.size();i++){
if(height[i]<height[i-1]){//必须是严格小于不能等于
left[i]=left[i-1];
}else{
left[i]=i;
}
}
//从右到左,找递减
right[size-1]=size-1;
for(int i=size-2;i>=0;i--){
if(height[i]<height[i+1]){
right[i]=right[i+1];
}else{
right[i]=i;
}
}
//遍历两个数组,找到最低点
int res=0;
for(int i=0;i<size;i++){
if(left[i]!=i&&right[i]!=i){//说明是一个最低点
printf("当前是:%d\n",i);
printf("当前是:%d\n",left[i]);
printf("当前是:%d\n",right[i]);
//首先得到两边最短的
int lHeight = height[left[i]];
int rHeight = height[right[i]];
int minHeight;
int lBound;
int rBound;
if(lHeight > rHeight){
minHeight = rHeight;
//从右到左,找第一个大于等于这个的
rBound=right[i];
for(lBound=i-1;lBound>=left[i]&&height[lBound]<height[rBound];lBound--);
}else{
minHeight = lHeight;
//从左到右,找第一个大于等于这个的
lBound=left[i];
for(rBound=i+1;rBound<=right[i]&&height[rBound]<height[lBound];rBound++);
}
//计算一个大的面积
int tot = (rBound-lBound-1)*minHeight;
for(int j=lBound+1;j<=rBound-1;j++){
tot-=height[j];
}
res+=tot;
}
}
return res;
}
};
二刷反思
要仔细考虑清楚问题的特征,某一点的积水量,就是取决于它左边最高高度和右边最高高度的最小值。。。
//为了得到不重复的结果,需要强制只能使用自己后面的元素,一种典型的dfs暴力方法
//相似的题目还有之前那个求最短的
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
int len = candidates.size();
dfs(candidates,target,0);
return res;
}
void dfs(vector<int>& candidates,int target,int idx){
if(target==0){//不需要求和了
res.push_back(path);
}else if(target<0){
return;//小于0肯定不行
}else{
for(int i=idx;i<candidates.size();i++){
path.push_back(candidates[i]);
dfs(candidates,target-candidates[i],i);
path.pop_back();
}
}
}
};