题目

面试官:小夕,做一下这道面试题吧。

小夕:好的,我可以借助辅助栈来实现吗?

面试官:可以的,说一下你的思路吧。

小夕:好的,我图形结合一下,说得清楚些。

第一种辅助栈思路

小夕:

  • 维护两个栈,一个输入栈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<Integer> 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<int> 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 []intmins []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_valueobj->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<Integer> 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方法可能会加入很多minint min = Integer.MAX_VALUE;Stack<Integer> 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<int> 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 = xself.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);elsehead = 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 = Nonedef 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.nextdef top(self) -> int:return self.head.valdef min(self) -> int:return self.head.min_valclass ListNode:def __init__(self,x=None,min_val=None,next=None):self.val = xself.min_val = min_valself.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;
};

小夕:面试官,你看我说得对不对。

面试官:不错不错,就是这个样子。

小夕:谢谢面试官,面试官你这么厉害

头条面试题,4种解法,60+图清晰讲解,面试官让我优化,小夕一通优化最终击败100%用户相关推荐

  1. 88道BAT Java面试题 助你跳槽BAT,轻松应对面试官的灵魂拷问

    88道BAT Java面试题 助你跳槽BAT,轻松应对面试官的灵魂拷问 前言: 备战金九银十逃脱不了面试官的灵魂拷问,笔者整理了88道Java面试,由于面试题太多文章没有包含答案,需要领取这些面试题答 ...

  2. 吐血整理的 Android 性能优化思维导图,让面试官眼前一亮

    引言 现如今 Android 开发行业的主要问题是因为初级的 Android 开发者太多了,导致初级开发的市场过于饱和,所以也就进一步导致初级和中级的开发者面临更大的竞争,因此想要脱离这种竞争现状,只 ...

  3. 史上最全的Java面试题集锦在这里,带你碾压面试官!

    一.网络原理 OSI 与 TCP/IP 各层的结构与功能,都有哪些协议 TCP 建立连接的过程,为什么要三次握手? TCP.UDP 协议的区别,各自的应用场景 打开浏览器,输入 URL 地址,访问主页 ...

  4. 2021年最全的自动化测试面试题及答案--看完后吊打面试官!自动化测试是什么?自动化测试学什么?

    一.前言 最近有童鞋和我抱怨,说网上很难搜到那些全面又合适的自动化测试面试题,这里根据我个人的经验以及收集整理的: 你没看错,不慌,慢慢来. 先从什么是自动化测试开始说起哈! 二.什么是自动化测试? ...

  5. 2020年最全的自动化测试面试题及答案--看完后吊打面试官!自动化测试是什么?自动化测试学什么?

    一.前言 最近有童鞋和我抱怨,说网上很难搜到那些全面又合适的自动化测试面试题,这里根据我个人的经验以及收集整理的: 你没看错,不慌,慢慢来. 先从什么是自动化测试开始说起哈! 二.什么是自动化测试? ...

  6. sql三张表的搜索要满足5种搜索条件的模糊搜索_面试三轮我倒在了一道 SQL 题上……| 原力计划...

    作者 | 牧小农的夏天 责编 | 王晓曼 出品 | CSDN博客 前言 最近小农在找工作,因为今年疫情的特殊原因,导致工作不是特别好找,所以一旦有面试电话,如果可以,都会去试一试,刚好接到一个面试邀请 ...

  7. android面试自定义view,资深面试官:自定义View的实现方式,你知道几种?

    前提 为什么要自定义View? 怎么自定义View? 当 Android SDK 中提供的系统 UI 控件无法满足业务需求时,我们就需要考虑自己实现 UI 控件.而且自定义View在面试时是很经典的一 ...

  8. 自动化测试面试题及答案,看完后吊打面试官!

    自动化测试是什么?自动化测试学什么?自动化测试面试题及答案?–看完后吊打面试官! 一.前言 最近有童鞋和我抱怨,说网上很难搜到那些全面又合适的自动化测试面试题,这里根据我个人的经验以及收集整理的: 你 ...

  9. 漫画:美团面试题(面试时,面试官给了我一块巧克力。。)

    今天是小浩算法"365刷题计划"第76天.这次小浩又出去面试,虽然面试官没让他修电暖气,但却给了他一块巧克力...(题目由读者在美团面试后提供) 01 PART 巧克力 巧克力的凹 ...

  10. 面试官:熟悉SQL优化吗?我只知道20种,其实远不止...

    在面试的时候,面试官很喜欢这么问: 熟悉SQL优化吗? 面对这种问题,不要害怕,田哥为你准备下面52条SQL语句性能优化策略.实在不行就多背几条,这样应对你的燃眉之急还是没问题. 「优化策略」 1.对 ...

最新文章

  1. linux脚本外输入参数,shell 脚本中关于用户输入参数的处理
  2. c#获取对象的唯一标识_Articy Importer Guide - 01 基本对象处理
  3. Effective C++ 学习笔记(11)
  4. Java GC 垃圾回收器
  5. 程序竞赛中常用的C字符串函数
  6. 关于.dll' could not be found 的问题以及解决方案
  7. 华为nova7se乐活版支持鸿蒙,华为nova7se乐活版和畅享20se哪个好 参数区别对比评测...
  8. ionic 图片显示在屏幕中间_iPad屏幕坏点亮点怎么看 自查iPad屏幕坏点亮点方法【详解】...
  9. 博客系统php源码,tjheer博客系统php版 v1.10
  10. atitit..代码生成流程图 流程图绘制解决方案 java  c#.net  php v2
  11. Service Started!!!-end In Service while
  12. telink泰凌微 8266 8250 8258IO中断唤醒睡眠
  13. 百度文库文章提取器(下)
  14. 嵌入式linux ucgui,嵌入式开发-uCGUI中文手册-uCGUI 简介.pdf
  15. android阿拉伯语言的数字
  16. labuladong算法小结
  17. 【DaVinci Developer专题】-32-Mode(Switch) Declaration Group中Alphabetic和Explicit的区别
  18. 纯电动汽车快慢充原理介绍
  19. 使用python实现局域网文件共享(速度超快)
  20. arduino智能浇花系统_基于Arduino的远程自动浇花系统设计

热门文章

  1. 毕业设计 ASP.Net+EasyUI开发 X X露天矿调度管理信息系统(一)
  2. Flex Builder 不能Profile的另一个原因:不能使用中文用户名
  3. hibernate笔记--缓存机制之 二级缓存(sessionFactory)和查询缓存
  4. LabVIEW 2011中文版下载及工具包下载
  5. [javascript] Promise API
  6. git 删除已经 add 的文件
  7. 工程选择LibGdx--开发环境搭建Strut2教程-java教程
  8. Intel处理器系列
  9. 你真的了解分层架构吗?——写给被PetShop毒害的朋友们
  10. 将 varchar 值转换为数据类型为 int 的列时发生语法错误