开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 19 天,点击查看活动详情
通过对这几个题的分析总结一点点小规律。
有效括号序列
给出一个仅包含字符'(',')','{','}','['和']',的字符串,判断给出的字符串是否是合法的括号序列
括号必须以正确的顺序关闭,"()"和"()[]{}"都是合法的括号序列,但"(]"和"([)]"不合法。
本题最先想到的方法是设置三个整形变量,因为只有三种字符。所以可以通过如果是左括号就n++,右括号就是n--,这种思路,找到结果是左括号和右括号配对的。但是对于"(]"和"([)]"是不符合要求的。
那么解决方法可以是把特殊情况的作为特殊值进行判断
这种做法虽然简单粗暴,但是对于特殊条件较多的组合,书写困难,或者说是考虑容易没有那么全面。
对于这类型括号匹配问题,我们最常用做法是:栈(这也是推荐用法)
括号匹配原则就符号先入先出,比如
一般符合要求的情况,栈顶和新既然的右边都是配对的,如果出现不配对,就证明这个序列无效
关于配对可以不出现判断,我们在加入栈时候,如果当前是左括号,,那么就加入右括号,证明我需要和右括号配对。当遇到右,就看栈顶和他是不是相等,如果相等就出栈
滑动窗口最大值
给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值
最先想到是两个指针的做法,比如
那么关键是怎么在窗口里面找到最大值。我们可以新建一个方法,里面传入left,right参数,和num数组。
从left到right直接数组进行遍历查询寻找最大值,返回。主函数就只需要把拿到的值,既然集合
但是这样的话,时间复杂度是n^2(因为外层right-》num.length n,内层left-》right n)
这种情况下,使用双向队列最容易
如果即将进入队列的下标的值大于队列后方的值,依次将小于的值拿出来去掉,再加入,保证队列是递增序。
每次取出队首就是最大值,如果某个下标已经过了窗口,则从队列前方将其弹出。
其实就是在0-size范围内,只需要加入最大值就可以。对于后续内容,继续这个操作
找出最小的k个数和找出第k大的数。
最直接方法就是对数组排序,只要排好序,第几大的、最小的就轻轻松松了。
所以关键是怎么排序?
Java常用的是冒泡和快排,我们知道冒泡时间复杂度比较大,所以一般使用快排,那么快排怎么书写?
怎么找到数据流中位数。
首先因为数据是一次一次读进去的,所以长度不固定,使用数组不方便,又因为中位数的算法,最直接就是拿到排序后的数据,然后进行中位数计算。
可以声明一个list接收传入数据,当数据传输完成,那么就可以把他变成有序数组,然后就能得到中位数了。
大家可以看出来中间那个两个for循环是冒泡排序,那么把他改成快排后,时间节约了很多
但其实这个题还可以使用平衡大堆小堆的方法来做,这个在牛客或者🗡指offer上面很多,这里不多说了。
规律
当涉及到第几大,或者中位数这种需要数组有序的,我们可以考虑先排序再做,那么就需要记得快排怎么写(敲重点)。
对于涉及符号匹配或者求字符串值的,优先考虑栈。
堆栈队列都是有友好空间的,在面试和比赛需要掌握的程度不一样,需要一个题分情况考虑(ps这几个题把,我看我的思路牛客比较少,可以参考参考,思路很简单的)