739. 每日溫度
題目連結:https://leetcode.cn/problems/daily-temperatures/
文章講解:https://programmercarl.com/0739.每日溫度.html
題目難度:中等
影片講解:https://www.bilibili.com/video/BV1my4y1Z7jj/
題目狀態:看題解
思路:
定義一個單調棧,該棧存放下標,規則是要保持其下標對應的溫度值從棧底到棧頭是單調遞減的。再定義一個和題目陣列大小相等的陣列ans
存放結果,初始化為0。具體步驟如下:
- 先將第一個元素的下標存入棧中。
- 迴圈遍歷溫度陣列:
- 若當前溫度小於等於棧頭元素的溫度,將當前溫度的下標壓入棧。
- 若當前溫度大於棧頭元素的溫度,將棧中比當前溫度低的元素都彈出,在彈出的時候將其壓入結果陣列中(i-st.top()),直到棧頭大於當前溫度,將當前溫度的下標壓入棧。
- 遍歷結束後,返回結果陣列。
程式碼:
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
int len = temperatures.size();
stack<int> st;
vector<int> ans(len, 0);
st.push(0);
for(int i = 1; i < len; ++i) {
if(temperatures[i] <= temperatures[st.top()]) st.push(i);
else {
while(!st.empty() && temperatures[i] > temperatures[st.top()]) {
ans[st.top()] = i - st.top();
st.pop();
}
st.push(i);
}
}
return ans;
}
};
496. 下一個更大元素 I
題目連結:https://leetcode.cn/problems/next-greater-element-i/
文章講解:https://programmercarl.com/0496.下一個更大元素I.html
題目難度:簡單
影片講解:https://www.bilibili.com/video/BV1jA411m7dX/
題目狀態:用其他方法過的,看題解學習一下單調棧的方法
思路一:巢狀迴圈
非常傳統的方法,遍歷整個nums1
,每遍歷一個元素就在nums2
中找到對應的元素下標,然後再在nums2
中從下標位置開始向後遍歷,直到找到一個比元素大的元素,將其值填入結果陣列中並跳出迴圈,若找不到直接返回,因為這個結果陣列初始化的時候將其全部值初始化為-1
了。
程式碼一:
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
int len1 = nums1.size(), len2 = nums2.size();
vector<int> ans(len1, -1);
for(int i = 0; i < len1; ++i) {
auto it = find(nums2.begin(), nums2.end(), nums1[i]);
int index = distance(nums2.begin(), it);
for(int j = index; j < len2; ++j) {
if(nums2[j] > nums1[i]) {
ans[i] = nums2[j];
break;
}
}
}
return ans;
}
};
消耗:
思路二:單調棧
將nums1
壓入一個unordered_map<int, int>
中,主要原因是它的查詢和增刪效率是最優的。
然後維護一個單調棧st
,這個棧從棧底到棧頭是單調遞減的,用來遍歷nums2
,當遇到元素比棧頭元素大的時候,就判斷一下棧頭元素是否在nums1
中存在,如果存在就表示其後面有比棧頭元素高的元素,將這個元素值更新到結果陣列中。
程式碼二:
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
int len1 = nums1.size(), len2 = nums2.size();
stack<int> st;
vector<int> ans(len1, -1);
if(len1 == 0) return ans;
unordered_map<int, int> umap;
for(int i = 0; i < len1; ++i) {
umap[nums1[i]] = i; // key:下標元素,value:下標
}
// 將nums2壓入單調棧
st.push(0);
for(int i = 1; i < len2; ++i) {
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) { // 看看umap中是否存在該元素
int index = umap[nums2[st.top()]]; // 根據map找到nums2[st.top()]在nums1中的下標
ans[index] = nums2[i];
}
st.pop();
}
st.push(i);
}
}
return ans;
}
};
消耗:
503. 下一個更大元素 II
題目連結:https://leetcode.cn/problems/next-greater-element-ii/
文章講解:https://programmercarl.com/0503.下一個更大元素II.html
題目難度:中等
影片講解:https://www.bilibili.com/video/BV15y4y1o7Dw/
題目狀態:自己的思路沒透過,好奇怪,chatGPT幫忙修改了一下,直接把我思路改了
思路:
-
迴圈陣列處理:
- 為了模擬迴圈陣列,我們遍歷陣列兩次。這樣可以確保每個元素都能找到它的下一個更大元素,即使這個元素在陣列的末尾。
-
使用棧:
- 棧用來儲存索引,而不是元素值。這使我們能夠直接在結果陣列中更新對應位置的值。
-
遍歷陣列:
- 在每次遍歷中,我們檢查當前元素是否大於棧頂元素對應的值。
- 如果是,則更新結果陣列中棧頂元素索引對應的值,並彈出棧頂。
- 如果當前索引在陣列的前半部分(即小於
len
),我們將其索引壓入棧中。
-
結果更新:
- 透過這種方式,所有元素的下一個更大元素都會在結果陣列中被正確更新。
程式碼:
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int len = nums.size();
stack<int> st;
vector<int> ans(len, -1);
for(int i = 0; i < 2 * len; ++i) {
int num = nums[i % len];
while(!st.empty() && nums[st.top()] < num) {
ans[st.top()] = num;
st.pop();
}
if(i < len) st.push(i);
}
return ans;
}
};
消耗: