• 代码随想录 | Day 58 - LeetCode 739. 每日温度、496. 下一个更大元素 I


            动态规划部分终于结束,今天是倒数第3天,开始单调栈部分。之前没有接触过单调栈,自己直接做没有想出这种方法。单调栈的主要应用场景是“一维数组中,寻找某个元素左/右边比它大/小的第一个元素”。需要注意栈中只需要存储下标,就可以通过所给的数组找到对应元素的值。还有无论哪种情况,都要记得在最后把当前元素也放入栈。最后,在结果像第2题一样要求是非有序且为子集时,可以借助map。


            第1题(LeetCode 739. 每日温度)自己没想出来O(n)的方法,看了题解的单调栈解法。核心思路是创建并维护一个数值上单调递减(因为这道题要求下一个更大的温度)的栈,符合规则就放入栈;不符合的话则需要弹出所有比当前数值小的元素,并同时对弹出元素对应位置的结果赋值(结果就是当前元素下标与被弹出元素下标的差值),最后再将当前元素放入栈。为实现这一目的,理论上既需要知道每个元素的值,又需要知道其下标,似乎需要将两者都放入栈中。但如果知道下标,通过temperatures可以直接获取温度值,所以栈中只需要存储下标即可。需要注意,最开始栈是空的,需要手动放入第0个元素或者在循环中对此做特殊处理。

            这样的做法会使得右边没有更大数字的元素永远无法进行res的赋值,而题目要求这些元素的结果均设置为0,所以可以在初始化时就将所有结果设置为0。

    1. class Solution {
    2. public:
    3. vector<int> dailyTemperatures(vector<int>& temperatures) {
    4. vector<int> res(temperatures.size(), 0);
    5. stack<int> st;
    6. st.push(0);
    7. for (int i = 0; i < temperatures.size(); ++i) {
    8. if (temperatures[i] <= temperatures[st.top()]) {
    9. st.push(i);
    10. }
    11. else {
    12. while (!st.empty() && temperatures[i] > temperatures[st.top()]) {
    13. res[st.top()] = i - st.top();
    14. st.pop();
    15. }
    16. st.push(i);
    17. }
    18. }
    19. return res;
    20. }
    21. };

            第2题(496. 下一个更大元素 I)与上一题的第1个不同在于最终要返回的结果是子集而不是全部,且该子集中数字相对于原集合是乱序的。这样一来如果完全照搬上一题的方法,时间复杂度就会因为统计结果而变成O(n²)。

            解决办法是用nums1作为键来创建一个map,值用来保存结果。得到正确结果后,再将其按照nums1的顺序转换为vector返回。在遍历nums2计算结果、弹出栈的过程中,只有某个元素在map的键中时才将其结果放入map。

            另外由于(1)结果是用map保存的;(2)最终要返回的结果不再是位置的差值,而是比当前元素大的第1个元素本身;(3)题目说明nums2中元素均不重复,所以这一题不再需要记录下标了,可以只记录数值。

            初始化方面,这道题需要改为初始化map,并全部初始化为-1。

    1. class Solution {
    2. public:
    3. vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
    4. unordered_map<int, int> map;
    5. for (int i = 0; i < nums1.size(); ++i) {
    6. map[nums1[i]] = -1;
    7. }
    8. stack<int> st;
    9. st.push(nums2[0]);
    10. for (int i = 0; i < nums2.size(); ++i) {
    11. if (nums2[i] <= st.top()) {
    12. st.push(nums2[i]);
    13. }
    14. else {
    15. while (!st.empty() && nums2[i] > st.top()) {
    16. if (map.find(st.top()) != map.end()) {
    17. map[st.top()] = nums2[i];
    18. }
    19. st.pop();
    20. }
    21. st.push(nums2[i]);
    22. }
    23. }
    24. vector<int> res(nums1.size());
    25. for (int i = 0; i < nums1.size(); ++i) {
    26. res[i] = map[nums1[i]];
    27. }
    28. return res;
    29. }
    30. };

            判断当前元素是否在map中存在,既可以像上面一样使用map.find(),也可以通过判断map.count()的结果是否为0来判断。

  • 相关阅读:
    软件界面设计培训
    postgreSQL中将字段从smallint类型改成boolean类型
    DNS有什么作用 43.227.220.X
    日撸Java三百行(day19:字符串匹配)
    Linux系统下祼机安装mysql8.0和docker mysql 8.0 性能差异对比~
    【数学建模】层次分析
    【机器学习】集成模型/集成学习:多个模型相结合实现更好的预测
    基于element-plus2.5.10 table组件实现分类table
    宝塔站点配置
    Qt编写跨平台RTSP/RTMP/HTTP视频流播放器
  • 原文地址:https://blog.csdn.net/weixin_43469527/article/details/127928408