突然发现虽然刷了很多算法,但是能力并没有得到提高,刷过的题也忘了很多,欲速则不达是真的,距离9月秋招开始差不多还有两个月吧,静下心来慢慢回顾总结,也刷一刷名企真题,持续更新,希望有帮助。按部就班最快,心平气和最燃 |
---|
1 一个左指针,一个右指针。其中左指针用于缩小范围,右指针用于扩大搜索范围。一般求滑动窗口的最小值都是在缩小左指针的时候取得的。
2 右指针扩展的条件时:只要当前还没有满足条件,就暴力增长,直到第一次满足条件为止。
3 左指针收缩的条件:只要当前指针的缩小还没影响窗口的可满足性,就一直暴力向左增长。一但当前指针向前移动的时候影响了窗口的可满足性,就记录下当前的窗口大小,并更新目前为止满足条件的最小窗口记录。之后,再次扩展右指针,使得窗口满足题目的条件。
这也是自己比较熟练的一个算法,以前用这个算法对华为的一道机考题进行了优化,将时间复杂度由传统方法的O(m*n)降低到了O(n)。
博客链接
参考例题
生成窗口最大值数组 牛客网链接>>>>>>答案
最大值减去最小值小于或等于num的子数组数量 牛客网链接>>>>>>答案
最短包含子串长度/最小覆盖子串(待完善)
双指针的基本思想是使用两个指针串联迭代数据结构,知道一个或两个指针达到某个条件停止。在排序数组或链表中搜索元素对时,两个指针通常很有用, 例如将数组的每个元素与其他元素进行比较时。
双指针问题又可以分为指针在两端向中间行驶和指针在一侧向另一侧行驶问题
参考例题
4-sum 3sum-closest 3-sum
最长无重复子串
长度最小的子数组
蓄水池问题
也被称为“龟兔算法”,基本思想是使用两个指针以不同的速度在数组或链表中移动。在处理循环链接列表或数组时,此方法非常有用。通过以不同的速度移动(例如,在循环链表中),算法证明两个指针必然会相遇。一旦两个指针都处于循环循环中,快速指针就应该捕获慢速指针。
应用举例(这一部分比较简单,注意边界条件即可)
链表或数组循环
用于找中间元素
需要知道某个元素的位置或链表的总长度
合并间隔模式是处理重叠间隔的有效技术。在涉及间隔的许多问题中,你可以需要找到重叠间隔或合并间隔(如果它们重叠)。给定两个间隔 a和 b,可能存在6中不同的间隔交互情况:
应用举例
区间重叠问题
区间列表的交集
借助HashMap的问题
添加链接描述
循环排序模式描述了一种处理涉及包含给定范围内的数字的数组问题的有趣方法。其一次遍历数组一个数字,如果正在迭代的当前数字不是正确的索引,则将其与正确索引处的数字交换。
应用举例
第一个缺失的正整数(有正有负循环排序代码比直接排序代码简单)
缺失数字(有很多种解题方案,循环排序方法的复杂度最优)
寻找重复数据(其实笔试的过程中可以用空间换时间和代码复杂度)
在许多问题中,可能会要求我们反转链表的一组节点之间的链接。通常,约束就是需要就地执行此操作,即使用现有节点对象而不使用额外内存。这是上述模式有用的地方。此模式一次反转一个节点,从一个指向链表头部的变量(当前)开始,一个变量(上一个)将指向已处理的上一个节点。以锁步方式,将通过将当前节点指向前一个节点,然后再转到下一个节点来反转当前节点。此外,更新变量“previous”以始终指向您已处理的上一个节点。
应用例题
添加链接描述
添加链接描述
在许多问题中,给出了一系列元素,需要我们将其分成两部分。为了解决这个问题,我们想要知道一个部分中的最小元素和另一个部分中的最大元素。这种模式是解决此类问题的有效方法。这种模式使用两个堆:找到最小元素的Min Heap和找到最大元素的Max Heap。该模式的工作原理是将前半部分的数字存储在Max Heap中,这是因为我们希望在上半部分找到最大的数字。然后将数字的后半部分存储在Min Heap中,因为我们希望在后半部分找到最小的数字。在任何时候,可以从两个堆的顶部元素计算当前数字列表的中值。
应用例题
窗口的中位数–利用优先队列
leetcode253. 会议室II(java):最小堆(非常常见的一道题 高频高频)
数据流的中位数
分金条的最小花费
做项目的最大收益
其实这个问题可以归为顶堆问题,由于更高频所以单独讨论,任何要求我们在给定集合中找到最大/最小/频繁“K”元素的问题都属于这种模式。
跟踪’K’元素的最佳数据结构是Heap。这种模式将利用Heap来解决从一组给定元素一次处理’K’元素的多个问题。大致思路是这样的: 根据问题将’K’元素插入到最小堆或最大堆中; 迭代剩余的数字,如果找到一个比堆中的数字大的数字,则删除该数字并插入较大的数字。
Top-K 数字频率问题代码
class Solution {
public int[] topKFrequent(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
PriorityQueue<Map.Entry<Integer, Integer>> maxheap = new PriorityQueue<>((a,b) -> b.getValue() - a.getValue());
int[] result = new int[k];
for(int i = 0; i < nums.length; i++){
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
for(Map.Entry<Integer, Integer> m : map.entrySet()){
maxheap.offer(m);
}
for(int i = 0; i < k; i++){
result[i] = maxheap.poll().getKey();
}
return result;
}
}
词频Top-K问题代码(注意一下比较器的定义)
class Solution {
public List<String> topKFrequent(String[] words, int k) {
Map<String, Integer> count = new HashMap();
for (String word: words) {
count.put(word, count.getOrDefault(word, 0) + 1);
}
PriorityQueue<String> heap = new PriorityQueue<String>(
(w1, w2) -> count.get(w1).equals(count.get(w2)) ?
w2.compareTo(w1) : count.get(w1) - count.get(w2) );
for (String word: count.keySet()) {
heap.offer(word);
if (heap.size() > k) heap.poll();
}
List<String> ans = new ArrayList();
while (!heap.isEmpty()) ans.add(heap.poll());
Collections.reverse(ans);
return ans;
}
}
应用例题
前K个高频元素
前K个高频单词
K-way Merge可以用于解决涉及一组排序数组的问题。给出’K’排序数组,可以使用Heap有效地执行所有数组的所有元素的排序遍历。我们可以在Min Heap中push每个数组的最小元素以获得最小值。获得总体最小值后,将下一个元素从同一个数组推送到堆中。然后,重复此过程以对所有元素进行排序遍历。
应用例题
合并K个排序链表
计算小和
参考文献
从名字上就听的出来,单调栈中存放的数据应该是有序的,所以单调栈也分为单调递增栈和单调递减栈
单调递增栈:栈中数据出栈的序列为单调递增序列
单调递减栈:栈中数据出栈的序列为单调递减序列
stack<int> st;
//此处一般需要给数组最后添加结束标志符,具体下面例题会有详细讲解
for (遍历这个数组)
{
if (栈空 || 栈顶元素大于等于当前比较元素)
{
入栈;
}
else
{
while (栈不为空 && 栈顶元素小于当前元素)
{
栈顶元素出栈;
更新结果;
}
当前数据入栈;
}
}
应用例题
视野总和
柱状图中最大矩形解答
柱状图中最大矩形
左程云书籍单调栈问题链接—其实把这个搞懂,其他的都是这个题的变形
文章参考自 educative 参考文献链接
在另外一篇博客中
从经验贴和自己的面试经验中可以看出,大厂的面试官其实都很和蔼,他们只是想快速地找出适合在公司工作的人,并不想为难我们,所以平时多刷题很重要,面试中的问题一般都是leetcode的原题或者变型题 |
---|
1.栈排序
单调栈问题,上文有说明;
2.链表实现队列
https://blog.csdn.net/qq_21808961/article/details/76239225
3.最长连续递增序列(leetcode-674)
https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence/
4.二维数组的打印问题(回行打印 环形打印 之字打印)
5.根据数组建立二叉排序树(平衡和非平衡两种)
https://blog.csdn.net/Danielntz/article/details/53418843
6.一个数组实现两个栈(共享栈问题)
7.二叉树宽度与深度
深度求解就是一个递归的过程,求宽度就采用按层遍历即可。宽度优先遍历也可求出深度。
8.二叉树是否对称(二叉树的一系列递归问题都应该掌握)
9.链表m到n反转和每k个一组进行旋转
https://www.nowcoder.com/practice/b49c3dc907814e9bbfa8437c251b028e?tpId=46&&tqId=29154&rp=1&ru=/ta/leetcode&qru=/ta/leetcode/question-ranking
10.贪心算法:N位数删除K个数字,使剩下的数字串最小
11.N皇后问题
12.找出来数组中每个元素后边第一个比它大的值(单调栈问题)
13.给你一个二叉树,从上往下看,然后左往右顺序输出你能看到节点,同一个竖直方向上上面的节点把下面的节点遮挡住了
14.链表反转,分别用遍历与递归实现(突然发现递归还挺有意思)
https://www.jianshu.com/p/b2542324898e
15.完全二叉树的最大深度与节点个数(左程云书上原题)
https://blog.csdn.net/qq_14842117/article/details/99864875
16.两个栈实现队列/两个队列实现栈
17.有序数组的交集和并集
https://blog.csdn.net/iteye_12801/article/details/82280726
18.删除链表中的重复值节点(包括保留问题和不保留问题)
https://www.nowcoder.com/practice/c087914fae584da886a0091e877f2c79?tpId=46&&tqId=29096&rp=1&ru=/ta/leetcode&qru=/ta/leetcode/question-ranking
https://www.nowcoder.com/practice/71cef9f8b5564579bf7ed93fbe0b2024?tpId=46&tags=&title=&diffculty=0&judgeStatus=0&rp=1&ru=/ta/leetcode&qru=/ta/leetcode/question-ranking
19.LeetCode 200. Number of Islands 岛屿的数量
20.二叉搜索树转有序双向链表(剑指offer原题)
21.回溯法-字符串全排列 ,可能有重复的,要去重
22.二叉搜索树第k个节点,不用中序遍历
23.有序数组查找重复元素个数
24.数组实现队列(大话数据结构中的实现非常好)
https://www.iteye.com/blog/jim8757-2060050
25.用二分法求开方
https://blog.csdn.net/u011489043/article/details/70126041
26.判断一颗树是不是二叉搜索树
27.链表第k-1个节点
28.手撕快排(不要低估基础算法)
29.二分法的一系列问题(不要低估基础算法)
30.数组中乘积最大的三个数
高端食材往往采用最简单的烹饪方法,算法也是。。。
https://blog.csdn.net/tjumiao/article/details/81189269?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-4.nonecase
31.求二叉树的深度,不使用递归(二叉树的问题挺高频)
32.实现链表,无序链表,对链表值奇偶分离并排序,空间复杂度O(1)
33.单调不递减数组,给一个target,找出大于等于target的下标index
34.单调不递减链表,删除掉重复值
35.无序数组构建一棵二叉排序树
36.行和列都是有序的二维矩阵找一个target值
37.是否是回文链表
38.打印出根节点到叶子节点的最长路径
39.不严格递增数组,要求删除出现次数大于k的数字,要求不要新建存储空间
40.链表相邻元素交换(跟每k个进行旋转的是同一个问题)
41.二叉树的最小公共祖先
42.输出根节点到叶子节点路径之和为target的路径列表(剑指offer原题)
https://www.nowcoder.com/practice/b736e784e3e34731af99065031301bca?tpId=13&&tqId=11177&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
43.【LeetCode】1038. 从二叉搜索树到更大和树
一道反向中序遍历的问题
https://blog.csdn.net/rabbitsockx/article/details/104350858
44.任意一个整型数组,判断是否可以将数组分为三个区间,每个区间中数值的和相同(荷兰国旗问题)
45.一个已经排序的数组,去除里面重复的元素 (leetcode中有个类似的问题:去重的时候元素可以有两个数是重复的,如果有三个以上的重复元素那么就留下两个比如:3333 去重后为33)
https://blog.csdn.net/feeltouch/article/details/45077589
46.错位的全排列(第一位不能是1,第二位不能是2)
47.k路链表合并
https://www.nowcoder.com/practice/65cfde9e5b9b4cf2b6bafa5f3ef33fa6?tpId=46&&tqId=29156&rp=1&ru=/ta/leetcode&qru=/ta/leetcode/question-ranking
48.二叉树的左视图 右视图问题(都可以根据二叉树的按层遍历解决)
49.输入一个数字n,构建一个完全二叉树并输出