代码随想录刷题记录 day50 每日温度+下一个更大元素 I
739. 每日温度
思想
1.暴力解 两次for 超时了
2.单调栈
花了点时间理解的。
单调栈的基础入门题。找到一个数组中右边的第一个大于 等于 或者小于当前元素的下标的位置
以时间换空间,用一个栈来记录右边第一个比当前元素大的元素。只需要遍历一次就好了
栈里面存放的是元素的下标。需要处理以下三种情况
- 当前遍历的元素temperatures[i]小于栈顶元素temperatures[st.top()]的情况
- 当前遍历的元素temperatures[i]等于栈顶元素temperatures[st.top()]的情况
- 当前遍历的元素temperatures[i]大于栈顶元素temperatures[st.top()]的情况
因为本题是要找到大于的元素,所以对于1.2两种情况 直接将元素的下标插入到栈中就好了。
对于找到了右边第一个大于的元素,则进行以下的处理。
stack.peek() 记录着的是栈顶元素的下标
i-stack.peek()表示当前的这个元素和栈顶所记录的元素的距离
res[stack.peek()] 赋值
出栈
while()表示对当前栈内元素 所有小于temperatures[i]的值就要记录距离并出栈
最终将当前的元素入栈
//大于栈顶对应的元素
//把所有小于的都弹出 同时记录数值
while(!stack.empty() && temperatures[i]>temperatures[stack.peek()]){
res[stack.peek()]=i-stack.peek();
stack.pop();
}
stack.push(i);
代码
class Solution {
// public int[] dailyTemperatures(int[] temperatures) {
// int [] ans=new int[temperatures.length];
// 暴力解
// for(int i=0;i<temperatures.length;i++){
// for(int j=i+1;j<temperatures.length;j++){
// if(temperatures[j]>temperatures[i]){
// ans[i]=j-i;
// break;//跳出当前一层的循环
// }
// }
// }
// return ans;
// }
public int[] dailyTemperatures(int[] temperatures) {
//单调栈 单调栈里存放元素的下标
Stack<Integer> stack=new Stack<>();
stack.push(0);
int [] res=new int[temperatures.length];
for(int i=1;i<temperatures.length;i++){
if(temperatures[i]<temperatures[stack.peek()] ){
//小于栈顶元素 直接入栈
stack.push(i);
}else if(temperatures[i]==temperatures[stack.peek()]){
//等于也是直接入栈
stack.push(i);
}else{
//大于栈顶对应的元素
//把所有小于的都弹出 同时记录数值
while(!stack.empty() && temperatures[i]>temperatures[stack.peek()]){
res[stack.peek()]=i-stack.peek();
stack.pop();
}
stack.push(i);
}
}
return res;
}
}
496. 下一个更大元素 I
思想
和前面一道题目的区别是这题目是两个数组,需要用一个hashmap来维护nums1的映射关系。
可以根据数值快速找到下标,还可以判断nums2[i]是否在nums1中出现过
key: num1[i] value i
HashMap<Integer,Integer> hashMap=new HashMap<>();
for(int i=0;i<nums1.length;i++){
hashMap.put(nums1[i],i);
}
栈中存放的是num1的下标
数组res来存放结果,根据题目要求 需要初始化为-1
讨论三种情况
- 当前遍历的元素nums2[i]小于栈顶元素nums2[stack.peek()]
- 当前遍历的元素nums2[i]等于栈顶元素nums2[stack.peek()]
- 当前遍历的元素nums2[i]大于于栈顶元素nums2[stack.peek()]
因为本题是找大于的 所以对于1.2两种,只要往栈里添加元素就好了。
考虑第三种情况,需要进行以下几个步骤
stack.peek() 栈顶元素,存放的是nums1的下标
nums2[stack.peek()] 获得具体元素的值
判断当前nums2的元素在nums1中是否出现过
出现过 index记录元素在nums1中的下标的位置
把元素弹出栈
while(!stack.empty() && nums2[i]>nums2[stack.peek()]){
if(hashMap.containsKey(nums2[stack.peek()])){
int index=hashMap.get(nums2[stack.peek()]);
res[index]=nums2[i];
}
stack.pop();
}
stack.push(i);
代码
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
//nums1 是nums2的子集 nums1中的值在nums2中都能找到
Stack<Integer> stack=new Stack<>();
int [] res=new int[nums1.length];
Arrays.fill(res,-1);
//用一个hashmap 来做映射 可以根据数值快速找到下标,还可以判断nums2[i]是否在nums1中出现过
HashMap<Integer,Integer> hashMap=new HashMap<>();
for(int i=0;i<nums1.length;i++){
hashMap.put(nums1[i],i);
}
System.out.println(hashMap);
//单调递增栈中存放的是nums1的下标
stack.push(0);
for(int i=1;i<nums1.length;i++){
if(nums2[i]<nums2[stack.peek()]){
//小于栈顶元素
stack.push(i);
}
else if(nums2[i]==nums2[stack.peek()]){
stack.push(i);
}
else{
//nums2 中的下一个元素比栈顶的元素大了 涉及到入栈和出栈的操作
//只是这一题需要先找到nums1中是否含有当前栈顶元素对应的元素
//如果有 则要记录结果
//如果没有 则直接出栈就好了
while(!stack.empty() && nums2[i]>nums2[stack.peek()]){
if(hashMap.containsKey(nums2[stack.peek()])){
int index=hashMap.get(nums2[stack.peek()]);
res[index]=nums2[i];
}
stack.pop();
}
stack.push(i);
}
}
return res;
}
}