代碼隨想錄算法訓練營|第六十一天|503.下一个更大元素II、42. 接雨水。刷题心得(c++)

目录

讀題

503.下一个更大元素II

看完代码随想录之后的想法

[42. 接雨水](#42. 接雨水)

看完代码随想录之后的想法

[503.下一个更大元素II - 實作](#503.下一个更大元素II - 實作)

思路

Code

[42. 接雨水 - 實作](#42. 接雨水 - 實作)

思路

原思路錯誤點

雙指針縱向運算思路

單調棧橫向運算思路

Code

[原思路 - 錯誤 (縱向運算)](#原思路 - 錯誤 (縱向運算))

雙指針縱向運算思路

單調棧橫向運算思路

總結

自己实现过程中遇到哪些困难

今日收获,记录一下自己的学习时长

相關資料

503.下一个更大元素II

[42. 接雨水](#42. 接雨水)


讀題

503.下一个更大元素II

看完代码随想录之后的想法

一開始看到環形數列的時候有點矇,但是在聽完卡哥的講解後,終於理解了,原來可以使用取mod的做法來模擬環形數列,在影片講解當中,最後有提到一個問題,假設在一個遞減的數列當中,比如說是4, 3, 2 那環形則會變成 4,3,2,4,3,2對應到的result則會是-1, 4, ,4, -1, -1 有提到後面的值會不會覆蓋到前面,我想說的是不會,因為只有當遇到了比較大的值才會觸發更新,那3, 2唯一會碰到也只會是在第二個4才會觸發更新,假設改為1,4,3,2,1,4,3,2 也一樣,最終1還是會更新到他的右邊第一個最大的數值。

42. 接雨水

看完代码随想录之后的想法

我原本的思路是縱向運算,但是使用到錯誤的方法,應該是要找左邊最大的以及右邊最大的,我的作法少了這點,看完隨想錄的講解後,才豁然開朗,使用橫向運算比較直覺一點,在理解上也比較清晰,如果遇到右邊比較大的元素,那就是右節點減去當前棧頂的下一個元素,再減去1就會是中間的的寬度,高度則是棧頂的左右元素取最小的減去棧頂對應的数組,兩者相乘,加到result當中就好了,用這個思路去理解就清晰很多了。

503.下一个更大元素II - 實作

思路

  1. 單調棧存放的是數組下標
  2. 單調棧性質為遞增
  3. 將遍歷大小擴為兩倍數組大小,並將i進行取mod運算。

Code

cpp 复制代码
class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        stack<int> st;
        vector<int> results(nums.size(), -1);
        for(int i = 0; i < (nums.size() * 2) ; i++) {
            while(!st.empty() && nums[st.top()] < nums[i % nums.size()]) {
                results[st.top()] = nums[i % nums.size()];
                st.pop();
            }
            st.push(i % nums.size());
        }

        return results;
    }
};

42. 接雨水 - 實作

思路

原思路錯誤點

原思路如果改變作法就會對了,因為是做縱向的運算,所以要找到左邊最大以及右邊最大的柱子,如果使用單調棧,則只會找到左邊以及右邊第一個比當前大的元素,而不是最大的,因此會少計算了一些面積。

雙指針縱向運算思路

  1. 使用兩個數組紀錄左邊最高以及右邊最高
  2. maxLeft 由左向右遍歷 maxLeft當前高度 max(當前高度,maxLeft前一個高度)
  3. maxRight 由右向左遍歷 maxRight當前高度 max(當前高度,maxRight前一個高度)
  4. 求和,遍歷数組,左右最高取最小,並減去當前高度
  5. 假設大於0,則加入到結果當中

單調棧橫向運算思路

  1. 單調棧存放元素為數組下標
  2. 單調棧性質為遞增
  3. 當前元素對應的数組值與棧頂元素對應的数組值比較與處理
    1. 小於
      1. 將當前元素放入棧頂
    2. 等於
      1. pop棧頂元素
      2. 將當前元素放入棧頂
      3. 因為相等的話,如果比較最小值時,當前元素與棧頂元素相減 = 0 無論如何相乘都只會是0
    3. 大於
      1. 儲存棧頂元素
      2. pop棧頂
      3. 高度是
        1. 當前元素與目前棧頂元素對應的数組數值取最小減去之前儲存棧頂元素對應的数組數值
      4. 寬度是
        1. 當前元素減去目前棧頂元素再減去1
      5. sum += h * w
      6. 儲存當前元素到單調棧中
  4. return sum.

Code

原思路 - 錯誤 (縱向運算)

cpp 复制代码
class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> st;
        vector<int> water(height.size(), 0);
        vector<int> leftH(height.size(), 0);
        int water = 0;
        for(int i = 0; i < height.size() ; i++) {
            while(!st.empty() && height[st.top()] < height[i]) {
                rightH[st.top()] = height[i];
                st.pop();
            }
            st.push(i);
        }

        while (!st.empty()) st.pop();

        for(int i = height.size() - 1; i >= 0; i--) {
            while(!st.empty() && height[st.top()] < height[i]) {
                leftH[st.top()] = height[i];
                st.pop();
            }
            st.push(i);
        }
        for(int i = 0; i < height.size(); i++) {
            if(min(rightH[i], leftH[i]) - height[i] >= 0)water += min(rightH[i], leftH[i]) - height[i];
        }
        return water;
    }
};

雙指針縱向運算思路

cpp 复制代码
class Solution {
public:
    int trap(vector<int>& height) {
        vector<int> maxLeft(height.size(), 0);
        vector<int> maxRight(height.size(), 0);
        int size = height.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;
    }
};

單調棧橫向運算思路

cpp 复制代码
class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> st;
        st.push(0);
        int sum = 0;
        for(int i = 1; i < height.size() ; i++) {
            if(height[st.top()] > height[i]){
                st.push(i);
            }
            else if(height[st.top()] == height[i]){
                st.pop();
                st.push(i);
            } 
            else 
            {
                while(!st.empty() && height[st.top()] < height[i]) {
                    int mid = st.top();
                    st.pop();
                    if(!st.empty()) {
                        int h = min(height[i], height[st.top()]) - height[mid];
                        int w = i - st.top() - 1;
                        sum += h * w;
                    }
                }
                st.push(i);
            }
        }
        return sum;
    }
};

總結

自己实现过程中遇到哪些困难

困難點主要是接雨水沒有想到可以這樣利用單調棧的性質,以及自己一開始在做接雨水題目時思路想成縱向運算,看完影片後才比較知道自己為甚麼做錯了。

今日收获,记录一下自己的学习时长

今天大概學習2hr,主要是了解了如何處理環形數列以及單調棧如何在接雨水這個題目中運用

相關資料

● 今日学习的文章链接和视频链接

503.下一个更大元素II

https://programmercarl.com/0503.下一个更大元素II.html

42. 接雨水

https://programmercarl.com/0042.接雨水.html

相关推荐
清水迎朝阳1 小时前
客户端软件 — 用户统计方案
服务器·c++·客户端·用户统计
Re.不晚1 小时前
挑战做100道力扣算法- DAY1
算法·leetcode·职场和发展
蓝悦无人机2 小时前
《Planning algorithms》读书笔记——第1章 引言
算法·读书笔记·规划算法·lavalle
Sagittarius_A*2 小时前
分组密码基础(二):Feistel 结构与 DES 的设计思想
算法·信息安全·密码学·des·数论
青山木2 小时前
Hot 100 --- 搜索插入位置
java·数据结构·算法·leetcode
再卷也是菜2 小时前
C++17(下)
c++
alexwang2113 小时前
HDU 4348 详细题解
c++·算法·题解·hdu·主席树·可持久化数据结构·可持久化线段树
程序员zgh3 小时前
C++ 拷贝赋值运算符 详解
c语言·开发语言·c++
可编程芯片开发3 小时前
基于分段变步长搜索RMDCFT算法的天基雷达空间机动目标检测方法MATLAB仿真,对比RMDCFT算法
算法
2501_946736164 小时前
在线考试平台如何选型?从功能、优势与应用场景角度详解
大数据·人工智能·算法