目录
讀題
503.下一个更大元素II
看完代码随想录之后的想法
42. 接雨水
看完代码随想录之后的想法
503.下一个更大元素II - 實作
思路
Code
42. 接雨水 - 實作
思路
原思路錯誤點
雙指針縱向運算思路
單調棧橫向運算思路
Code
原思路 - 錯誤 (縱向運算)
雙指針縱向運算思路
單調棧橫向運算思路
總結
自己实现过程中遇到哪些困难
今日收获,记录一下自己的学习时长
相關資料
503.下一个更大元素II
42. 接雨水
一開始看到環形數列的時候有點矇,但是在聽完卡哥的講解後,終於理解了,原來可以使用取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還是會更新到他的右邊第一個最大的數值。
我原本的思路是縱向運算,但是使用到錯誤的方法,應該是要找左邊最大的以及右邊最大的,我的作法少了這點,看完隨想錄的講解後,才豁然開朗,使用橫向運算比較直覺一點,在理解上也比較清晰,如果遇到右邊比較大的元素,那就是右節點減去當前棧頂的下一個元素,再減去1就會是中間的的寬度,高度則是棧頂的左右元素取最小的減去棧頂對應的数組,兩者相乘,加到result當中就好了,用這個思路去理解就清晰很多了。
class Solution {
public:
vector nextGreaterElements(vector& nums) {
stack st;
vector 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;
}
};
原思路如果改變作法就會對了,因為是做縱向的運算,所以要找到左邊最大以及右邊最大的柱子,如果使用單調棧,則只會找到左邊以及右邊第一個比當前大的元素,而不是最大的,因此會少計算了一些面積。
class Solution {
public:
int trap(vector& height) {
stack st;
vector water(height.size(), 0);
vector 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;
}
};
class Solution {
public:
int trap(vector& height) {
vector maxLeft(height.size(), 0);
vector 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;
}
};
class Solution {
public:
int trap(vector& height) {
stack 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,主要是了解了如何處理環形數列以及單調棧如何在接雨水這個題目中運用
● 今日学习的文章链接和视频链接
https://programmercarl.com/0503.下一个更大元素II.html
https://programmercarl.com/0042.接雨水.html