本人今年应届刚入职杭州某IT企业,日常工作中深感自身算法和代码能力薄弱,之前找工作虽然也刷过leetcode,但找到工作后并没有坚持下来,因此想开个刷题专栏监督自己,希望能够提升自身coding能力~ 如有错误或者更优解法,还请评论指出~
本文为刷题前在网上寻觅的刷题计划及分类总结,觉得非常有用,打算按照题目tag来刷,先刷每个tag中的easy和medium题。
本文参考博客园的“fish1996”大佬写的博客,感谢大佬的分类总结。因为本人喜爱markdown的风格,因此将其改写成了markdown格式,以便进行检索,后续根据刷题进程不断细分类别,希望能够对大家有所帮助。
1 https://leetcode-cn.com/problems/two-sum/
初始化1个hashmap,一次遍历即可完成。判断target - nums[i]是否在hashmap中,如果在就返回结果,如果不在就将nums[i]插入到hashmap中。
26 https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
单指针法/双指针法进行数组去除重复元素
35 https://leetcode-cn.com/problems/search-insert-position/
经典二分法,需要注意边界条件
3 https://leetcode.com/problems/longest-substring-without-repeating-characters/
维护一个不含重复字符的滑动窗口。需要记录每个字符最后出现的位置,当遇到重复字符的时候,就把窗口首部调到上一次出现这个字符的下一个位置。
76 https://leetcode.com/problems/minimum-window-substring/
滑动窗口题。维护一个包含t中所有字符的最小滑动窗口,首先用一个hashmap记录所有t中的字符和出现次数,在s中每遇到一次计数器加一,找到了符合条件的窗口后,尝试向右移动窗口左指针,直到恰好能够满足条件为止。更新当前最小滑动窗口。
209 https://leetcode.com/problems/minimum-size-subarray-sum/
维护一个大于等于sum的最小滑动窗口。
239 https://leetcode.com/problems/sliding-window-maximum/
求滑动窗口中的最大值。(1) 使用ordered_map,动态更新,取首元素, NlogK。(2) 维护一个指向最大值的指针,当指针不再在窗口内时,向后移动这一指针到合适的位置。最坏时间复杂度是O(NK),但均摊表现比1还要好。(3)使用单调队列,维护单调递减的队列,队首不再在窗口内时弹出队首,有更大的元素弹出队尾。当前最大元素为队尾元素。接近O(N)。
424 https://leetcode.com/problems/longest-repeating-character-replacement/
维护一个最多包含k个额外字符的滑动窗口。需要记录当前出现次数最多字符的出现次数来判断窗口是否合法,如果超过了,就把首指针向后挪一位,同时更新最多出现次数。对每个合法窗口,取其中的最大值。
438 https://leetcode.com/problems/find-all-anagrams-in-a-string
主要思路是维护两个hashmap,一个记录期望出现的字符,一个记录当前出现的字符。当前出现的字符随着窗口滚动不停更新,每次移动窗口后,都判断当前窗口是否满足条件。同时维护一个满足条件的count变量,通过比较当前出现字符和期望出现字符的个数来更新,当count等于期望字符串的长度时,意味着当前窗口满足条件。
480 https://leetcode.com/problems/sliding-window-median/
求滑动窗口的中位值。可以维护一个mutilmap。
576 https://leetcode.com/problems/permutation-in-string/
同438。
904 https://leetcode.com/problems/fruit-into-baskets/
查找最多出现k个字符的最大滑动窗口。可以维护一个包含所有字符出现最后下标的哈希表,每次查到数字超过k个,就把begin指针移到最小的最后出现下标的下一个。
978 https://leetcode.com/problems/longest-turbulent-subarray/
检查前后两个数字是否满足大于或者小于的关系,如果满足计数器加一,否则清空。扫描两次处理奇数偶数情况。
992 https://leetcode.com/problems/subarrays-with-k-different-intergers
计算滑动窗口中恰好出现k个不同字符的窗口数目。这道题的一个可以通过的暴力算法是n2的,找到一个满足条件的滑动窗口后,把begin指针后移,直到不到满足为止。统计出现个数。我们需要维护一个可以快速找到k个数字中,最后出现位置最早的那个数字出现的位置,使我们能够快速移动begin指针。
1004 https://leetcode.com/problems/max-consecutive-ones-iii/
维护最多包含k个0的滑动窗口,一旦超过了k个0,把队首的0 pop出来。不断更新当前滑动窗口中的数据个数,并取最大值返回即可。
31 https://leetcode.com/problems/next-permutation/
找到下一个排列数。从右到左找到第一个nums[ i ] < nums[ i + 1]的pair,然后在后面找到比nums[ i ] 大的最小数字,把它交换过来。i 之后的数字也一一交换。
46 https://leetcode.com/problems/permutations/
输出所有排列数。递归中,最快的方法是直接交换,实际上执行的是选择操作,选择了一个数据后,把它交换到前面;可以保证下一次选择不会包含着一数字,并且数字被选择的概率都是相等的。
47 https://leetcode.com/problems/permutations-ii/
输出所有的排列数(带重复)。在选择的时候,使用hashmap记录在位置i处选过的数据,避免选择了重复的数据。
60 https://leetcode.com/problems/permutation-sequence
求第k个排列数。数学解法,可以找一下规律。比如对于1234的排列数,一共有24种。我们从左到右依次决定排列数是哪些。首先第一个数有4种可选的,一共有24种,那么每种就是6个,我们用 k / 6,看它落在哪个区间,就取哪个数字。
之后,还有三个数可选,因为一共有6种,所以每种有2个,我们计算k / 2……以此类推得到所有位的数字。因为k从0计数算起来更简单,所以我们一开始做k–。
996 https://leetcode.com/problems/number-of-squareful-arrays/
这道题要求找到满足条件的排列数个数。可以在生成排列数的同时检查是否满足条件。
求最大面积的:题号85(最大面积矩形) 221(最大面积正方形) 1139(最大面积边框正方形)
5 https://leetcode.com/problems/longest-palindromic-substring/
爬台阶类型问题。考虑字符串的中心字符会更加方便,为了处理奇数和偶数,可以开成2 * n - 1的dp。或者直接从中心往两边扩展,查找最长的。
10 https://leetcode.com/problems/regular-expression-matching/
匹配类型问题。状态方程稍微有些麻烦,如果当前匹配(包括.匹配),则从i - 1, j - 1转换到i ,j ,但如果当前匹配为 ,因为可代表匹配0个,可选择匹配或不匹配。
32 https://leetcode.com/problems/longest-valid-parentheses/
最长子串类型问题。
44 https://leetcode.com/problems/wildcard-matching/
匹配类型问题。
62 https://leetcode.com/problems/unique-paths/
爬台阶类型问题。从上方或左方汇总结果。
63 https://leetcode.com/problems/unique-paths-ii
爬台阶类型问题。从上方或左方汇总结果,有障碍则不汇总。
64 https://leetcode.com/problems/minimum-path-sum/
爬台阶类型问题。从上方或左方叠加最小值。
72 https://leetcode.com/problems/edit-distance/
爬台阶类型问题(2D)。要么选择替换,要么选择添加一个,选择其中转换次数最小的。
85 https://leetcode.com/problems/maximal-rectangle/
最大面积问题。先计算每一列的前缀和,可以把每一行看作横坐标,当前的值看作高度,得到一个直方图一样的东西,接下来只需计算直方图中的最大矩形面积。时间复杂度O(N3),用单调栈做是O(N2)
87 https://leetcode.com/problems/scramble-string/
记忆化搜索。在所有可能的交换结果中找是否存在满足条件的。
91 https://leetcode.com/problems/decode-ways
爬台阶类型问题。当前要么解析一个字节,要么解析两个字节。
95 https://leetcode.com/problems/unique-binary-search-trees-ii/
记忆化搜索。权值在(i, j) 之间的树可以存起来,作为更大的树的子树。
96 https://leetcode.com/problems/unique-binary-search-trees-ii/
爬台阶类型问题。同上,但无需存储所有结果了。从左右子树汇总结果。
97 https://leetcode.com/problems/interleaving-string/
匹配类型问题。需从多种选择中找到满足条件的。
115 https://leetcode.com/problems/distinct-subsequences/
匹配类型问题。
120: https://leetcode.com/problems/triangle/
爬台阶类型问题。相当于带权重的一次爬台阶。
123 https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/
分治。分成两部分,叠加两边最大的结果。
132 https://leetcode.com/problems/palindrome-partitioning-ii/
划分类型问题。先计算出所有可能的回文串,dp[ i ] 代表前 i 个字符的最小划分,找到以 i 结尾的所有回文串,取划分最小的那个作为结果。
139 https://leetcode.com/problems/word-break/
划分类型问题。
140 https://leetcode.com/problems/word-break-ii
划分类型问题。和139差不多,但是有些test case 实在太烦人了。
152 https://leetcode.com/problems/maximum-product-subarray
多状态转换类型问题。需要维护当前的最大值和最小值,在两者之间因为正负数可以发生转换。
174 https://leetcode.com/problems/dungeon-game/
爬台阶类型问题。但是需要从终点到起点反向求解,才能得到合法的递推关系,记录的是到达当前位置需要的hp。
188 https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/
多状态转换类型问题(带次数限制)。存在手上持有股票和手上不持有股票状态,多了一个最大k次交易的限制条件,因为在状态转移方程中,需要多考虑一个k的维度。
213 https://leetcode.com/problems/dungeon-game/
多状态转换类型问题。需要考虑当前偷,当前不偷,第一次偷了,第一次没偷。
221 https://leetcode.com/problems/maximal-square/
最大面积问题。看三个重叠的正方形加上当前位置能否凑成更大的正方形。
264 https://leetcode.com/problems/ugly-number-ii/
数字类问题。大的丑数是小的丑数乘以2,3,5得到的,每次选择最小的作为下一个。
279 https://leetcode.com/problems/perfect-squares
数字类问题。查找当前数字减去一个平方数对应的最小拆分次数。
300 https://leetcode.com/problems/longest-increasing-subsequence/
最长子序列问题。经典dp。
304 https://leetcode.com/problems/range-sum-query-2d-immutable/
最大面积问题。类似221。
309 https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/
多状态转换类型问题。持有股票状态,卖出股票状态,冷却状态。
312 https://leetcode.com/problems/burst-balloons
区间题。需要考虑每个区间的长度,从小往大更新。
313 https://leetcode.com/problems/super-ugly-number/
数字类问题。同264。
321 https://leetcode.com/problems/create-maximum-number
分治。左最大 + 右最大的组合中挑一个最大的。
322 https://leetcode.com/problems/coin-change/
背包类型问题。总金额为背包容量,记录每个金额的最小次数。
338 https://leetcode.com/problems/counting-bits
数字类型问题。简单dp。
343 https://leetcode.com/problems/integer-break/
数字类型问题。乘积取最大的。
354 https://leetcode.com/problems/russian-doll-envelopes/
最大子序列问题。二分法做速度会更快。
357 https://leetcode.com/problems/count-numbers-with-unique-digits
数字类型问题。
363 https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k
最大面积问题。同时用到了二分,思考这道题可以先从数组入手,再扩展到矩阵。
368 https://leetcode.com/problems/largest-divisible-subset/
最长子序列和问题。不仅需要求出最长的,还需要输出最长的,所以需要记录路径。
375 https://leetcode.com/problems/guess-number-higher-or-lower-ii
分治。在最优解下,取左右最大的 + k。问题描述让人很困惑,不知道它需要的是最优解下的情况。
416 https://leetcode.com/problems/partition-equal-subset-sum/
背包类型问题。总和的一半为背包总容量,找到能够恰好填满背包的物体。
647 https://leetcode.com/problems/palindromic-substrings/
爬台阶类型问题。回文子串个数,为了处理奇偶回文,可以开一个2 * n + 1长度的dp容器。
650 https://leetcode.com/problems/2-keys-keyboard/
爬台阶类型问题。状态可由上一个因数转换过来。
673 https://leetcode.com/problems/number-of-longest-increasing-subsequence/
最长子序列类型问题。需要开两个数组,在维护最长长度的同时更新最长长度的数量。
714 https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/
多状态转换类型问题。存在手上持有股票和手上不持有股票状态。
740 https://leetcode.com/problems/delete-and-earn/
爬台阶类型问题。根据当前数字和前一数字相差是否为1决定从前一数字转换到当前数字,还是从前前一数字转换到当前数字。
764 https://leetcode.com/submissions/detail/234958158/
计算每个格子四边最长的1。
801 https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/
多状态转换问题。交换和不交换两种。
808 https://leetcode.com/problems/soup-servings
记忆化搜索。直接模拟题意即可,但有一个数学上的trick,并没有想到。
813 https://leetcode.com/problems/largest-sum-of-averages
划分类型问题(带次数限制)。递推考虑的不只是从前i个数字到前i + 1个数字,还需要考虑从划分为k到划分为k + 1组,相当于在后面叠加一组。
877 https://leetcode.com/problems/stone-game/
拿左拿右取最大的那种结果。非递归写法是从后往前推导。
931 https://leetcode.com/problems/minimum-falling-path-sum/
爬台阶类型问题。可以从上一层的左中右选择最小的。
935 https://leetcode.com/problems/knight-dialer
爬台阶类型问题。n + 1长度的从n 长度的累加得到。
956 https://leetcode.com/problems/tallest-billboard
背包类型问题。要点在于记录的是两个背包的差值。
960 https://leetcode.com/problems/delete-columns-to-make-sorted-iii/
最长子序列类型问题。求n个字符串都符合的最长字典序子序列即可。
983 https://leetcode.com/problems/minimum-cost-for-tickets/
背包类型问题。一年总天数为背包容量。
1024 https://leetcode.com/problems/video-stitching/
背包类型问题。片段总长度为背包容量。
1027 https://leetcode.com/problems/longest-arithmetic-sequence/description/
最长子序列类型问题。之前状态可存hash中。
1039 https://leetcode.com/problems/minimum-score-triangulation-of-polygon/
记忆化搜索。需要以边作为子问题划分的基础。
1043 https://leetcode.com/problems/partition-array-for-maximum-sum/
限制长度的划分。注意划分为k个连续集合,和划分的连续集合中最多k个数字,以及划分为k个可不连续的子集的区别。
1048 https://leetcode.com/problems/longest-string-chain/
爬台阶类型问题。从k - 1长度转换到k长度,取其中总长最大的。
背包类型问题(2D)。当前书可以单独放,也可以选择和前面n本一起放。
1139 https://leetcode.com/problems/largest-1-bordered-square
最大面积问题。类似85,由于是边框问题,要同时考虑横向累积和纵向累积,而85只需考虑其中一个就够了。
1143 https://leetcode.com/problems/longest-common-subsequence/
最长公共子序列。经典dp。
1155 https://leetcode.com/problems/number-of-dice-rolls-with-target-sum/
背包类型问题。带次数限制,可多次使用的完全背包。
56 https://leetcode.com/problems/merge-intervals/
先排序,再逐个检查当前区间能否和结果队列中最后一个区间合并。
57 https://leetcode.com/problems/insert-interval/
先把在新区间之前的都加入结果,和新区间存在重叠的取最大最小作为边界,在新区间之后的都加入结果。
435 https://leetcode.com/problems/non-overlapping-intervals/
先排序,一旦检测到重叠,移除end位置比较大的元素。
452 https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/
维护一个当前最小的重叠区域,如果新的区间和这个区间重叠,那么缩小这个区间,否则重置。每重置一次计数加一。
208 https://leetcode.com/problems/implement-trie-prefix-tree/
实现字典树。包含查询单词,和查询单词是否包含前缀。
在求单源最短路径中,我们可能会遇到两种情况,一种是无权的最短路径,另一种是有权的最短路径。
对于无权的最短路径,因为我们是按层访问的,所以我们只需要跟踪当前搜索层数;一旦我们访问到了某个结点,那么当前的层数就一定是到达它的最短路径。
而对于有权的最短路径,我们往往采取贪心的策略,在已经确定了最短路径的结点中,选择它们相邻的未访问过的结点的最小权重路径,加入访问结点集合中。
在有权的情况下,我们常常会用到一个dist容器,用于存储出发点到当前点的最短路径,并且在发现了更短的路径后,需要更新dist里的数据,这是考虑到以下情况:
当我们访问到蓝色结点时,我们会同时更新它的邻居的最短距离,比如将橙色结点更新为dist[blue] + 8; 但是此时我们只是确定了蓝色结点的路径是最短的,还无法保证橙色结点的路径是最短的;因此需要在绿色结点访问到橙色结点时,更新橙色结点的最短路径。
102 https://leetcode.com/problems/binary-tree-level-order-traversal/
树的层次遍历。基础题。
126 https://leetcode.com/problems/word-ladder-ii/
单源无权最短路径。难点在于要记录所有的路径。我的做法是先用宽搜得到最短路径的邻接关系,之后再利用深搜从后往前归纳所有路径,然后把路径倒序。
127 https://leetcode.com/problems/word-ladder/submissions/
单源无权最短路径。
207 https://leetcode.com/problems/course-schedule/
拓扑排序。计算所有点入度,入度为0的点放入队列。每pop一个节点,它的邻居入度都减一,如果出现了入度为0的点,再放入队列。如果访问的节点数等于课程数,那么可以完成所有课程。
301 https://leetcode.com/problems/remove-invalid-parentheses/
搜索所有可能的去除组合,判断是否是有效括号,如果是就加入结果。
310 https://leetcode.com/problems/minimum-height-trees/
类拓扑排序。找到只有一个邻居的点加入队列,每pop一个节点,它的邻居的邻接表就减去这一节点,直到只剩下一/两个节点。
513 https://leetcode.com/problems/find-bottom-left-tree-value/
树的层次遍历。深搜应该也可以的。
515 https://leetcode.com/problems/find-largest-value-in-each-tree-row/
树的层次遍历。
542 https://leetcode.com/problems/01-matrix/
多源无权最短路径。和单源相比,也就是把所有的0加入起始队列就可以了。
743 https://leetcode.com/problems/network-delay-time/
单源有权最短路径。相当于求到每个点的最短路径,然后去其中最大值。
752 https://leetcode.com/problems/open-the-lock/
单源无权最短路径。把锁的状态记录为字符串即可。
773 https://leetcode.com/problems/sliding-puzzle/
单源无权最短路径。特别的时需要用字符串来记录所有状态量,找到目标状态量后就退出,我们总能保证找到时用到的步数是最少的。
778 https://leetcode.com/problems/swim-in-rising-water/
宽度优先搜索。使用优先队列,每次选择值最小的作为下一个,并更新最大值作为结果。
787 https://leetcode.com/problems/cheapest-flights-within-k-stops/
单源有权最短路径。由于有k的次数限制,用宽搜会更加直观。记录当前到达终点的最短路径,如果有更短的,把新的节点加入队列。
847 https://leetcode.com/problems/shortest-path-visiting-all-nodes/
单源无权最短路径(带状态)。判断重复节点访问需要考虑当前状态:访问过哪些节点。
854 https://leetcode.com/problems/k-similar-strings/
宽度优先搜索。每次匹配一个字符,第K次后退出。
863 https://leetcode.com/problems/all-nodes-distance-k-in-binary-tree/
先从树建图,然后做层次遍历。
864 https://leetcode.com/problems/shortest-path-to-get-all-keys/
单源无权最短路径(带状态)。判断重复节点访问需要考虑当前状态:带了几把钥匙。
909 https://leetcode.com/problems/snakes-and-ladders/
单源无权最短路径。比较麻烦的一点是要换算位置和对应数字,此外要特殊处理梯子,因为遇到了梯子/蛇一定要滑过去,所以我们可以当作把这一位置作为跳板直接到达了梯子末端,就好像没有来过这一位置一样。
934 https://leetcode.com/problems/shortest-bridge/
多源无权最短路径。先用深搜给一个岛屿加上标记,之后的做法就类似于542了,取最小的最短路径即可。
1091 https://leetcode.com/problems/shortest-path-in-binary-matrix/
单源无权最短路径。
1129 https://leetcode.com/problems/shortest-path-with-alternating-colors/
单源无权最短路径,但有限制条件。这道题要求每次走不同颜色的路径,需要注意的是不同颜色路径到同一个结点的访问状态需要分别维护。
1135 https://leetcode.com/contest/biweekly-contest-5/problems/connecting-cities-with-minimum-cost/
最小生成树。使用优先队列, 从一个空集合开始,加入任一顶点,并找到该集合中顶点连接的权重最小的边,把该边连接的点也加入集合。直到所有的点都加入了集合,意味着找到了最小生成树。
1136 https://leetcode.com/contest/biweekly-contest-5/problems/parallel-courses/
拓扑排序。
(1) 对于有向图,记录所有顶点的入度(指向该顶点的边的个数)
(2) 找到所有入度为0的顶点,把顶点放入队列
(3) 从队列pop出一个元素,该顶点则是当前满足条件的顶点,可将计数加一,并把它指向的顶点的入度都减一,重复(2)(3)直到队列为空
(4)如果已经找不到入度为0的顶点,而当前计数还没有覆盖到所有顶点,那么说明有向图中可能出现了环路。
17 https://leetcode.com/problems/letter-combinations-of-a-phone-number/
暴力搜索所有可能的电话号码组合。
22 https://leetcode.com/problems/generate-parentheses
暴力搜索所有可能的括号组合。需要传入当前需要的’(‘和’)'数量。
37 https://leetcode.com/problems/sudoku-solver/
暴力搜索可能的解。发现无法继续时就回退到上一步。
39 https://leetcode.com/problems/combination-sum/
暴力搜索所有可能的等于sum的组合。为了避免生成重复,先进行排序,按照非递减的顺序找下一个数字。
40 https://leetcode.com/problems/combination-sum-ii/
暴力搜索所有可能的等于sum的组合。和39相比存在重复,选择的时候跳过重复即可。
51 https://leetcode.com/problems/n-queens/
回溯。
52 https://leetcode.com/problems/n-queens-ii/
回溯。
90 https://leetcode.com/problems/subsets-ii
暴力搜索所有可能的集合结果。
113 https://leetcode.com/problems/path-sum-ii/
暴力搜索所有可能的等于sum的组合。
133 https://leetcode.com/problems/clone-graph/
递归拷贝。如果已经拷贝过,就直接设置指针,没有拷贝过,就去拷贝。
200 https://leetcode.com/problems/number-of-islands/
每搜索一趟就能遍历一个岛屿,搜索后加上visit标记,一共搜了几次就有几个岛屿。
241 https://leetcode.com/problems/different-ways-to-add-parentheses/
分治。先记录左边运算结果,再计算右边运算结果,最后把两个结果合并起来。
698 https://leetcode.com/problems/partition-to-k-equal-sum-subsets/
记忆化搜索。首先求出划分为k份后每个集合的总和目标值,每次取一个没有访问过的数据作为下一个累加数据,每找到一个目标值后份数减一,目标值重置为0。看能否恰好减为0。
417 https://leetcode.com/problems/pacific-atlantic-water-flow/
记忆化搜索。返回值是pair对,记录当前位置能否到达两个海洋,如果它能到达的位置能到达海洋,那么它也能到达。最后扫一遍所有数据,找到两个都为true的加入结果。
529 https://leetcode.com/problems/minesweeper/
搜索遍历。每次扫描到某个空白节点后都判断它能够被填充,不能则返回,能则继续搜索,并修改指向内容,作为visit访问标记。
785 https://leetcode.com/problems/is-graph-bipartite/
二分图判断。给每个节点染色,并且检查它的邻居和它的颜色是否相等,如果存在相等说明不是二分图。
851 https://leetcode.com/problems/loud-and-rich/
建立有向图,搜索遍历所有比它富有的人,取其中最安静的。
967 https://leetcode.com/problems/numbers-with-same-consecutive-differences/
搜索所有满足条件的结果。
1034 https://leetcode.com/problems/coloring-a-border/
深度优先搜索。先全涂一个色,然后对边界和非边界分别涂色。
42 https://leetcode.com/problems/trapping-rain-water/
维护递减的单调栈。遇到大于栈顶的,就pop,因为当前栈顶元素左右两边的高度都一定比它高,所以可以同时计算它(横向的)蓄水量。
84 https://leetcode.com/problems/largest-rectangle-in-histogram
维护递增的单调栈,当发现当前数字比栈顶要小的时候,此时栈顶元素是最大的(大于栈里的下一个元素,也大于当前元素),所以可以计算以当前栈顶元素为高的矩形面积,并比较是不是最大的。
150 https://leetcode.com/problems/evaluate-reverse-polish-notation/
栈模拟递归。遇到运算符就pop两个数字进行计算,并把结果push进去。
316 https://leetcode.com/problems/remove-duplicate-letters/
维护递增的单调栈。首先,统计每个数字出现的次数,每次访问过就把出现次数减一。递增的单调栈对应着最小字典序的结果,已经在栈中的加一个visit标记,避免重复入栈,如果遇到比栈顶更小的,并且栈顶对应的字符在后面也有出现,可以考虑之后再入栈这一字符。所以可以把栈顶pop出来,替换为新的字符,并更新visit标记。
331 https://leetcode.com/problems/verify-preorder-serialization-of-a-binary-tree/
栈模拟递归。这道题需要记录一个count值,表示当前树还有多少个地方可以插入新的节点(包括插入数字和插入Null)。如果插入的是数字节点,那么会多一个可用的位置(新的节点占用了一个,但又新增了两个);如果插入的是null,那么它只会占用一个,所以会少一个可用的位置。每次遇到没有可用位置的时候,意味着当前字符串非法。扫描到最后时,如果可用位置还有剩余,也意味着当前字符串非法。
341 https://leetcode.com/problems/flatten-nested-list-iterator/
栈模拟递归。先把所有数据逆序入栈,如果栈顶是数字就直接返回,如果栈顶是链表,把链表所有值逆序入栈,然后pop当前数据,再循环检查栈顶是否为数字。
385 https://leetcode.com/problems/mini-parser/
栈模拟递归。解析括号,直接使用递归解析更加简单。
402 https://leetcode.com/problems/remove-k-digits
维护递增的单调栈。出现了比栈顶小的,就可以移除栈顶的元素,此时k减去1。
456 https://leetcode.com/problems/132-pattern/
维护递减的单调栈。从后往前遍历,相当于寻找231paterrn。遇到更大的数就pop出来,同时记录栈顶的值(作为第二大的数),之后判断接下来的值小于这个第二大的数即可。
503 https://leetcode.com/problems/next-greater-element-ii/
维护递减的单调栈。不过由于题目要求是循环的,需要两个pass,第二个pass处理循环生效的next greater,同时需要把下标已经超出范围的队首数据及时pop出来。
739 https://leetcode.com/problems/daily-temperatures/
维护递减的单调栈。因为要找到比它高的第一个温度,所以遇到递减的都缓存起来,等到有更高的再一次性更新。
1019 https://leetcode.com/problems/next-greater-node-in-linked-list/
维护递减的单调栈。这道题对象是链表,不像数组可以快速通过下标索引,所以比较方便的做法是在栈中同时记录数字和对应的下标,并且默认填0,如果找到了比它大的第一个数,再修改下标对应的数字。
4 https://leetcode.com/problems/median-of-two-sorted-arrays/
双指针二分问题。把两个数组x,y划分为两个大小相等(或差1)的集合,维护数据maxLeft, minRight,哪边不满足maxLeft < minRight就移动一下指针。
11 https://leetcode.com/problems/container-with-most-water/
双指针二分问题。指针记录首尾位置,哪边更矮哪边的指针向中间移动,同时更新最大容水面积。
15 https://leetcode.com/problems/3sum/
双指针二分问题。
16 https://leetcode.com/problems/3sum-closest/
双指针二分问题。对于排好序的数组,首先确定三个数位置在中间的那个数字,然后在它左右搜索另外两个数,如果大于目标,则右指针左移,否则左指针右移。
18 https://leetcode.com/problems/4sum/
双指针二分问题。和3sum相比,要先选定两个数,而不是一个数。
33 https://leetcode.com/problems/search-in-rotated-sorted-array/
根据下标二分问题。检查二分后的半段是否满足递增条件,如果满足且数据落在这一区间,就在这一区间查找,否则到另一区间查找。
34 https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
根据下标二分问题。要点是改变low或high的时候把当前数字mid也包含进来,因为它也可能是结果。
35 https://leetcode-cn.com/problems/search-insert-position/
74 https://leetcode.com/problems/search-a-2d-matrix/
根据下标二分问题。
162 https://leetcode.com/problems/find-peak-element/
根据下标二分问题。每次检查mid左右两个数和mid的关系,再决定如何进行下一步。
250 https://leetcode.com/problems/search-a-2d-matrix-ii
双指针二分问题。从矩阵的右上角开始搜索,到下标越界后退出。
315 https://leetcode.com/problems/count-of-smaller-numbers-after-self/
先额外存一个排序好的数组。然后查找lower_bound,看有多少个数比它小,并把这个数从排序数组中移除。
475 https://leetcode.com/problems/heaters/
二分查找上下界问题。对加热器进行排序,通过二分查找距离最近的热水器,并求所有最近距离的最大值。
528 https://leetcode.com/problems/random-pick-with-weight/
二分查找上下界问题。首先计算一个累积的频数,根据总频数来进行随机,之后通过二分查找得到当前随机数对应的下标。
704 https://leetcode.com/problems/binary-search/
标准二分查找
875 https://leetcode.com/problems/koko-eating-bananas/
二分猜答案问题。也就是在一定的求解空间中找到最小满足条件的值,使得KoKo能够以最慢的速度在特定时间内吃完所有香蕉。
911 https://leetcode.com/problems/online-election/
二分查找上下界问题。主要是根据时间来二分,先预先计算好当前时间点对应的选举人,存到hashmap中。之后通过二分找到时间,再通过hash找到对应选举人。
1011 https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/
二分猜答案问题。也就是在一定的求解空间中找到最小满足条件的值,使得货船能够以最小的容量在特定时间内运完所有货物。
1146 https://leetcode.com/problems/snapshot-array/
二分查找上下界问题。每次修改值的时候记录一下当前快照的值,然后每次查找当前下标特定快照id时的值时,二分查找小于等于这一快照id对应的值即可。
【哈希】(19)
30 https://leetcode.com/problems/substring-with-concatenation-of-all-words/
用hash记录目标值,从每个下标开始搜索当前字符串是否满足条件,满足则加入结果。
36 https://leetcode.com/problems/valid-sudoku/
哈希检测重复。
49 https://leetcode.com/problems/group-anagrams/
所有的字符串hash到字典序。
347 https://leetcode.com/problems/top-k-frequent-elements/
维护每个数字出现频率,每个频率对应数字,然后从高频率往低搜索。
467 https://leetcode.com/problems/unique-substrings-in-wraparound-string/
哈希计数。遇到特定值的时候就添对应容器加计数,最后把所有计数累加起来得到结果。
523
同560类型题。
560 https://leetcode.com/problems/subarray-sum-equals-k/
使用哈希表记录之前出现的前缀和sum - k。
781 https://leetcode.com/problems/rabbits-in-forest/
值为n的可以和其它n + 1个值为n的成组,统计每个值出现的次数,看它们可以组成多少组相同颜色的兔子,然后乘以组中兔子个数。
890 https://leetcode.com/problems/find-and-replace-pattern/
维护两个哈希,a中第i位数字和b中第i位数字相互映射,检测之后的相同数字是否也满足这种映射。
895 https://leetcode.com/problems/maximum-frequency-stack/
维护两个哈希。一个哈希记录每个数字出现的频率,一个哈希记录每个频率出现的数字,因为可能有多个,可存入栈中。每次取最大频率对应的栈顶值,并移除。如果最大频率变为0,那么移除这一频率。
930 https://leetcode.com/problems/binary-subarrays-with-sum/
记录连续0出现的数字,计算所有(zeros[i] + 1) * (zeros[i + S] + 1)的累加。
954 https://leetcode.com/problems/array-of-doubled-pairs
记录每个数字出现频率。按绝对值排序,对于每个数字,查找是否存在2 * x的数字,如果存在,就把它移除,否则返回false。
974 https://leetcode.com/problems/subarray-sums-divisible-by-k/
使用hash记录当前前缀和%K,如果前面存在相同的数字,那么意味着存在这样的连续子数组。
981 https://leetcode.com/problems/time-based-key-value-store/
维护unordered_map
>的结果,二分查找每个key对应的时间戳。
1044 https://leetcode.com/problems/longest-duplicate-substring/
哈希字符串匹配。先二分,再哈希查找是否存在长度为k的重复字符串。
1072 https://leetcode.com/problems/flip-columns-for-maximum-number-of-equal-rows/
假设当前行是结果。查找和它相等,以及和它恰好相反的子串数量,取最大值。
1074 https://leetcode.com/problems/number-of-submatrices-that-sum-to-target/
对任何两行/列的前缀和,求子数组的前缀和。
1124 https://leetcode.com/problems/longest-well-performing-interval/
等价于找和大于0的最长区间。
1138 https://leetcode.com/problems/alphabet-board-path/
哈希记录每个字母的下标。按照曼哈顿距离挪过去。
23 https://leetcode.com/problems/merge-k-sorted-lists/
把所有数据加入堆里,再pop出来构建新链表。
215 https://leetcode.com/problems/kth-largest-element-in-an-array/
维护最大为K的堆。时间复杂度O(NlogK)。
692 https://leetcode.com/problems/top-k-frequent-words/
维护最大为K的堆。
793 https://leetcode.com/problems/k-closest-points-to-origin/
维护最大为K的堆。
1383 https://leetcode.com/problems/maximum-performance-of-a-team/
维护最大为K的堆。这里首先将所有人按照效率排序,优先选高效的,然后逐步剔除速度慢的人。
128 https://leetcode.com/problems/longest-consecutive-sequence/
把相邻元素合并到一个集合中,取数量最大的那个集合作为结果。哈希的做法是先把所有值放到哈希里,对每个值查找n+1和n-1的值有哪些,记录两端长度。找到了从哈希表中移除。
684 https://leetcode.com/problems/redundant-connection/
类似于最小生成树。每遇到一对节点把它们Union一下,如果已经在一个集合了,就返回这对边,说明是要被去掉的。
924 https://leetcode.com/problems/minimize-malware-spread
优先去除所在集合只包含它一个初始节点的初始节点,如果有多个这样的节点,取集合较大的。如果集合大小一样,或者该集合包含了多个初始节点,取下标最小的。
【贪心】(10)
45 https://leetcode.com/problems/jump-game-ii/submissions/
可以使用搜索完成。但标准做法是贪心,从当前位置跳到下一个位置时,选择下一个能跳到最远位置的地方。
55 https://leetcode.com/problems/jump-game/
暴力算法是n2。贪心思想是从后往前查询能跳到当前位置的,如果找到了,更新当前位置。最终位置如果能到0就返回true。
134 https://leetcode.com/problems/gas-station
如果A->B无法完成到达,那么中间也没有答案(之前累积的结果都是正的,最后一个位置让它不再为正数;如果把起始指针向后移动,情况只会更糟);如果气体总和大于消耗量,那么必然有解。
378 https://leetcode.com/problems/monotone-increasing-digits/
从后往前遍历,找到最后一个i + 1小于i的pair,之后的数字都设置为9,找到小于的时候,把上一个数字减一。
630 https://leetcode.com/problems/course-schedule-iii/
按照结束时间排序,如果当前课程无法在ddl前完成了,就去掉一个时间最长的课程。贪心的标准做法是按结束时间排序后尽可能选,选不了的就放弃。但是这道题的区别在于它的开始时间并不是确定的。
789 https://leetcode.com/problems/escape-the-ghosts/
如果能和鬼在终点相遇,那么也会在其他地方相遇。
870 https://leetcode.com/problems/advantage-shuffle/
In ordered to maximize the advantage of array A with respect to B, we had better choose the smallest element in array A that is larger than the element in B. After each selection, we erase the data we choose in A to avoid repetition.
948 https://leetcode.com/problems/bag-of-tokens/
排序。从左边消耗,能量不够了从右边取,直到无法补充能量,或首尾指针相遇。
955 https://leetcode.com/problems/delete-columns-to-make-sorted-ii/
从左到右扫描,如果有一个数字不满足字典序,那么删掉该列,否则保留。
1147 https://leetcode.com/problems/longest-chunked-palindrome-decomposition/
左边右边开始依次匹配,匹配到了就加一。
94 https://leetcode.com/problems/binary-tree-inorder-traversal/
树的中序遍历。非递归的做法是使用栈,先入栈所有左子树,pop出来的时候入栈当前节点的右子树的所有左子树。
98 https://leetcode.com/problems/validate-binary-search-tree
检查是否是合法二叉搜索树。对于所有结点,检查是否满足大于左子树,小于右子树。
105 https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
根据中序和前序重建树。前序第一个作为根,在中序找到这个数字,左边的是左子树,右边的是右子树。
144 https://leetcode.com/problems/binary-tree-preorder-traversal/
树的前序遍历。非递归的做法是使用栈,先入栈右子树,再入栈左子树。
145 https://leetcode.com/problems/binary-tree-postorder-traversal/
树的后序遍历。非递归的做法是使用栈,先入栈左子树,再入栈右子树,再把结果反过来。
173 https://leetcode.com/problems/binary-search-tree-iterator/
树的中序遍历。查找输出二叉搜索树的下一个最大值,相当于使用非递归进行中序遍历。
199 https://leetcode.com/problems/binary-tree-right-side-view/
树的层次遍历。输出每层最后一个结点。
222 https://leetcode.com/problems/count-complete-tree-nodes/
统计完全二叉树的节点个数。可以先判断当前子树是不是满二叉树,是的话直接返回2^n - 1,否则递归查找。
230 https://leetcode.com/problems/kth-smallest-element-in-a-bst/
中序遍历,输出第k个数字。
236 https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/
最小公共祖先。
865 https://leetcode.com/problems/smallest-subtree-with-all-the-deepest-nodes
同1123。
1026 https://leetcode.com/problems/maximum-difference-between-node-and-ancestor/
返回当前节点子节点的最大值和最小值,计算差并更新结果。
1123 https://leetcode.com/problems/lowest-common-ancestor-of-deepest-leaves
最小公共祖先,选择左右节点中高度比较小的结点对应的答案,如果高度一样,返回自己。
2 https://leetcode.com/problems/add-two-numbers/
19 https://leetcode.com/problems/remove-nth-node-from-end-of-list/
传说中这道题的标准做法是维护两个指针,让一个指针先走n步,然后两个一起动。第一个指针到尽头了,第二个指针就是要删的位置。
24 https://leetcode.com/problems/swap-nodes-in-pairs/
记录了last,cur,next,nnext指针,交换完了一次跳2格
61 https://leetcode.com/problems/rotate-list/
一些奇怪的找规律题,也不知道是啥类型,就叫数学吧?= =
6 https://leetcode.com/problems/zigzag-conversion/
类似编码解码一样的zigzag打印。
43 https://leetcode.com/problems/multiply-strings/
字符串计算乘法。
48 https://leetcode.com/problems/rotate-image/
打印旋转矩阵。
54 https://leetcode.com/problems/spiral-matrix/
打印旋转矩阵。
223 https://leetcode.com/problems/rectangle-area/
计算矩形面积。
228 https://leetcode.com/problems/summary-ranges/
连续数字打印成特定格式。
537 https://leetcode.com/problems/complex-number-multiplication/
计算复数相加。
885 https://leetcode.com/problems/spiral-matrix-iii/
打印旋转矩阵。
1104 https://leetcode.com/problems/path-in-zigzag-labelled-binary-tree/
zigzag打印2^n.
41 https://leetcode.com/problems/first-missing-positive/
原地排序。把下标对应的数字都交换到下标处。之后再从左到右查到第一个i + 1 != A[i]的元素,即为答案。
75 https://leetcode.com/problems/sort-colors/
计数排序。
179 https://leetcode.com/problems/largest-number/
排序。将数字转换为字符串,比较s1 + s2 和 s2 + s1
229 https://leetcode.com/problems/majority-element-ii/
投票法。3分记两票。满足则加一票,为0则选举当前,否则都减去一票。
238 https://leetcode.com/submissions/detail/232467850/
计算首尾累积乘积。
287 https://leetcode.com/problems/find-the-duplicate-number/
快慢指针。查找是否存在环。快指针走2步,慢指针走1步,相遇则存在环。设慢指针走了路程s,则快指针走了2s,环长度为s。若环的起始位置为d,则慢指针的位置在起始位置过一点的地方,它只要再走d步又可以回到起始位置 。
775 https://leetcode.com/submissions/detail/235207901/
检查错位的数字是否都是相邻的。
807 https://leetcode.com/problems/max-increase-to-keep-city-skyline/
模拟题。
912 https://leetcode.com/problems/sort-an-array/
排序练习。作为复习,快速排序的做法是:选取一个主元(可取首中尾的中位数,然后把比它小的交换到左边,比它大的交换到右边)。每次快排结束,总能保证一个数字被放到了正确位置。
1014 https://leetcode.com/problems/best-sightseeing-pair/
i,j合并同类项,分别求两个的最大值。