LeetCode刷题日记盛最多水的容器

节后第一天,鉴于五一五天都没做过题,有点遗忘了,今天来看一道简单点的题,练下手。

先看下题:

给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

暴力法

一般看完这个题优先的思路是暴力法,两层循环嵌套,然后得到最大值,时间复杂度为O(n^2),由于官方已经加大了测试用例的规模,暴力法会超时,已经过不了了。

那我们想想其他的方法吧,在数组和链表两个比较简单的线性表求面积的时候,经常会用到一种思想,双指针,这个后面遇到这类题的时候,没思路可以往这方面想。

双指针

什么叫双指针呢,顾名思义,就是用两个指针(内存里的指针是记录引用地址的内存空间,这个地址会指向引用的实际存储位置),记录左右边界位置,然后按照一定条件移动双指针,达到求最大面积的目的。

以这个题为例,我们要求面积最大值,就需要宽和高足够大就可以,但是我们需要知道柱子的面积最大值,就需要移动左右指针,该怎么定义移动规则呢?

其实很简单,我们假设左指针left=0,右指针right=a.length-1;,这时候有V=(right-left)*Math.min(a[left],a[right]),然后我们这时候想要得到比这个面积大的区域,首先left和right一定会往中间走,宽一定是会变小的,要使面积变大,就一定要高竟可能大,因此我们舍弃高较小的那根柱子,然后不断重复上述过程,直到left==right。

我们不难发现,利用双指针法,成功将时间复杂度由O(n^2)降为了O(n).所以可以知道双指针法能减少一层遍历。

思路想明白之后代码实现就很简单了,下面是其中一种实现:

int max = 0;
for (int left = 0, right = a.length - 1; left < right; ) {
    int v = (right - left) * (a[left] < a[right] ? a[left++] : a[right--]);
    max = max < v ? v : max;
}

return max;
写在最后

数组相关的题大多比较简单,很多都是一些固定的模式,一开始可能觉得很神奇,这东西还能这么玩?但是摸清楚套路之后感觉也就那样,所以数组相关的题没啥注意的,多练就行。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值