[CP / Leetcode] 11. Container With Most Water - 盛最多水的容器

分析

首先观察题目条件:

2<=n<=1050<=height[i]<=104

n 的范围来看,O(n2) 的暴力解法肯定是不行了; height[i] 的范围比较小,或许是突破口。

不过,还是从暴力先开始考虑,万一经过优化之后时间复杂度降下来了呢?

暴力解法的话,需要成对地遍历 height 数组中元素 ai,aj,求出 max(min(ai,aj)|ij|),考虑到有一半的组合是重复的,可以优化成 max(min(ai,aj)(ij)),且规定 i>j,但这样做之后复杂度依然是 O(n2)

还能再优化吗?

max 肯定是不能去掉的,否则就存在 O(1) 的解法,显然这样的解法并不存在,而 min 不怎么耗时间,也并非优先考虑的优化对象。

本质上看,若想降低时间复杂度,需要缩小遍历(搜索)的范围。仔细想一想,在遍历时,怎样的元素是不用考虑的呢?……好像没有。问题在于,我们没有事先提取有关的 height 数组的任何信息,或者说,没有获得任何信息熵,因而这些数据对于我们而言具有同等的不确定性,也就无法带有倾向性地去选择某些元素了。

如果是以前的我,一定会遇事不决就来个排序吧……但只做排序看上去也是于事无补的,顶多是把 min 给去掉,并不能带来多少提升。

现在只剩下最后一条路可走,就是一开始的取值范围:

0<=height[i]<=104

看起来好像需要开一个大小为 104 的桶,但这样做,考虑所有的元素都相等的极端情况,用桶就无法求解了。

貌似无路可走了!虽然挺想看提示或者题解的,但是不能看,否则就没意思了。

不行。再想想再想想。

首先遍历 height[i] 是必须做的,也就是至少有 O(n) 的时间复杂度,如果能在 O(logn) 或更快的时间内,找到和当前的 height[i] 相关的可行解……

如果使用排序,只选取满足 height[j]height[i]j(设有 k 个满足上述条件的 j),便能将目标简化为:

max[aimax(|ij1|,|ij2|,,|ijt|,,|ijk|)]

数形结合(这里需要更严谨的证明),还能进一步简化:

max[aimax(|ijmin|,|ijmax|)]

得想办法快速计算出 jminjmax ——事实上它们确实可以被快速地计算出来,只要倒序扫描一遍数组就行了!

到这里已经可以写出代码了,由于排序的存在,时间复杂度是 O(logn),但是用桶可以优化到 O(n)

代码(O(n)

class Solution {
public:
int maxArea(vector<int>& height) {
using pair = std::pair<int, int>;
std::vector<pair> bukket(1e4 + 5, {INT_MAX, INT_MIN}); // min max
int n = height.size();
for (int i = 0; i < n; i++) {
bukket[height[i]].first = std::min(bukket[height[i]].first, i);
bukket[height[i]].second = std::max(bukket[height[i]].second, i);
}
int curMin = INT_MAX, curMax = INT_MIN;
int ans = 0;
for (int i = 1e4; i >= 0; i--) {
int iMin = bukket[i].first, iMax = bukket[i].second;
if (iMin == INT_MAX)
continue;
curMin = std::min(curMin, iMin);
curMax = std::max(curMax, iMax);
int a1 = std::max(iMin - curMin, curMax - iMin);
int a2 = std::max(iMax - curMin, curMax - iMax);
ans = std::max(ans, i * std::max(a1, a2));
}
return ans;
}
};

后记

image
边写 blog 边做这道题,前前后后大概花了 4 个小时,但自己做出来比看过答案之后再写,感觉要好上一万倍。

嗯,我肯定是把简单的事情搞复杂了,所以接下来研究 editorial。

什么,居然是双指针?!未曾设想过的算法。看来又能学到新的技巧了。

因为题解网上都有,这里就不记录双指针解法了。赶紧再刷几道类似的题巩固一下……

posted @   ZXPrism  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示