微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

leetcode之单调栈

问题模型:给定一个序列,求这个序列当中,每一个数左边比它小而且离它最近的数(或者右边,比它大而且离它最近的数)

比如:给定一个数组,求每个元素左侧比它小,而且离它最近的元素是多少

维护一个单调递增的栈(越往上越大)

 实现如下:

for(int i=0;i<nums.length;i++)
{
  while(stack.size()!=0&&stack.top()>=nums[i])
  {
     stack.pop();
  }
  //跳出循环说明此时栈内为空,或者栈顶元素小于nums[i]
  //这时就可以把nums[i]加入到栈顶,栈仍然维持单调递增
 stack.push(nums[i]);
}

以上只是维护了一个单调递增的栈,由于还要统计出每个元素的左侧第一个比它小的数,所以还要再这个代码的基础上加几行代码

for(int i=0;i<nums.length;i++)
{
  while(stack.size()!=0&&stack.top()>=nums[i])
  {
     stack.pop();
  }
  //跳出循环说明此时栈内为空,或者栈顶元素小于nums[i]
 
  //如果栈为空,那就为-1
  if(stack.size()==0)
  {
    nums[i]=-1;
  }
  else//如果栈不为空,那就等于栈顶元素
  {
     nums[i]=stack.top();
  }

  //这时就可以把nums[i]加入到栈顶,栈仍然维持单调递增
  stack.push(nums[i]);
}

单调栈还是栈,只是通过一些设置,使得每次新元素进栈后,栈内的元素都保持有序(单调递增或者单调递减)

比如构建一个单调递增栈:

从栈顶到栈底,元素大小依次递增(也就是说越往下,元素越大)

比如:

一维数组中,寻找任意一个元素右边第一个比自己大的数,或者是一个元素左边第一个比自己小的数的时候就要用到单调栈

例题1:力扣739 每日温度

题目意思:找出每一天要过几天才能碰到一个更高的温度

nums = [73, 74, 75, 71, 71, 72, 76, 73]

总结就是:构造一个单调递增栈,从栈顶到栈底元素越来越大,

将nums数组中每一个元素nums[i]进栈之前,都要和此时栈顶的元素nums[stack.top()]进行比较

如果nums[i]小于等于栈顶元素,就进栈

如果nums[i]大于栈顶元素,就把栈顶元素出栈,继续和新的栈顶元素比较,直到比新的栈顶元素小或者栈空了才进栈

也就是:(1)小于等于栈顶元素或者栈为空才进栈

(2)有元素出栈,才更新result数组的值,result[要出栈的元素下标]=]要进栈的元素下标-要出栈的元素下标

class Solution 
{
    public int[] dailyTemperatures(int[] nums) 
    {
        int[]  result=new int[nums.length];

        Stack<Integer>  stack=new Stack();

        stack.push(0);

        for(int i=1;i<nums.length;i++)
        {
            if(nums[i]<=nums[stack.peek()]||stack.size()==0)
            {
                stack.push(i);
            }
            if(nums[i]>nums[stack.peek()])
            {
               while(stack.size()!=0&&nums[i]>nums[stack.peek()])
               {
                   int temp=stack.peek();
                   result[temp]=i-temp;
                   stack.pop();
               }
               //跳出这个循环之后,要么栈空了,要么栈顶元素比nums[i]大了
               stack.push(i);
            }
        }
        return result;
    }
}

站在栈顶元素的角度,只有碰到比自己大的元素,它才被弹出栈

如果要找出下一个更大的元素:

class Solution 
{
    public int[] nextGreaterElements(int[] nums)
    {
         int[]  result=new int[nums.length];

         Arrays.fill(result,-1);

        Stack<Integer>  stack=new Stack();

        stack.push(0);

        for(int i=1;i<nums.length;i++)
        {
            if(nums[i]<=nums[stack.peek()]||stack.size()==0)
            {
                stack.push(i);
            }
            if(nums[i]>nums[stack.peek()])
            {
               while(stack.size()!=0&&nums[i]>nums[stack.peek()])
               {
                   int temp=stack.peek();
                   result[temp]=nums[i];
                   stack.pop();
               }
               //跳出这个循环之后,要么栈空了,要么栈顶元素比nums[i]大了
               stack.push(i);
            }
        }
        return result;
    }
}

496. 下一个更大元素 I - 力扣(LeetCode)

 输入一个数组 nums,请你返回一个等长的数组,这个数组中的元素是nums数组中每个元素下一个更大的元素(如果后面没有比这个数更大的数,那就存-1)

把数组的元素想象成并列站立的人,元素大小想象成人的身高

 那么显然nums数组中第一个元素2的下一个更大元素就是4(第一个比2高的元素)

int[] nextGreaterElement(int[] nums) 
{
    int n = nums.length;
    
    // 存放答案的数组
    int[] res = new int[n];
    
    Stack<Integer> stack = new Stack<>(); 
    
    //从最后一个元素开始往栈里放,一直到将最后一个元素放进栈里
    for (int i = n - 1; i >= 0; i--) 
    {
        //
        while (stack.isEmpty()==false && stack.peek() <= nums[i])
        {
            // 矮个起开,反正也被挡着了。。。
            s.pop();
        }
        
        // nums[i] 身后的更大元素
        res[i] = s.isEmpty() ? -1 : s.peek();
        s.push(nums[i]);
    }
    return res;
}

原文地址:https://www.jb51.cc/wenti/3285904.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐