《程序员面试代码指南》之栈和队列中的套路

再过几个月要找实习了,有必要花些时间有条理,分专题的好好复习一下。

已经在工作的本科室友给我推荐了左程云的《程序员面试代码指南》,由于我们主要都用java,所以觉得这本书还挺不错的,就准备按照上面的框架复习。

栈和队列这一章差不多第二遍看了,有些题目觉得有点繁琐,看的比较泛,而且第一次看的那几个题忘得差不多了。

首先,栈和队列的基本结构已经特性,我就不提了。
拿出几个一星的题
1 设计一个有getMin功能的栈(这个应该还是挺容易想到的,用另外一个栈保存min值)
2 由两个栈组成队列(数据结构中都会出现的经典题目)
3 用一个栈实现另外一个栈的排序。
4 仅用递归函数逆序一个栈。
前面两个题比较简单。
后面两个题对如何用递归函数操作栈不太熟悉的同学就没前两个直观了。
后面两题主要是考察栈的递归操作,递归的话,你就要找到重复相同步骤是什么,以及每重复一次这个步骤的中间状态。
栈元素排序,中间状态是什么,也就是栈顶的前两个元素排好序,栈顶的前3个元素排好序(不妨设从栈顶到栈底升序),如果栈顶端的n个元素已经按从上到下递增的顺序排好,我们下一步做的就是把第n+1个元素排好序,可以想到,先把这n个数弹出到另外一个栈中去(现在是降序了),然后得到第n+1个数的值,也就是执行pop,然后把比他大的都push回原来的栈,再把它push回去,再把比他小的那些push回去。
第4题的话,也按照这种思路来,中间步骤是什么,首先要明确栈的递归后的操作只能是吧栈顶或者栈底的数,前面一个题就是把栈顶的给弄出来,而这个题就需要把栈底的数弄出来,然后把剩下的树逆序,然后把这个以前是栈底的数给push进去。(代码我就不贴了)需要一个getAndRemoveLast()的函数和一个reverse()的函数。

然后两星三星的题目来了:
1 生成窗口最大值数组
2 求子矩阵的大小
3 最大值减最小值等于num的数量
这三个题的基础都是双端队列。在java中也就是LinkedList
而作者的意思也就是栈和队列算法题中的较难和难的题目中都是用这个套路。
首先我说一下这个套路是什么。
1 用双端队列
2 队列中保存的不是值而是id
而这种套路能够解决哪些问题,举个例子,如果过来的数据是3,5,2,4,6
当3来时 队列【0(3)】 i= 0
5 【1(5)】 i =1
2 【1(5),2(2)】 i = 2
4 【1(5),3(4)】 i = 3
6 【4(6)】(小括号内6表示值,4表示他在数组的index) i =4
队列的队头数组中从0个数记录了到当前为止的最大值,而通过对队头的操作可以得到其中的子数组的结果,比如从【2-3】的最大值是i = 3的时候把队头的元素1(5)poll出去(因为1不在2-3内)的队头3(4),而这种结构能够很快的解决计算数组的子数组的最大最小值问题,所以1,3 题就完全按照这个套路来。第一个根据窗口大小判断队头是否在窗口内,不是的话就把它pop出去。第三题也是一样,两个队列一个记录最大值,一个记录最小值,当最大减去最小就继续往队尾加,当小于就把队头往后移动。
而第二题是随处可见的经典题目,说白了也就是条形图找最大矩形,他用这种套路保存了当前能够往前面扩展的最远距离比如条形图
这里写图片描述
当算的第10个矩形的时候,这时候队尾应该是【7(3),8(10),9(15)】根据这种结构就能够得到它向右
10向右扩展高最大只能是20 * 1
把 9 poll出去的时候表示10向右扩展到9高只能是 15 面积15*2
同理 8时 面积 10 * 3
这种方案在解决在题目中子数组和最大最小同时出现时,非常有效。

其他有几个内容比较繁琐,而且比较偏的题目就没一一列出来,以上题目个人认为是第一章中很具有代表性的题目。花一点时间弄懂了,其他考察栈和队列的题目做起来才更加得心应手。

代码细节那些很重要,但清晰的思路更加重要。

以上是绝大多数个人理解,有错误或不足,望见谅!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值