739. 每日温度
一顿操作猛如虎,一看击败5%。一眼顶针,鉴定为在存栈的时候把值和下标一起存了,所以导致了问题。
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
stack<vector<int>> temp;
int n = temperatures.size();
vector<int> result(n);
for(int i=0; i<n; i++){
while(!temp.empty() && temperatures[i] > temp.top()[0]){
int pos = temp.top()[1];
result[pos] = i - pos;
temp.pop();
}
temp.push(vector<int> {temperatures[i], i});
}
return result;
}
};
果然如此,改完之后就对了,击败93.07%。
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
stack<int> temp;
int n = temperatures.size();
vector<int> result(n);
for(int i=0; i<n; i++){
while(!temp.empty() && temperatures[i] > temperatures[temp.top()]){
int pos = temp.top();
result[pos] = i - pos;
temp.pop();
}
temp.push(i);
}
return result;
}
};
496.下一个更大元素 I
虽然卡哥说只是加了一点难度,但实际上变量一变多,我的脑子立刻就不够用了,接连犯错。每一层下标取完,出来对应什么含义,脑子一下就不清醒了。
做完之后看了下解析,我的做法和卡哥的做法还不太一样,具体区别体现在哈希表的建立方法上。
我的代码:
1 哈希map怎么插入值忘了。
想了半天是push还是append还是啥,最后一看答案,答案说直接通过键值的方式添加:nextbig[nums2[pos]] = nums2[i]。难怪我想不出来是什么关键词。
2 在往单调栈里面压入值的时候,应该压入的是下标而不是元素值!
写的时候整个人昏头了,写了个添加元素值的代码。
3 这里讲到的“下一个单调元素”就说的不是哪一个元素了,而是元素的值。
这一点和上一题是不一样的,小小的坑了我一下。我直接nextbig[nums2[pos]] = i;了。但这里才应该写元素值,而非下标。
4 没写找不到下一个更大元素时的处理逻辑。
其实也不算难,加上一个爆搜去找找看就行了。但是我还是第一时间没想出来的。我想的是nextbig[nums1[j]] == 0,因为未经赋值初始化是0,但这样写如果刚好有一个元素的值是0的话还是会出问题的,所以还是得用搜索。
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
unordered_map<int, int> nextbig;
stack<int> numnum;
for(int i=0; i<n; i++){
while(!numnum.empty() && nums2[numnum.top()] < nums2[i]){
int pos = numnum.top();
nextbig[nums2[pos]] = nums2[i];
numnum.pop();
}
numnum.push(i);
}
vector<int> result;
for(int j=0; j<m; j++){
if (nextbig.find(nums1[j]) == nextbig.end()) {
result.push_back(-1);
}
else{
result.push_back(nextbig[nums1[j]]);
}
}
return result;
}
};
卡哥的代码:
与我的代码的区别在于哈希表的建立方式,我的方法建立了nums2中的元素和对应的下一个更大元素之间的哈希关系,而卡哥的方法建立的是nums1和nums2之间的哈希关系。整体思路上应该是差不多的。
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
stack<int> st;
vector<int> result(nums1.size(), -1);
if (nums1.size() == 0) return result;
unordered_map<int, int> umap; // key:下标元素,value:下标
for (int i = 0; i < nums1.size(); i++) {
umap[nums1[i]] = i;
}
st.push(0);
for (int i = 1; i < nums2.size(); i++) {
while (!st.empty() && nums2[i] > nums2[st.top()]) {
if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素
int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标
result[index] = nums2[i];
}
st.pop();
}
st.push(i);
}
return result;
}
};
看了解析感觉它的这个代码里面有些比我的还要绕,比如这个:
int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标
result[index] = nums2[i];
就让我看了半天,我们挨个说:
1 st.top()表示栈顶元素,栈里面存的是nums2当中每个元素对应的下标。
2 nums2[st.top()]将nums2当中每个元素对应的下标还原为元素的值。
3 umap[nums2[st.top()]]找到nums1当中,和当前nums2的值相等的元素的下标。
4 result[index]表示根据找到的nums1当中下标的位置,将nums2[i](下一个最大元素的值)赋给它。
属实是有点难度,光看了理解就比较难了,写出来就更是难上加难了。
503.下一个更大元素II
因为感觉如果写一个循环然后还要去分大于n和小于n的情况进行分别处理,个人感觉直接把同一个代码重复两遍即可,所以挥挥手写出如下代码:
class Solution {
public:
vector<int> nextGreaterElements(vector<int>& nums) {
int n = nums.size();
stack<int> st;
vector<int> result(n);
for(int i=0; i<n; i++){
while(!st.empty() && nums[st.top()] < nums[i]){
int pos = st.top();
result[pos] = nums[i];
st.pop();
}
st.push(i);
}
for(int i=0; i<n; i++){
while(!st.empty() && nums[st.top()] < nums[i]){
int pos = st.top();
result[pos] = nums[i];
st.pop();
}
st.push(i);
}
while(!st.empty()){
int pos = st.top();
result[pos] = -1;
st.pop();
}
return result;
}
};
还以为这么写必然是万无一失的,没想到看了眼结果,两次循环竟然与一次循环的返回值一模一样。经过了两分半的研究,终于发现问题出在最后一个循环这里:
看似好像没什么问题,但实际却并不是,我们第一遍循环的时候就把一些没找到更大值的压入了栈内,第二遍循环的时候虽然把第一遍时没找到,且存在更大元素的那些元素给弹了出来,但是后面又加进去了!那此时再出栈并且赋值为-1,明明找到的正确答案又被-1覆盖回去了。
while(!st.empty()){
int pos = st.top();
result[pos] = -1;
st.pop();
}
那怎么办呢?两个办法:
1 赋值改成vector<int> result(n, -1);
此时我们发现,后面这个循环不用跑了,里面有一个还是有两个也不重要了。
2 在第二次循环里注释掉st.push(i);
为什么可以这么做?请看GPT:
简单来说就是,第二次遍历实际只是处理第一次遍历时的剩余元素,因此第二次遍历完全不需要再去插入新的元素。
看了卡哥解析之后发现可以写成i % nums.size(),只能说学到了。确实这样就不需要去分前n和后n讨论了,一点也不用担心写的麻烦的问题。并且GPT里面还写成了int num = nums[i % n];,这样后面只要用num这样简单的三个字母就能代替nums[i % nums.size()]这一大串。这种怎么让自己写的更舒服的办法还是要好好学习的。