代码随想录算法训练营第59天|503.下一个更大元素II,42. 接雨水

503.下一个更大元素II

力扣题目链接

思路

  • 单调栈+循环数组

代码

class Solution {
public:
    vector nextGreaterElements(vector& nums) {
        vector res(nums.size(),-1);
        int count=0;
        stack st;
        for(int i=0;inums[st.top()]){
                res[st.top()]=nums[i%nums.size()];
                st.pop();
            }
            st.push(i%nums.size());
        }
        return res;
    }
};
  • 时间复杂度O(n)
  • 空间复杂度O(n)

42. 接雨水

力扣题目链接

思路

双指针法

  • 按列接雨水,遍历所有列,求出每一列所能接雨水的体积,相加(第一列和最后一列不接雨水)
  • 求出每一列所能接雨水的体积:寻找左右两边最高的柱子

动态规划

  • 使用双指针遍历过程中存在重复计算

  • 因此可以使用动态规划,将每一个位置左边的最高高度和右边的最高高度分别记录到数组中

  • 当前位置,左边最高高度是前一个位置的左边最高高度和当前位置高度的最大值

    • 从左向右遍历:maxLeft[i]=max(height[i],maxLeft[i-1]);
  • 当前位置,右边最高高度是前一个位置的右边最高高度和当前位置高度的最大值

    • 从右向左遍历:maxRight[i]=max(height[i],maxRight[i+1]);

单调栈

  • 按行接雨水
  • 当前元素>栈顶元素,出栈元素1(凹槽底部),出栈后栈顶元素(凹槽左侧柱子),所接雨水=(当前元素-出栈后栈顶元素-1)*(min(当前元素,出栈后栈顶元素)-出栈元素1)
  • 当前元素==栈顶元素,出栈,将当前元素入栈(保留相同元素最右边的那个,便于计算宽度)
  • 当前元素<栈顶元素,入栈

双指针法改进

  • leftmax:当前位置左边高度的最大值,rightmax:当前位置右边高度的最大值

  • left:从左向右移动,right:从右向左移动

  • 两指针相遇,循环结束

  • 两指针未相遇

    • leftmax
    • leftmax>=rightmax,下标right处所接雨水量=rightmax-height[right],right–
  • 对于left来说,leftmax是准确的,rightmax不一定准确,因为区间(left,right)的值未遍历,但left的rightmax一定>=right的rightmax,当我们求leftmax

我的解法
  • 单调栈从左往右和从右往左分别分别计算出当前元素的左右两侧下一个更大元素
  • 按行接雨水=(left-right-1)*(min(height[left],height[right])-height[i])
  • 为了避免重复接雨水,(left,right)对需要去重

代码

双指针法

class Solution {
public:
    int trap(vector& height) {
        int res=0;
        for(int i=0;i=0;j--)
                leftheight=max(leftheight,height[j]);
            for(int j=i+1;j
  • 时间复杂度O(n^2)
  • 空间复杂度O(1)

动态规划

class Solution {
public:
    int trap(vector& height) {
        vector maxLeft(height.size());
        vector maxRight(height.size());
        // 记录每一个位置左边高度的最大值
        maxLeft[0]=height[0];
        for(int i=1;i=0;i--){
            maxRight[i]=max(maxRight[i+1],height[i]);
        }
        //计算结果,求和
        int res=0;
        for(int i=0;i
  • 时间复杂度O(n)
  • 空间复杂度O(n)

单调栈

class Solution {
public:
    int trap(vector& height) {
        int res=0;
        stack st;
        st.push(0);
        for(int i=1;iheight[st.top()]){
                int down=height[st.top()];
                st.pop();
                if(!st.empty()){
                    res+=(i-st.top()-1)*(min(height[i],height[st.top()])-down);
                }
            }
            st.push(i);
        }
        return res;
    }
};
  • 时间复杂度O(n)
  • 空间复杂度O(n)

双指针改进

class Solution {
public:
    int trap(vector& height) {
        int leftMax=0,rightMax=0;
        int left=0,right=height.size()-1;
        int res=0;
        while(left
  • 时间复杂度O(n)
  • 空间复杂度O(1)

我的解法

class Solution {
public:
    void create(vector& height,vector& next){
        stack st;
        for(int i=0;iheight[st.top()]){
                next[st.top()]=i;
                st.pop();
            }
            st.push(i);
        }
    }
    int trap(vector& height) {
        vector next1(height.size(),-1);
        vector next2(height.size(),-1);
        //翻转数组
        vector height2(height.size());
        for(int i=height.size()-1,j=0;i>=0;i--,j++)
            height2[j]=height[i];
        //计算正序和逆序下一个更大元素
        create(height,next1);
        create(height2,next2);
        for(int i=0;i> map(height.size(),vector(3,-1));
        int count=0;
        for(int i=0;i

你可能感兴趣的:(代码随想录刷题,算法,leetcode,c++)