1、题目描述:
2、题解:
对比做:双指针(缩减搜索空间):力扣11. 盛最多水的容器
方法1:双指针法
思路:
定义双指针left,right,一个向右走,一个向左走,那么还需要定义左边的最大高度leftmax和右边的最大高度rightmax
循环:
找出left左边的最大高度leftmax
找出right右边的最大高度rightmax
找到较小的值,更新res和指针
返回res
Python实现:
class Solution:
def trap(self, height: List[int]) -> int:
#双指针
n = len(height)
if n < 3:
return 0
left,right = 0,n - 1
leftmax,rightmax = height[0],height[n-1]
res = 0
while left < right:
leftmax = max(leftmax,height[left])
rightmax = max(rightmax,height[right])
if leftmax < rightmax :
res += leftmax - height[left]
left += 1
else:
res += rightmax - height[right]
right -= 1
return res
C++实现:
class Solution {
public:
int trap(vector<int>& height) {
// 双指针
if(height.size() < 3){
return 0;
}
int left = 0,right = height.size() - 1;
int res = 0;
int left_max = height[0],right_max = height[height.size()-1];
while (left < right){
left_max = max(left_max,height[left]);
right_max = max(right_max,height[right]);
if (left_max < right_max){
res += left_max - height[left];
++left;
}else{
res += right_max - height[right];
--right;
}
}
return res;
}
};
方法2:动态规划
其实就是找两个数组,一个记录左边比i高的,一个记录右边比i高的
然后res += min(leftmax[i],rightmax[i])-height[i]
water[i] = min(
# 左边最高的柱子
max(height[0..i]),
# 右边最高的柱子
max(height[i..end])
) - height[i]
Python实现:
class Solution:
def trap(self, height: List[int]) -> int:
#动态规划,辅助数组
if not height:
return 0
n = len(height)
leftmax = [0] * n
rightmax = [0] * n
ans = 0
#初始化
leftmax[0] = height[0]
rightmax[n-1] = height[n-1]
for i in range(1,n):
leftmax[i] = max(leftmax[i - 1],height[i])
for j in range(n - 2, -1, -1):
rightmax[j] = max(rightmax[j+1],height[j])
for i in range(n):
ans += min(leftmax[i],rightmax[i]) - height[i]
return ans
C++实现:
class Solution {
public:
int trap(vector<int>& height) {
//动态规划
if(height.size() == 0)
return 0;
int size = height.size(),res = 0;
vector<int> left_max(size),right_max(size);
left_max[0] = height[0],right_max[size-1] = height[size - 1];
for (int i =1;i < size;i++){
left_max[i] = max(height[i],left_max[i-1]);
}
for (int i = size - 2;i >= 0;i--){
right_max[i] = max(height[i],right_max[i+1]);
}
for (int i = 1;i < size - 1;i++){
res += min(left_max[i],right_max[i]) - height[i];
}
return res;
}
};
方法3:单调栈
单调栈:
一句话题解:
里面保存的是下标,而下标对应的height值的递减的,遇到比上个height值小的就入栈,否则,就出栈,然后计算积水面积
设置栈stack,积水面积res,指针current。
移动指针:
当栈不空,且当前高度大于栈顶高度的时候,就循环:
出栈,并找到出栈元素所对应的height值h(下面就是求h的左右两边的最小高度-h 然后再乘以宽度,得到此时的积水面积)
如果栈空,break
求出current和栈顶的距离distance
求此时的积水面积,s = (min(height[current],height[height[-1]]) - h ) * distance
更新res,也即res += s
把当前指针入栈
向右移动指针
返回res
Python实现:
class Solution:
def trap(self, height: List[int]) -> int:
#单调栈
res = 0
stack = []
current = 0
while current < len(height):
while stack and height[current] > height[stack[-1]]:
h = height[stack.pop()]
if not stack:
break
distance = current - stack[-1] - 1
s = (min(height[current],height[stack[-1]]) - h ) * distance
res += s
stack.append(current)
current += 1
return res
C++实现:
class Solution {
public:
int trap(vector<int>& height) {
//单调栈
int res = 0,current = 0;
stack<int> st;
while (current < height.size()){
while( !st.empty() && height[current] > height[st.top()]){
int h = height[st.top()];
st.pop();
if (st.empty())
break;
int distance = current - st.top() - 1;
int s = (min(height[current],height[st.top()])-h) * distance;
res += s;
}
st.push(current);
++current;
}
return res;
}
};
3、复杂度分析:
方法1:
时间复杂度:O(N)
空间复杂度:O(1)
方法2:
时间复杂度:O(N)
空间复杂度:O(N)
方法3:
时间复杂度:O(N)
空间复杂度:O(N)