盛最多水的容器(Container-With-Most-Water)
題幹如下:
給你 n 個非負整數 a1,a2,…,an,每個數代表座標中的一個點 (i, ai) 。在座標內畫 n 條垂直線,垂直線 i 的兩個端點分別為 (i, ai) 和 (i, 0)。找出其中的兩條線,使得它們與 x 軸共同構成的容器可以容納最多的水。
說明:你不能傾斜容器,且 n 的值至少為 2。
圖中垂直線代表輸入陣列 [1,8,6,2,5,4,8,3,7]。在此情況下,容器能夠容納水(表示為藍色部分)的最大值為 49。
示例:
輸入:[1,8,6,2,5,4,8,3,7]
輸出:49
來源:力扣
根據題意,將題目抽象為數學模型:給定一個 陣列array 和 兩個索引X、Y,在隨意移動 X、Y 的過程中,求 S = |Y-X| * Min( array[X], array[Y] ) 的最大值,其中 Min( array[X], array[Y] ) 記為 H。
- |Y-X| 表示索引差值的絕對值
- Min( array[X], array[Y] ) ,是因為在 |Y-X |固定的前提下,容器的納水量完全取決於較小的高度,所以這邊取 Min。
解題思路
我們將 X 指向陣列的第一個位置,Y 指向陣列的最後一個位置。按照上面的公式求出 S 的值並記錄。判斷 array[X] 和 array[Y] 的值,如果 array[X] > array[Y] 則 Y 向左移動,如果 array[X] < array[Y] 則 X 向右移動,如果 array[X] = array[Y] 則 X 向右移動,Y 向左移動。總之,索引指向的元素值較小的移動,如果相等則一起移動。解釋如下:
假設 X 指向的元素為 2,Y 指向的元素為 7。由於 2 比 7 小,所以 X 向右移。至於為什麼不是 Y 向左移動是因為 H的值 是 array[X] 和 array[Y] 中較小的值,如果將 Y 向左移動,假設 array[Y-1] 比 array[X] 大,這時 H的值 仍為 array[X],而(Y - X)的值卻變小了,因此 S 也變小了。假設 array[Y-1] 比 array[X] 小,這時 H的值 為 array[Y-1] ,較之前變小了,並且 (Y - X)的值也變小了,因此 S 也變小了。所以要移動元素值較小的索引。如果 array[X] 和 array[Y] 相等,則 X 和 Y 一起移動,分析過程與不相等一致。
流程圖分析如下:
程式碼實現
GO語言實現
func maxArea(height []int) int {
var (
i = 0
j = len(height) - 1
max = 0
minHeight = 0
)
for i < j {
// H 的 計算
if height[j] > height[i] {
minHeight = height[i]
} else {
minHeight = height[j]
}
// 記錄面積,也就是納水量
newMax := (j - i) * minHeight
if newMax > max {
max = newMax
}
// 移動高度小的指標,如果相等則一起移動
if height[j] > height[i] {
i++
} else if height[j] < height[i] {
j--
} else {
j--
i++
}
}
return max
}
思考
這題是我個人比較喜歡的,解題的過程很像自己在做職業規劃時權衡利弊的模樣。 H的值 好比職業技能的深度,|Y-X|的值 好比職業技能的廣度,S的值 好比職場的價值,價值是由廣度和深度一起決定的。有時候如果無法在深度上有提升,不必死磕,試試擴充套件一下廣度。
總結
每天進步一點點,加油!
完整程式碼:https://github.com/wx-satellite/go-leetcod…( 如果對你有幫助,點個 star 鼓勵一下喲 )
本作品採用《CC 協議》,轉載必須註明作者和本文連結