Leetcode 11 盛水最多的容器

it2024-08-17  50

更加丰富内容可查看我的个人博客:xukang’s blog

方法1、双循环枚举

时间复杂度 O(N^2)

class Solution { public: int maxArea(vector<int>& height) { int res = 0; for (int i = 0; i < height.size() - 1; i++) { for (int j = i + 1; j < height.size(); j++) { res = max(res, min(height[i], height[j]) * (j - i)); } } return res; } };

方法2、双指针

对于双指针方法,数组和链表相关题目经常会用到

时间复杂度 O(N)

为什么双指针的做法是正确的?

双指针代表了什么?

​ 双指针代表的是 可以作为容器边界的所有位置的范围。在一开始,双指针指向数组的左右边界,表示 数组中所有的位置都可以作为容器的边界,因为我们还没有进行过任何尝试。在这之后,我们每次将 对应的数字较小的那个指针 往 另一个指针 的方向移动一个位置,就表示我们认为 这个指针不可能再作为容器的边界了。

为什么对应的数字较小的那个指针不可能再作为容器的边界了?

​ 反正法 : 假设当前左指针和右指针指向的数分别为 x 和 y,不失一般性,我们假设 x <= y。同时,两个指针之间的距离为 t 。那么,它们组成的容器的容量为: ​ min(x, y) ∗ t = x ∗ t

我们可以断定,如果我们保持左指针的位置不变,右指针往左移,这个容器的容量就不会超过 x ∗ t了。

如果我们任意向左移动右指针,指向的数为 y1 ,两个指针之间的距离为 t1 ,那么显然有 t1 < t,并且 min (x, y1) <= min (x , y):

如果 y1 <= y,那么 min(x, y1) <= min(x, y);如果 y1 > y , 那么 min(x, y1) = x = min(x, y);

结合 t1 < t 和 min (x, y1) <= min (x , y) 得到 min(x, y1) ∗ t1 < min(x, y) ∗ t

即无论我们怎么移动右指针,得到的容器的容量都小于移动前容器的容量。也就是说,我们可以通过移动指向较小值的那个指针,来遍历数组,达到减少时间复杂度的效果

class Solution { public: int maxArea(vector<int>& height) { int res = 0; int i = 0; int j = height.size() - 1; while (i < j) { // if (height[i] <= height[j]) { // res = max(res, height[i] * (j - i)); // i++; // } else { // res = max(res, height[j] * (j - i)); // j--; // } /* 三目表达式虽然优雅!但是容易犯错! 如果(j - i) * height[i++] 写成 height[i++] * (j - i) 就出错了! */ res = height[i] <= height[j] ? max(res, (j - i) * height[i++]) : max(res, (j - i) * height[j--]); } return res; } };
最新回复(0)