首页 > 编程语言 >代码随想录算法训练营第五九天 | 下一个更大元素II、接雨水

代码随想录算法训练营第五九天 | 下一个更大元素II、接雨水

时间:2024-03-16 23:58:05浏览次数:27  
标签:nums int 训练营 随想录 height II length sum stack

目录

LeetCode 503.下一个更大元素II
LeetCode 42. 接雨水

下一个更大元素II

给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。

数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。

  • 问题的关键在于在遍历的过程中模拟走了两遍 nums
class Solution {
    public int[] nextGreaterElements(int[] nums) {
        Deque<Integer> stack = new LinkedList<>();
        int[] res = new int[nums.length];
        Arrays.fill(res, -1);

        stack.push(0);
        int length = nums.length;
        for (int i = 0; i < length * 2; i++) {            
            while (!stack.isEmpty() && nums[i % length] > nums[stack.peek()]) {
                res[stack.peek()] = nums[i % length];
                stack.pop();
            }
            stack.push(i % length);
        }
        return res;
    }
}

接雨水

  • 暴力
    • 也是使用双指针。
    • 按照列来计算的话,宽度一定是1了,我们再把每一列的雨水的高度求出来就可以了。
    • 只要记录左边柱子的最高高度 和 右边柱子的最高高度,就可以计算当前位置的雨水面积,这就是通过列来计算。
    • 当前列雨水面积:min(左边柱子的最高高度,记录右边柱子的最高高度) - 当前柱子高度。 min(lHeight, rHeight) - height。
    • 只要从头遍历一遍所有的列,然后求出每一列雨水的体积,相加之后就是总雨水的体积了。
    • 时间复杂度为 O ( n 2 ) O(n^2) O(n2),空间复杂度为 O ( 1 ) O(1) O(1)。 超时

在这里插入图片描述

class Solution {
    public int trap(int[] height) {
        // 暴力
        int sum = 0;
        for (int i = 0; i < height.length; i++) {
            // 第一个柱子和最后一个柱子不接水
            if(i == 0 || i == height.length - 1) continue;

            int rHeight = height[i]; // 记录右边柱子的最高高度
            int lHeight = height[i]; // 记录左边柱子的最高高度
            for (int r = i + 1; r < height.length; r++){
                rHeight = Math.max(rHeight, height[r]);
            }
            for (int l = i - 1; l >= 0; l--){
                lHeight = Math.max(lHeight, height[l]);
            }
            int h = Math.min(rHeight, lHeight) - height[i];
            if (h > 0) sum += h;
        }
        return sum;
    }
}
  • 双指针优化

    • 优化思路是讲取左侧最高高度和右侧最高高度脱离出来,提前处理
    • 暴力解法中,为了得到两边的最高高度,使用了双指针来遍历,每到一个柱子都向两边遍历一遍,这其实是有重复计算的。
    • 我们把每一个位置的左边最高高度记录在一个数组上(maxLeft),右边最高高度记录在一个数组上(maxRight),这样就避免了重复计算。
    • 从左向右遍历:maxLeft[i] = max(height[i], maxLeft[i - 1]);
    • 从右向左遍历:maxRight[i] = max(height[i], maxRight[i + 1]);
class Solution {
    public int trap(int[] height) {
        // 双指针优化
        if (height.length <= 2) return 0;
        int[] maxLeft = new int[height.length];
        int[] maxRight = new int[height.length];
        int length = height.length;

        // 记录每个柱子左边柱子的最大高度
        maxLeft[0] = height[0];
        for (int i = 1; i < length; i++) {
            maxLeft[i] = Math.max(height[i], maxLeft[i-1]);
        }

        // 记录每个柱子右边柱子的最大高度
        maxRight[length-1] = height[length-1];
        for (int i = length-2; i >= 0; i--) {
            maxRight[i] = Math.max(height[i], maxRight[i+1]);
        }

        // 求和
        int sum = 0;
        for (int i = 0; i < length; i++) {
            int count = Math.min(maxLeft[i], maxRight[i]) - height[i];
            if (count > 0) sum += count;
        }
        return sum;
    }
}
  • 单调栈
    • 单调栈就是保持栈内元素有序,需要自己维持顺序。
    • 通常是一维数组,要寻找任一个元素的右边或左边第一个比自己大或者小的元素的位置,此时用单调栈。

在这里插入图片描述

class Solution {
    public int trap(int[] height) {
        if (height.length <= 2) return 0;
        Stack<Integer> stack = new Stack<Integer>();
        stack.push(0);
        int sum = 0;
        for (int i = 1; i < height.length; i++) {
            if (height[i] < height[stack.peek()]) {
                stack.push(i);
            }
            else if (height[i] == height[stack.peek()]) {
                stack.pop();
                stack.push(i);
            }
            else {
                // pop up all lower value
                while (!stack.isEmpty() && height[i] > height[stack.peek()]) {
                    int mid = stack.peek();
                    stack.pop();
                    if (!stack.isEmpty()) {
                        int h = Math.min(height[stack.peek()], height[i]) - height[mid];
                        int w = i - stack.peek() - 1;
                        int hold = h * w;
                        if (hold > 0) sum += hold;
                    }
                }
                stack.push(i);
            }

        }
        return sum;
    }
}

标签:nums,int,训练营,随想录,height,II,length,sum,stack
From: https://blog.csdn.net/SUburbuia/article/details/136669669

相关文章

  • 代码随想录一刷总结
    总结我就不过多总结技术性的东西了,只讲讲自己的感受。呜呜有时候钱还是让别人去赚吧,如果自驱力不行(其实九成都不行,不用太自信嘿嘿)那么就让外部环境影响你吧,报个代码训练营也挺好的,最起码我从来没有认真刷过那么多题。而且力扣官方的题解呀,真的是有时候被吓死,全是新语法,我看......
  • 122. 买卖股票的最佳时机 IIc
    intmax(inti,intj){if(i>j)returni;returnj;}intmaxProfit(int*prices,intpricesSize){int**dp=(int**)malloc(sizeof(int*)*pricesSize);for(inti=0;i<pricesSize;i++)dp[i]=(int*)malloc(sizeof(int)*2);dp[0][0]=0,dp[0][......
  • 代码随想录算法训练营day24 | leetcode 77. 组合
    目录题目链接:77.组合题目链接:77.组合题目描述:给定两个整数n和k,返回范围[1,n]中所有可能的k个数的组合。你可以按任何顺序返回答案。示例1:输入:n=4,k=2输出:[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4],]示例2:输入:n=1,k=1输出:[[1]......
  • 90. 子集 IIC
    /***Returnanarrayofarraysofsize*returnSize.*Thesizesofthearraysarereturnedas*returnColumnSizesarray.*Note:Bothreturnedarrayand*columnSizesarraymustbemalloced,assumecallercallsfree().*/inttemp[20];intcmp(constv......
  • 代码随想录算法训练营第十一天| 20. 有效的括号 1047. 删除字符串中的所有相邻重复
    20.有效的括号https://leetcode.cn/problems/valid-parentheses/description/publicbooleanisValid(Strings){if(s==null)returntrue;Stack<Character>stack=newStack<>();for(inti=0;i<s.length();i++){......
  • 代码随想录 第21天 | ● 530.二叉搜索树的最小绝对差 ● 501.二叉搜索树中的众数 ●
    leetcode:530.二叉搜索树的最小绝对差-力扣(LeetCode)思路:判断最小绝对差,肯定用中序遍历,双指针一前一后依次判断。classSolution{intresult=Integer.MAX_VALUE;TreeNodepre=null;publicintgetMinimumDifference(TreeNoderoot){if(root==......
  • 通关代码随想录!!!
    60天的坚持,52篇博客,142道力扣题,自己还是做到了......
  • 40. 组合总和 IIc
    /***Returnanarrayofarraysofsize*returnSize.*Thesizesofthearraysarereturnedas*returnColumnSizesarray.*Note:Bothreturnedarrayand*columnSizesarraymustbemalloced,assumecallercallsfree().*/inttemp[100];intcmp(const......
  • 代码随想录算法训练营第四十七天| ● 198.打家劫舍 ● 213.打家劫舍II ● 337.打家
    打家劫舍 题目链接:198.打家劫舍-力扣(LeetCode)思路:每一家的最大收益来源只有两个,一个是这家不偷,那么最大收益等于从上一家出来的最大收益,另一个是偷这一个家,因此最大收益等于从上上一家出来的最大收益加这一家的收益。classSolution{public:introb(vector<int>&nu......
  • iis使用动态 IP 限制
     使用动态IP限制(下载页面提示已停用)https://www.iis.net/downloads/microsoft/dynamic-ip-restrictionshttps://learn.microsoft.com/en-us/iis/manage/configuring-security/using-dynamic-ip-restrictions特征动态IP限制模块包括以下主要功能:根据并发请求数......