/** * https://leetcode.cn/problems/container-with-most-water/?envType=study-plan-v2&envId=top-interview-150 * @param {number[]} height * @return {number} */ const maxArea = function (height) { }; /* 暴力解法,组合所有的可能,得出最大的面积,会超时 */ function f1(height) { const n = height.length; let mArea = -Infinity; let cArea;// 计算的面积 for (let i = 0; i < n; i++) { for (let j = i + 1; j < n; j++) { cArea = Math.min(height[i], height[j]) * (j - i); if (cArea > mArea) mArea = cArea; } } return mArea; } /* 使用双指针,定义一个left和一个right,首先判断height[left] 和 height[right]两者直接谁底,因为盛水量是底的那一端决定的, 计算当前值并且使用mArea保存起来这个值,之后继续移动地的那一侧,假设height[right]比height[left]底,那么就right--,然后继续 比较,反之left++,循环条件为left < right */ function f2(height) { let mArea = -Infinity; // 能盛水的最大面积 let cArea; // 缓存计算的面积,避免重复计算 let left = 0; let right = height.length - 1; while (left < right) { cArea = Math.min(height[left], height[right]) * [right - left]; if (cArea > mArea) mArea = cArea; if (height[right] > height[left]) { // 如果右端比左端高,移动底的那一段 left++; } else { right--; } } return mArea; } /* 优化:假设当前右边比左边高,那么我们应该移动左边,面积不仅仅是由两端高度较低的那一端决定的,同时也由right - left这个底部决定, 在移动的过程中,这个底部一定是不断变小的,所以当这个决定性的最短边小于之前的最短边,那就没必要计算了,100%小于之前的结果,所以 应该定义一个记录有效边高度的变量,用来跳过不必要的判断,以此提高小效率 */ function f2(height) { let mArea = -Infinity; // 能盛水的最大面积 let cArea; // 缓存计算的面积,避免重复计算 let left = 0; let right = height.length - 1; while (left < right) { cArea = Math.min(height[left], height[right]) * (right - left); if (cArea > mArea) mArea = cArea; if (height[left] < height[right]) { let prevLeft = height[left]; // 增加跳过无效left的逻辑 while (left < right && height[left] <= prevLeft) { left++; } } else { let prevRight = height[right]; // 增加跳过无效right的逻辑 while (left < right && height[right] <= prevRight) { right--; } } } return mArea; }