代码随想录算法训练营 ---第五十八天

今天开启单调栈的征程。

第一题:

简介:

本题有两种解法,第一种:暴力破解 两层for循环 时间复杂度为O(n^2) 超时了

                             第二种:单调栈解法也是今天的主角。

单调栈是什么?
  • 单调递增栈:单调递增栈就是从栈顶到栈底是从小到大  作用场景:求解某一个在当前数左面或右面第一个大的数
  • 单调递减栈:单调递减栈就是从栈顶到栈底数据是从大到小 作用场景:求解某一个在当前数左面或右面第一个小的数

    单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是整个数组只需要遍历一次。

  • 更直白来说,就是用一个栈来记录我们遍历过的元素,因为我们遍历数组的时候,我们不知道之前都遍历了哪些元素,以至于遍历一个元素找不到是不是之前遍历过一个更小的,所以我们需要用一个容器(这里用单调栈)来记录我们遍历过的元素。

    在使用单调栈的时候首先要明确如下几点:

  • 单调栈里存放的元素是什么?                                                                                                       单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接T[i]就可以获取。
  • 单调栈里元素是递增呢? 还是递减呢?
本题思路: 

本题我们使用单调栈,首先是由题意我们要求第一个大的数,所以我们使用单调递增栈。然后我建议大家用草稿纸来模拟一下整个单调栈的运行过程。

 for(int i=1;i<temperatures.size();i++){
            if(temperatures[i]>temperatures[st.top()]){
              while(!st.empty() &&temperatures[i]>temperatures[st.top()]){
                  result[st.top()] = i - st.top();
                  st.pop();
              }
              st.push(i);
            }else if(temperatures[i] == temperatures[st.top()]){
                    st.push(i);
            }else{
                    st.push(i);
            }
        }

此代码为遍历过程,大家跟着走一遍就可明白单调栈工作流程。 或者可以去看代码随想路录算法视频跟着卡哥走一遍。

代码实现:

 vector<int> dailyTemperatures(vector<int>& temperatures) {
        stack<int> st;
        vector<int> result(temperatures.size(),0);
        st.push(0);
        for(int i=1;i<temperatures.size();i++){
            if(temperatures[i]>temperatures[st.top()]){
              while(!st.empty() &&temperatures[i]>temperatures[st.top()]){
                  result[st.top()] = i - st.top();
                  st.pop();
              }
              st.push(i);
            }else if(temperatures[i] == temperatures[st.top()]){
                    st.push(i);
            }else{
                    st.push(i);
            }
        }
        return result;
    }

第二题:

简介:

本题相对于前一题,无太大差别,我们只需在本题中找出nums1中数值 对应 nums2 中的位置即可求出此题,其他代码与上题相同。

代码实现: 

未优化版:
 vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
           stack<int> st;
           vector<int> result(nums2.size(),-1);
           vector<int> result2;
           st.push(0);
           for(int i=1;i<nums2.size();i++){
               if( nums2[i]>nums2[st.top()]){
                   while(!st.empty() &&nums2[i]>nums2[st.top()]){
                       result[st.top()] = nums2[i];
                       st.pop();
                   }
                   st.push(i);
               }else if(nums2[i] == nums2[st.top()]){
                   st.push(i);
               }else{
                   st.push(i);
               }
           }
             for(int i=0;i<nums2.size();i++){
                cout<<result[i]<<"  ";
           }
          for(int i=0;i<nums1.size();i++){
               for(int j=0;j<nums2.size();j++){
                   if(nums1[i]==nums2[j]){
                       result2.push_back(result[j]);
                       break;
                   }
               }
           }
        
      return result2;
    }
优化版:
 vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
           stack<int> st;
        vector<int> result(nums1.size(), -1);
        if (nums1.size() == 0) return result;

        unordered_map<int, int> umap; // key:下标元素,value:下标
        for (int i = 0; i < nums1.size(); i++) {
            umap[nums1[i]] = i;
        }
        st.push(0);
        for (int i = 1; i < nums2.size(); i++) {
            if (nums2[i] < nums2[st.top()]) {           // 情况一
                st.push(i);
            } else if (nums2[i] == nums2[st.top()]) {   // 情况二
                st.push(i);
            } else {                                    // 情况三
                while (!st.empty() && nums2[i] > nums2[st.top()]) {
                    if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素
                        int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标
                        result[index] = nums2[i];
                    }
                    st.pop();
                }
                st.push(i);
            }
        }
        return result;
    }

总结: 

今天是单调栈的一天,我感觉只要明白单调栈的运行过程,就可以解决问题了。不算太难,继续加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/227531.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在vue中深度选择器的使用

一、为什么要使用深度选择器 在vue中&#xff0c;当我们使用了第三方库中的组件时&#xff0c;想要更改一些样式&#xff0c;达到我们想要的效果&#xff0c;由于scoped的影响直接编写同名样式时&#xff0c;是覆盖不了组件内的样式的。 为了达到我们想要的效果&#xff0c;…

关于最长上升子序列的动态规划问题的优化算法(二分搜索)

最长递增子序列 暴力解法&#xff1a; 思路&#xff1a;使用动态规划的思想&#xff0c;判断当前元素之前的所有元素&#xff0c;如果比当前元素小&#xff0c;则修改当前元素的最长递增子序列&#xff08;需判断是否需要修改&#xff09;。 时间复杂度&#xff1a;O(n^2) im…

智能优化算法应用:基于天鹰算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于天鹰算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于天鹰算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.天鹰算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

记一次Java内存溢出导致程序宕机的问题及排查

Hi, I’m Shendi 记一次Java内存溢出导致程序宕机的问题及排查 问题场景 今天在使用工具中的 word 转 pdf 出了问题&#xff0c;报502错误&#xff0c;打开服务器发现服务被关闭了&#xff0c;起初以为是误关&#xff0c;打开后重新转换又出现了这个问题&#xff0c;在项目文件…

Redis保证高可用的三种方式

Redis保证高可用主要有三种方式&#xff1a;主从、哨兵、集群。 主从复制了解吗&#xff1f; Redis主从复制简图 主从复制&#xff0c;是指将一台 Redis 服务器的数据&#xff0c;复制到其他的 Redis 服务器。前者称为 主节点(master)&#xff0c;后者称为 从节点(slave)。且…

【EXCEL】offset函数

语法&#xff1a; offset(reference,row,column,[height],[width]) 例子&#xff1a;

Java网络编程 *TCP与UDP协议*

网络编程 什么是计算机网络? 把分布在不同地理区域的具有独立功能的计算机,通过通信设备与线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统 简单来说就是把不同地区的计算机通过设备连接起来,实现不同地区之前的数据传输 网络编程是干什么的? 网络…

UDS诊断 10服务

文章目录 简介诊断会话切换请求和响应1、请求2、子功能3、肯定响应4、否定响应5、特殊的NRC 为什么划分不同会话报文示例UDS中常用 NRC参考 简介 10服务&#xff0c;即 Diagnostic Session Control&#xff08;诊断会话控制&#xff09;服务用于启用服务器中的不同诊断会话&am…

【软件测试】系统测试

一、系统测试概念 系统测试&#xff08;System Testing&#xff09;是将已经集成好的软件系统&#xff0c;作为整个基于计算机系统的一个元素&#xff0c;与计算机硬件、外设、某些支持软件、数据和人员等其他元素结合在一起&#xff0c;在实际运行环境下&#xff0c;对计算机…

定兴县第三实验小学开展“宪法宣传周”系列活动

2023年12月4日是我国第十个国家宪法日&#xff0c;我校集中深入学习宣传宪法&#xff0c;弘扬宪法精神&#xff0c;维护宪法权威&#xff0c;开展“宪法宣传周”系列活动。 宪法主题升旗仪式 五&#xff08;6&#xff09;班薛谨熙同学以《学法懂法 与我同行》为主题做国旗下讲…

K-means算法通俗原理及Python与R语言的分别实现

K均值聚类方法是一种划分聚类方法&#xff0c;它是将数据分成互不相交的K类。K均值法先指定聚类数&#xff0c;目标是使每个数据到数据点所属聚类中心的总距离变异平方和最小&#xff0c;规定聚类中心时则是以该类数据点的平均值作为聚类中心。 01K均值法原理与步骤 对于有N个…

共创共赢|美创科技获江苏移动2023DICT生态合作“产品共创奖”

12月6日&#xff0c;以“5G江山蓝 算网融百业 数智创未来”为主题的中国移动江苏公司2023DICT合作伙伴大会在南京成功举办。来自行业领军企业、科研院所等DICT产业核心力量的百余家单位代表参加本次大会&#xff0c;共话数实融合新趋势&#xff0c;共拓合作发展新空间。 作为生…

9.关于Java的程序设计-基于Springboot的家政平台管理系统设计与实现

摘要 随着社会的进步和生活水平的提高&#xff0c;家政服务作为一种重要的生活服务方式逐渐受到人们的关注。本研究基于Spring Boot框架&#xff0c;设计并实现了一种家政平台管理系统&#xff0c;旨在提供一个便捷高效的家政服务管理解决方案。系统涵盖了用户注册登录、家政服…

Java se的语言特征之封装

目录 封装的概念常见的一些包静态成员变量代码块 封装的概念 可以理解为套壳屏蔽细节,将数据和操作数据的方法进行有机的结合,隐藏对象的属性和实现细节,仅对外公开接口和对象进行交互 从语法的层面来理解就是,被private修饰的成员变或者成员方法,只能在当前类中使用,但是可以…

力扣541.反转字符串 II

文章目录 力扣541.反转字符串 II示例代码实现总结收获 力扣541.反转字符串 II 示例 代码实现 class Solution {public String reverseStr(String s, int k) {char[] ans s.toCharArray();for(int i0;i<ans.length;i2*k){int begin i;int end Math.min(ans.length-1,begin…

3、Linux_系统用户管理

1.Linux 用户管理 1.1概述 Linux系统是一个多用户多任务的操作系统&#xff0c;任何一个要使用系统资源的用户&#xff0c;都必须首先向系统管理员申请一个账号&#xff0c;然后以这个账号的身份进入系统。root用户是系统默认创建的管理员账号。 1.2添加用户 语法 useradd […

QT----Visual Studio打开.ui文件报错无法打开

问题 在我安装完qt后将它嵌入vs&#xff0c;后新建的文件无法打开ui文件 解决方法 右击ui文件打开方式,添加,程序找到你qt的安装目录里的designer.exe。点击确定再次双击就能够打开。

【每日一题】重新规划路线

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;深度优先搜索方法二&#xff1a;广度优先搜索 写在最后 Tag 【深搜】【广搜】【树】【2023-12-07】 题目来源 1466. 重新规划路线 题目解读 题目给定一张由 n个点&#xff08;使用 0 到 n−1 编号&#xff09;&#…

Linux查看命令的绝对路径

linux查看命令的绝对路径 在Linux中&#xff0c;可以使用以下命令来查看命令的绝对路径&#xff1a; 1、which 命令名 例如&#xff0c;要查看chronyc命令的绝对路径&#xff0c;可以运行&#xff1a; which chronyc 2、whereis 命令名 例如&#xff0c;要查看chronyc命令…

好单库无代码API集成:广告推广与营销系统的高效电商平台连接方式

电商平台与无代码API集成的协同效应 随着数字化浪潮的不断推进&#xff0c;电子商务的生态正在快速演变。在这个过程中&#xff0c;电商平台的实时数据同步和高效运营对于保持竞争力至关重要。好单库作为电商领域的一大创新&#xff0c;提供了无需编程的API集成解决方案&#…