代碼隨想錄算法訓練營|第六十天|739. 每日温度、496.下一个更大元素 I。刷题心得(c++)

目录

讀題

739. 每日温度

自己看到题目的第一想法

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

496.下一个更大元素 I

自己看到题目的第一想法

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

739. 每日温度 - 實作

思路

Code

清晰版

精簡版

496.下一个更大元素 I - 實作

思路

原思路

代碼隨想錄思路

Code

原思路

代碼隨想錄思路

總結

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

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

相關資料

739. 每日温度

496.下一个更大元素 I


讀題

739. 每日温度

自己看到题目的第一想法

就是用每個數去遍歷後面的數,但超時了,程式碼如下。

class Solution {
public:
    vector dailyTemperatures(vector& temperatures) {
        vector highTemp(temperatures.size(), 0);
        for(int i = 0; i < temperatures.size(); i++) {
            int high = 0;
            highTemp[i] = high;
            for(int j = i + 1; j < temperatures.size();j++) {
                if(temperatures[i] > temperatures[j]) high++;
                else {
                    high++;
                    highTemp[i] = high;
                    break;
                }
            }
        }
        return highTemp;
    }
};

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

單調棧,就是當要尋找一個元素左邊或者右邊第一個比自己大的元素位置,就可以考慮使用單調棧。

其本質是使用空間換時間,在遍歷的過程中使用棧來記錄右邊比當前元素高或低,優點就是数組只需要遍歷一次

使用單調棧時需要明確

  1. 單調棧裡存放的元素是甚麼
  2. 單調棧是遞增還是遞減,(順序方面因人而異,以我來說,就是跟著卡哥的順序,從棧頂到棧底,逐步遞增或遞減)

每日溫度就是一個單調棧很經典的題目,右邊第一個比自己大的元素在甚麼時候。

單調棧存放的元素是數組下標,方便在results数組中進行計算。

單調棧是遞增,可以想像假設當前元素比棧頂大,為了維持單調棧,就需要pop出來,棧頂元素就是右邊第一個比較大的元素就是當前元素。

看完卡哥的講解後對於單調棧就比較清晰了。

496.下一个更大元素 I

自己看到题目的第一想法

第一瞬間其實就想到這個只是繞一個彎,一樣單調棧是放数組下標,但是在遍歷nums2的過程中,紀錄當前元素有沒有跟nums1相同的數值,如果相同,則紀錄nums2的下標為多少到result2,其他部分一樣是製作出一個右邊第一個比自己大的元素的数組result。

之後再遍歷result2的数組,將results裡面有result2的位置讀取,假設不是-1,則將result2的值,改為nums2的當下數值加上比這個元素大的數值是後面第幾個出現的。

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

看完之後才知道我想得很複雜,其實可以使用map,nums1的數值當作key,下標當作value,在遇到右邊第一個比較大的元素時,判斷nums1有沒有nums2[st.top()]的數值,如果有則將利用map快速找到nums1的對應下標使用nums2的當前元素更新results數組。之前沒有想過這樣的解法。

739. 每日温度 - 實作

思路

  1. 單調棧存放的元素

    數組下標

  2. 單調棧性質 - 遞增 (棧頂到棧底)

  3. 當 棧頂大於等於當前數值時,儲存當前数組的下標到單調棧

  4. 當 棧頂小於當前數值時,代表找到第一個比較大的元素。

    • while循環,值到棧為空或者棧頂大於等於當前數值
      • results[st.top()] = i - st.top() → st.top 是原數組下標,跟results数組是對應的,至於i - st.top() 代表棧頂的位置跟當前元素的距離為和
      • 將棧頂元素pop出來
  5. return results數組。

Code

清晰版

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

        return results;
    }
};

精簡版

class Solution {
public:
    vector dailyTemperatures(vector& temperatures) {
        stack st;
        vector results(temperatures.size(), 0);
        st.push(0);
        for(int i = 1; i < temperatures.size(); i++) {
            while(!st.empty() && temperatures[st.top()] < temperatures[i]) {
                results[st.top()] = i - st.top();
                st.pop();
            }
            st.push(i);
        }

        return results;
    }
};

496.下一个更大元素 I - 實作

思路

原思路

  1. 建立兩個數組
    1. result 紀錄nums2的每個數值右邊第一個最大元素
    2. result2 紀錄 nums1 在 nums2 的位置
  2. 遍歷nums2的過程中,紀錄當前元素有沒有跟nums1相同的數值,如果相同,則紀錄nums2的下標為多少到result2
  3. 使用單調棧更新result数組
  4. 遍歷result2數組
    1. results裡面有result2的位置讀取,假設不是-1,則將result2的值,改為nums2的當下數值加上比這個元素大的數值是後面第幾個出現的
    2. 不是則更新為-1
  5. return result2數組

代碼隨想錄思路

  1. 建立map紀錄nums1的數值與下標映射關係
    1. key = nums1數值
    2. value = nums1對應下標。
  2. 遇到右邊第一個比較大的元素時
    1. 判斷map中是否有對應的nums2的棧頂下標所映射到的數值
    2. 如果有則將利用map快速找到nums1的對應下標使用nums2的當前元素更新results數組

Code

原思路

class Solution {
public:
    vector nextGreaterElement(vector& nums1, vector& nums2) {
        stack st;
        vector results(nums2.size(), -1);
        vector results2(nums1.size(), -1);
        for(int i = 0; i < nums2.size(); i++) {
            for(int j = 0; j < nums1.size(); j++) {
                if(nums1[j] == nums2[i]) {
                    results2[j] = i;
                    break;
                }
            }
            while(!st.empty() && nums2[st.top()] < nums2[i]) {
                results[st.top()] = i - st.top();
                st.pop();
            }
            st.push(i);
        }
        for(int k = 0; k < nums1.size(); k++) {
            int temp = results2[k];
            if(results[temp] != -1) results2[k] = nums2[temp + results[temp]];
            else results2[k] = results[temp];
            
        }

        return results2;
    }
};

代碼隨想錄思路

class Solution {
public:
    vector nextGreaterElement(vector& nums1, vector& nums2) {
        stack st;
        vector results(nums1.size(), -1);
        unordered_map umap;
        for (int i = 0; i < nums1.size(); i++) {
            umap[nums1[i]] = i;
        }
        for(int i = 0; i < nums2.size(); i++) {
            while(!st.empty() && nums2[st.top()] < nums2[i]) {
                if(umap.count(nums2[st.top()]) > 0) {
                    results[umap[nums2[st.top()]]] = nums2[i];
                }
                st.pop();
            }
            st.push(i);
        }

        return results;
    }
};

總結

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

第一次理解單調棧的題目,在理解上花了比較長的時間,並且自己對於map的使用不太熟悉,所以在第二題時,想到了更繞的解法。

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

今天大概學習2hr,主要是去理解單調棧的思維,理解不難,但是在實踐過程中需要多練習。

相關資料

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

739. 每日温度

https://programmercarl.com/0739.每日温度.html

496.下一个更大元素 I

https://programmercarl.com/0496.下一个更大元素I.html

你可能感兴趣的:(c++,leetcode)