攒青豆--接水滴问题

110 阅读1分钟

攒青豆问题

思路

攒青豆问题类似木桶原理,每个柱子上能攒的青豆数量取决于左右两边的柱子高度具体表现为,每一列能接多少青豆取决于该列的左边最高的heightL和右边最高的heightR中较小的一个,具体为height[i]接上青豆之后的高度为height[i]所在列的左边最高的heightL[i]和右边最高的heightR[i]中较小的一个,即第i列能攒的青豆数为min(heightL[i],heightR[i])-height[i]。 具体实例如主题所给的height为列,height = [5,0,2,1,4,0,1,0,3] 对于height[2]:

9db4417a59b7c8620b27c99f42d67de.jpg

解题方法

动态规划

由上述思路可以知道只要记录左边所有柱子的最高高度和右边所有柱子的最高高度,就可以计算当前位置的青豆数量。

  1. 创建两个dp数组分别记录height[i]左边的最高列的高度heightL[i]和右边列的最该列的高度heightR[i];代码实现为

     vector<int>heightL(height.size(),0);
     vector<int>heightR(height.size(),0);
    
  2. 可得递推公式heightL[i]=max(heightL[i-1],height[i]),即本列左边列的最大高度为前一个位置的左边最高高度和本高度的最大值。 从左往右遍历可得heightL,从右往左遍历可得heightR 具体代码实现为:

int size=height.size(); //遍历得到第i个柱子左边的最大高度
maxLeft[0]=height[0];
for(int i=1;i<size;i++){ 
heightLt[i]=max(heightL[i-1],height[i]); 
}
heightR[size-1]=height[size-1]; 
for(int j=size-2;j>=0;j--){ 
heightR[j]=max(heightR[j+1],height[j]); 
}

3.求和,从左往右遍历,同时遍历heightL和heightR 累加得到最终的青豆数 具体代码实现为

        int sum = 0;
        for (int i = 0; i < size; i++) {
            int count = min(heightL[i], heightR[i]) - height[i];
            if (count > 0) sum += count;
        }

整体代码如下: