剑指Offer 面试题30. 包含min函数的栈(easy)


前往LeetCode做题

题目

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

最小栈

使用两个栈,一个栈用来正常放入元素。另一个栈用来,存储每一时刻的最小值

class MinStack {

    // 定义两个栈,一个存储普通的元素。一个用来作为同步的最小栈,即同步栈中的每一层存储的都是该情况下的最小元素。
    Stack<Integer> stack = new Stack<Integer>();
    Stack<Integer> minStack = new Stack<Integer>();

    /** initialize your data structure here. */
    public MinStack() {

    }
    
    public void push(int x) {
        // 元素推入栈中
        stack.push(x);
        if(minStack.isEmpty()){
            minStack.push(x);
        }else{
            minStack.push(Math.min(minStack.peek(), x));
        }
    }
    
    public void pop() {
        stack.pop();
        minStack.pop();
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int min() {
        return minStack.peek();
    }
}

新奇:这题可以自建链表结构做!!!

自定义链表的用处真的太有意思了。之前对于链表的定义都只是局限在单链表领域,即链表中的一个节点存储一个值,和一个指向下一个节点的Node变量

class Node{
	int val;
	Node next;
	public Node(int val){
		this.val = val;
	}
}

但是最近接触到的几道题目,都说明了链表的结构非常多样!

像我们平常接触到的二叉树,N叉树,双向链表等等。都是非常经典的链表的运用。

至于为什么:计算机的底层只有两种存储方式(顺序存储、链式存储)。所以一般我们常用的数据结构,都是建立在这之上的逻辑层面的抽象,所以链表的作用千万不要小瞧。

思路如下:使用链表

  • 每个链节点,都维护了一个该节点的时候最小值,和本身的值
  • 初始化的时候,初始化链表的 head头节点
  • 入栈的时候,贴到 head的后面(head.next),并和之前的那个节点的最小值比较,更新最小值
  • 弹出元素的时候,将链表的第一个弹出即可
class MinStack {
    // 定义一个节点,节点中维护了两个值,一个当前时刻的最小值。一个当前节点的值
    private class Node{
        int val;
        int min;
        Node next;
        public Node(int val, int min){
            this.val = val;
            this.min = min;
        }
    }

    private Node head;

    public MinStack() {
        head = new Node(0,0);
    }
    
    public void push(int x) {
        if(head.next == null){
            head.next = new Node(x, x);
        }else{
            // 取出原来head.next的最小值
            int min = head.next.min;
            // 更新最小值
            min = Math.min(min, x);
            // 创建新节点,并插入到链表的后面
            Node node = new Node(x, min);
            node.next = head.next;
            head.next = node;
        }
    }
    
    public void pop() {
        if(head.next != null)
            head.next = head.next.next;
    }
    
    public int top() {
        if(head.next == null){
            return -1;
        }
        // 如果栈中不为空,去头节点后面一个
        return head.next.val;
    }
    
    public int min() {
        // 由于节点中维护了一个最小元素,所以直接返回 头节点下一个即可
        return head.next.min;
    }
}

最后一个链表参考自:宝石

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值