自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(189)
  • 收藏
  • 关注

原创 hot100 146.LRU缓存

一开始哨兵节点sentinel的prev和next都指向sentinel。随着节点的插入,sentinel的next指向链表的第一个节点(最上面的书),sentinel的prev指向链表的最后一个节点(最下面的书)。答:在删除链表末尾节点的时候,也要删除哈希表中的记录,这需要知道末尾节点的key。(2)空间复杂度:O(min(p,capacity)),其中p为put的调用次数。写法一:标准库(面试一般不让调用标准库,需手写链表)。(1)时间复杂度:所有操作均为O(1)。写法二:手写双向链表。

2025-12-31 12:49:19 197

原创 hot100 23.合并K个升序链表

2.一个巧妙的思路是,把lists一分为二(尽量均分),先合并前一半的链表,再合并后一半的链表,然后把这两个链表合并成最终的链表。3.八八合并:把lists[0]和lists[4]合并(相当于合并前八条链表),合并后的链表保存在lists[0]中;2.四四合并:把lists[0]和lists[2]合并(相当于合并前四条链表),合并后的链表保存在lists[0]中;把lists[2]和lists[3]合并,合并后的链表保存在lists[2]中,以此类推。(2)空间复杂度:O(m),堆中至多有m个元素。

2025-12-30 21:28:31 921

原创 hot100 148.排序链表

从图形上理解,递归深度是O(logn),每一层的链表长度之和是O(n),计算高为O(logn),底边长为O(n)的矩形面积,得到O(nlogn)。例如[4,2,1,3],把第一个节点和第二个节点归并,第三个节点和第四个节点归并,得到[2,4,1,3]。例如[2,4,1,3],把前两个节点和后两个节点归并,得到[1,2,3,4]。(5)分割出两段长为step的链表,合并,把合并后的链表插到新链表的末尾。(4)以此类推,直到归并的长度大于等于链表的长度为止,此时链表已经是有序的了。

2025-12-29 11:57:25 367

原创 hot100 138.随机链表的复制

(5)举例:有一个链表1->2->3,依次复制每个节点(创建新节点并复制val和next),把新节点直接插到原节点的后面,形成一个交错链表:1->1'->2->2'->3->3'。(7)然后遍历这个交错链表,假如节点1的random指向节点3,那么就把节点1'的random指向节点3的下一个节点3',这样就完成了对random指针的复制。1.题目要求:深拷贝一个链表,要求新链表中的每个节点都是新创建的,并且这些节点的random指针都指向新链表中的相应节点。(1)时间复杂度:O(n),其中n是链表的长度。

2025-12-28 19:45:48 303

原创 hot100 25.K个一组翻转链表

7.特殊情况:当翻转部分的长度不足k时,在定位end完成后,end == null,已经到达末尾,说明题目已经完成,直接跳出循环return即可。4.初始时需要两个变量pre和end,pre表示待翻转链表的前驱,end表示待翻转链表的末尾。6.翻转链表,然后将三部分链表连接起来,然后重置pre和end指针,然后进入下一次循环。3.需要记录翻转链表的前驱和后继,方便翻转完成后把已翻转和未翻转的部分连接起来。1.时间复杂度:O(n*K),最好的情况为O(n),最差的情况为O(n^2)。

2025-12-26 19:31:27 239

原创 hot100 24.两两交换链表中的节点

(1)递归边界:如果head或者head.next为空,说明剩余节点不足两个,无需交换,返回head。(2)先交换以node3为头节点的链表,即递归调用swapPairs(node3)。(2)空间复杂度:O(n),递归需要O(n)的栈空间。(1)时间复杂度:O(n),其中n为链表的长度。(2)空间复杂度:O(1),仅用到若干额外变量。(1)时间复杂度:O(n),其中n为链表的长度。(5)返回node2,作为交换后的链表头节点。(3)把node1指向递归返回的链表头。(4)把node2指向node1。

2025-12-26 18:01:25 259

原创 hot100 19.删除链表的倒数第N个节点

题解见。

2025-12-26 17:31:03 107

原创 hot100 2.两数相加

(2)循环即遍历链表l1和l2,每次把两个节点值l1.val,l2.val与进位值carry相加,除以10的余数即为当前节点需要保存的数位,除以10的商即为新的进位值。代码实现时,有一个简化代码的小技巧,如果递归中发现l2的长度比l1更长,那么可以交换l1和l2,保证l1不是空节点,从而简化代码逻辑。2.每次把两个节点值l1.val,l2.val与进位值carry相加,除以10的余数即为当前节点需要保存的数位,除以10的商即为新的进位值。(1)时间复杂度:O(n),其中n为l1长度和l2长度的最大值。

2025-12-25 21:11:04 191

原创 hot100 21.合并两个有序链表

2.比较list1和list2的节点值,如果list1的节点值较小,则把list1加入到新链表的末尾,然后把list1替换成它的下一个节点。——如果list1的节点值更小,那么就取出list1,递归调用mergeTwoLists(list1.next,list2),拿到递归返回的链表,把list1插在前面。——如果list2的节点值更小,那么就取出list2,递归调用mergeTwoLists(list1,list2.next),拿到递归返回的链表,把list2插在前面。二、方法二:递归(头插法)。

2025-12-25 20:09:07 242

原创 hot100 142.环形链表Ⅱ

见。

2025-12-25 19:21:24 140

原创 hot100 141.环形链表

这个时候用“相对速度”思考,慢指针不动,快指针相对于慢指针每次只走一步,那么快慢指针一定会相遇。slow在fast的后面,如果fast不为空,那么slow也肯定不为空。也就是fast在探路,slow走的都是fast走过的路。1.思路:快慢指针法。如果链表有环的话,快指针一定可以在一段时间后追上慢指针,这两个指针一定会相遇。2.注意:代码比较两个节点的时候,比较的是内存地址是否一致,并没有比较节点的val。(1)快指针会不会跳过慢指针,从来不会和慢指针相遇呢?(1)时间复杂度:O(n),其中n是链表的长度。

2025-12-25 18:55:11 213

原创 hot100 234.回文链表

第二张图反转链表后,我们得到了两条链表:一条是1->2->3->4,另一条是6->5->4。4.然后把中间节点到链表末尾反转,如上图所示,反转后得到链表6->5->4,其头节点记作head2,这样就能从head2开始,依次访问原链表的最后一个节点、倒数第二个节点、倒数第三个节点...。第一张图反转链表后,我们得到了两条链表:一条是1->2->3,另一条是5->4->3。7.问:为什么不反转整个链表,这样也可以访问原链表的最后一个节点、倒数第二个节点、倒数第三个节点......?(2)空间复杂度:O(1)。

2025-12-24 20:55:35 227

原创 hot100 206.反转链表

1.思路:比如链表为1->2->3,创建一个新的空链表,然后用头插法依次把节点1,2,3插到这个新链表的头部,就得到了链表3->2->1,这正是反转后的链表(头插法就是把一个节点插入到链表的头节点,那么node就插在了链表的左侧,新链表的头节点就为node)。(2)空间复杂度:O(n),递归需要O(n)的栈空间。(1)时间复杂度:O(n),其中n为链表节点的个数。(1)时间复杂度:O(n),其中n为链表节点的个数。(3)第三轮循环结束后,得到链表3->2->1。(2)第二轮循环结束后,得到链表2->1。

2025-12-24 14:21:04 192

原创 hot100 160.相交链表

具体来说:如果p不是空节点,那么更新p为p.next,否则更新p为headB;如果q不是空节点,那么更新q为q.next,否则更新q为headA。(1)时间复杂度:O(m + n),其中m是第一条链表的长度,n是第二条链表的长度。除了交点,每个节点都会被指针p访问至多一次,每个节点都会被指针q访问至多一次。(4)循环结束时,如果两条链表相交,那么此时p和q都在相交的起始节点处,返回p;如果两条链表不相交,那么p和q都在空节点,所以也可以返回p,即空节点。(2)不断循环,直到p = q。

2025-12-24 13:28:56 161

原创 hot100 240.搜索二维矩阵Ⅱ

2.总结:利用matrix行列有序的性质,我们可以用O(1)的时间获取O(m)或O(n)的信息。相比之下,O(mn)的暴力查找(一个一个地找),每次花费O(1)的时间,只获取了O(1)的信息。(1)时间复杂度:O(m + n)。其中m和n分别为matrix的行数和列数,每次循环排除掉一行或者一列,一共m + n行列,最坏情况下需要排除m + n - 1行列才能找到答案。(2)空间复杂度:O(1)。

2025-12-24 11:23:56 219

原创 hot100 48.旋转图像

(5)(i,j)->(j,n - 1 - i)可以通过两次翻转操作得到:(i,j)->(转置)(j,i)->(行翻转)(j,n - 1 - i)。(4)所以位于第i行第j列的元素,去到第j行第n - 1 - i列,即(i,j)->(j,n - 1 - i)。——行翻转:就是把每一行都翻转,位于(j,i)的元素去到(j,n - 1 - i)。——转置:就是把矩阵按照主对角线翻转,位于(i,j)的元素去到(j,i)。——第i行的元素去到第n - 1 - i列(i从0开始)。——第j列的元素去到第j行。

2025-12-22 15:59:18 450

原创 hot100 54.螺旋矩阵

2.用一个长为4的方向数组DIRS = [(0,1),(1,0),(0,-1),(-1,0)]分别表示右下左上四个方向,同时用一个下标di表示当前方向,初始值设为0,表示一开始向右。一般地,每4组都会把矩阵最外面的一圈去掉(就像剥洋葱),矩阵的行数会减少2,列数会减少2,所以行列的减少是有规律的。走n步即1,2,3,4。其中,第1,3,5组都是向右或向左走的,长度依次为4,3,2。其中,第2,4组都是向下或向右走的,长度依次为2,1。(1)从(0,-1)开始(即把初始值设为(0,0)左边的元素)。

2025-12-22 13:13:44 484

原创 hot100 73.矩阵置零

对于matrix[i][j],如果rowHasZero[i] = true或colHasZero[j] = true,则说明i行有0或者j列有0,于是把matrix[i][j]变为0。对于matrix[i][j],如果matrix[i][0] = 0或者matrix[0][j] = 0,则说明i行有0或者j列有0,于是把matrix[i][j]变为0。2.规则:对于matrix[i][j],如果i行有0,或者j列有0,那么把matrix[i][j]变成0,否则matrix[i][j]不变。

2025-12-21 20:57:43 610

原创 hot100 41.缺失的第一个正数

2,但由于nums[nums[2]] = nums[1] = 1,所以nums[2]是个影分身,并且其真身坐在了正确的座位上,所以可以忽略nums[2],向后遍历。(3)一般地,为了兼容“当前学生是真身,坐在正确的座位上”和“当前学生是影分身,且其真身坐在正确的座位上”这两种情况,我们可以把i = nums[i]套一层nums[i],用nums[i] = nums[nums[i]]判断。(3)向后遍历,nums[2] = 4,他应当坐在nums[4]上,所以他和nums[4]交换。

2025-12-21 16:21:15 681

原创 hot100 238.除自身以外的数组的乘积

(1)要计算pre[i],可以先计算出nums[0]到nums[2]的乘积pre[i - 1],再乘上nums[i - 1],就得到了pre[i]。即pre[i] = pre[i - 1] * nums[i - 1]。(2)同理可得,post[i] = post[i + 1] * nums[i + 1]。(2)定义post[i]表示从nums[i + 1]到nums[n - 1]的乘积。(1)定义pre[i]表示从nums[0]到nums[i -1]的乘积。(2)空间复杂度:O(1),返回值不计入。

2025-12-21 14:39:25 144

原创 hot100 189.轮转数组

(2)反转后数组变成了[7,6,5,4,3,2,1],拆分成[7,6,5] + [4,3,2,1],对比最终目标,只需要把[7,6,5]反转,把[4,3,2,1]反转,就得到了[5,6,7,1,2,3,4]。(1)把[1,2,3,4,5,6,7]看成[5,6,7] + [1,2,3,4],首先要保证[5,6,7]在[1,2,3,4]的前面,这可以通过反转[1,2,3,4,5,6,7]得到。1.根据示例一,要把[1,2,3,4,5,6,7]变成[5,6,7,1,2,3,4]。(2)空间复杂度:O(1)。

2025-12-21 14:07:13 199

原创 hot100 56.合并区间

思路:题解见代码随想录专栏。

2025-12-21 12:10:28 134

原创 hot100 53.最大子数组和

2.可以一边遍历数组计算前缀和,一边维护前缀和的最小值(相当于股票的最低价格),用当前的前缀和(卖出价格)减去前缀和的最小值(买入价格),就得到了以当前元素结尾的子数组和的最大值(利润),用它来更新答案的最大值(最大利润)。(2)如果nums[i]和前面的子数组拼起来,也就是在以nums[i - 1]为结尾的最大子数组和之后添加nums[i],那么dp[i] = dp[i - 1] + nums[i]。(1)如果nums[i]单独组成一个子数组,那么dp[i] = nums[i]。

2025-12-21 11:44:12 540

原创 hot100 76.最小覆盖子串

5.遍历s,设当前枚举的子串右端点为right,把字母c = s[right]的出现次数加1。减一前,如果cntS[x] = cntT[x],说明x的出现次数不满足要求,把less加1。3.初始化left = 0,以及一个空哈希表(或者数组)cntS,用来统计s子串中的每个字母的出现次数。答:s的子串BANC中每个字母的出现次数,都大于等于t = ABC中的每个字母的出现次数,这就叫涵盖。——重复以上三步,直到less > 0,即cntS有字母的出现次数小于cntT中该字母的出现次数为止。

2025-12-20 19:56:03 492

原创 hot100 239.滑动窗口最大值

这是因为窗口在一步一步地向右滑动(像只蜗牛),所以元素也是一个一个地离开窗口,不会出现同一轮循环中有多个元素离开窗口的情况。为什么代码中的队首离开窗口写的是if而不是while?1.右边入(元素进入队尾,同时维护队列的单调性)。思路:利用单调队列维护滑动窗口。3.记录/维护答案(根据队首)。2.左边出(元素离开队首)。

2025-12-19 20:02:35 192

原创 hot100 560.和为K的子数组

1.前缀和的定义:s[0] = 0,s[i] = nums[0] + nums[1] + ... + nums[i - 1]。设i < j,如果nums[i]到nums[j - 1]的元素和等于k,用前缀和表示就是s[j] - s[i] = k。要找的是j左边有多少个s[i] = 1。3.枚举右节点,维护左节点:以nums = [1,1,-1,1,-1],k = 1为例,其前缀和数组为s = [0,1,2,1,2,1]。(2)可以把s[j] - s[i] = k移项,得到s[i] = s[j] - k。

2025-12-19 19:05:07 329

原创 hot100 438.找到字符串中所有字母异位词

所以只要s'的长度等于p的长度,就说明s'的每种字母的出现次数和p的每种字母的出现次数都相同,就说明s'是p的异位词,于是把s'的左端点下标加入答案。枚举子串s'的右端点,如果发现s’其中一种字母的出现次数大于p的这种字母的出现次数,则右移s'的左端点(缩小窗口)。如果发现s'的长度等于p的长度,则说明s'的每种字母的出现次数等于p的每种字母的出现次数,即s'是p的异位词。如果s'的每种字母的出现次数和p的每种字母的出现次数都相同,那么s'是p的异位词,并把s'的左端点下标加入答案。

2025-12-18 20:42:21 229

原创 hot100 3.无重复字符的最长子串

1.时间复杂度:O(n)。2.空间复杂度:O(1)。(一)方法一:整型数组。(二)方法二:布尔数组。

2025-12-18 20:01:31 131

原创 hot100 42.接雨水

题解见代码随想录专栏。

2025-12-18 12:36:14 162

原创 hot100 15.三数之和

2.优化二:如果nums[i]与后面最大的两个数相加nums[i] + nums[n - 2] + nums[n - 1] < 0,那么内层循环不可能存在三数之和等于0,但继续枚举,nums[i]可以变大,所以后面还有机会找到三数之和等于0,continue外层循环(跳过本次迭代,进入下一次循环迭代)。(1)在外层循环中,如果发现nums[i] = nums[i - 1],那么nums[i]与后面两个数组成的和为0的三元组,nums[i - 1]也能组成一模一样的三元组,这就重复了。

2025-12-16 19:39:33 137

原创 hot100 11.盛水最多的容器

(a)由(2)推理可知,如果固定左边的柱子,移动右边的柱子,那么水的高度一定不会增加,且宽度一定减少,所以水的面积一定减少。水的宽度是两根柱子之间的距离d = 8,水的高度取决于两根柱子之间较短的那个,即左边柱子的高度h = 3。(4)一开始,先检查右上方的单元格(0,7),即考虑最左边的0号柱子和最右边的7号柱子,计算它们之间容纳水的面积,然后比较一下两根柱子的高度,关注其中较短的一根。(c)如果移动右边的柱子,新的水面高度一定不会超过左边柱子的高度3,也就是不会超过现在水面的高度。

2025-12-16 18:33:27 223

原创 hot100 283.移动零

5.由于每次操作后,[i0,i - 1]对应的元素值全为0这一性质始终成立,所以nums遍历结束后(i == n),[i0,n - 1]对应的元素值全为0,且[0,i0 - 1]都是交换过去的非0元素,这样就满足了题目“将所有的0移动到数组的末尾”的要求。(2)举例:如nums = [0,0,1,2],把1放到最左边的空位上,数组就变成了[1,0,0,2]。= 0的情况,就把nums[i]移动到最左边的空位上,也就是交换nums[i]和nums[i0]。(1)时间复杂度:O(n),其中n是nums的长度。

2025-12-16 16:23:13 375

原创 hot100 128.最长连续序列

各个连续序列(链)是相互独立的,如果发现其中一条链的长度至少为m/2(长度×2>=m),由于不可能还有一条长度大于m/2的链(否则这两条链的长度之和就超过m了),答案不会再增大,此时可以直接返回答案。如果nums =[1,1,1,...,1,2,3,4,5,...](前一半都是1),遍历nums的做法会导致每个1都跑一个O(n)的循环,总的循环次数是O(n^2),会超时。2.核心思路:对于nums中的元素x,以x为起点,不断查找下一个数x + 1,x + 2,...是否在nums中,并统计序列的长度。

2025-12-16 12:57:14 223

原创 hot100 49.字母异位词分组

(3)因此,示例1返回的二维列表中,包含三个列表,分别为:[eat,tea,ate],[tan,nat],[bat],三个列表的顺序随意。2.举例:以示例1为例。输入:strs = [eat,tea,tan,ate,nat,bat]。(1)每个字符串各自排序,得到aet,aet,ant,aet,ant,abt。——排序后是aet的字符串,排序前是eat,tea,ate。——排序后是ant的字符串,排序前是tan,nat。——排序后是abt的字符串,排序前是bat。

2025-12-15 19:28:22 118

原创 hot100 1.两数之和

1.思路:先枚举下标i,再枚举下标j,然后判断nums[i] + nums[j] == target。(1)时间复杂度:O(n^2),两层for循环,其中n为nums的长度。(2)空间复杂度:O(n),哈希表需要O(n)的空间。(1)时间复杂度:O(n),其中n为nums的长度。(2)空间复杂度:O(1),仅用到了若干额外变量。1.思路:如下图所示。

2025-12-15 17:38:49 180

原创 代码随想录 109.冗余连接Ⅱ

(2)题目要求:有一个有向图,是由一棵有向树 + 一条有向边组成的(所以此时这个图就不能称之为有向树),现在要求找到这条有向边并将其删除,使得这个图可以恢复为有向树。节点3的入度为2,但在删除边的时候,由于存在有向环,只能删这条边(节点1->节点3),如果删除边(节点4->节点3),那么删除后本图也不是有向树了,因为找不到根节点。(4)有向树的性质:对于一棵有向树,只有根节点的入度为0,其他节点的入度都为1(因为该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点)。

2025-12-15 13:36:58 280

原创 代码随想录 684.冗余连接

2.题目要求:对于一个无向图,返回一条可以删去的边,使得结果图是一个有着N个节点的树(即,只有一个根节点)。3.思路:可以从前向后遍历每一条边(因为优先让前面的边连上),边的两个节点如果不在同一个集合,就加入集合(即同一个根节点)。(2)如果边的两个节点已经出现在同一个集合里,则说明这条边的两个节点已经连在一起了,再加入这条边一定就出现环了,如下图所示。4.注意:题目已说明该图是在树的基础上添加一条边得到,因此只会有一条冗余边,因此可以在遇到同一个根的两个节点后直接返回即可。这道题也是并查集基础题目。

2025-12-15 11:07:45 174

原创 代码随想录 1971.寻找图中是否存在路径

【代码】代码随想录 1971.寻找图中是否存在路径。

2025-12-14 18:18:40 170

原创 代码随想录 并查集理论基础

(1)放到同一个数组或者set或者map中,这样就表示两个元素在同一个集合(但是这么多元素分门别类,可不止一个集合,可能是成百上千个集合,这时会定义很多的数组,不好实现)。这是因为find函数向上寻找根节点,father[u]表示u的父节点,那么让father[u]直接获取find函数返回的根节点,这样就让u的父节点变成根节点。(4)最后要判断两个元素是否在同一个集合里,如果通过find函数找到两个元素属于同一个根的话,那么这两个元素就是同一个集合,代码如下所示。(2)判断两个元素在不在同一个集合。

2025-12-14 16:36:26 903

原创 代码随想录 463.岛屿的周长

在这道题中,值为0表示非岛屿(不可遍历),值为1表示岛屿(可遍历),可以用2表示已经遍历过的岛屿。(6)如何在DFS遍历时求岛屿的周长:求岛屿周长的方法很多,如果用DFS遍历来求的话,有一种很简单的思路,那就是岛屿的周长就是岛屿方格和非岛屿方格相邻的边的数量。1.网格问题:网格问题是这样的一类搜索问题:由m×n个小方格组成一个网格,每个小方格与其上下左右的四个方格被认为是相邻的,要在这样的网格上进行某种搜索。(1)首先,每个方格与其上下左右的四个方格相邻,则DFS每次要分出四个岔。

2025-12-14 15:01:20 245

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除