leetcode 42 接雨水

简介: leetcode 42 接雨水

接雨水

9d4fea0391e344dcb426f3de585e70d5.png

双指针(超时)

class Solution {
public:
    int trap(vector<int>& height) {
        int left,right,result=0;
        for(int i=1 ; i<height.size()-1 ;i++)
        {
            left = height[i];
            right = height[i];
      //找到左右最高点
            for(int j=i+1 ; j<height.size();j++)
                if(height[j] > right) right = height[j];
            for(int j=i-1; j>=0 ;j--)
                if(height[j] > left) left = height[j];
            //计算当点的雨水,累加
            result = result + min(left,right) - height[i];
        }
        return result;
    }
};


单调栈


8d10fe8738504eeaaedc40df8a0ffbfb.png


从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。

因为一旦发现添加的柱子高度大于栈头元素了,此时就出现凹槽了,栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。


d6e4f50e74964d478a8e236c54d0e289.png

遇到相同的元素,更新栈内下标,就是将栈里元素(旧下标)弹出,将新元素(新下标)加入栈中。

例如 5 5 1 3 这种情况。如果添加第二个5的时候就应该将第一个5的下标弹出,把第二个5添加到栈中。

因为我们要求宽度的时候 如果遇到相同高度的柱子,需要使用最右边的柱子来计算宽度。

8759e87f81fc4908bfffe67bfced99fd.png


单调栈处理逻辑

  • 先将下标0的柱子加入到栈中
  • 然后开始从下标1开始遍历所有的柱子
  • 如果当前遍历的元素(柱子)高度小于栈顶元素的高度,就把这个元素加入栈中,因为栈里本来就要保持从小到大的顺序(从栈头到栈底)。
  • 如果当前遍历的元素(柱子)高度等于栈顶元素的高度,要跟更新栈顶元素,因为遇到相相同高度的柱子,需要使用最右边的柱子来计算宽度。
  • 如果当前遍历的元素(柱子)高度大于栈顶元素的高度,此时就出现凹槽了,如图所示:栈顶和栈顶的下一个元素以及要入栈的三个元素来接水!

cfb13601cf514dabb0a1027d393d423c.png

class Solution {
public:
    int trap(vector<int>& height) {
        if(height.size()<=2) return 0;
        stack<int> st;
        int result = 0;
        st.push(0);
        for(int i=1 ; i<height.size() ;i++)
        {
          //当前柱子比栈顶的小
            if(height[i] < height[st.top()])
                st.push(i);
            //当前柱子和栈顶相等
            else if(height[i] == height[st.top()])
            {
                st.pop();
                st.push(i);
            //当前柱子比栈顶的大,产生了凹陷
            }else if(height[i] > height[st.top()])
            {
                while(st.empty()==0 && height[i] > height[st.top()])
                {
                    int mid = st.top();
                    st.pop();
                    if(st.empty()==0) 
                    {
                        int left = st.top();
                        int right = i;
                        int h = min(height[left] , height[right]) - height[mid];
                        int w = right - left -1;
                        result += h*w;
                    }
                }
                st.push(i);
            }
        }
        return result;
    }
};

二刷(双指针超时)

class Solution {
public:
    int trap(vector<int>& height) {
        int result = 0;
        for(int i=1; i<height.size()-1 ;i++)
        {
            int left = i;
            int right = i;
            for(int j=left ; j>=0 ; j--)
                if(height[j] > height[left]) left = j;
            for(int j=right ; j<height.size() ; j++)
                if(height[j] > height[right]) right = j;
            if(left != i && right != i)
            {
                result += min(height[left] , height[right]) - height[i];
            }      
        }
        return result;
    }
};

二刷(总面积 - 柱子面积 = 水面积)

class Solution {
public:
    int trap(vector<int>& height) {
        int sum = 0;
        int rel = 0;
        int max_h = 0;
        int tmp_h;
        for(int i = 0 ; i<height.size() ;i++)
            if(height[i] > height[max_h]) max_h = i; //计算最高点
        tmp_h = 0;
        for(int i = 0 ; i<max_h ;i++) //从左往最高点算
        {
            if(height[i] >= height[tmp_h]) tmp_h = i;
            sum += height[tmp_h];
            rel += height[i];
        }
        tmp_h = height.size()-1;
        for(int i = height.size()-1 ; i > max_h ;i--)//从右往最高的算
        {
            if(height[i] >= height[tmp_h]) tmp_h = i;
            sum += height[tmp_h];
            rel += height[i];
        }
        return sum - rel; //总面积 - 真实柱子面积 = 水面积
    }
};

二刷(单调栈)

class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> my_stack;
        int result = 0;
        my_stack.push(0);
        for(int i=1 ; i<height.size() ; i++)
        {
            if(height[i] < height[my_stack.top()])
                my_stack.push(i);
            else if(height[i] == height[my_stack.top()])
            {
                my_stack.pop();
                my_stack.push(i);
            }else if(height[i] > height[my_stack.top()])
            {
                while(my_stack.size() != 0 && height[i] > height[my_stack.top()] )
                {
                    int mid = my_stack.top();
                    my_stack.pop();
                    if(my_stack.size() != 0)
                    {
                        int left = my_stack.top();
                        int right = i;
                        result += (right - left - 1) * ( min( height[left] , height[right]) - height[mid] );
                    }
                }
                my_stack.push(i);
            }
        }   
        return result;
    }
};
相关文章
|
6月前
|
容器
leetcode-407:接雨水 II
leetcode-407:接雨水 II
74 0
|
6月前
|
图计算 索引
leetcode-42:接雨水
leetcode-42:接雨水
55 0
|
算法 测试技术 图计算
|
1月前
|
算法 图计算 C++
Leetcode第42题(接雨水)
这篇文章介绍了解决LeetCode第42题“接雨水”问题的不同算法,包括双指针法和单调栈法,并提供了C++的代码实现。
16 0
Leetcode第42题(接雨水)
|
3月前
|
存储
【面试题】接雨水
【面试题】接雨水
13 0
|
5月前
|
算法 图计算
力扣经典150题第十六题:接雨水
力扣经典150题第十六题:接雨水
28 0
|
6月前
|
容器
每日一题——接雨水(单调栈)
每日一题——接雨水(单调栈)
|
6月前
|
图计算
【每日一题Day274】LC42接雨水 | 单调栈
【每日一题Day274】LC42接雨水 | 单调栈
48 0
|
算法
【LeetCode力扣】42. 接雨水
【LeetCode力扣】42. 接雨水
78 0
|
测试技术
Leecode 42. 接雨水
Leecode 42. 接雨水
96 1