大家好,我是吳師兄,
今天的題目來源于 LeetCode 第 11 號問題:盛最多水的容器,難度為「中等」,屬于雙指針的經(jīng)典題目。
一、題目描述
給你 n 個非負整數(shù) a1,a2,...,an,每個數(shù)代表坐標中的一個點 (i, ai) 。在坐標內(nèi)畫 n 條垂直線,垂直線 i 的兩個端點分別為 (i, ai) 和 (i, 0) 。
找出其中的兩條線,使得它們與 x 軸共同構(gòu)成的容器可以容納最多的水。
二、題目解析
一開始,我們先去考慮相距最遠的兩個柱子所能容納水的面積。
![79f574dc-0e24-11ed-ba43-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/96/00/wKgaomTnEKGANfLDAADOeumReLM373.jpg)
接下來去思考,我們?nèi)ヒ苿幽母訒雍线m?
這里我們需要注意一點:無論移動哪根柱子,柱子之間的寬度都是變小的。
移動右邊那根更高的柱子?
![7a146cc0-0e24-11ed-ba43-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/96/00/wKgaomTnEKGARUpcAADMewPwJ7A588.jpg)
![7a20b4a8-0e24-11ed-ba43-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/96/00/wKgaomTnEKGAINTKAADJ4lyiI2Q807.jpg)
由于水面高度是由最短的柱子決定的,所以移動右邊那根更高的柱子的時候,水面高度一定是不會增加,甚至有可能遇到更短的柱子而變小,而寬度有一定再減少,所以水的面積也一定減少。
移動左邊那根更短的柱子?
這時候,水的高度是不確定的,那么面積也是不確定的,有可能比之前更大,也有可能更小或者相等。
所以,我們可以得出一個結(jié)論:移動兩根柱子之間更短的那根柱子,才有可能在寬度一定變小的情況下,找到一個更高的水面,從而使得面積有可能更大。
那接下來這道題目的解法也就有了:
1、設(shè)置兩個索引,分別指向容器的兩側(cè),即索引left
指向最左邊的柱子,索引right
指向最右邊的柱子。
![7a3639ea-0e24-11ed-ba43-dac502259ad0.jpg](https://file1.elecfans.com//web2/M00/96/00/wKgaomTnEKGAaCQNAADWrJliFwM508.jpg)
2、記錄下此時的水的面積,可以定義為 res
3、觀察需要向內(nèi)移動哪根柱子
- 1)如果移動較高的柱子,由于水的寬度在變小,而水的高度一定不會增加,所以最終水的面積不會超過之前記錄的水的面積 res
- 2)所以,只能移動較短的柱子,然后計算此時水的面積,再與之前記錄的水的面積 res 進行比較,保存那個更大的值
4、再去判斷應(yīng)該向內(nèi)移動哪根柱子
5、直到left
和right
相遇為止
三、參考代碼
1、Java 代碼
//登錄AlgoMooc官網(wǎng)獲取更多算法圖解
//https://www.algomooc.com/587.html
//作者:程序員吳師兄
//代碼有看不懂的地方一定要私聊咨詢吳師兄呀
//盛最多水的容器(LeetCode11):https://leetcode-cn.com/problems/container-with-most-water/
classSolution{
publicintmaxArea(int[]height){
//設(shè)置兩個索引,分別指向容器的兩側(cè)
//索引left指向最左邊的柱子
intleft=0;
//索引right指向最右邊的柱子
intright=height.length-1;
//設(shè)置一個變量用來保存當下水的最大面積
intres=0;
//移動left和right,直到left和right相遇為止
while(left//水的寬度是right-left
intwidth=right-left;
//水的高度由兩根柱子最短的那根決定
inth=Math.min(height[left],height[right]);
//計算此時水的面積
intarea=width*h;
//如果此時水的面積大于了我們之前保存的那個值,我們需要更新一下
if(area>=res){
//更新res的值為area,確保res一直都是最大的值
res=area;
}
//接下來去觀察需要移動哪根柱子:必定是最短的那根柱子
//如果左邊的柱子更短,那么向內(nèi)移動左邊的柱子,因為只有這樣,才有可能找到一個更高的水面
//在寬度一定變小的情況下,水的面積才有可能增大
if(height[left]//向內(nèi)移動左邊的柱子
left++;
//如果右邊的柱子更短,那么向內(nèi)移動右邊的柱子,因為只有這樣,才有可能找到一個更高的水面
//在寬度一定變小的情況下,水的面積才有可能增大
}else{
//向內(nèi)移動右邊的柱子
right--;
}
}
//最后返回最大的面積res即可
returnres;
}
}
2、C++ 代碼
//登錄AlgoMooc官網(wǎng)獲取更多算法圖解
//https://www.algomooc.com/587.html
//作者:程序員吳師兄
//代碼有看不懂的地方一定要私聊咨詢吳師兄呀
//盛最多水的容器(LeetCode11):https://leetcode-cn.com/problems/container-with-most-water/
classSolution{
public:
intmaxArea(vector<int>&height){
//設(shè)置兩個索引,分別指向容器的兩側(cè)
//索引left指向最左邊的柱子
intleft=0;
//索引right指向最右邊的柱子
intright=height.size()-1;
//設(shè)置一個變量用來保存當下水的最大面積
intres=0;
//移動left和right,直到left和right相遇為止
while(left//水的寬度是right-left
intwidth=right-left;
//水的高度由兩根柱子最短的那根決定
inth=min(height[left],height[right]);
//計算此時水的面積
intarea=width*h;
//如果此時水的面積大于了我們之前保存的那個值,我們需要更新一下
if(area>=res){
//更新res的值為area,確保res一直都是最大的值
res=area;
}
//接下來去觀察需要移動哪根柱子:必定是最短的那根柱子
//如果左邊的柱子更短,那么向內(nèi)移動左邊的柱子,因為只有這樣,才有可能找到一個更高的水面
//在寬度一定變小的情況下,水的面積才有可能增大
if(height[left]//向內(nèi)移動左邊的柱子
left++;
//如果右邊的柱子更短,那么向內(nèi)移動右邊的柱子,因為只有這樣,才有可能找到一個更高的水面
//在寬度一定變小的情況下,水的面積才有可能增大
}else{
//向內(nèi)移動右邊的柱子
right--;
}
}
//最后返回最大的面積res即可
returnres;
}
};
3、Python 代碼
#登錄AlgoMooc官網(wǎng)獲取更多算法圖解
#https://www.algomooc.com/587.html
#作者:程序員吳師兄
#代碼有看不懂的地方一定要私聊咨詢吳師兄呀
#盛最多水的容器(LeetCode11):https://leetcode-cn.com/problems/container-with-most-water/
classSolution:
defmaxArea(self,height:List[int])->int:
#設(shè)置兩個索引,分別指向容器的兩側(cè)
#索引left指向最左邊的柱子
left=0
#索引right指向最右邊的柱子
right=len(height)-1
#設(shè)置一個變量用來保存當下水的最大面積
res=0
#移動left和right,直到left和right相遇為止
whileleft#水的寬度是right-left
width=right-left
#水的高度由兩根柱子最短的那根決定
h=min(height[left],height[right])
#計算此時水的面積
area=width*h
#如果此時水的面積大于了我們之前保存的那個值,我們需要更新一下
ifarea>=res:
#更新res的值為area,確保res一直都是最大的值
res=area
#接下來去觀察需要移動哪根柱子:必定是最短的那根柱子
#如果左邊的柱子更短,那么向內(nèi)移動左邊的柱子,因為只有這樣,才有可能找到一個更高的水面
#在寬度一定變小的情況下,水的面積才有可能增大
ifheight[left]#向內(nèi)移動左邊的柱子
left+=1
#如果右邊的柱子更短,那么向內(nèi)移動右邊的柱子,因為只有這樣,才有可能找到一個更高的水面
#在寬度一定變小的情況下,水的面積才有可能增大
else:
#向內(nèi)移動右邊的柱子
right-=1
#最后返回最大的面積res即可
returnres
四、復(fù)雜度分析
時間復(fù)雜度:O(N),雙指針總計最多遍歷整個數(shù)組一次。
空間復(fù)雜度:O(1),只需要額外的常數(shù)級別的空間。
審核編輯 :李倩
-
JAVA
+關(guān)注
關(guān)注
19文章
2975瀏覽量
105157 -
容器
+關(guān)注
關(guān)注
0文章
499瀏覽量
22125 -
代碼
+關(guān)注
關(guān)注
30文章
4828瀏覽量
69063
原文標題:雙指針,從兩頭開始內(nèi)卷,先卷了挫的那頭
文章出處:【微信號:TheAlgorithm,微信公眾號:算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
華盛昌工業(yè)高溫雙激光紅外測溫儀產(chǎn)品介紹
超級電容器的為什么雙電層間隔小
面試常考+1:函數(shù)指針與指針函數(shù)、數(shù)組指針與指針數(shù)組
![面試常考+1:函數(shù)<b class='flag-5'>指針</b>與<b class='flag-5'>指針</b>函數(shù)、數(shù)組<b class='flag-5'>指針</b>與<b class='flag-5'>指針</b>數(shù)組](https://file.elecfans.com/web2/M00/20/B3/pYYBAGGfNNmAK-PZAAJsGM5Cgk0227.jpg)
一面低壓柜最多能放多少臺電容器
![一面低壓柜<b class='flag-5'>最多</b>能放多少臺電<b class='flag-5'>容器</b>](https://file1.elecfans.com/web2/M00/F8/F4/wKgaomaGQGaAdIqjAARJEXG4KIY470.jpg)
雙電層法拉電容器相較于傳統(tǒng)化學(xué)電池有什么優(yōu)點?
![<b class='flag-5'>雙</b>電層法拉電<b class='flag-5'>容器</b>相較于傳統(tǒng)化學(xué)電池有什么優(yōu)點?](https://file1.elecfans.com/web2/M00/F5/EC/wKgaomZ-L4CAFJd0AABhpi6_4y8950.png)
面試中的高頻問題:指針函數(shù)與函數(shù)指針,你能完美應(yīng)對嗎?
![面試中的高頻問題:<b class='flag-5'>指針</b>函數(shù)與函數(shù)<b class='flag-5'>指針</b>,你能完美應(yīng)對嗎?](https://file.elecfans.com/web2/M00/20/B3/pYYBAGGfNNmAK-PZAAJsGM5Cgk0227.jpg)
靜電計和驗電器的指針偏角和什么有關(guān)?
指針式萬用表概述及工作原理 指針式萬用表的使用技巧及注意事項
探尋未來科技:超親水聚合物超級電容器
爆點十足!騰盛精密半導(dǎo)體技術(shù)矩陣亮相雙展
![爆點十足!騰<b class='flag-5'>盛</b>精密半導(dǎo)體技術(shù)矩陣亮相<b class='flag-5'>雙</b>展](https://file1.elecfans.com/web2/M00/C5/44/wKgZomX72Z2AVT00AAAXtMirytE562.jpg)
雙電層電容器的分類及優(yōu)點
雙電層電容器和贗電容器的區(qū)別
C語言的指針用法
![C語言的<b class='flag-5'>指針</b>用法](https://file1.elecfans.com/web2/M00/C2/A8/wKgZomXmuoSAKJcMAAANYarH0Zw193.jpg)
評論