【leetcode】刷题指南


刷题策略

  1. 第一遍刷企业top面试题简单题,记录每题的解答过程,出乎意料的题记录到这里。
  2. 按解题模式刷题,每个模式刷3题。这里将leetcode题目分为了几个模式。
  3. 标准库中的数据结构和算法,学会它们的基本使用方法。
  4. 参加leetcode每周的周赛,适应面试节奏。
  5. 适应牛客网编程规则。这点很重要,平常面试大多用牛客网进行网上笔试,其需要自己写main函数,自己读取输入,自己按照格式进行输出,若平时只是刷leetcode没练过,第一次遇到肯定懵逼,这里强烈推荐OJ在线编程常见输入输出练习场
  6. 查漏补缺。刷企业top面试题中等题,同时计算时间复杂度和空间复杂度,并总结答题模板和套路。
  7. 刷牛客上的题。面试不仅仅是算法题,还有许多选择题,智力题,有些时候不需要撕算法,但是要计算复杂度。

TODO

  • 素数筛子,这里还有这里

知识点总结

  • 【leetcode】高频题目整理_所有题目汇总篇( High Frequency Problems, All Problems )
  • 【数据结构】二叉树结构
  • 总结二叉树的遍历方法(广度优先遍历、深度优先遍历以及前序、中序、后序遍历)
  • 异或知识点:
    • 一个数与自己异或,结果为0。例如1 ^ 1 = 0
    • 任何数与0异或,结果为这个数本身。例如3 ^ 0 = 3b1010 ^ b0000 = b1010
    • 二进制的0或1与1异或,结果为对这一位取反。例如b1010 ^ b1111 = b0101
    • 异或满足结合律:(a ^ b) ^ c = a ^ (b ^ c)交换律a ^ b = b ^ a
  • 反转也个vector记得只需要遍历(size+1)/2的元素,不要遍历完所有的元素。
  • leetcode中C++常用的stl数据结构(使用频率从高到低):
    • vector
    • string
    • unordered_map
    • queue
    • priority_queue
    • pair
    • stack
    • lists(目前没用过)
    • set(目前没用过)
  • int value = - (1<<31); 会报错
  • int value = 1<<31 - 1;得到结果为1073741824,因为<<优先级较低,执行的是1<<(31-1)
  • 类型最大最小值。在标准头文件中定义有INT_MAX表示int类型的最大值。类似的还有很多,详情见这里。在新版本C++中,又提供了头文件,提供了模板函数,例如std::numeric_limits::min()获取int类型最小值。这些头文件中leetcode都默认include了

一些小技巧

  • 异或。两个相同的数异或的结果为0,任何数与0异或的结果为这个数本身。
  • 检查一个float变量x是否为整数数。C++中好像没有很好的又简单的方法,可以判断x-(int)x<1e-8 为true则x可看作整数。
  • 头文件中的numeric_limits::max()可以返回对应类型(这里是int)的最大值。同理,numeric_limits::min()返回对应类型(这里是int)的最小值。
  • leetcode执行时间运行所有测试用例的总耗时。
  • leetcode执行不同测试用例时,全局遍历值会保留,所以若数据范围小于一定值,如1e4的量级时,可以采用第一次执行时暴力计算范围内所有可能的结果,存放到全局变量,后续执行时只需要查表就好,这样整个代码逻辑会非常简单。具体例子可题目 【leetcode】5178. 四因数( Four Divisors)

TODO的题目

需要再次TODO的题目。

  • 【leetcode】53. 最大子序和(Maximum Subarray):我的题解,只写出了暴力法
  • 【leetcode】69. x 的平方根( Sqrt(x) ):我的解法,只写出了暴力法,二分法有些问题
  • 【leetcode】70. 爬楼梯( Climbing Stairs ):我的解法只实现了3种。官方题解有6中解法,有时间看一看
  • 【leetcode】121. 买卖股票的最佳时机( Best Time to Buy and Sell Stock ),我的解法。官方题解区有人总结了股票问题的解题模板,看一下。
  • 【leetcode】169. 多数元素( Majority Element ) | 我的解答 | 官方题解有很多种方法:排序法,随机法,分治法,投票法。(分治和投票没看懂)
  • 【leetcode】172. 阶乘后的零( Factorial Trailing Zeroes ) | 我的解答
  • 【leetcode】189. 旋转数组( Rotate Array ) | 我的解答 | 官方题解3的核心是他的数学证明,其证明了回到原点后为什么是从相邻的下一个元素开始,而不是下下个或下下下个开始;其还证明了为什么操作了n次后就保证将数组旋转完毕(这一点的证明,需要证明每一次操作都一定能将一个元素放到正确位置上)
  • 【leetcode】190. 颠倒二进制位( Reverse Bits ) | 我的解答 | 如果函数会被多次调用,如何优化速度?
  • 【leetcode】191. 位1的个数( Number of 1 Bits ) | 我的解答 | 官方的n&(n-1)值得借鉴,另外看到别人贴java中integer类的方法(我觉得这种方法本质是把每一位二进制作为十进制数相加,例如1011的汉明权重就为1+0+1+1=3),常数步骤就能算出。最后,如果函数会被多次调用,如何优化速度?
  • 【leetcode】198. 打家劫舍( House Robber ) | 我的解答 | 官方题解的动态规划太简洁了。wang的解法也很好,递归加缓存,以及动态规划模板。
  • 【leetcode】202. 快乐数( Happy Number ) | 我的解答 | 本题有个问题,一是如何证明不存在无限但不循环的情况,一开始没想通,写不出来。
  • 【leetcode】412. Fizz Buzz( Fizz Buzz ) | 我的解答 | 这类体没有什么套路,就模拟整个过程。但是也可以有好的编程方式使得代码更易于维护,例如官方题解
  • 剑指 Offer 40. 最小的k个数 | 快速选择学习一下。
  • 剑指 Offer 57. 和为s的两个数字 | 因为数组已经排序过,写一下分治+二分的写法。
  • 剑指 Offer 11. 旋转数组的最小数字 | 尝试O(logN)复杂度
  • 剑指 Offer 17. 打印从1到最大的n位数 | 参考并实现剑指offer书上大数的打印方法。
  • 剑指 Offer 04. 二维数组中的查找 | 尝试线性时间复杂度的方法

题目分类

模拟题

模拟题指的是没有特别的方法,按照题目要求用代码模拟每个步骤,最终得到结果。(当然也有的题可以通过数学或其他方法直接得到答案)

  • 【leetcode】5336. 上升下降字符串( Increasing Decreasing String ) | 我的解答

位操作

  • 【leetcode】136. 只出现一次的数字( Single Number ) | 我的思路
  • 【leetcode】191. 位1的个数( Number of 1 Bits ) | 我的解答 | 官方的n&(n-1)值得借鉴,另外看到别人贴java中inter类的方法,常数步骤就能算出。最后,如果函数会被多次调用,如何优化速度?
  • 【leetcode】190. 颠倒二进制位( Reverse Bits ) | 我的解答 | 如果函数会被多次调用,如何优化速度?
  • 【leetcode】268. 缺失数字( Missing Number ) | 我的解答
  • 【leetcode】371. 两整数之和( Sum of Two Integers ) | 我的解答

双指针

  • 【leetcode】141. 环形链表( Linked List Cycle ) | 我的思路
  • 【leetcode】160. 相交链表( Intersection of Two Linked Lists ) | 我的思路
  • 【leetcode】202. 快乐数( Happy Number ) | 我的解答
  • 【leetcode】234. 回文链表( Palindrome Linked List ) | 我的解答

投票法

  • 【leetcode】169. 多数元素( Majority Element ) | 我的解答

随机法

  • 【leetcode】169. 多数元素( Majority Element ) | 我的解答

数学法

  • 【leetcode】172. 阶乘后的零( Factorial Trailing Zeroes ) | 我的解答
  • 【leetcode】204. 计数质数( Count Primes ) | 我的解答
  • 【leetcode】268. 缺失数字( Missing Number ) | 我的解答
  • 【leetcode】326. 3的幂( Power of Three ) | 或者提前算好所有结果
  • 【leetcode】279. 完全平方数( Perfect Squares ) | 参考题解,还有这个更清楚的解释 | 四平方数定理: 任何一个正整数都可以表示成不超过四个整数的平方之和。推论:满足四数平方和定理的数n(四个整数的情况),必定满足 n=4^a(8b+7)。
  • 【leetcode】5361. 圆和矩形是否有重叠 | 我的解答 | 暴力法,区域划分法(普适思路)、数学法

反转法

  • 【leetcode】189. 旋转数组( Rotate Array ) | 我的解答
  • 【leetcode】234. 回文链表( Palindrome Linked List ) | 我的解答

动态规划

  • 【leetcode】198. 打家劫舍( House Robber ) | 我的解答 | 官方题解的动态规划太简洁了
  • 【leetcode】213. 打家劫舍 II | 错了好多次
  • 【leetcode】337. 打家劫舍 III | 它那个最有子问题想不明白,一定比记忆化好吗?
  • 【leetcode】5419. 两个子序列的最大点积 | dp的初始值设置为多少需要好好考虑,一开始用的递归,但是初始值不会设置,导致一直出错。
  • 【leetcode】10. 正则表达式匹配 | 这个居然能用动态规划做
  • 【leetcode】5. 最长回文子串 | 不太熟,需要二刷,还有其他方法,比如中心扩散法不懂。

递归

  • 【leetcode】206. 反转链表( Reverse Linked List ) | 我的解答 | 递归有点巧妙。难点是递归后如何返回结果。
  • 【leetcode】234. 回文链表( Palindrome Linked List ) | 我的解答 | 递归法没看
  • 【leetcode】107. 二叉树的层次遍历 II( Binary Tree Level Order Traversal II ) | 参考题解

链表

  • 【leetcode】237. 删除链表中的节点( Delete Node in a Linked List ) | 我的解答

排序

  • 【leetcode】242. 有效的字母异位词( Valid Anagram ) | 我的解答

哈希表

  • 【leetcode】242. 有效的字母异位词( Valid Anagram ) | 我的解答 | TODO: 完成进阶要求。 首先要了解unicode,可参考这篇文章
  • 【leetcode】350. 两个数组的交集 II( Intersection of Two Arrays II ) | 我的解答 | 进阶要求没有完成,这里有关于进阶的讨论。(这里有个技巧,通过递归的方式巧妙的把输入参数交换)
  • 【leetcode】128. 最长连续序列 | 这题的哈希表的使用效果出乎意料
  • 【剑指offer】面试题 17.26. 稀疏相似度 | 还没消化,另外,浮点数精度怎么解决?为什么能那样解决?
  • 剑指 Offer 03. 数组中重复的数字 | 这题是写41. 缺失的第一个正数的基础,看一下
  • 【leetcode】41. 缺失的第一个正数

二叉树

  • 【leetcode】101. 对称二叉树( Symmetric Tree ) | 我的题解 | 实际考察的不是递归也不是非递归,而是考察如何灵活的遍历二叉树
  • 【leetcode】104. 二叉树的最大深度( Maximum Depth of Binary Tree ) | 我的题解 | 同样考察的是遍历二叉树。非递归方式实现一下,没啥特殊的可以把这题删了
  • 【leetcode】108. 将有序数组转换为二叉搜索树( Convert Sorted Array to Binary Search Tree )
  • 【leetcode】102. 二叉树的层次遍历( Binary Tree Level Order Traversal ) | 我的解答 | 遍历简单,如何按照要求拿出数据是难点
  • 【leetcode】112. 路径总和( Path Sum ) | 虽然很简单,不过有些细节导致我提交错了三次。如何判断一个节点为叶子节点,并不是一个p == nullptr就行
  • 【leetcode】113. 路径总和 II( Path Sum II ) | 我的解答 | 出乎意料的是,我的解答方法空间复杂度为O(N^2)时间复杂度为O( Nlog(N) ),跟我想的不一样。
  • 【leetcode】5338. 二叉树中的最长交错路径( Longest ZigZag Path in a Binary Tree) | 我的解答 | 路径起点不一定在root
  • 【leetcode】510. 二叉搜索树中的中序后继 II( Inorder Successor in BST II ) | 我的解答 | 考察对二叉搜索树的理解

  • 【leetcode】5354. 通知所有员工所需的时间( Time Needed to Inform All Employees ) | 我的解答 | 第一次遍历非二叉树的树

Cyclic Sort

  • 【leetcode】268. 缺失数字( Missing Number ) | 我的解答 | 依然是排序法,但要求O(n)时间复杂度(库函数sort是O(nlog n)复杂度)

并查集

  • 【leetcode】5354. 通知所有员工所需的时间( Time Needed to Inform All Employees ) | 我的解答
  • 【leetcode】765. 情侣牵手( Couples Holding Hands ) | 需要二刷。并查集的方法还是没有吃透,一是思路没那么直观,二是感觉思路是那么回事,但是代码实现时用了很多等价的概念替换,没有完全翻译思路。
  • 【leetcode】684. 冗余连接 | 这个比较难想到
  • 【leetcode】1319. 连通网络的操作次数 | 如果答案要求返回操作方法,又怎么做?这就与684题有点关系了
  • 【leetcode】685. 冗余连接 II | 要想多好几步,分情况讨论。感觉hard的某些题想要简洁的代码实现比较困难,但是可以通过分情况讨论,转换为若干个medium题来做。
  • 【leetcode】399. 除法求值( Evaluate Division ) | 带权值边的并查集,以及使用哈希表构建并查集。
  • 【leetcode】128. 最长连续序列 | 使用哈希表实现的并查集,并且本题不太容易想到并查集的方法。

状态压缩

  • 【leetcode】5337. 每个元音包含偶数次的最长子字符串( Find the Longest Substring Containing Vowels in Even Counts ) | 这个题解不错 | 我的解答 | 第一次接触这种题,一开始以为用滑动窗口,结果发现窗口应该两边都是可变的,很麻烦。这种题一般要把窗口其中一边固定,另一边移动才行。并且这题有个细节,就是默认状态的初始值。这里还给了一些状态压缩的其它题目

子集问题

  • 【leetcode】78. 子集( Subsets ) | 官方题解 给出了这类问题的几种解法

预处理

这里指的是一些题目,用常规解法不好解,或者难以想出来,但是用暴力法却能轻易解答,并且通过某些技巧能使得暴力法不超时。

  • 【leetcode】5178. 四因数( Four Divisors) | 我的解答 | 这位的题解有点骚,因为数据量不大,它预先暴力计算范围内所有结果放到全局变量,然后查表,使得代码逻辑非常简洁。

BFS广度优先搜索

  • 【leetcode】5366. 检查网格中是否存在有效路径 | 一开始用DFS+回溯写出来了,但是cell到cell的判断没弄到,导致代码不忍直视…
  • 【leetcode】994. 腐烂的橘子 | 这题在判断走不走下个cell时,只需要判断哪个cell就可以了,而5366. 检查网格中是否存在有效路径判断能不能走时,需要考虑当前cell和下一个cell才能确定。
  • 【leetcode】279. 完全平方数 (Perfect Squares
    ) | 怎么把这种问题抽象成图或树,以便进行BFS。另外如何剪枝。
  • 【leetcode】133. 克隆图( Clone Graph ) | BFS不好写,本来想用BFS的,结果发现一环套一环,写着写着就成DFS了。新结点内存的申请可以在入队时,也可以在出队时,但是出队时不知道当前结点是谁的邻居,而在入队时就可以轻易知道哪些结点是该结点的邻居。
  • 【leetcode】127. 单词接龙( Word Ladder ) | 无论是DFS还是BFS,要想进行遍历的首要条件是,我怎么判断能否从当前结点步进到下个结点?这一题主要就是解决这个问题。这里速度的优化也是挺好的,可以看看 | 两个提速点,一是单词距离的计算,二是双向BFS
  • 【leetcode】529. 扫雷游戏( Minesweeper ) | 我的解答 | 这题有个地方没有处理好,导致一开始超时,后来发现了,但是加的地方不对,导致出错。
  • 【leetcode】417. 太平洋大西洋水流问题( Pacific Atlantic Water Flow ) | BFS需要知道起点在哪,还要知道终点条件或者终点在哪,若直接知道终点在哪,可以考虑双边BFS。本题主要难点是从何地开始遍历
  • 【leetcode】310. 最小高度树( Minimum Height Trees ) | 注意一个图结点数为0时肯定没边,结点数为1时也没有边。另外这题还是以哪里作为遍历起点的问题,不同的选择可能超时。这里是反向BFS(几乎和拓扑排序一样,但要注意无向图的拓扑排序需要避免重复遍历),可以想象成从所有叶子结点向根结点遍历,与双边BFS中的反向遍历是不同的,双边BFS遍历虽然也是从叶子结点向根节点遍历,但它是把叶子结点当作根节点来遍历的。
  • 【leetcode】261. 以图判树( Graph Valid Tree ) | 要能成为树需要满足两个条件,一是元素相连不断开,二是没有环。(拓扑排序可以检测环但检测不出断点,普通的邻接表+BFS可以检测断点但检测不出环,而邻接矩阵+BFS可以检测出断点和环,因为邻接矩阵可以表示a到b也可以保证b到a的连接是否可连)
  • 【leetcode】505. 迷宫 II ( The Maze II ) | 这题也可以看看,结果不是最先到达终点的距离,而是最短距离。
  • 【leetcode】117. 填充每个节点的下一个右侧节点指针 II( Populating Next Right Pointers in Each Node II) | 我的解答 | 加深二叉树BFS的理解

DFS 深度优先搜索

DFS递归实现好处是简单,坏处是每次递归处理操作必须是相同的,若不相同需要加一些条件判断;DFS递归迭代实现(借助stack)好处是更灵活,例如我可以很方便的对第一次迭代进行与其他迭代不一样的操作,并且减少了调用函数时局部变量的入栈,速度会快一些,内存占用也少一些,坏处是代码稍微长一点。

  • 【leetcode】257. 二叉树的所有路径 ( Binary Tree Paths ) | 这题用来训练使用stack进行带回溯的DFS。| 可以用一个堆,堆元素为结点和路径的pair,或者用两个堆,结点堆和路径堆,对两个堆进行相同操作,这两个方法其实本质相同;还有个方法就是一个堆,再用一个map来记录每个结点的路径,但缺点就是程序结束时许多无用内存还一直占用着。
  • 【leetcode】110. 平衡二叉树 ( Balanced Binary Tree ) | 这个错了好多次,因为一开始并没想到用嵌套的递归,相当于自顶向下(后面发现单个递归也能写,相当于自底向上)。那么怎么提速?
  • 【leetcoe】733. 图像渲染 (Flood Fill) | 有个容易死循环的地方
  • 【leetcode】394. 字符串解码 (Decode String) | 递归有些抽象
  • 【leetcode】114. 二叉树展开为链表( Flatten Binary Tree to Linked List) | 我的解答 | 想了挺久的,有递归和迭代两种方法,迭代方法不需要stack
  • 【leetcode】109. 有序链表转换二叉搜索树 ( Convert Sorted List to Binary Search Tree) | 有一些细节,不断取中位数的主要作用是为了保持二叉树平衡,次要作用是拿根结点值
  • 【leetcode】105. 从前序与中序遍历序列构造二叉树
  • 【leetcode】105. 从前序与中序遍历序列构造二叉树 | 我的解答 | 要弄清楚前序遍历和中序遍历在构造二叉树过程中,分别提供了什么约束,使得构造的二叉树是唯一的
  • 【leetcode】106. 从中序与后序遍历序列构造二叉树 | 加深理解前序遍历与后序遍历的关系,前序遍历结果是DLR,后序遍历结果反转后相当于DRL,可用105题的解法。
  • 【leetcode】863. 二叉树中所有距离为 K 的结点 (All Nodes Distance K in Binary Tree) | 官方题解的方法二没理解
  • 【leetcode】491. 递增子序列( Increasing Subsequences ) | 怎么去重是关键
  • 【leetcode】638. 大礼包 (Shopping Offers)| 这种题不太懂,一开始无从下手
  • 【leetcode】332. 重新安排行程 | 欧拉图,一笔画完问题。错了挺多次,最后勉强不超时
  • 【leetcode】332. 重新安排行程 | DFS和欧拉图的方法都可以解
  • 【leetcode】494. 目标和 | 这题比较简单,但是容易错,因为测试样例会让你溢出
  • 【leetcode】576. 出界的路径数 | 第一次遇到数据这么大的,以及第一次使用3维记忆化。

贪心法

  • 【leetcode】1405. 最长快乐字符串 | 周赛题,看了一些排名前几的,大家都是按照自己的理解写,没有写得特别简洁优雅的,过阵子再来看看。
  • 【leetcode】765. 情侣牵手 | 这些贪心类题目,不要怕麻烦一定要分情况讨论,想清楚了的话代码就几行。这题一看之下似乎贪心不得,仔细考虑了以后还是可以的。

数据管理

这类题不知道怎么称呼,暂且就叫数据管理吧,主要考察如何厘清数据之间的关系,构造合理的数据结构,按照格式输出数据,不一定很难,但是写起来很繁琐,想要简洁优雅的写出来很难。

  • 【leetcode】1418. 点菜展示表 | 可以来练练手
  • 【leetcode】1396. 设计地铁系统

回溯

  • 【leetcode】10. 正则表达式匹配 | 回溯我觉得是用于b*这里

字符串

  • 【面试金典6th】面试题 16.18. 模式匹配 | 很考验逻辑能力

单调队列

  • 剑指 Offer 59 - I. 滑动窗口的最大值 | 单调队列,不太熟

相关/参考链接

TODO: 找一些plan,或者how to prepare interview or algorithm 之类的资料比较有用,简单的知识总结和汇总在没有plan的前提下毫无作用。

  • cplusplus 或 cppreference | 查找c++标准自带的数据结构和标准函数用法
  • 前几百题题解 | 用于搜索题解
  • 五分钟学算法 在网站上搜"第 x 号题",就可以搜到对应的leetcode动画题解 。
  • leetcode动画题解
  • Algo Deck | 看了bit操作那里,感觉总结了一些常用运算可能有用: Algo Deck is an Open-Source Collection of +200 Algorithmic Cards to Help you Preparing your Algorithm & Data Structure Interview
  • interview | 给出的目录可以了解到要掌握哪些知识点 : C/C++ 技术面试基础知识总结,包括语言、程序库、数据结构、算法、系统、网络、链接装载库等知识及面试经验、招聘、内推等信息。
  • 贪婪策略系列 - 覆盖篇
  • 【算法提高班】并查集
  • 构造二叉树系列
  • leetcode题解
  • LeetCode 问题分类讲解 | 看过他的dp题解,讲得特别细节。另外看了他网站也有对题目分类,先mark
  • AcWing 题解 | 这里也有许多详细题解。
  • William Lin的youtube | leetcode周赛全球前几,周赛视频题解,以及比赛直播
  • fucking-algorithm | 60多篇基于leetcode为主题的文章,涵盖了一些算法题型和解答技巧,致力做到举一反三、通熟易懂。目前有动态规划系列、数据结构系列、算法思维系列、高频面试系列等类别。

你可能感兴趣的:(#,Leetcode)