关于数据结构和算法:LeetCode刷题日记之盛最多水的容器

51次阅读

共计 1057 个字符,预计需要花费 3 分钟才能阅读完成。

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

先看下题:

给你 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