当青训营遇上码上掘金——主题4攒青豆

69 阅读1分钟

解法1——动态规划

  • 下标为i的柱子能攒到的青豆数量为攒完青豆后达到的最大高度值减去柱子高度height[i]
  • 攒完青豆后达到的最大高度值为下标i柱子两边的柱子最大高度的最小值
  • 求得最大高度值后,一次遍历遍历求和便可得到结果

求解步骤

  1. 正向遍历,求解柱子i左侧柱子的最大值leftMax[i]
leftMax[0] = height[0];
for(int i = 1; i < n; i++)
{
    leftMax[i] = max(leftMax[i-1], height[i]);
}
  1. 反向遍历,求解柱子i右侧柱子的最大值rightMax[i]
rightMax[n - 1] = height[n - 1];
for (int i = n - 2; i >= 0; i--) 
{
    rightMax[i] = max(rightMax[i + 1], height[i]);
}
  1. 最后一次正向遍历,求解结果
int res = 0;
for(int i = 0; i < n; i++)
{
    res += min(leftMax[i], rightMax[i]) - height[i];
}

完整代码

 int trap(vector<int>& height) {
        //动态规划
        //定义两个数组分别求取对于第i个元素左边/右边最高的坐标
        auto n = height.size();
        if(n == 0) return 0;

        vector<int> leftMax(n);
        vector<int> rightMax(n);

        //从左到右遍历更新leftMax
        leftMax[0] = height[0];
        for(int i = 1; i < n; i++)
        {
            leftMax[i] = max(leftMax[i-1], height[i]);
        }

        //从右往左更新rightMax
        rightMax[n - 1] = height[n - 1];
        for (int i = n - 2; i >= 0; i--) {
            rightMax[i] = max(rightMax[i + 1], height[i]);
        }

        //动态规划求最小结果
        int res = 0;
        for(int i = 0; i < n; i++)
        {
            res += min(leftMax[i], rightMax[i]) - height[i];
        }

        return res;
    }

复杂度分析

  • 第一次正向遍历时间复杂度O(n),反向遍历时间复杂度O(n),最后一次遍历时间复杂度O(n)。总的时间复杂度O(n)
  • 空间复杂度O(n)