动态规划之42.接雨水

前言

仅仅给出,我做该题的历程,做法是按列计算,还有按行计算的方法。也可以利用双指针给本文的动态规划解法进行空间优化。

题目链接:42. 接雨水 - 力扣(LeetCode)

题目描述:

分析:

错误思路记录(可以不看):刚开始,我的思路被局限在了整体,想法是找出U 型,然后计算出中间的储水量,然后相加,就得到答案了。这样的想法忽略了 ,一个大的U 型里可以有多个U 型,会导致结果偏小。思来想去,有很多尝试,但最终样例通过率在 200/300,发现了剩下的问题,但是无法解决。

也算是见识到了困难题的威力了。

于是看了提示:按列看 这是最简单,最易理解的想法了。

只要看该列的左边和右边是否有比之高的列,有就计算该列能有多个块水,然后统计起来就可以了。

正常思路是向左向右遍历,找到最大的。可以预见到有很多的重复计算。

然后就想到,好像和动态规划有点关系!想着之后,还真是!! 就是一个动态规划的题。

只看找最左边最大值 对与 I 来说,左边最大值 = i-1 的左边最大值 或者 i -1 位置的值。

dp[i] 表示 第 i 列,左边的最大值

可以得到状态转移方程 dp[i] = max (dp[i-1],height[i-1]);

找右边最大值同理。

题解

public static int trap(int[] height) {
            // 把眼光放在最小的地方,按列来计算,找到 某列的最左边最高的,和最右边最高的。
            int sum = 0;
            int[] max_left = new int[height.length];
            int[] max_right = new int[height.length];

            for (int i = 1; i < max_right.length; i++) {
                max_left[i] = Math.max(max_left[i-1],height[i-1]);
            }
            for (int i = height.length - 2; i >= 0; i--) {
                max_right[i] = Math.max(max_right[i + 1], height[i + 1]);
            }
            // 遍历每一列
            for(int i =1;i<height.length - 1;i++)
            {
                int min = Math.min(max_left[i],max_right[i]);
                if(min > height[i])
                {
                    sum += (min - height[i]);
                }
            }
            return sum;
        }

当然,该代码还可以优化空间,也可以按照行的方式去计算。

收获

  • 有时候直接观察问题局部的特征,以局部的问题,去解决整体的问题,会更加的高效。
  • 提供了一个这种题的思路,当整体的考虑很复杂时,就可以尝试从局部查看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值