数据结构-单调栈 leetcode 下一个更大的数

数据结构-单调栈 leetcode 下一个更大的数2

由leetcode题目引入:

在这里插入图片描述
刷题时看到这道题,第一反应使用循环数组暴力解题了,附上代码

暴力解题代码

public static int[] nextGreaterElements(int[] nums) {
        int[] res = new int[nums.length];
        Arrays.fill(res,-1);
        int j;
        int index;
        for (int i = 0; i < nums.length; i++) {
            j = i + 1;
            while ((index = (j % nums.length)) != i){
                if (nums[index] > nums[i]){
                    res[i] = nums[index];
                    break;
                }
                j++;
            }
        }
        return res;
    }

提交后发现速度较慢 查看题解后了解到单调栈这种数据结构,接下来了解一下单调栈

什么是单调栈

简而言之,就是栈中的元素时单调有序的
具体根据单调递增和单调递减又可以分为单调递增栈和单调递减栈(这里的单调是指pop出元素的顺序)
了解到以上概念之后,就动手实现一个单调栈

模拟单调栈流程:

  • 给定数据:7 6 4 9
  • 使用单调栈解决 流程模拟
  • 遍历7 此时栈为空 ,将7入栈 此时栈内元素为7
  • 遍历6 此时栈顶元素为7, 6<7 将6入栈 此时栈内元素为7 6
  • 遍历4 此时栈顶元素为6, 4<6 将4入栈 此时栈内元素为7 6 4
  • 遍历9 此时栈顶元素为9, 9>4 不满足入栈条件
    • 循环处理 将4 出栈 此时栈内元素为7 6
    • 将6 出栈 此时栈内元素为7
    • 将7 出栈 此时栈内元素为空
  • 栈为空 满足入栈条件 将9入栈 此时栈内元素为9

单调栈代码

package stack;

/**
 * 单调栈实现 单调递增实现(每次取出元素先取出最小的元素 待元素全部取出是递增的方式取出的)
 *
 */
public class MonStack {
    private Node head;

    private int length;

    public MonStack(){
        head = new Node(0,null);
        length = 0;
    }

    public void push(int element){
        while (!isEmpty() && peek() < element){
            pop();
        }
        length++;
        Node node = new Node(element, head.next);
        head.next = node;
    }

    public int pop(){
        if (isEmpty())
            return -1;
        length--;
        Node node = head.next;
        head.next = node.next;
        return node.element;
    }

    public int peek(){
        return head.next.element;
    }

    public boolean isEmpty(){
        return length == 0;
    }

    private class Node{
        private int element;
        private Node next;
        public Node(int element,Node next){
            this.element = element;
            this.next = next;
        }
    }

    public static void main(String[] args) {
        MonStack monStack = new MonStack();
        monStack.push(7);
        monStack.push(6);
        monStack.push(4);
        monStack.push(3);
        monStack.push(12);
        System.out.println(monStack.pop());
        System.out.println(monStack.pop());
        System.out.println(monStack.pop());
    }
}

应用单调栈解决该题

/**
     * 优化
     * 根据题意的性质可知 如果一个数找到了他的下一个更大元素 那么在该更大元素之前和该数之后的数(二者之间的数)的下一个更大元素都是该更大元素
     * 例: 7 6 4 9
     * 7之后的大数为9 那么在7之后 9之前的所有数他的大数都是9
     * 使用单调栈解决 流程模拟
     * 遍历7 此时栈为空 将7入栈
     * 遍历6 此时栈顶元素为7 6<7 将6入栈
     * 遍历4 此时栈顶元素为6 4<6 将4入栈
     * 遍历9 此时栈顶元素为9 9>4 不满足入栈条件
     *      循环处理 将4 出栈 并设置4的下一个更大元素为9
     *             将6 出栈 并设置6的下一个更大元素为9
     *             将7 出栈 并设置7的额下一个更大元素为9
     * 此时栈为空 将9入栈
     * 继续遍历 for循环结束也没有找到比9更大的元素 直接结束即可
     * 可以使用单调栈来解决
     * @param nums
     * @return
     */
    public static int[] nextGreaterElements_new(int[] nums) {
        int[] res = new int[nums.length];
        Arrays.fill(res,-1);
        Deque<Integer> stack = new LinkedList();
        // 循环nums.length*2 - 1 的原因:因为本题是循环查找 但却最多循环不会超过两次 所以直接循环两次即可
        // 如果需要多次循环 则直接取模即可
        for (int i = 0; i < nums.length*2 - 1; i++) {
            // 单调栈入栈的规则是 栈不为空 && 栈顶元素大于要入栈的元素
            // 如果不满足该条件则将栈顶元素移除 以满足上述条件
            // 简而言之,入栈的元素都是比第一个入栈元素值小的元素 只不过这里比较的是元素值的大小 入栈的是该元素的下标
            while (!stack.isEmpty() && nums[stack.peek()] < nums[i%nums.length]){
                res[stack.pop()] = nums[i % nums.length];
            }
            stack.push(i % nums.length);
        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值