算法学习day59

这篇具有很好参考价值的文章主要介绍了算法学习day59。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.力扣503.下一个更大元素II

1.1 题目描述

题目描述:

给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字x的下一个更大元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,循环搜索它的下一个更大的数。如果不存在,输出-1。

例1:

输入:[1, 2, 1]

输出:[2, -1 , 2]

解释:第一个1的下一个更大的数是2;数字2找不到下一个更大的数输出-1;第二个1的下一个最大的数需要循环搜索,结果也是2.

1.2 分析

当我们需要在一个循环数组中找到每个元素的下一个更大元素时,可以使用单调栈的思想来解决这个问题。

假设我们有一个循环数组 nums,为了方便处理,我们可以将它复制一份拼接到原数组的末尾,从而得到一个长度为原数组两倍的新数组 nums。这样处理后,我们就可以把循环数组 nums 看成一个普通的数组,从而用单调栈来解决。

接下来就是单调栈的操作:

我们用一个栈来存储数组元素的下标。首先,我们将数组的第一个元素的下标 push 进栈中,即 st.push(0)。

然后,从数组的第二个元素开始遍历数组,对于数组的每个元素 nums[i],如果它小于或等于栈顶元素所对应的元素 nums[st.top()],则将它的下标 i push 进栈中,表示它的下一个更大元素还没有找到

如果 nums[i] 大于栈顶元素所对应的元素 nums[st.top()],则说明栈顶元素的下一个更大元素就是 nums[i],我们可以将栈顶元素所对应的结果 result[st.top()] 赋值为 nums[i],表示它的下一个更大元素是 nums[i],然后将栈顶元素 pop 出栈,继续判断新的栈顶元素和当前元素的大小关系

重复执行上述操作,直到遍历完整个数组。最后,我们得到的结果数组 result 中存储的就是每个元素的下一个更大元素了。由于我们把原数组复制拼接到末尾,所以最后需要将结果数组 result 调整为原数组的大小,即执行 result.resize(nums.size() / 2)。

时间复杂度为 O(n),因为每个元素只会入栈出栈一次。

1.3代码

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        // 拼接一个新的nums,使其成为长度为原数组两倍的数组
        vector<int> nums1(nums.begin(), nums.end());
        // 将nums1中的所有元素插入到nums的末尾,从而得到一个新的nums
        nums.insert(nums.end(), nums1.begin(), nums1.end());
        // 用新的nums大小来初始化result
        vector<int> result(nums.size(), -1);
        if (nums.size() == 0) return result;

        // 开始单调栈
        stack<int> st;
        // 单调栈的初始化
        st.push(0);
        for (int i = 1; i < nums.size(); i++) {
            // 如果当前元素比栈顶元素小或相等,直接入栈
            if (nums[i] <= nums[st.top()]) st.push(i);
            // 如果当前元素比栈顶元素大,那么栈中所有比当前元素小的元素的下一个更大元素就是当前元素
            else {
                while (!st.empty() && nums[i] > nums[st.top()]) {
                    result[st.top()] = nums[i];
                    st.pop();
                }
                st.push(i);
            }
        }
        // 最后再把结果集即result数组resize到原数组大小
        result.resize(nums.size() / 2);
        return result;
    }
};

2.力扣42. 接雨水

2.1 题目描述

题目描述:

给定n个非负整数表示每个宽度为1的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

算法学习day59
输入:height=[0,1,0,2,1,0,1,3,2,1,2,1]

输出:6

解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

2.2 分析

双指针法:

按照列来计算,宽度为1.将每一列的雨水高度求出来即可。

计算该列取决于左侧最高柱子和右侧最高柱子中最矮小的减去自身。转换为公式如下:

计算公式:min(左侧最高,右侧最高)- 本身高度。

结合下图更好理解:
算法学习day59
列4 左侧最高的柱子是列3,高度为2(以下用lHeight表示)。

列4 右侧最高的柱子是列7,高度为3(以下用rHeight表示)。

列4 柱子的高度为1(以下用height表示)

那么列4的雨水高度为 列3和列7的高度最小值减列4高度,即: min(lHeight, rHeight) - height。

列4的雨水高度求出来了,宽度为1,相乘就是列4的雨水体积了。
同样的操作,从头遍历一遍所有的列,然后求出每一列雨水的体积。相加就是总雨水的体积了。注:第一个柱子和最后一个柱子不接雨水

代码如下:

for(int i = 0 ; i < height.size() ; i++){
    // 第一个柱子和最后一个柱子不接雨水、
    if(i == 0 || i == height.size() - 1) continue;
}

在for循环中求左右两边最高柱子,代码如下:

int rHeight = height[i]; // 记录右边柱子的最高高度
int lHeight = height[i]; // 记录左边柱子的最高高度
for(int r = i+1 ; i height.size(); r++){
    if(height[r] > rHeight) rHeight = height[r];
}
for(int l = i -1 ; l>= 0; l--){
    if(height[l] > lHeight) lHeight = height[l];
}

最后计算该列的雨水高度:

int h = min(lHeight,rHeight) -height[i];
if(h>0) sum += h;// 注意只有h大于零的时候,才统计到总和之中。

优化:

之前为了得到两边的最高高度,使用双指针来遍历,每到一个柱子都行两边遍历一遍。考虑把每一个位置的左边最高高度记录在一个数组上(maxLeft),右边最高高度记录在一个数组上(maxRight),即可避免重复。

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

从左向右遍历:maxLeft[i] = max(height[i],maxLeft[i-1])

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

2.3 代码

class Solution {
public:
    int trap(vector<int>& height) {
        // 如果height的长度小于等于2,那么无法形成水坑,直接返回0
        if (height.size() <= 2) return 0;
        // 初始化一个数组,用来记录每个柱子左边柱子最大高度
        vector<int> maxLeft(height.size(), 0);
        // 初始化一个数组,用来记录每个柱子右边柱子最大高度
        vector<int> maxRight(height.size(), 0);
        // 获取maxRight数组的大小
        int size = maxRight.size();

        // 计算每个柱子左边柱子的最大高度
        maxLeft[0] = height[0]; // 第一个柱子的最大高度就是它本身
        for (int i = 1; i < size; i++) {
            // 当前柱子的左边柱子最大高度,是当前柱子高度和左边柱子的最大高度中较大的那个
            maxLeft[i] = max(height[i], maxLeft[i - 1]);
        }
        // 计算每个柱子右边柱子的最大高度
        maxRight[size - 1] = height[size - 1]; // 最后一个柱子的最大高度就是它本身
        for (int i = size - 2; i >= 0; i--) {
            // 当前柱子的右边柱子最大高度,是当前柱子高度和右边柱子的最大高度中较大的那个
            maxRight[i] = max(height[i], maxRight[i + 1]);
        }
        // 计算每个柱子能存放的水量,并将结果求和
        int sum = 0;
        for (int i = 0; i < size; i++) {
            // 当前柱子能存放的水量,等于左边柱子最大高度和右边柱子最大高度中较小的那个减去当前柱子的高度
            int count = min(maxLeft[i], maxRight[i]) - height[i];
            if (count > 0) sum += count;
        }
        return sum; // 返回总的水量
    }
};


3.参考资料

[代码随想录]文章来源地址https://www.toymoban.com/news/detail-413176.html

到了这里,关于算法学习day59的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Day58|leetcode 739. 每日温度、496.下一个更大元素 I

    今天开始单调栈! 题目链接:739. 每日温度 - 力扣(LeetCode) 视频链接:单调栈,你该了解的,这里都讲了!LeetCode:739.每日温度_哔哩哔哩_bilibili 题目概述   给定一个整数数组  temperatures  ,表示每天的温度,返回一个数组  answer  ,其中  answer[i]  是指对于第  i  天,下

    2024年02月09日
    浏览(27)
  • 力扣算法刷题Day59|单调栈

    力扣题目:# 503.下一个更大元素II  刷题时长:参考题解后2min 解题方法:单调栈 复杂度分析 时间O(n) 空间O(n) 问题总结 如何解决环的问题 本题收获 循环数组解决方案 思路一:将两个nums数组拼接在一起,使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即res

    2024年02月13日
    浏览(46)
  • 算法学习day59

    题目描述: 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字x的下一个更大元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,循环搜索它的下一个更大的数。如果不存在,输出-1。 例1: 输入:[1, 2

    2023年04月14日
    浏览(20)
  • 力扣labuladong一刷day59天动态规划

    力扣labuladong一刷day59天动态规划 一、509. 斐波那契数 题目链接:https://leetcode.cn/problems/fibonacci-number/description/ 思路:这是非常典型的一道题,下面是优化过的代码,a,b就是dp数组,因为每计算一个值,需要前两个值,这个a,b就是用来记录前两个值,避免重复计算,递推公式便

    2024年01月21日
    浏览(37)
  • leetcode 503. 下一个更大元素 II

             本题类似于下一个更大元素I ,区别就是数组变成循环的了,可以将nums数组先double一下,如:{1,2,1}变成{1,2,1,1,2,1},再用单调栈的方法求出ans数组,最后将ans数组截一半即可。 代码如下:

    2024年02月11日
    浏览(25)
  • leetcode 496. 下一个更大元素 I

             这题提供暴力解法和单调栈法两种方法。         题中说了数组中没有重复的元素,为了避免重复遍历nums2数组,可以用一个哈希map和单调栈stack将nums2数组中的每个元素对应其查询值存储在map中,类似于每日温度。然后再遍历nums1查询相应元素对应的查询值。 代码

    2024年02月11日
    浏览(29)
  • 【栈】Leetcode 496 下一个更大元素I

    ---------------🎈🎈题目链接🎈🎈------------------- 两个栈进行操作,一个栈用来遍历寻找,一个栈用来保留 将待寻找的nums2中的元素入栈,之后遍历nums1, 如果栈顶元素大于nums1[i],则记录max,记录后弹出栈顶元素至tempstack,继续遍历栈,直到找到相等的为止 如果栈顶元素小于

    2024年01月17日
    浏览(34)
  • leetcode496. 下一个更大元素 I 【单调栈】

    【简单题】(暴力遍历法很简单)但是时间复杂度很高,n的立方级别了。。。 代码: 运行结果:   进阶方法: 进阶: 你可以设计一个时间复杂度为  O(nums1.length + nums2.length)  的解决方案吗? 答案思路:【单调栈】 怎么样才能使得 用 nums1中的元素去 nums2中查找的时候,能

    2024年02月10日
    浏览(33)
  • leetcode503. 下一个更大元素 II 单调栈

    思路: 与之前 739、1475 单调栈的问题如出一辙,唯一不同的地方就是对于遍历完之后。栈中元素的处理,之前的栈中元素因无法找到符合条件的值,直接加入vector中。而这里需要再重头遍历一下数组,找是否有符合条件的,如果仍然找不到的话,才会把它赋值然后加入vecto

    2024年02月11日
    浏览(25)
  • 力扣题库刷题笔记496-下一个更大元素

    1、题目如下: 2、个人Python代码实现   代码如下: class Solution:     def nextGreaterElement(self, nums1: List[int], nums2: List[int]) - List[int]:         #空列表用于输出结果         ans = []         for i in nums1:             #如果nums2中不包含或者最后一位元素为当

    2023年04月26日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包