力扣刷题笔记个人总结版(优化与实现综合)
128.最长连续子序列【数组】:用集合存储数组元素,遍历数组,前一个数字存在则跳过,不存在则统计长度
15.三数之和【双指针】:数组排序后,固定第一位数字,双指针求另外两数之和,注意重复可跳过情况
42.接雨水【双指针】:记录左右指针的最高记录高度,每次移动高度小的指针:如果高度比最高纪录大则更新,小则更新容量=原容量+(最高纪录-当前高度)
438.找到字符串中所有字母异位词【滑动窗口】:用两个数组来统计字符串中字母的个数来判断两个字符串异位(s.charAt(i)-‘a’)
560.和为K的子数组【前缀和】:用一个哈希表存储数组0~length的前缀和,如果当前Sum-k数存在(即当前数组和减去这些前缀数就是符合条件的子数组),则结果数量加上前缀i的个数,更新前缀和
239.滑动窗口的最大值【优先队列】:利用优先队列(堆)存储窗口内的元素和下标,每次滑动时添加元素进入队列,然后取出堆顶元素,不在窗口内则移除队列,在窗口内则加入结果集
76.最小覆盖子串【滑动窗口】:用两个哈希表分别存储窗口和目标字符和数量,左右指针指向当前窗口边界。右边界扩张,如果遇到目标字符则存入哈希表并数量加一,如果加入后数量等于目标数量,则使得有效计数加一,然后判断有效计数是否达到目标哈希表的大小,达到则证明满足条件,判断长度并进行左边界收缩,如果收缩的是目标字符,则判断收缩后该字符数量是否等于目标数量,不等于则使得有效计数减一。
41.缺失的第一个正数【三次遍历】:第一次遍历将负数转换为数组长度N+1,第二次遍历将正数(小于N+1)对应的数组下标位置的数转换为负数,第三次遍历,如果有正数则输出结果,没有则输出N+1;
56.合并区间【排序】:先将区间按左边界排序,然后遍历区间,如果是第一个区间或当前区间的左边界大于结果集中最后一个区间的右边界,则创建新区间加入结果集,否则当前区间与结果集中最后一个区间合并。
57.矩阵置零【矩阵】:两次遍历,一次记录零数据的行和列,二次将记录的行或列上元素置零(进阶:用矩阵的第一行和第一列代替两个标记数组)
54.螺旋矩阵【矩阵】:定义上下左右边界,依次加入
48.旋转图像【矩阵】:循环每层,从左到右利用公式(i, j) → (j, n-1-i) 对每层进行n次交换,每次交换四个位置的数,n为当前矩阵的阶数(此时n=left+right+1)
234回文链表【链表】:使用快慢指针找到中间节点,然后将中间节点后半部分链表翻转,双指针比较
2.两数相加【链表】:构建新链表,从两个链表头节点遍历相加,为空的那个视为零
24.两两交换链表中的节点【链表】:递归调用,记录新头节点,让原头节点的next指向后续交换后的新头节点
25.K 个一组翻转链表【链表】:递归调用,每次遍历K个节点,使用虚节点连接下一顺序节点,然后依次调整翻转K个节点
148.排序链表【归并排序】:递归使用快慢指针划分左右子链表,排序然后合并两个有序子链表
146.LRU缓存【链表】:使用哈希表和链表存储元素进行实现,链表自定义节点,并记录头节点和尾节点(虚)
101.对称二叉树【递归】:递归检查两个节点是否相等(对称节点比较)
98.验证二叉搜索树【递归】:设置上下限,递归检查左右子树
114.二叉树展开为链表【前驱节点】:标记当前节点,如果当前节点存在左节点,则标记为下一个节点,然后寻找下一节点的最右节点,将该节点的右指针指向当前节点的右指针,然后将当前节点的左子树转换为右子树,检查下一节点
437.路径总和 III【前缀和】:利用Map存储当前路径下的前缀和以及出现次数,深度遍历树节点,利用当前路径和减去目标数出现的路径次数获取符合条件的结果,同时将该路径和放入Map集合,向下遍历,当返回时该前缀和减一。
236.二叉树的最近公共祖先【dfs】:二叉树的最近公共祖先一定满足条件:1.左右子树中包含两个节点 2.本身是其中一个节点,左右子树中包含另一个节点。用两个标志位代表左右子树包含情况,深度遍历树。
124.二叉树中的最大路径和【dfs】:记录最大路径和,深度遍历树,路径和为左右子树的最大贡献加上节点的值,更新记录,返回最大贡献值(节点加上左右子树中最大贡献)
207.课程表【拓扑排序】:使用邻接表存储边,深度遍历未完成的节点,当遍历过程中访问重复节点时(当前路径下)则判断为false,成功完成所有节点时为true
79.单词搜索【回溯+dfs】:遍历每个节点进行dfs和回溯,如果为最后一个字符,标记结果为true,如果字符不符合条件直接返回,满足条件则修改当前字符为特殊字符(标记已访问,回溯后需要改回来),再对四个方向进行深度遍历。
208.前缀树【26叉树】:利用一个长度为26的数组记录子节点,以及标志位记录是否为结束节点
51.N 皇后【回溯】:记录列和正负对角线是否存在棋子,从每一行开始遍历列检查冲突和放置棋子,回溯。
4.寻找两个正序数组的中位数【排除法】:转换为求两个数组中第k小的数(k即中位数),使用排除法,每次比较两个数组中k/2-1处的的元素大小,以此可以排除较小数组中的前k/2-1个元素。
394.字符串解码【栈】:用一个栈记录数字,一个栈记录字符,遍历字符串,记录当前数字和当前字符串,遇到’[‘时将当前数字和当前字符串先入栈,遇到’]'时出栈一个数字n,并重复此时字符串n次,并添加到栈顶字符串后。
84.柱状图中最大的矩形【栈】:使用单调递增栈,遍历元素,弹出栈顶比当前元素大的元素,并计算面积,高度为弹出的柱子,宽度为左边界。
347.前K个高频元素【堆】:使用一个Map统计数字及频率,然后利用迭代器将结果记录到一个List中,最后对这个List建堆,调整和取出结果。
139.单词拆分【动态规划】:用集合当作字典,利用动态规划数组记录字符串s中0~i处的字符是否能被分割,遍历字符串,如果前半段能被分割且后半段字符在字典中,记录动态规划数组为true。
416.分割等和子集【动态规划】:计算半值(等和),使用二维数组记录前N个数中可以达到目标数的情况(背包问题)
32.最长有效括号【动态规划】:使用数组记录当前字符长度下的最长有效长度(包含本字符),如果该字符为(则有效长度为0,字符为)通过前一个字符判断,前一个字符为(则长度为前前字符长度+2,为)则判断前一个有效字符之前是否为(;
72.编辑距离【二维动态规划】:用二维数组记录两个字符数组中的最小距离,初始化当某个字符长度为0时,所需操作数为另一个字符的长度,进行迭代:当两个字符数组中最后一个字符相等时,dp等于前置条件的最小距离;不相等时,等于3中情况下的最小值。
274.H 指数:排序后遍历,如果当前数组元素大于长度,则更新指数
135.分发糖果:先从左遍历,维护左数组,当大于左边时糖果等于左边糖果数+1,然后从右遍历,当大于右边时糖果等于原糖果数和右边糖果数+1的最大值(保证糖果不会少),统计糖果数
902.最大为 N 的数字组合【数位动态规划】:先统计少于N位的数量(必小于目标数),再统计位数等于N的数量(动态规划,dp[i][2]统计前i位小N和等于N的数量)
82.删除排序链表中的重复元素 II:双指针结合虚节点,一个指针指向当前有效节点的尾部(prev),一个找下一个不重复的节点
14.最长公共前缀:纵向对比
28.找出字符串中第一个匹配项的下标:KMP待学
ACM模式
importjava.util.*;importjava.io.*;importjava.lang.*;publicclassMain{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);while(scanner.hasNextInt()){intn=scanner.nextInt();System.out.println("读取到数字: "+n);}scanner.close();}}~~~