首页 > 编程语言 >代码随想录算法训练营第四十七天|Day47 单调栈

代码随想录算法训练营第四十七天|Day47 单调栈

时间:2024-11-16 21:17:20浏览次数:3  
标签:int 栈顶 top 元素 随想录 第四十七 数组 Day47 stack

739. 每日温度

https://programmercarl.com/0739.%E6%AF%8F%E6%97%A5%E6%B8%A9%E5%BA%A6.html

思路

int* dailyTemperatures(int* temperatures, int temperaturesSize, int* returnSize) {
    int* answer = (int*)malloc(temperaturesSize * sizeof(int));
    int* stack = (int*)malloc(temperaturesSize * sizeof(int));
    int top = -1; 
    *returnSize = temperaturesSize; /
    for (int i = 0; i < temperaturesSize; i++) {
        answer[i] = 0;
    }
    for (int i = 0; i < temperaturesSize; i++) {    
        while (top != -1 && temperatures[i] > temperatures[stack[top]]) {
            int idx = stack[top--]; 
            answer[idx] = i - idx; 
        }
        stack[++top] = i;
    }
    free(stack);   
    return answer;
}

学习反思

使用单调栈的思想来解决每日温度的问题。在遍历温度数组的过程中,我们使用一个栈来保存当前元素的索引。如果栈不为空且当前温度大于栈顶元素对应的温度,说明找到了栈顶元素的下一个更高温度,将栈顶元素弹出,并计算两个索引之间的距离,保存在答案数组中。最后将当前元素的索引压入栈中。代码中使用了两个指针topitop表示栈顶元素的索引,初始化为-1,i表示当前遍历到的温度数组的索引。同时,还使用了两个数组answerstackanswer用来保存结果,stack用来保存温度数组元素的索引。在代码开头,通过malloc函数动态分配了两个数组的内存大小,并将temperaturesSize赋给了*returnSize。接下来,先将answer数组的所有元素初始化为0。然后,通过一个循环遍历温度数组,内部通过一个while循环来处理每个温度元素。在while循环中,如果栈不为空且当前温度大于栈顶元素对应的温度,就说明找到了栈顶元素的下一个更高温度,将栈顶元素弹出,并计算两个索引之间的距离,保存在答案数组中。最后将当前元素的索引压入栈中。最后,释放了栈的内存,并返回答案数组。这段代码使用了单调栈的思想来快速解决每日温度问题,时间复杂度为O(n),空间复杂度为O(n)。

496.下一个更大元素 I

https://programmercarl.com/0496.%E4%B8%8B%E4%B8%80%E4%B8%AA%E6%9B%B4%E5%A4%A7%E5%85%83%E7%B4%A0I.html

思路


int* nextGreaterElement(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
    int* ans = (int*)malloc(nums1Size * sizeof(int));
    int* nextGreater = (int*)malloc(10001 * sizeof(int));
    for (int i = 0; i < 10001; i++) {
        nextGreater[i] = -1; 
    }
    int* stack = (int*)malloc(nums2Size * sizeof(int));
    int top = -1;     
    for (int i = 0; i < nums2Size; i++) {
        while (top != -1 && nums2[stack[top]] < nums2[i]) {
            nextGreater[nums2[stack[top]]] = nums2[i]; 
            top--; 
        }
        stack[++top] = i; 
    }

    for (int i = 0; i < nums1Size; i++) {
        ans[i] = nextGreater[nums1[i]]; 
    }

    free(stack);
    free(nextGreater);    
    *returnSize = nums1Size;
    return ans; 
}

学习反思

使用单调栈的思想来解决下一个更大元素的问题。给定两个数组nums1nums2,要求在nums2中找到nums1中每个元素的下一个更大元素。代码中使用了一个辅助数组nextGreater,用来保存每个元素的下一个更大元素。数组的大小设为10001,原因是nums2中的元素范围在0到10000之间。在代码开头,通过malloc函数动态分配了两个数组的内存大小,并将nums1Size赋给了*returnSize。接着,通过一个循环将nextGreater数组的所有元素初始化为-1。然后,通过一个循环遍历nums2数组,内部通过一个while循环来处理每个元素。在while循环中,如果栈不为空且栈顶元素对应的值小于当前元素的值,就说明找到了栈顶元素的下一个更大元素,将栈顶元素弹出,并将当前元素的值赋给对应的nextGreater数组元素。最后将当前元素的索引压入栈中。然后,通过一个循环遍历nums1数组,将每个元素对应的下一个更大元素从nextGreater数组中取出并保存在答案数组ans中。最后,释放了栈和nextGreater数组的内存,并返回答案数组。这段代码使用了单调栈的思想来快速解决下一个更大元素的问题,时间复杂度为O(m+n),其中m和n分别为nums1nums2的长度。空间复杂度为O(m+n)。

503.下一个更大元素II

https://programmercarl.com/0503.%E4%B8%8B%E4%B8%80%E4%B8%AA%E6%9B%B4%E5%A4%A7%E5%85%83%E7%B4%A0II.html

思路

int* nextGreaterElements(int* nums, int numsSize, int* returnSize) {
    int* ans = (int*)malloc(numsSize * sizeof(int));
    for (int i = 0; i < numsSize; i++) {
        ans[i] = -1;     }
    int* stack = (int*)malloc(numsSize * sizeof(int));
    int top = -1; 
    for (int i = 0; i < 2 * numsSize; i++) {
        int currentIndex = i % numsSize;
        while (top != -1 && nums[currentIndex] > nums[stack[top]]) {
            ans[stack[top]] = nums[currentIndex]; 
            top--; 
        }
        if (i < numsSize) {
            stack[++top] = currentIndex; 
        }
    }

    free(stack);
    *returnSize = numsSize;    
 return ans; 
}

学习反思

实现了一个函数,用于找到数组中每个元素的下一个更大元素。函数输入一个整数数组nums,数组大小为numsSize,输出一个大小为numsSize的整数数组ans,其中ans[i]表示nums[i]的下一个更大的元素,如果不存在则为-1。这个函数的实现使用了单调栈的思想。首先,初始化ans数组,将每个元素都设置为-1。然后,创建一个数组stack和一个变量top,用于实现单调栈的操作。遍历2 * numsSize次,以保证循环可以回到起点。在每次循环中,通过取余操作获取当前元素的实际索引。然后,通过一个while循环,从栈顶开始比较当前元素和栈顶元素,如果当前元素大于栈顶元素,则将栈顶元素在ans数组中对应的位置设置为当前元素,并将栈顶指针top减1。这是因为栈顶元素的下一个更大元素已经找到了。接下来,如果当前循环次数小于numsSize,表示还有元素尚未入栈。此时,将当前元素的索引入栈,并将top指针加1。循环结束后,释放栈的内存,将returnSize指向numsSize,最后返回ans数组。这段代码的时间复杂度为O(n),其中n为nums数组的大小。空间复杂度为O(n),主要是用于存储ans和stack数组。

总结

加油!!!

标签:int,栈顶,top,元素,随想录,第四十七,数组,Day47,stack
From: https://blog.csdn.net/a6666999d/article/details/143806445

相关文章

  • 代码随想录算法训练营第四十八天|Day48 单调栈
    42.接雨水https://programmercarl.com/0042.%E6%8E%A5%E9%9B%A8%E6%B0%B4.html思路inttrap(int*height,intheightSize){intans=0;intleft=0,right=heightSize-1;intleftMax=0,rightMax=0;......
  • 代码随想录算法训练营day47| 739. 每日温度 496.下一个更大元素 I 503.下一个
    学习资料:https://programmercarl.com/0739.每日温度.html#算法公开课单调栈:用数组模拟单调栈,今天的题中,栈中元素都保存的索引值基本思路:将新元素和栈顶索引对应值比较,如果要保持单调递增,则需要新元素不大于栈顶索引对应值;若满足就加入新元素索引到栈中;若不满足,就根据具体题意看......
  • 代码随想录算法训练营day46| 647. 回文子串 516.最长回文子序列
    学习资料:https://programmercarl.com/0647.回文子串.html#算法公开课动态规划最后一部分:回文字符串子串是从原字符串中连续截取的;子序列可以是从原字符串中不连续提取出元素构成的学习记录:647.回文子串(难构造dp数组,dp数组是从原字符串截取[i,j]范围的片段是否是回文字符串,布尔......
  • 代码随想录:有序数组的平方
    代码随想录:有序数组的平方仍然是双指针,一开始也想到了双指针,不过很笨的创造了两个数组,一个负数的一个正数的,两个数组比大小后插入。但其实可以直接把原数组平方后,从左右两边插入。有两点值得注意:1.已知数组大小的情况下,可以直接倒着插入数组。2.创建vector时需要指定元素的个数......
  • 代码随想录算法训练营第一天| 704. 二分查找、35.搜索插入位置、27. 移除元素、977.有
    文档讲解:代码随想录视频讲解:代码随想录状态:完成4道题一、数组理论基础数组:连续内存空间,存储类型相同的元素集合,适合读不适合写注意:Python里可以存储不同类型的元素,但刷题时都是按照相同元素去做的相同元素占用存储的空间大小是一样的,下一个元素的位置就确定了数组时间......
  • 代码随想录算法训练营第二天| 209.长度最小的子数组、59. 螺旋矩阵 II
    文档讲解:代码随想录视频讲解:代码随想录状态:完成2道题滑动窗口滑动窗口:两个指针一前一后组成滑动窗口,并计算滑动窗口中的元素的问题适用场景:字符串匹配问题、子数组问题、定长问题滑动窗口模板:如果一个字符进入窗口,应该增加windows计数器;如果一个字符将移除窗口的......
  • 代码随想录算法训练营第三十天| 452. 用最少数量的箭引爆气球 、435. 无重叠区间 、76
    452.用最少数量的箭引爆气球思路:以前做过最大不相交子序列的题,这次也是往这根据某一端排序的思路想的,排序后如下图,只需要维护一个公共序列的右边界r就可以了,下一次判断时,只需要判断子区间的左边是否小于r。这个题有点坑的是使用Arrays排序,如果使用昨天的方法:Arra......
  • 代码随想录算法训练营 | 200.岛屿的数量
    岛屿的数量题目链接:https://leetcode.cn/problems/number-of-islands/此题目要点:dfs和bfs都可以解决此题,但是使用dfs代码会更加的简洁首先对grid进行遍历,每一个节点都进行检查,判断是否是1(陆地)如果是,则进行dfs深搜,并将所有搜到的岛屿节点全置为0,表示此块岛屿已经被搜过了,防......
  • 代码随想录算法训练营day45| 115.不同的子序列 583. 两个字符串的删除操作 72.
    学习资料:https://programmercarl.com/0115.不同的子序列.html#算法公开课动态规划系列之编辑距离问题学习记录:115.不同的子序列(当遇到相同字母时,可以选择也可以不选;刚开始没看懂;dp[i][j]是对应i-1结尾和j-1结尾,这样的目的是方便第一行和第一列初始化)点击查看代码classSolut......
  • 代码随想录:二分查找
    代码随想录:二分查找二分法标志:数组顺序排列且无重复简单的二分法,写法是左闭右闭的写法,此种情况的left可以等于right,故while里有等号。classSolution{public:intsearch(vector<int>&nums,inttarget){intleft=0;intright=nums.size()-1;......