![](https://img-blog.csdnimg.cn/20201014180756724.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
力扣刷题
文章平均质量分 61
Xaiver_97
学生狗,小白一枚
展开
-
LeetCode 718. 最长重复子数组/最长公共子串(C++)
唯一的不同就在于,最长子序列允许序列并非连续的,而最长子数组(子串)要求序列是连续的。而“12”和“32”子串在dp数组中保存的值就为1,因此它们最后一位相等,然后再往前找,发现不相等,于是最长就为1。我们可以看到,经过这样的滑动窗口之后,数组1的每个数都和数组2的每一个数对齐进行了一次匹配比较,因此只需要记录下匹配过程中的最大子串就完成了整个过程。在暴力解法中,我们开始计算公共子串的长度的步骤总是等到两个数组的当前元素相等的时候才开始,但是两个元素相等的位置我们根本不知道在哪,所以任何地方都有可能,即。原创 2022-09-27 22:26:42 · 750 阅读 · 1 评论 -
LeetCode 1143. 最长公共子序列(C++)
若我们用二维表格的代替dp数组,我们会发现,点(i, j)可能会依赖于其上边(i-1, j),左边(i, j-1),以及左上方(i-1, j-1)的值,因此我们需要从头开始迭代来计算出表格中的每一个数值,最后取右下角的数值即为最终的结果。在上面的代码中,我们开辟的数组行和列都比实际的长度要多一位,这是因为我们比较两个字符串第一位dp[0][0]的时候也需要利用上一个状态,而上一个状态有可能是dp[-1][-1], dp[-1][0], dp[0][-1]。,这个不需要证明,显然可以得出这样的结论。原创 2022-09-20 19:51:34 · 544 阅读 · 0 评论 -
LeetCode 2085. 统计出现过一次的公共字符串(C++)
对于word1中的每一个字符串,判断其在word1中是否只出现了一次,而且也在word2中也恰好出现一次,若满足条件,计数器加1。这种方法不需要额外的空间,但是耗时很高。我们可以遍历两个数组,以哈希表来存储其中出现的元素,若出现一次则为true,若出现多余一次则为false。最后再遍历一遍哈希表即可。遍历、哈希表、STL方法。原创 2022-09-19 17:09:07 · 453 阅读 · 0 评论 -
LeetCode 23. 合并K个升序链表(C++)
对于数组中每个链表我们在头部都放置一个指针,将最小的元素放进结果链表中。一种简单的思路就是每次进行两两合并,比如以第一个链表最为最终链表,那么把剩下的链表都合并到第一个链表上来。还需要判断一下数组中没有链表和只有一个链表的情况。这种方法的缺点就是要扫描第一个链表很多遍,会产生重复的对比,因此时间复杂度比较高,但是不需要额外的空间,因此空间复杂度较低。我们可以采用归并的算法使得链表两两合并,这样能够使得合并步骤的时间复杂度由k降为logk级别,因此下面采用归并的方法合并。原创 2022-09-16 21:14:01 · 240 阅读 · 0 评论 -
LeetCode 46. 全排列(C++)
因此回溯要求的就是我们可以回到上一步的状态,看看是否有其他的选择,如果有的话就输出下一种选择。因此我们可以用一张表来记录哪些元素当前是已经选择了的,在回退的时候修改这张表就可以了。这道题要输出所有的数的全排列,首先我们可以想到的是依次选数,假设数组的大小为3,那么第一个位置就有3种选择,三种选择下面对应的第二个位置又分别有两种选择,第三个位置没有选择。用队列记录下每一层的所有情况,并在下层遍历的时候,根据上层的每一项分别添加上每一种可能加入队列,直到所有数都被选择进队列。广度优先遍历、回溯、树形结构。原创 2022-09-16 13:22:47 · 523 阅读 · 0 评论 -
LeetCode 103. 二叉树的锯齿形层序遍历(C++)
实现锯齿形遍历,首先发现这道题要求是层序遍历,和层序遍历不相同的地方就在于它每隔一行就会由“从右向左”变为“从左向右”,依次在这两个状态之间转换。那么很容易想到的就是使用标志位来判断到底应该是哪个状态,同时由于从右向左和从左向右对节点顺序有要求,那么使用双端队列或者双栈就成了很容易想到的解法。二叉树层序遍历、双端队列。原创 2022-09-15 23:26:28 · 818 阅读 · 0 评论 -
LeetCode 257. 二叉树的所有路径(C++)
使用先序遍历,使用字符串记录下已经经历过的节点,若找到叶子节点,则把叶子结点经过的路径加入结果中。若并非叶子节点,则加入“->”,接着遍历左右孩子。想要找到二叉树的所有路径,也就是找到所有的子节点,那么必然会涉及到二叉树的遍历。因此我们可以采用深度优先的方法(先、中、后序遍历),也可以采用广度优先的方法(层序遍历)。广度优先的方法则需要维护两个队列,一个队列用于层序遍历,另一个队列用于存储根节点到第一个队列中每个节点的路径,因此广度优先写起来比较麻烦,这也就暂时不写这个方法了。原创 2022-09-15 22:07:04 · 375 阅读 · 0 评论 -
LeetCode 236. 二叉树的最近公共祖先(C++)
其核心思想就是,对于某个节点(假设为curNode)来说,假设我找到了一个左孩子或者右孩子是p或者q,那么我就不需要继续往下递归找我的子树了,我只需要往上返回这个节点(假设为findNode)即可,让上层节点(curNode的父节点)判断它的右子树情况,若上层节点的右子树没找到p或者q,说明剩下一个一定在findNode的子树里面。由于我们判断的是左子树或右子树是否包含p或q,因此在第一种情况并非一定要祖先的左右节点正好是p,q,而是祖先的左子树中包含p,右子树中包含q即可。这样我们就可以使用这个方法了。原创 2022-09-14 15:36:53 · 724 阅读 · 0 评论 -
LeetCode 5. 最长回文子串(C++)
一个字符串是否是回文串,可以分解为更小规模的问题,比如一个字符串str = "abba" 是否为回文串,首先我可以判断str[0] == str[3],也就是最左边和最右边做判断。例如字符串总长为4,若我们的从第二行看(i=1),其子串只可能为str[1][2], str[1][3], str[1][4],即只需要3个空间来记录。对于每个字符,都可能是单中心或者双中心,因此在遍历的时候我们需要考虑单中心(回文子串长度为奇)和双中心(回文子串长度为偶数)两种情况,取两种情况的最大者作为我们最终的结果。原创 2022-09-13 14:56:04 · 4820 阅读 · 1 评论 -
利用union判断CPU大小端以及大小端转换(C++)
0x12345678。这个数的低位,指的就是右边,比如78就是低位。而高位指的就是左边,比如12就是高位。常见的处理器如X86、ARM等一般用的都是小端,其中某些处理器可以设置大小端。我们知道存放一个数的内存地址一般是连续的,那么就有两种情况,我们可以利用union来查看自己的机器是大端还是小端存储。,这样整个数在内存中看起来就是顺序排列的。,高位的字节放在内存高地址。这样整个数在内存中看起来就像是逆序排列的。,低位的字节放在内存高地址。原创 2022-09-11 23:27:52 · 731 阅读 · 0 评论 -
LeetCode 200. 岛屿数量(C++)
思路:我们从题目中可以得知,孤立的岛屿旁边全是海,假设岛屿范围内每一个‘1’是岛屿的一部分,那么我们从岛屿的任意一部分登岛,走遍岛屿的每一块土地,就能确定岛屿的大小和范围。为了找遍所有的岛屿,我们还需要把走过的土地都标记为0,防止从同一岛屿的另一部分登岛。记录岛屿的数量加1,再继续找还没有'1'的部分,走遍下一个岛屿。比如下面的例子,不同颜色的'1'表示不同岛屿的一部分。对于这道题来说,广度优先遍历值得注意的地方在于,要先把当前出队的元素上下左右置0(若有岛屿部分),然后再把那些置过0的元素入队。原创 2022-09-11 19:37:20 · 2046 阅读 · 0 评论 -
LeetCode 429. n-叉树的层序遍历(C++)
和二叉树类似,n叉树层序遍历也是一层一层输出节点,返回值应该是一个二维数组。我们可以用一个队列来存储每一层的节点,输出节点的时候将其孩子加入队列。同时使用一个变量来记录每一层的节点数量,当出队的节点数量等于该层节点数,就完成了当前层的遍历。以此类推,直到队列为空就说明遍历完了整棵树。n-叉树和二叉树唯一不同的地方就在于其孩子并非左右孩子两个,而是需要把当前节点的所有孩子加入队列。原创 2022-09-09 22:47:26 · 1011 阅读 · 0 评论 -
LeetCode 102. 二叉树的层序遍历(C++)
思路:二叉树的层序遍历要求是一层一层输出节点,返回值应该是一个二维数组。我们可以用一个队列来存储每一层的节点,输出节点的时候将其左孩子和右孩子加入队列,这样就可以完成层序遍历。原创 2022-09-09 22:19:17 · 418 阅读 · 0 评论 -
LeetCode 15. 三数之和(C++)
这道题一个比较麻烦的地方就是去重,比如数组[-2, -1, -1, 0, 3, 3],我们固定-2,当左边指针指到-1的时候可以和最右边的3匹配使总和为0,此时将答案记录下来,将左边指针和右边指针同时向中间移动,但是会发现又碰到了-1和3,这样就会出现重复的三元组,不符合题目的要求。因此这道题需要对固定的第一个数进行去重,左指针和右指针的数也需要去重。由于当前数组是排序过后的,因此已经是有序的,所以右边的数一定比左边的大,因此我们固定的数必须要小于0,才有可能使得其和后面两个数加在一起等于0。原创 2022-09-09 21:59:00 · 222 阅读 · 0 评论 -
LeetCode 25. K个一组翻转链表(C++)
比如翻转后的子链需要连接到原链最后一个节点的next,但是如果是第一个翻转的子链就没有上一个节点,因此这里本来需要进行特殊的if判断,我们引入哨兵节点之后就可以统一化处理。还需要注意的地方就是,这道题如果最后剩余的元素不到k,那么最后就不进行翻转,因此我们需要先探路,探路后发现长度满足条件再进行翻转。尾插法则比上一种方法要更加简洁,其思想是找到待翻转部分的头和尾,将从头开始一个个把节点接在尾的后面,这样的好处就是翻转完之后当前部分和下一部分还是非常自然的接在一起的。原创 2022-09-08 20:31:14 · 268 阅读 · 0 评论 -
LeetCode 122. 买卖股票的最佳时机 II(C++)
思路:通过历史最小值来判断哪一天买入,然后通过当前节点往后看是否跌了来判断是否卖出,感觉也类似于贪心。但是买股票用贪心的方法本来就是收益最大化的手段啊。思路:某一天的利润等于max(前一天的利润,前一天的利润加上昨天买今天卖的利润)原创 2022-09-04 16:54:41 · 330 阅读 · 0 评论 -
LeetCode 14. 最长公共前缀(C++)
思路:既然要找公共子前缀,那么直接遍历整个数组,首先看一个字母是不是,是的话看两个字母是不,以此类推。要注意的是,公共子前缀的最长长度不超过数组中最短的字符串长度。因此可以先通过一轮遍历找出数组中最短的字符串。再进行正式的比较操作。思路:对于数组中每一个字符串,依次比较它们的第一位是否一样,是的话就继续检查第二位,直至检查到某个字符串末尾,时间复杂度是O(mn),空间复杂度O(1)原创 2022-09-04 15:28:30 · 1548 阅读 · 0 评论 -
LeetCode 226. 翻转二叉树(C++)
翻转二叉树这道题目,根据力扣上的图示可以很好的理解,就是左子树和右子树交换位置,左子树的左子树和左子树的右子树交换位置,以此类推,因此这道题目应该是一道递归很好解的题目。原创 2022-09-03 22:48:40 · 213 阅读 · 0 评论 -
LeetCode 169. 多数元素(C++)
显然,因为目标值超过数组长度的一半,那么只需返回排序之后中间的结果即可。原创 2022-09-03 21:52:38 · 292 阅读 · 0 评论 -
LeetCode 234. 回文链表(C++)
这种方法需要一个额外的节点用来保存链表头结点,并且在递归到达最里层的时候往后走,这样就可以实现头指针向后,尾指针向前对比。解法1的问题在于要开辟额外数组,递归虽然不用开辟额外空间,但是需要占用系统栈的空间,而且效率可能还更差。原创 2022-09-03 19:25:04 · 334 阅读 · 0 评论 -
LeetCode 112. 路径总和(C++)
这道题思路比较简单,但是要注意的是,一定要找到叶子结点才能判断是否满足,因此一定要遍历完所有的叶子结点,那么很容易想到的就是DFS,因此可以采用递归的方法。原创 2022-09-02 17:39:02 · 217 阅读 · 0 评论 -
LeetCode 543. 二叉树的直径 (C++)
这道题我觉得官方题解有点难懂,反而是我自己的思路更好想明白这个问题。根据题目定义,某个根节点二叉树的直径实际上就是其左子树的深度加上右子树深度之和,因此求深度的问题很容易想到使用DFS递归。但是呢,问题在于二叉树的最大直径并非是一定经过根节点的,因此所有节点都有机会得到最大的直径,所以我们可以设置一个全局的最大直径并不断对其进行更新。原创 2022-09-02 15:28:50 · 230 阅读 · 0 评论 -
LeetCode 101. 对称二叉树 (C++)
树对称,则说明从根往下走,根的左孩子的情况和根的右孩子情况相同(即要空都是空,不空的话值一定相等),根左孩子的左孩子情况与根右孩子的右孩子情况相同。思路:很容易想到的是树的层次遍历,因此需要队列。可以用一个队列存左子树的情况,一个队列存右子树的情况,然后比较即可。但是想一想,也可以不需要两个队列,一个队列就能搞定,只要依次序交叉存左孩子和右孩子的情况即可。那么在比较的时候,一次弹出两个元素就可以了。原创 2022-09-01 23:30:11 · 229 阅读 · 0 评论 -
LeetCode 110.平衡二叉树 (C++)
平衡二叉树,指的就是每个节点的左右子树高度相差不超过1的树思路:首先需要知道左子树和右子树的高度,那么可以定义一个depth函数求高度,要求高度那么很显然是递归函数,从上向下找到最高的再返回上来。总的判断二叉树平衡又需要满足三个条件:1、当前节点是平衡的2、当前节点的左子树是平衡的3、当前节点的右子树是平衡的因此判断是否平衡的函数也是一个递归函数。这种解法容易想到,但是有一个问题在于很多操作都重复求了同一个节点的高度,因此这种方法的时间复杂度较高。原创 2022-09-01 21:02:02 · 397 阅读 · 0 评论 -
LeetCode 155.最小栈 (C++)
解法1:可以使用multiset来对元素进行保存,因为multiset总是有序的,因此可以快速得到栈中最小的元素。具体思路:栈中不存真实的val数值,而是val与最小值之间的差值。而且只要栈中元素为负(差值为负),就说明当前的真实值就是当前的最小值。这种方法不需要额外的辅助集合或者辅助栈,只需要维护一个全局最小值即可,但是根据题目的限制,存差值的话如果栈为int型会溢出,因此必须要为long long型。解法2:辅助栈,主栈和辅助栈共同进退,唯一不同的就是辅助栈保存的是每一次操作后,当前栈中的最小值。...原创 2022-08-31 23:43:21 · 198 阅读 · 0 评论 -
LeetCode 144.二叉树的前序遍历 (C++)
思想还是向左遍历之前,让当前节点左子树的最右节点指向自己,这样回溯的时候就能找到。二叉树的前序遍历就是,根 -> 左 -> 右,这样的次序。解法1:递归,这个模板是前中后通用的。解法2:迭代(手动建栈模拟系统操作)解法3:Morris遍历。...原创 2022-08-31 21:32:56 · 319 阅读 · 0 评论 -
LeetCode 145.二叉树的后序遍历 (C++)
二叉树后序遍历的Morris方法可以说是最难的,主要思想还是把左子树的最右节点指向根节点。然后回来的时候把指针给取消。但是不同的地方就在于打印的时候要么是只打印左孩子单个叶子节点,要么就是打印根节点及其右孩子叶子节点,因此每次打印的时候需要使用reverse来反转一下,而且最后树的总的根节点需要单独打印,所以最后会对root进行单独的打印操作。二叉树的后序遍历就是, 左 -> 右 -> 根 ,这样的次序。解法1:递归,这个模板是前中后通用的。解法2:迭代(手动建栈模拟系统操作)解法3:Morris遍历。原创 2022-09-01 17:44:23 · 263 阅读 · 0 评论 -
LeetCode 69.x的平方根 (C++)
其中带有下标的x都是迭代法每一步的近似根,而分母的不带下标的x则为想要求根的数。这道题实际上就是让你在不用sqrt()的情况下求平方根。原创 2022-08-31 15:40:37 · 246 阅读 · 0 评论 -
LeetCode 94.二叉树的中序遍历 (C++)
因为中序遍历的话我们需要一直深入到左子树底,这样就找不到最初的根节点了,因此这里的想法就是将二叉树改造为线索二叉树。由于根节点左子树中的最右下的节点一定是根节点中序遍历的前驱结点,因此只需要每往下找一层左子树的时候,将根节点赋给前驱结点的right即可,这样就可以找到根节点了。但是要注意的是,二叉树的遍历理论上不会改变二叉树结构,所以要保证遍历完之后所有前驱节点的right重新指向空才行,否则leetcode就会报stack over flow的问题。解法2:迭代,用栈来模拟递归调用的过程。...原创 2022-08-30 20:18:40 · 499 阅读 · 0 评论 -
LeetCode 160.相交链表 (C++)
大致思路就是:当第一个节点走到第一条链尾的时候,将节点放在第二条链头,然后继续走;当第二个节点走到第二条链尾的时候,将节点放在第一条链头,然后继续走。每次这两个节点都只走一步,如果他们之间有重合的部分,那么必然会在第一个地方相遇。如果没有重合的部分,那么最后就会在nullptr处相遇。假设第一条链长度为a,第二条链长度为b,长度不包括重合部分。若重合部分链长为c;那么用着个方法,节点在相遇(或同指向nullptr的时候),第一条链最后走的总长度就是a+c+b,第二条链走的总长度就是b+c+a。...原创 2022-08-28 19:43:17 · 289 阅读 · 0 评论 -
LeetCode 88. 合并两个有序数组(C++)
由于第一种方法从需要从nums1的头开始一直遍历到尾,因此就需要一个额外的辅助数组。然而nums1的末尾都是0,我们如果从尾一直遍历到头就可以实现原地合并。因此原来是谁小谁进去,现在变为谁大谁进去。这种方法也没啥好讲的,就是把nums2的元素先填到nums1的真实元素的后面(即那些用0占位的地方),然后调用sort对nums1排序即可。以最终的nums1数组为核心,每一个位置进行判断,到底是用copy_nums1的值还是用nums2的值,直到结尾。解法2:追加然后排序。...原创 2022-08-28 17:21:02 · 261 阅读 · 0 评论 -
LeetCode 20. 有效的括号(C++)
2、可以用map来存括号对,碰到s里面的字符直接找,速度很快,但是要将右括号存为key,不然碰到右括号的时候没法找。3、注意循环结束以后,只有栈为空才是正确匹配情况,如果栈还有东西说明匹配失败。1、可以先判断字符串s是不是2的倍数,如果不是,直接返回false。解法:用栈匹配的方法来判断括号是否符合。...原创 2022-08-27 21:35:55 · 169 阅读 · 0 评论 -
LeetCode 141. 环形链表(C++)
若链表有环,则pos的值为链表中的位置下标(从0开始编号)。其中题目中每个节点的数字是迷惑作用,思路:用一个set来把碰到过的指针都存下来,如果在遍历的过程中发现set中有这个指针,那么说明有环,返回true。给你一个链表的头节点指针head ,判断链表中是否有环。这里快指针一次走2步,走3步,甚至走更多步都可以,慢指针一定要比快指针的步子小。思路:使用一块一慢两个指针,若链表有环,慢的指针迟早都会和快的指针相遇。下面的代码是快指针一次走2步,慢指针一次走1步。还可以写成快指针一次3步,慢指针一次2步。..原创 2022-08-27 21:00:33 · 327 阅读 · 0 评论 -
LeetCode 121. 买卖股票的最佳时机(C++)
因为要求股票收益的最大值,因此我可以新建一个数组用来存取每两天股票价格的差值,这样N天就可以构造一个大小为N-1的数组,这个数组里面存放着每两天股票涨了多少或者跌了多少。要求股票收益最大的时候,那么只需要在每天的价格往前看,假设自己在当天以前的最低点购买,利益是多少,如果当前点的收益比全局收益更大则更新全局收益。同时保存当前以前的全局最低点。这里动态规划的思路是,下一个状态只与前一个状态有关。如果当前值减掉历史最小值大于前一个状态,当前状态就设为当前值减掉历史最小值,否则当前状态就等于前一个状态。...原创 2022-08-27 18:04:07 · 462 阅读 · 0 评论 -
LeetCode 21.合并两个有序链表(C++)
然后进行循环,只要不满足循环退出的条件,就一直在两条链之间进行穿针引线,最后将两条链的节点穿在一条线上,返回哨兵节点的next就结束了。答:若未触发边界条件,将当前处理的节点返回给上层。若触发边界条件,返回不为空的那个链。答:需要把两个链中较小的那个节点的next指向下一层递归的结果。迭代的方法就是先设置一个哨兵节点来防止一些边界情况。2、结束的边界条件是什么?1、当前层我要干什么?3、我需要返回什么?...原创 2022-08-27 16:00:21 · 358 阅读 · 0 评论 -
LeetCode 53.最大子数组和(C++)
暴力求解的方法很容易想到,就是用滑动窗口的方法,但是时间复杂度太高了,因此这里就不写了。这道题主要可以用两种方法求解,一种是贪心法,一种是动态规划。原创 2022-07-20 23:50:39 · 609 阅读 · 0 评论 -
LeetCode 392.判断子序列(C++)
这道题目考察的是动态规划,实际上就是需要把大问题分解成一个个的子问题。要想找到子序列s在长序列t中是否存在,那么就可以分解为,找子序列s的每一个字符是否在长序列t中依次存在。原创 2022-07-20 17:34:09 · 313 阅读 · 0 评论 -
LeetCode 215. 数组中的第K个最大元素(C++)
这道题实际上就只是考察排序知识,重点是要注意一下题目里说的第k大的,如果从小到大排序那么取元素的时候就要从后往前取。同时题目中要求要以O(n)的复杂度来完成,但是主流的排序时间复杂度的下界普遍都是O(nlogn),因此我们需要采用一些方法来提前结束排序。由于快排每一次确定一个元素的位置,因此我们只需要根据k是比当前排序元素大还是比排序元素小来对一侧进行快排,最终找到位于nums.size()-k的元素就是数组中第K大的元素。建好堆之后只需要做k-1次的交换与调整,那么做完之后第k大的元素就必然在堆的顶部。原创 2022-05-25 15:56:02 · 848 阅读 · 0 评论 -
LeetCode 1.两数之和(C++)
题目地址:力扣解法1:为了保证低的时间复杂度,那么只能对nums容器进行一轮遍历。可以用map来保存每个遍历过的数字以及对应的下标。这样当遍历到新数字的时候,需要要以及target与当前数字的差值是否存在于map中即可class Solution {public: vector<int> twoSum(vector<int>& nums, int target) { // 创建map,key用于存放数组中出现的数字,value用于存放其下标原创 2022-05-23 09:28:45 · 139 阅读 · 0 评论 -
LeetCode 3.无重复字符的最长字串(C++)
思路:我们注意到,在上一种方法里,找到以某个字符为开头的最长不重复子串的循环终止条件就是当前子串的中某处和子串尾出现了相同的字符。因此这就告诉我们了,如果把当前子串的头移动到子串中某处的后一位,那么当前子串一定是一个不重复的串,所以这个信息也就意味着我们可以重复利用这一个串一直往后找,因此就没必要每轮都从起始的字符的头开始找。而且上面用的是头指针来控制循环的,但我们知道,实际上尾指针走到了字符串末尾,最长不重复的子字符串长度就可以确定下来,结束循环,因此这里我们采用尾指针来控制循环。原创 2022-03-18 17:40:14 · 949 阅读 · 0 评论