最小min函数的栈 动漫算法文字版 leetcode版

题目

面试官:小夕,做一下这道面试题吧。
小夕:好的,我可以借助辅助栈来实现吗?
面试官:可以的,说一下你的思路吧。
小夕:好的,我图形结合一下,说得清楚些。

第一种辅助栈思路

小夕:

  • 维护两个栈,一个输入栈A,一个辅助栈B,辅助栈用于存储当前栈中的最小值
  • 每次元素 x 入栈,输入栈 A 直接入栈
  • 辅助栈 B 入栈时为空直接入栈,如果 B 不为空,首先取 B 的栈顶元素 min,如果 x 大于min,那么辅助栈 B 继续入栈 min 值,如果 x 小于等于 min,那么辅助栈 B 入栈 x
  • 这样辅助栈 B 中每次入栈的元素都是当前栈的最小值
  • 这样取栈的 min 值时, 直接返回 B 的栈顶元素即可,时间复杂度是 O(1)
  • pop 出栈的话 栈 A 和 栈 B 都出栈,也是时间复杂度是 O(1),push 入栈时间复杂度也是 O(1)

拿题目中[-2,0,-3]举例。

第一种辅助栈图解思路

动画

代码

Java

class MinStack {
    Stack A, B;
    /** initialize your data structure here. */
    public MinStack() {
        A = new Stack<>();
        B = new Stack<>();
    }
    
    public void push(int x) {
        A.push(x);
        if (B.empty() || x < B.peek()) { // 辅助栈B为空 或者x小于B的栈顶元素,那么把x入B栈,这样B顶部始终是最小值
            B.push(x);
        } else {
            B.push(B.peek());  // x比B栈顶元素大,那么B栈顶是最小元素,继续B继续入一个栈顶的最小元素。
        }
    }
    
    public void pop() { 
        A.pop();
        B.pop();
    }
    
    public int top() {
        return A.peek();
    }
    
    public int min() { // B栈顶维护了一个最小值
        return B.peek();
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.min();
 */

C++

class MinStack {
public:

    stack stk,min_stk;//stk为原栈,min_stk为记录每次最小值的栈
    /** initialize your data structure here. */
    MinStack() {
        
    }
    
    void push(int x) {
       stk.push(x);
       if(min_stk.size()) x=min(x,min_stk.top());//x表示当前的最小值
       min_stk.push(x);
    }
    
    void pop() {
        min_stk.pop();
        stk.pop();
    }
    
    int top() {
        return stk.top();//返回原栈的栈顶
    }
    
    int getMin() {
        return min_stk.top();//返回每次最小值的栈的栈顶
    }
};

Python

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.A = []
        self.B=[]


    def push(self, x: int) -> None:
    
        self.A.append(x)
        if not self.B or  self.B[-1]>x:
            self.B.append(x)
        else:
            self.B.append(self.B[-1])


    def pop(self) -> None:
        self.A.pop();
        self.B.pop();

        
    def top(self) -> int:

        return self.A[-1]

    def min(self) -> int:
        return self.B[-1]

Go

type MinStack struct {
    elems []int
    mins []int
}


/** initialize your data structure here. */
func Constructor() MinStack {
    return MinStack{make([]int,0),make([]int,0)}
}



func (this *MinStack) Push(x int)  {
    this.elems = append(this.elems, x)

    if len(this.mins) == 0 || this.GetMin() >= x {
        this.mins = append(this.mins, x)
    } else {
        this.mins = append(this.mins, this.GetMin())
    }

}

func (this *MinStack) Pop()  {
    this.elems = this.elems[:len(this.elems)-1]
    this.mins = this.mins[:len(this.mins)-1]
}


func (this *MinStack) Top() int {
    return this.elems[len(this.elems) - 1 ]
}


func (this *MinStack) GetMin() int {
    return this.mins[len(this.mins)-1]
}

JS

/** 
 * 解法1  辅助栈
*/
var MinStack = function() {
  this.stack1 = [];
  this.stack2 = [];
};

/** 
 * @param {number} x
 * @return {void}
 */
MinStack.prototype.push = function(x) {
  this.stack1.push(x);
  const stack2Len = this.stack2.length;

  if (stack2Len === 0 || this.stack2[stack2Len - 1] >= x) {
    this.stack2.push(x);
  } else {
     this.stack2.push(this.stack2[stack2Len - 1]);
  }
};

/**
 * @return {void}
 */
MinStack.prototype.pop = function() {
  if (this.stack1.pop() === this.stack2[this.stack2.length - 1]) {
    this.stack2.pop();
  }
};

/**
 * @return {number}
 */
MinStack.prototype.top = function() {
  return this.stack1[this.stack1.length - 1];
};

/**
 * @return {number}
 */
MinStack.prototype.min = function() {
  return this.stack2[this.stack2.length - 1];
};

面试官:不错,你这个时间复杂度每个都是O(1),由于借助了辅助栈,空间复杂度是 O(n)。那你能否在你的借助辅助栈的基础上优化一下呢?
小夕: 不是很会啊

第二种辅助栈图解思路

小夕:面试官,想请教一下这个算法该如何优化。。。
面试官:借助辅助栈的思路确实不错,但是辅助栈其实不用每次都压入一个元素,每次只压入当前栈最小值即可。我给你画几张图就很容易记录了~
小夕:好的,辛苦辛苦!!!

图解思路

动画

面试官:题解思路就是这些,代码你写一下,我看你理解到尾没。
小夕:好的。

第二种代码

C

#define max_size 10000
//x_stack存储正常入栈元素,min_stack用来存储入栈时栈中最小的元素
//x_top和min_top分别为栈顶的下标
//min_value用来存储最小值
typedef struct {
    int *x_stack;
    int *min_stack;
    int x_top;
    int min_top;
    int min_value;
} MinStack;

/** initialize your data structure here. */

MinStack* minStackCreate() {
    MinStack *obj = (MinStack*)malloc(sizeof(MinStack));
    obj->x_stack = (int*)malloc(sizeof(int) * max_size);
    obj->min_stack = (int*)malloc(sizeof(int) * max_size);
    obj->min_top = obj->x_top = -1;
    obj->min_value = 0;
    return obj;
}

void minStackPush(MinStack* obj, int x) {
    if(obj->x_top < max_size)
    {
        if(obj->x_top == -1)
            obj->min_value = x;
        obj->x_stack[++(obj->x_top)] = x;
        if(x < obj->min_value)
            obj->min_value = x;     //当前元素比min_value小时改变min_value
        obj->min_stack[++(obj->min_top)] = obj->min_value;
    }
}

void minStackPop(MinStack* obj) {
    --(obj->x_top);
    --(obj->min_top);
    if(obj->min_top != -1)
        obj->min_value = obj->min_stack[obj->min_top];//出栈后将min_value变成min_stack的栈顶元素
}

int minStackTop(MinStack* obj) {
    return obj->x_stack[obj->x_top];
}

int minStackMin(MinStack* obj) {
    return obj->min_stack[obj->min_top];
}

void minStackFree(MinStack* obj) {
    free(obj->x_stack);
    free(obj->min_stack);
    free(obj);
}

/**
 * Your MinStack struct will be instantiated and called as such:
 * MinStack* obj = minStackCreate();
 * minStackPush(obj, x);
 
 * minStackPop(obj);
 
 * int param_3 = minStackTop(obj);
 
 * int param_4 = minStackMin(obj);
 
 * minStackFree(obj);
*/

Java

class MinStack {
    Stack A, B;
    public MinStack() {
        A = new Stack<>();
        B = new Stack<>();
    }
    public void push(int x) {
        A.add(x);
        if(B.empty() || B.peek() >= x)
            B.add(x);
    }
    public void pop() {
        if(A.pop().equals(B.peek()))
            B.pop();
    }
    public int top() {
        return A.peek();
    }
    public int min() {
        return B.peek();
    }
}

JS

// ac地址:https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof/
// 原文地址:https://xxoo521.com/2020-01-31-stack-min/

/**
 * initialize your data structure here.
 */
var MinStack = function() {
    this.dataStack = [];
    this.minStack = []; // 辅助栈
};

/**
 * @param {number} x
 * @return {void}
 */
MinStack.prototype.push = function(x) {
    this.dataStack.push(x);

    const length = this.minStack.length;
    if (!length) {
        this.minStack.push(x);
    } else if (x <= this.minStack[length - 1]) {
        this.minStack.push(x);
    }
};

/**
 * @return {void}
 */
MinStack.prototype.pop = function() {
    const { minStack, dataStack } = this;
    if (minStack[minStack.length - 1] === dataStack[dataStack.length - 1]) {
        minStack.pop();
    }

    dataStack.pop();
};

/**
 * @return {number}
 */
MinStack.prototype.top = function() {
    const length = this.dataStack.length;
    if (length) {
        return this.dataStack[length - 1];
    } else {
        return null;
    }
};

/**
 * @return {number}
 */
MinStack.prototype.min = function() {
    const length = this.minStack.length;
    if (!length) return null;
    return this.minStack[length - 1];
};

Python

class MinStack:

    def __init__(self):
        self.stack = []

    def push(self, x: int) -> None:
        if not self.stack:
            self.stack.append((x,x))
        else:
            min_num = self.min()
            if x <= self.min():
                self.stack.append((x,x))
            else:
                self.stack.append((x,min_num))

    def pop(self) -> None:
        self.stack.pop(-1)

    def top(self) -> int:
        return self.stack[-1][0]

    def min(self) -> int:
        return self.stack[-1][1]

第三种使用单栈来实现

面试官:不错不错,你这里借助了辅助栈去实现,这道面试题你想一想有没有不借助辅助栈,只使用一个辅助栈的实现思路?
小夕:只使用一个栈还能实现???
面试官:我提醒你一下,当压栈的值小于栈中最小值时,先把最小值入栈,然后再把需要压栈的值入栈,最后再更新栈中最小值。如果压栈的值大于栈中最小值的时候,直接压栈。
小夕:哦哦哦!!!我好像知道是怎么回事了,我画几张图,辛苦面试官看看小夕理解的对不对。

图解思路

动画

第三种使用单栈来实现代码

Java

class MinStack {//push方法可能会加入很多min
    int min = Integer.MAX_VALUE;
    Stack stack = new Stack<>();

    public void push(int x) {
        //如果加入的值小于最小值,要更新最小值
        if (x <= min) {
            stack.push(min);
            min = x;
        }
        stack.push(x);
    }

    public void pop() {
        //如果把最小值出栈了,就更新最小值
        if (stack.pop() == min)
            min = stack.pop();
    }

    public int top() {
        return stack.peek();
    }

    public int min() {
        return min;
    }
}

C++

class MinStack {
public:
    int min=0x3f3f3f3f;
    stack stk;//stk栈
    /** initialize your data structure here. */
    MinStack() {
        
    }
    
    void push(int x) {
        //如果加入的值小于最小值,要更新最小值
        if (x <= min) {
            stk.push(min);
            min = x;
        }
        stk.push(x);
    }
    
    void pop() {
        //如果把最小值出栈了,就更新最小值
        int p = stk.top();
        stk.pop();
        if (p == min)
        {
            min = stk.top();
            stk.pop();
        }
    }
    
    int top() {
        return stk.top();//返栈的栈顶
    }
    
    int getMin() {
        return min;//返回栈的栈顶
    }
};

Python

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.min_value =float('inf')
        self.stack = []
    def push(self, x: int) -> None:
        if x<=self.min_value:
            self.stack.append(self.min_value)
            self.min_value = x
        self.stack.append(x);

    def pop(self) -> None:
        if self.stack.pop()==self.min_value:
            self.min_value = self.stack.pop()


    def top(self) -> int:
        return self.stack[-1]

    def min(self) -> int:
        return self.min_value

JS


/** 
 * 解法3  单调栈
*/
var MinStack = function() {
  this.stack = [];
  this.min = Number.MAX_SAFE_INTEGER;
};

/** 
 * @param {number} x
 * @return {void}
 */
MinStack.prototype.push = function(x) {
  if (x < this.min) {
    this.min = x;
  }
  this.stack.push(x);
};

/**
 * @return {void}
 */
MinStack.prototype.pop = function() {
  if (!this.stack.length) return;

  const curValue = this.stack.pop();

  if (this.min === curValue) {
    this.min = Math.min(...this.stack);
  }
};

/**
 * @return {number}
 */
MinStack.prototype.top = function() {
  const len = this.stack.length;

  if (!len) return Infinity;

  return this.stack[len - 1];
};

/**
 * @return {number}
 */
MinStack.prototype.min = function() {
  return this.min;
};

Go

// 单个栈
type MinStack struct {
    stack []int;
}


/** initialize your data structure here. */
func Constructor() MinStack {
    return MinStack{make([]int,0)}
}


func (this *MinStack) Push(x int)  {

    if len(this.stack)==0 || this.GetMin()>x {
        this.stack = append(this.stack,x,x)
    }else{
        this.stack = append(this.stack,this.GetMin(),x)
    }


}


func (this *MinStack) Pop()  {
    this.stack = this.stack[:len(this.stack)-2]
}


func (this *MinStack) Top() int {
    return this.stack[len(this.stack)-1]
}


func (this *MinStack) GetMin() int {
    return this.stack[len(this.stack)-2]
}

自定义链表节点

面试官:不错,就是这个意思,代码也写得不错,还会这么多语言,厉害了。
面试官:其实这道题我之前还见过一个自己定义链表的数据结构的解法。
小夕:啊,面试官真是见多识广
面试官:你只需要定义一个链表节点,这个链表节点的定义我给你定义出来,你根据这个结构就知道怎么做了!
小夕:谢谢面试官!我按照这个节点定义说一下我的思路。

链表节点定义

class ListNode {
    public int val;
    public int min;//最小值
    public ListNode next;

    public ListNode(int val, int min, ListNode next) {
        this.val = val;
        this.min = min;
        this.next = next;
    }
}

图解思路

动画

代码

Java

class MinStack {
    //链表头,相当于栈顶
    private ListNode head;

    //压栈,需要判断栈是否为空
    public void push(int x) {
        if (empty())
            head = new ListNode(x, x, null);
        else
            head = new ListNode(x, Math.min(x, head.min), head);
    }

    //出栈,相当于把链表头删除
    public void pop() {
        if (empty())
            throw new IllegalStateException("栈为空……");
        head = head.next;
    }

    //栈顶的值也就是链表头的值
    public int top() {
        if (empty())
            throw new IllegalStateException("栈为空……");
        return head.val;
    }

    //链表中头结点保存的是整个链表最小的值,所以返回head.min也就是
    //相当于返回栈中最小的值
    public int min() {
        if (empty())
            throw new IllegalStateException("栈为空……");
        return head.min;
    }

    //判断栈是否为空
    private boolean empty() {
        return head == null;
    }
}

class ListNode {
    public int val;
    public int min;//最小值
    public ListNode next;

    public ListNode(int val, int min, ListNode next) {
        this.val = val;
        this.min = min;
        this.next = next;
    }
}

Python

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.head = None


    def push(self, x: int) -> None:
        if not self.head:
            self.head = ListNode(x,x,None)
        else:
            p = ListNode(x,min(x,self.head.min_val),self.head)
            self.head = p    
        


    def pop(self) -> None:
        self.head = self.head.next


    def top(self) -> int:
        return self.head.val

    def min(self) -> int:

        return self.head.min_val

class ListNode:
    def __init__(self,x=None,min_val=None,next=None):
        self.val = x
        self.min_val = min_val
        self.next = next

JS

/** 
 * 解法2  链表
*/
class LinkNode {
  constructor(val, min) {
    this.val = val;
    this.min = min;
    this.next = null;
  }
}

var MinStack = function () {
  this.head = null;
};

/**
 * @param {number} x
 * @return {void}
 */
MinStack.prototype.push = function(x) {
  if (this.head === null) {
    this.head = new LinkNode(x, x);
  } else {
    const temp = new LinkNode(x, Math.min(x, this.head.min));
    [temp.next, this.head] = [this.head, temp];
  }
};

/**
 * @return {void}
 */
MinStack.prototype.pop = function() {
  if (this.head !== null) {
    this.head = this.head.next;
  }
};

/**
 * @return {number}
 */
MinStack.prototype.top = function() {
  if (this.head !== null) {
    return this.head.val;
  }

  return Infinity;
};

/**
 * @return {number}
 */
MinStack.prototype.min = function() {
  if (this.head !== null) {
    return this.head.min;
  }

  return -Infinity;
};

小夕:面试官,你看我说得对不对。
面试官:不错不错,就是这个样子。
小夕:谢谢面试官,面试官你这么厉害

你可能感兴趣的:(最小min函数的栈 动漫算法文字版 leetcode版)