leetcode笔记

1.为什么分发糖果可以左边遍历右边遍历取最大值就完事了。
左边遍历可以确定左边上坡的值,右边遍历确定下坡的值,然后波峰取两者中更大的那一个。
里面的证明包含了贪心算法,找波谷之间的糖果如何分配,波谷全部分配成1,然后后面的上坡加1,波峰要取更大的那个值。

我写题时的思考路程:
1.首先要能知道大致流程,这题就是一个输入队列一个输出队列,先push,遇到poped的第一个时就停止然后这时就表示压入弹出该数字,然后需要判断是继续push还是一直pop。
2.得到代码的大体框架,这里是一个大循环包含两个小循环,小循环分别是push的循环和pop的循环。这里是最关键的。
3.实现小循环并且后续保证调试按照所想的运行,小循环涉及大量的越界处理。
4.最后找到退出条件,包括小循环退出条件和大循环的。其实就是题目的终止条件。
其中每一步都有大量技巧在里面,所以入门还是有难度的。 一个是越界处理,一个是框架的找寻。 框架找寻需要找到一个比较好的例子,然后模拟去看哪些地方拆分成小循环,这个例子找寻也有技巧。

区间最值计算用单调队列,这是hard题但是在其他中等题却有应用。

很多最值问题都可以用二分法解决。

然后很多区间值问题可以滑动窗口和前缀和试试。

快速获取数组的随机值的方法,得到随机索引然后和尾部交换再删除尾部值。数组快速删除的方法也是基于交换尾部数据。快速删除还可以是hashmap加节点式的双向链表。

有整除可以尝试的最小公倍数容斥原理,mod,多路归并,堆。

追求常熟空间一般是位操作。n&(n-1)可以消除最后一个置1位,n&(-n)可以得到最低位。异或可以消除两个相同的。如果数组有3个相同的,记得有个数电相关的忘了。

一些回溯操作涉及数组减小可以尝试逆向思维。回溯不从第一步而是考虑最后一步。

碰到不会做的数组题想想先排个序。数组相关(排序,滑动窗口,dp)。
或者归并排序找逆序对。

二叉树的树形dp,赋值层数和列数,map存每一层节点。

删除的常数时间操作可以给数组交换末尾后删除末尾。

数组子序列的题目,可以考虑排序,然后还有二分和双指针(一般配合排序)。这里就用不了单调栈。
最长上升子序列的dp。

有些暴力法比如统计所有左右括号的对应索引,统计所有字符的连续字串的区间。

  1. 满足条件的子序列数目
    就排序然后二分,枚举小的那个计算贡献。要说思路那只能是先考虑枚举然后找符合条件的可选项,发现可选项是一个临界值以下的。
    子序列可以排序的情况,只跟子序列的最大最小值有关而与其顺序无关,这时可以优先排序。如果与顺序有关那用dp。

子数组的题目一般要想到前缀和(涉及区间求和)加哈希表,单调栈(区间最值,一侧最值),dp,滑动窗口,单调队列
子数组总结

虾皮面试题 链表环的入口,很多时候退出循环的条件都是在第一行,但事实上有时候不应该在第一行,而应该在中间,习惯性的放的第一行是因为初始条件就不符合需要直接退出,而在这道题里面显然初始条件直接是退出循环但是与我们思考的不符合。
简单总结就是退出循环的语句要放在中间而不一定在开头。放在开头仅仅是合并了初始化条件的判断,我们应该放在中间,对于初始条件的判断放在循环外。

美团面试题 是跟字符串处理相关的,我感觉字符串可以先转为字符数组再操作,这样用下表索引代替字符串的截取函数会比较好,时间空间消耗会小很多。

较没把握的或者没思路的或者需要特别进行记忆的题目:
搜索旋转排序数组
将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。
此时有序部分用二分法查找。无序部分再一分为二,其中一个一定有序,另一个可能有序,可能无序。就这样循环.
这里二分是缩小查找范围,平时的二分比较简单,就是通过单调性,左边和右边满足的条件不一致找到这个边界。缩小范围的判断准则差距比较大。
共同点在二分时不将lr的边界改变加入作为判断。

lc300. 最长递增子序列
特殊记忆
lc129. 求根节点到叶节点数字之和
有保存路径的简单解法,有比较妙的,记录每个节点的值,但只有到叶子节点才需要加。
lc题解当叶子节点和其他三种情况的返回不能一致时,不能简单的使用null来返回。
总结:二叉树跟叶子节点有关时一般都拆分四种情况,而不是一个null判断返回。

String[] num = str.split("\\.");

  1. 字符串解码
    有括号然后需要栈的都可以用map记录括号然后递归解决。用栈也是可以的相当于自己维护递归栈。

面试技巧:学会化简题目,当题目很复杂时化简,先完成简单的功能,面试官也不会刁难的。后面再做完善。能跑通特例就行。

lc4. 寻找两个正序数组的中位数
这里因为是板子而不是索引所以多考虑了一个越界问题,其实还好。

lc402.移掉K位数字
这里算是比较难了。一个思路难,单调栈加贪心。自己想的时间复杂度会比较高。

lc128. 最长连续序列
这个需要你会灵活的写并查集。或者用set解题。

s.startsWith()

lc718. 最长重复子数组
很多类似的两个字符串或者两个数组都是用的dp。算是较为模糊的题吧。

lc440. 字典序的第K小数字(需要练练)
hard,我觉得吧难度在没有很难搞个例子出来模拟,单看代码还是不复杂的。

数组排序要转换成包装类型才能自定义排序。

lc498. 对角线遍历
简单的就是循环,然后简单解法就是将两边的三角形加进来,但是满足矩形范围才算数。

lc329. 矩阵中的最长递增路径
正常的搜索是需要保存一个visited路径状态信息来防止有环无限搜索,但是这里不需要,因为不会访问路径中已经访问的节点,它是递增的。在此基础使用记忆化就行了。记忆化只需要设置方法返回值并且加缓存。

lc460lfu
主要需要记map的value节点存了什么,节点存key,value,频次。然后每个频次还要保存一个双向链表来保证删除最近最久未使用。

堆排序要记得结构,完全二叉树,用索引代替表示树中的位置。

lc862. 和至少为 K 的最短子数组
前缀和加单调队列,比较难想到最优解。第二次遇到单调队列。

剑指 Offer 51. 数组中的逆序对
印象深刻,归并排序

lc670. 最大交换
稍微思考一下

lc295. 数据流的中位数
很多题目分奇偶,那我们面试可以先只考虑简单的偶数情况。瞬间难度降低了不少。

lc887. 鸡蛋掉落
难以理解,算了。

lc264. 丑数 II
用堆很简单。。

lc85. 最大矩形
和另一个正方形的不同,那个可以直接dp,这个要每一层循环做判断。

KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第八个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法的C++代码实现:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值