演算法之雙指標(共同點:核心邏輯思路:即先找到比較小的區域(例如決定了存水量),然後在比較小的區域中找到一個最大值))~盛最多水的容器~~~接雨水
演算法之雙指標(共同點:核心邏輯思路:即先找到比較小的區域(例如決定了存水量),然後在比較小的區域中找到一個最大值)
~盛最多水的容器~~~接雨水
1,盛最多水的容器:
題意:
給你 n 個非負整數 a1,a2,...,an,每個數代表座標中的一個點 (i, ai) 。在座標內畫 n 條垂直線,垂直線 i 的兩個端點分別為 (i, ai) 和 (i, 0) 。找出其中的兩條線,
使得它們與 x 軸共同構成的容器可以容納最多的水。
說明:你不能傾斜容器。
解法:雙指標
思路:面積的公式~寬(下標之差~雙指標)* 高(取決於左右兩側兩個柱子中比較小的那個柱子)
詳細:咱從左側(left = 0),右側(right = height.size() - 1)循壞:
如果高出現在左側: if (height[left] <= height[right]) 左側的柱子比右側低,則 高 的可能性出現在左側區域,需要在左側找到一個最大的值(作為高)
同時,通過更新 當前的面積(如果當前的 寬(雙指標下標之差)* 高(左側某個最大值)與前一個面積比較,大於則更新面積)
右側同理。。。。
總結:“左側的柱子比右側低,則 高 的可能性出現在左側區域,需要在左側找到一個最大的值(作為高)”~思路,即先找到比較小的區域,然後在比較小的區域中找到一個最大值
public int maxArea(int[] height) { intleft = 0, right = height.length - 1; int ans = 0; while (left < right) { //面積公式 高:最小的 【左柱子,右柱子】 int area = Math.min(height[left], height[right]) * (right - left); ans = Math.max(ans, area); // 需要找小的: if (height[left] <=height[right]) { // 左側柱子比較低,較小的柱子可能性出現在左側 ++left; //遍歷找那個最大值,同時更新面積,最後得到的面積即最大面積啦 } else { --right; } } return ans; }
2,接雨水:
題意:
給定n
個非負整數表示每個寬度為 1
的柱子的高度圖,計算按此排列的柱子,下雨之後能接多少雨水。
解法:雙指標
思路: 當前水柱A上可以接收的水量取決於左右兩側最低那個柱子與它的高度差
(例如左側比右側低,則左側區域決定了它的高度差)然後再左側區域中找到最高的柱子~(與當前水柱A)最大高度差,即單位水量
詳細:咱從左側(left = 0),右側(right = height.size() - 1)循壞:
如果比較低的柱子出現在左側:if (height[left] <= height[right]) 則決定水柱A最大接收水量的可能性出現在左側區域,
需要在左側找到一個最大的值
同時,通過更新 當前的左側最大水柱(當前height[left] 與前一個 left_max 比較,大於則更新左側最大水柱)
右側同理。。。。
public int trap(int[] height) { int left = 0, right = height.length - 1; int ans = 0; int left_max = 0, right_max = 0; while (left < right) { if (height[left] < height[right]) { // 左側柱子比較低,較小的柱子(決定存水量)可能性出現在左側 if (height[left] >= left_max) { left_max = height[left]; } else { ans += (left_max - height[left]); //計算當前儲存的水量 } ++left; //遍歷找那個最大值,同時更新最大值,最後得到的即是最大值啦 } else { if (height[right] >= right_max) { right_max = height[right]; } else { ans += (right_max - height[right]); } --right; } } return ans; }