# 11.Container With Most Water <span class="tag" data-diff="medium" /> {%hackmd RN5D4nggQRO8wzNqxuvlNw %} ## 題目 Given n non-negative integers $a_1, a_2, ..., a_n$ , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at $(i, a_i)$ and $(i, 0)$. Find two lines, which together with x-axis forms a container, such that the container contains the most water. Note: You may not slant the container and n is at least 2. ![](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/07/17/question_11.jpg) The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49. **Example:** ``` Input: [1,8,6,2,5,4,8,3,7] Output: 49 ``` ## 思路 最簡單的做法是跑2個迴圈,將所有結果找出最大值。但這樣的做法需要 $O(n^2)$ 的時間複雜度。於是我自己想出來另一個做法,主要概念是水從最低的柱子往上淹,該柱子會去找離他最遠還沒被淹掉的的另一根柱子,計算之間的面積,更新最大值,另外會maintain一個array,紀錄還沒被淹掉的柱子。 ```javascript let x = height.map((x,i) => i), y = height.map((x, i) => [i, x]).sort((a,b) => b[1] - a[1]); let temp, max = 0; while(temp = y.pop()){ let [a, b] = temp; x.splice(x.indexOf(a), 1); let d_x = Math.max(a - x[0], x[x.length - 1] - a), area = d_x * b; max = area > max ? area : max; } return max; ``` 一開始會把每個元素記錄其index和高度,並以高度排序。排序會需要 $O(nlogn)$ 的時間,但之後只需要一個一個pop出元素,花費 $O(n )$ 的時間即可找出最大值,總時間複雜度是 $O(nlogn)$。 另外,在討論區看到大神的厲害想法,也把它紀錄下來: 越大的面積需要兩個元素在x方向距離越遠,高度差越小且越接近最大高度,所以一開始最遠的兩端,計算面積,之後將較小的那一端去除,重複上述動作,計算完整個array即可得到最大值。 ```javascript let max = 0, i = 0, j = height.length - 1; while(i < j){ max = Math.max(max, Math.min(height[i], height[j]) * (j - i)); if(height[j] > height[i]) i ++ ; else j --; } return max; ``` 這種作法只需要loop過一遍array花 $O(n)$ 的時間就可以完成,真的很厲害XDD