刷题记录:数组问题

题目:给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

class Solution {

    public int maxArea(int[] height) {

        /*思路(暴力):height保存线高,两线之间的角标差值就是底,有效存水面积就是低与两线之间较小值的乘积。

        可以依次计算每两线之间的存水量,留下最大的结果。*/

        int temp;

        int result = 0;

        for (int i = 0; i < height.length; i++) {

            for (int j = i + 1; j < height.length; j++) {

                temp = Math.min(height[i],height[j]) * (j - i);

                if (result < temp) {

                    result = temp;

                }

            }

        }

        return result;

    }

}

代码运行没问题,一提交,果然超出了时间限制。我还是太菜了。

=========================================================================

这个题的难度在于,不仅仅需要找到尽可能的边长,而且在找尽可能的边长的同时寻找尽可能的低长(脚标差),因此常规的排序达不到效果。到这里我的脑子就想不出什么好办法了,看看大佬们怎么解决的吧!

查了一下官方思想:

在每个状态下,无论长板或短板向中间收窄一格,都会导致水槽 底边宽度 -1 变短:

若向内移动短板 ,水槽的短板 min(h[i],h[j]) 可能变大,因此下个水槽的面积可能增大 。
若向内 移动长板 ,水槽的短板 min(h[i],h[j])​ 不变或变小,因此下个水槽的面积一定变小 。
因此,初始化双指针分列水槽左右两端,循环每轮将短板向内移动一格,并更新面积最大值,直到两指针相遇时跳出;即可获得最大面积。

按照这个思想编写一手:

class Solution {

    public int maxArea(int[] height) {

        //初始化双指针

        int i = 0;

        int j = height.length - 1;

        //记录最大结果

        int temp;

        int result = 0;

        while (i < j) {

            temp = (j - i) * Math.min(height[i], height[j]);

            if (result < temp) {

                result = temp;

            }

            //移动水槽板过程

            if (height[i] > height[j]) {

                j--;

            } else {

                i++;

            }

        }

        return result;

    }

}

=========================================================================

在讨论区看到了有个大佬在官方解答基础上,引入了快速跳过过程,大大提交了效率,惊为天人!

class Solution {

    public int maxArea(int[] height) {

        //初始化双指针

        int i = 0;

        int j = height.length - 1;

        //结果

        int temp;

        int result = 0;

        while (i < j) {

            temp = (j - i) * Math.min(height[i], height[j]);

            int minHeight = Math.min(height[i], height[j]);

            result = Math.max(result, temp);

            //相比于之前一次只推一格木板,一次推多格木板

            while (height[i] <= minHeight && i < j) {

                i++;

            }

            while (height[j] <= minHeight && i < j) {

                j--;

            }

        }

        return result;

    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值