本日劳绩:单调栈理论,逐日温度,下一个更大元素Ⅰ,下一个更大元素Ⅱ
1. 单调栈理论(来自代码随想录)
应用场景:一维数组寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置
存放的元素:数组下标
递增还是递减:单调递增栈(从栈顶到栈底)求右边第一个比自己大的(遍历发现比自己大的元素);单调递减栈求右边第一个比自己小的(遍历的目的是发现比自己小的元素)
2. 逐日温度
题目链接:739. - 力扣(LeetCode)
思绪:用单调递增栈。如果当前元素比栈顶元素小,直接参加栈;反之记录结果,并不断弹出栈中比当前元素小的元素。
方法:
- class Solution {
- public int[] dailyTemperatures(int[] temperatures) {
- int len=temperatures.length;
- Stack<Integer> stack=new Stack<>();
- int[] result=new int[len];
- stack.push(0);
- for (int i=1;i<len;i++){
- if (temperatures[i]<=temperatures[stack.peek()]){
- stack.push(i); // 加入更小的元素
- }else{
- // 一直弹出比当前元素小的并记录
- while (!stack.isEmpty()&&temperatures[stack.peek()]<temperatures[i]){
- result[stack.peek()]=i-stack.peek();
- stack.pop();
- }
- stack.push(i); // 加入当前下标
- }
- }
- return result;
- }
- }
复制代码 3. 下一个更大元素Ⅰ
题目链接:496. - 力扣(LeetCode)
思绪:和逐日温度差不多,只不过在遇到目的元素时,必要判断栈顶元素是否在nums1中。这必要利用map映射存储nums1的值和下标。存储值是为了快速判断当前值是否在nums1中,存储的下标对应结果数组的下标。
方法:
- class Solution {
- public int[] nextGreaterElement(int[] nums1, int[] nums2) {
- int len1=nums1.length;
- int len2=nums2.length;
- int[] result=new int[len1];
- Arrays.fill(result,-1); // 最后栈中留下的元素默认-1
- // 记录数组1中值和下标的对应关系,便于判断当前元素是否存在于nums1中,下标对应结果的下标
- HashMap<Integer,Integer> map=new HashMap<>();
- for (int i=0;i<len1;i++){
- map.put(nums1[i],i);
- }
- // 求nums2中比当前元素大的右边第一个元素
- Stack<Integer> stack=new Stack<>();
- stack.push(0);
- for (int i=1;i<len2;i++){
- if (nums2[i]<=nums2[stack.peek()]){
- stack.push(i);
- }else {
- while (!stack.isEmpty()&&nums2[i]>nums2[stack.peek()]){
- if (map.containsKey(nums2[stack.peek()])){ // 收集结果
- int index=map.get(nums2[stack.peek()]);
- result[index]= nums2[i];
- }
- stack.pop();
- }
- stack.push(i);
- }
- }
- return result;
- }
- }
复制代码 总结:Arrays.fill(数组,添补值) 可以用于Java中数组的初始化。
4. 下一个更大元素Ⅱ
题目链接:503. - 力扣(LeetCode)
思绪:遍历两倍长度的数组,求当前元素的值时将下标 i 取余数组长度,其余的思绪和逐日温度雷同。
方法:
- class Solution {
- public int[] nextGreaterElements(int[] nums) {
- int len=nums.length;
- Stack<Integer> stack=new Stack<>();
- int[] result=new int[len];
- Arrays.fill(result,-1);
- stack.push(0);
- for (int i=1;i<len*2;i++){
- if (nums[i%len]<=nums[stack.peek()]){
- stack.push(i%len);
- }else {
- while (!stack.isEmpty()&&nums[i%len]>nums[stack.peek()]){
- result[stack.peek()]=nums[i%len];
- stack.pop();
- }
- stack.push(i%len);
- }
- }
- return result;
- }
- }
复制代码 总结:循环都涉及到下标取余数组长度的操作。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |