8.20:
反转链表
反转链表Ⅱ
k个一组反转链表
二叉树中序遍历 非递归
二叉树层序遍历 非递归
二叉树前序遍历 非递归
二叉树后序遍历 非递归
二叉树后序遍历 递归
8.21
岛屿数量
8.22
两数之和
字母异位词分组
最长连续序列
移动零
盛水最多的容器
三数之和
接雨水
无重复字符的最长子串:滑动窗口+哈希表
找到字符串中所有字母异位词
8.23
和为k的子数组:前缀和 + 哈希
滑动窗口最大值:单调栈
最小覆盖子串:滑动窗口 + 哈希
最大子数组和:一维dp
合并区间:模拟
轮转数组:模拟
螺旋矩阵:模拟
搜索二维矩阵:两次二分
链表相交:双指针模拟
反转链表:三个指针
反转链表Ⅱ:三个指针 + 三个不变量
k个一组反转链表:三个指针+四个不变量
回文链表:快慢指针找中点+反转链表
8.24:
环形链表:快慢指针
环形链表Ⅱ:快慢指针+结论:从相遇点和head起始指针
合并两个有序链表:双指针+模拟
两数相加:大数相加链表版
删除链表的倒数第N个节点:快慢指针+模拟
两两交换链表中的节点:2个一组反转链表
随机链表的复制:哈希表固定做法
每日温度:单调栈
排序链表:链表的归并排序
合并k个升序链表:优先队列模拟最小堆+lambda表达式书写比较器
二叉树的最大深度:简单递归
翻转二叉树:简单的dfs / bfs,可以实现递归/非递归 dfs bfs
9.2
反转链表Ⅱ: 设置不变量pre cur nxt p0, 完成k个反转,置p0->next->next / p0->next
数组中的第k大元素:优先队列模拟小根堆<元素,容器,比较器> <int,vector<int>,greater<int>>
岛屿数量:dfs,遍历每一个节点,判断合法性之后进行染色,然后dfs
反转链表:设置不变量pre cur nxt, 反转即可
长度最小的子数组:滑动窗口解决,维护i for循环遍历右边界,维护l变量左边界,满足值之后再缩小左边界
括号生成:backtracking回溯模板题,依据left < right来剪枝以及设置返回条件
重排链表: 快慢指针找到中间节点,反转后半段链表,然后cur1 cur1_nxt cur2 cur2_nxt模拟即可
排序链表:链表的归并排序,快慢指针找到中点 fast = head->next,中点处断开,归并递归,然后合并两个升序链表即可。
排序数组:数组的归并排序,直接l+r>>1找到中点即可,左右归并排序完,合并两个有序数组即可。
排序数组:数组的快速排序模板,设置x为nums[l],然后设置i,j,设置while循环,最后quick_sort左右区间
爬楼梯:dp入门题目,注意n = 1/ 2特殊判断即可
最长递增子序列:设置dp[i]为以第i个元素结尾的最 长递增子序列长度,双重循环,内部循环为j = 0; j < i,来dp[i] = max(dp[i],dp[j]+1)来更新长度
9.3
括号生成:经典回溯解决,回溯每一个位置是放左括号还是右括号,然后通过left > right剪枝
无重复字符的最长子串:哈希表+滑动窗口,set保存窗口内元素,维护l r左右边界,每次进入循环查看r元素是否在哈希表内,不在即r++,否则弹出l元素
轮转数组:首先记得对k取模,之后先反转所有元素,然后反转前半段和后半段即可
被围绕的区域:图的dfs遍历,先搜索边缘四个边的区域,dfs为O的节点更改为占位符,然后再遍历整个图,将不是占位符的所有位置置为X
二叉树的锯齿型遍历:正常二叉树的层序遍历,维护flag判断奇偶进行翻转某一层的tmp
寻找旋转排序数组中最小值:二分查找即可,nums[mid]>nums[nums.size()-1]这样作为参考值。要考虑全递增的情况和只有两个元素的情况
9.4
最长递增子序列:设置dp[i]为i元素结尾的最长递增子序列的长度,设置双重循环,更新dp[i] = max(dp[i],dp[j]+1) ,每轮更新res
验证二叉搜索树:二叉搜索树中序遍历是有序的,可以递归中序遍历一波,然后判断是否有序
验证二叉搜索树:使用stack实现的非递归中序遍历,循环while(!st.empty() || cur != nullptr) 事先设置好cur = root进行操作
回文子串:二维dp,设置dp[i][j]为区间[i,j]是否为回文,然后递推关系需要dp[i+1][j-1],所以需要遍历顺序为从下到上从左到右
接雨水:设置leftmax和rightmax,每次进入循环更新leftmax和rightmax,每次移动短的那个,所以left和right中间有一个是当前遍历最大的那个,可以算出left或者right处的接水数量
最长连续序列:哈希表unordered_map<int,int>存储<当前元素,是否出现过>,每次取一个元素左右寻找元素,记录长度
9.5
重排链表:记住即可。先快慢指针找到中点,然后翻转后半部分的链表,最后设置cur1,cur1_nxt,cur2,cur2_nxt进行while(cur2->next)循环即可
排序链表:链表的归并排序,记住最开始判断if(!head||!head->next) return head;记住这里的快慢指针slow = head, fast = head->next. 记住 ListNode * left = sortList(slow) ,ListNode * right = sortList(temp)
数组中的第k大元素:优先队列模拟堆排序,O(nlogk)时间复杂度,当k比较小的时候趋近于O(n)
排序数组:手撕快速排序,quick_sort(nums,l,r) 设置x = nums[l], 然后设置i = l - 1, j = r + 1
设置循环即可,最后分治递归左右片段quick_sort(nums,l,j) quick_sort(nums,j+1,r);
最长回文子串:二维dp,dp[i][j]为区间[i,j]是否为回文。遍历顺序从下到上,从左到右。条件判断为:s[i] == s[j],还有j - i < 3. 最后维护长度,s.substr(begin,len);
9.8
最小差:排序后双指针,差值可能会int类型越界,res设置为LONG_MAX类型,每次++较小元素的指针,绝对差值计算abs((long)a[i] - (long)b[j])
最大子数组和:设置一维dp[i]为第i个元素结尾的最大子数组和,然后进入遍历,若dp[i-1] < 0 dp[i] = nums[i] 若dp[i-1] >=0 dp[i] = dp[i-1] + nums[i]
无重复字符的最长子串:哈希表+滑动窗口, 每次进入循环模板为if(find) insert else erase
二叉树的最近公共祖先:记住做法即可。祖先要么为p q 要么为第一个实现p q 在其两侧的节点。
记忆代码即可
二叉树的最大路径和:二叉树的最大链路和模板,最大路径和为(左/右)最大链路和 + 当前节点值,只需要遍历二叉树得到每一个节点的最大路径和然后记录res即可。 注意可能为负数,所以最大链路和可以为0.以及res一开始初始化为INT_MIN
分割等和子集:01背包模板(是否能装满背包类问题) 初始化为0,先物品后背包,物品正序,背包倒叙,int j = 容量, j >= 当前物品重量
最后一块石头的重量Ⅱ:01背包模板(背包最多装多少的问题),初始化为0,先物品后背包,物品正序,背包倒序,int j = 容量, j >= 当前物品重量
目标和:01背包模板(背包装满有多少种方法) 背包dp[0] = 1,其他为0,先物品后背包,物品正序,背包倒序,dp[j] += dp[j-nums[i]] 返回dp[最大容量]即可