- 博客(203)
- 收藏
- 关注
原创 763. 划分字母区间
例如,字符串 “ababcc” 能够被分为 [“abab”, “cc”],但类似 [“aba”, “bcc”] 或 [“ab”, “ab”, “cc”] 的划分是非法的。然后我们遍历字符串,索引i表示当前片段的末尾位置,lastIdx表示当前片段内字母出现的最远位置,当片段进入一个新的字母,我们就需要更新lastIdx,直到i==lastIdx,就说明这个片段内的所有字母都包含在这个片段中了。就是所有的这个字母都在这个片段中,也就是这个字母最后出现的位置小于等于片段的末尾位置。输出:[9,7,8]
2025-07-09 16:33:20
109
原创 45. 跳跃游戏2
核心思想就是要想跳跃次数最小,那么就每一步都往能够到达的最远处跳。这样每跳一步,我们都能够刷新一些新的可以到达的位置,然后遍历这些新位置,更新能够到达的最远距离。每个元素 nums[i] 表示从索引 i 向后跳转的最大长度。返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。输入: nums = [2,3,1,1,4]解释: 跳到最后一个位置的最小跳跃数是 2。
2025-07-09 15:27:08
54
原创 55. 跳跃游戏
初始时maxDis为0,表示我们只能在第0个位置跳,第0个位置最多可以跳两步,那就意味着我们最远可以到达2这个位置,也就意味着我们可以去1和2这两个位置继续跳,不断地刷新我们的最远距离,直到超过n-1。maxDis还限制着我们能够访问的元素,maxDis以内是我们能够到达的元素,那么我们就可以到这些位置去跳跃,以此来更新maxDis。我们维护一个能都到达的最远位置maxDis,如果maxDis >= n - 1,则说明能够到达最后一个下标,返回true。输入:nums = [2,3,1,1,4]
2025-07-08 17:30:53
110
原创 121. 买卖股票的最佳时机1
我们不知道哪天卖出获得的利润最大,那如果我们能知道每一天卖出股票能获得的最大利润,那么所要求的最大利润就是这n天中利润最大的那一天卖出所收获的利润。如果我们知道第 i 天 之前股票的最低价格preMin,那么第 i 天卖出能获得的最大利润 = prices[i] - preMin。解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。
2025-07-08 16:58:23
69
原创 347. 前K个高频元素
有了所有元素的出现次数,我们只需要知道出现的最高次数maxCnt,然后创建一个长度为maxCnt+1的数组buckets用来存储出现次数相同的元素。buckets[i]表示出现次数为i的所有元素。给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。要返回出现频率前k高的元素,那么我们首先肯定要知道每个元素出现的次数,我们可以借助Map来实现。输入: nums = [1,1,1,2,2,3], k = 2。最后倒序遍历bucket,输出前k个元素即可。
2025-07-08 16:08:32
122
原创 84. 柱状图中最大的矩形
它的宽取决于heights[i]这个高度能够以i为中心向左右分别延伸多远的距离,也就是说从i向分别向左右扩张,直到遇到第一个小于它的柱子,记为left[i]和right[i],那么矩阵的width=right[i] - left[i] + 1。既然在第一个for循环里我们同时计算出了left[i]和right[i],那么我们就可以更新ans了,也就是说,不必在用left[i]和right[i]记录下来,之后再计算了, 直接一个for循环搞定。而对于每个矩阵,它的高为heights[i],它的宽是多少呢?
2025-07-07 21:30:32
222
原创 739. 每日温度
当我们从左到右遍历每一天的温度,我们是不知道后面哪一天的温度比这天高的,所以我们不能立马计算出answer[i],那么我们就需要先把i用一个栈存起来,表示还未找到更高温度的天,然后继续往后遍历,但是在遍历的过程中,我们需要先看看这天的温度是否比栈顶那天的温度高,如果是,则栈顶元素找到了答案,出栈并计算答案,然后继续和栈顶元素比较,直到栈空或者遇到大于当前温度的天。输入: temperatures = [73,74,75,71,69,72,76,73]输出: [1,1,4,2,1,1,0,0]
2025-07-07 17:14:15
185
原创 394. 字符串解码
分别用到两个栈,一个是mutilStack用来存储括号里的字符串的重复次数,一个preStack用来存储括号里的字符串重复之后需要拼接的前缀字符串。当遇到 ‘]’ 时,就把重复次数和前缀出栈,然后把当前字符串重复curMutil次拼接在前缀后面,最后把拼接好的字符串再赋给curStr继续遍历。此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。输出:“accaccacc”
2025-07-05 23:53:07
112
原创 155. 最小栈
这道题的考点就在于如何在常数时间内获取到栈中的最小元素。我们只需要在push的时候,将val和以val为栈顶的最小值同时入栈,也就是说栈中的元素是一个int[]数组,保存val和以val为栈顶的栈中最小值。设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。void push(int val) 将元素val推入堆栈。那么只需要知道栈顶元素,我们就可以知道此时栈中的最小值了。int getMin() 获取堆栈中的最小元素。int top() 获取堆栈顶部的元素。
2025-07-05 21:21:04
147
原创 20. 有效的括号
这道题我们只需要遍历字符串,遇到一个左括号就将它保存起来,遇到一个有括号就把最新保存的左括号拿出来比较是不是它对应的左括号,也就是说最新保存的左括号先拿出来比较,那么我们自然就想到用栈这个数据结构来保存左括号。注意的是,如果在比较过程中,遇到一个右括号但是栈为空时,也可以直接返回false。给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。然后可以用一个Map来保存右括号和左括号的映射关系,方便与栈顶的左括号进行比较。左括号必须用相同类型的右括号闭合。
2025-07-05 21:02:14
120
原创 4. 寻找正序数组的中位数
也就是一种划分情况,枚举i的个数,也就得到不同的左右部分划分情况,其中只有一个划分情况能够满足左边部分的最大值小于右边部分的最小值,此时也就找到了中位数,如果数组元素个数是奇数,中位数=左边部分的最大值,如果是偶数,则中位数=(左边部分最大值 + 右边部分最小值)/ 2。满足条件的划分是唯一的,并且此时的 i 是满足nums1[i] <= nums2[j + 1]的最大值,而这个i我们可以通过二分的方法来查找。,所以我们如果知道了i,自然也就知道了j,也就得到了。输出:2.00000。
2025-07-05 20:28:52
228
原创 33. 搜索旋转排序数组
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2]。输入:nums = [4,5,6,7,0,1,2], target = 0。而查找旋转排序数组的最小值正好对应。
2025-07-04 22:12:29
209
原创 153. 寻找旋转排序数组中的最小值
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]]。如果nums[mid] <= nums[n - 1],那么最小值一定在mid的左边,或者mid就是最小值所在位置,则可以更新right。解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
2025-07-04 21:29:12
109
原创 34. 在排序数组中查找元素的第一个和最后一个位置
这样循环结束后的left就是第一个大于等于target的位置,如果等于target,则是target在数组中的开始位置;其实我们在找结束位置时,可以不用新的二分查找逻辑,我们只需要复用查找开始位置的二分查找逻辑即可,只不过我们查找的不再是target的开始位置,而是target+1的开始位置,我们找到了target+1的开始位置,那么该位置的前一个位置自然就是target的结束位置了。如果没有target的开始位置,说明数组中没有这个元素,自然也就不必再找结束位置了,可以提前返回答案。
2025-07-03 21:46:06
165
原创 74. 搜索二维矩阵
如果我们将矩阵按行拼接成一个一维矩阵,那么就是一道常规的二分查找题目,只需令left=0,right=m*n - 1,然后来更新mid即可。现在问题是如何通过mid获取到矩阵中的元素,有了mid,mid_i = mid / n, mid_j = mid % n。输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3。给你一个整数 target ,如果 target 在矩阵中,返回 true;每行的第一个整数大于前一行的最后一个整数。
2025-07-03 20:58:23
243
原创 35. 搜索插入位置
如果nums[mid] > target,那么mid就是第一个大于target的元素位置,插入位置就是该位置。由于right = mid - 1,那么right指向已经改变,所以插入位置就是left和mid指向的位置。如果nums[mid] < target,那么mid就是最后一个小于target的元素位置,插入位置应该是下一个位置。由于left= mid + 1,也就正好是需要插入的位置。思考退出循环前的最后一次循环,这一次循环肯定是left,right,mid指向相同位置。就是常规的二分法解题思路。
2025-07-03 17:16:43
139
原创 51. N皇后
同样也有2n-1条↖斜线,每条斜线的行号-列号是相等的,但是值是从-(n-1),-(n-2)…0,1,2,n-1,所以不能直接映射到bool数组的下标,需要先将行号-列号的值+(n-1),从而将每条斜线的值映射到0到2n-2。对于n*n的二维数组,一共有2n-1条↗斜线,每条斜线的行号+列号都是相等的,并且每条斜线的值依次从0到2n-2递增,所以bool数组的每个元素就对应一条↗斜线。n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
2025-06-27 18:24:11
356
原创 131. 分割回文串
对于每层递归,我们去遍历所有可能的分割点,然后判断起始点到分割点的子串是否是回文串,如果是则可以将子串加入path并继续往下分割。给你一个字符串 s,请你将 s 分割成一些 子串,使每个子串都是 回文串。返回 s 所有可能的分割方案。这道题还是通过回溯的方法暴力枚举所有可能的分割情况。当分割起点=字符串s的长度时,就是收获结果的时候。输出:[[“a”,“a”,“b”],[“aa”,“b”]]输入:s = “aab”
2025-06-27 16:47:18
105
原创 22. 括号生成
我觉得本质上来说,就是从数组中[‘(’, ‘)’]可重复地选择元素,生成一个长度为2n的括号组合。4、因为我们的path是使用的字符数组,直接覆盖掉了之前的值,所以不用恢复现场。只用恢复cnt1和cnt2即可。数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。3、当左括号和有括号的数量都等于n时,就是收获结果的时候。2、左括号的数量不能小于有括号的数量。1、左括号的数量不能超过n。
2025-06-26 20:59:50
185
原创 39. 组合总和
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。3、因为同一个数字可以无限制重复被选取,也就意味着上一层选取了的元素,下一层也可以选取,那么在递归调用backtrack的时候startIdx就保持不变。2、因为是求组合,那么结果和元素顺序无关,所以回溯方法的参数需要一个startIdx记录当前层的选择元素的开始索引。总体上这道题采用回溯的方法解决。
2025-06-26 20:21:19
206
原创 208. 实现Trie(前缀树)
这道题就是构造一个26叉树,分别代表26个字母,然后将单词拆分成一个个字母,从上至下为每一个字母找到它存放的位置,因此每个单词在该树中都拆分成一条路径,并且需要标识单词最后一个字母结束的位置。以便分清以某一个字母结束的路径组成的词是单词还是前缀。boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);例如apple,第一个字母是a,那么它对应的就是root的第a- 'a’个子节点,p对应的就是a的第p-'a’个子节点,以此递推。
2025-06-25 09:51:26
190
原创 207. 课程表
在选修某些课程之前需要一些先修课程。先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi。那么问题就转换为在这个有向图中找环,如果有则不能完成所有课程,如果没有则可以完成。我们可以遍历访问图中的每个节点,节点的状态有三种,分别是0:未访问,1:访问中,2:已访问。例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1。就是在dfs过程中遇到处于访问中的节点。
2025-06-24 18:17:21
202
原创 994. 腐烂的橘子
腐烂的橘子我们用一个队列q来存储,当队列不为空时,每过一分钟,腐烂的橘子就会向外扩散一层。我们需要把当前层的橘子出队,然后把它扩散到的橘子入队,直至队列为空或者没有新鲜橘子了。这是一道多源BFS的题,首先我们需要知道初始时有哪些腐烂的橘子(接下来会以这些橘子为源头向外扩散)和新鲜的橘子(用于最后判断是否还有剩余新鲜橘子)。最后如果还有新鲜橘子就说明单元格中不可能没有新鲜橘子,否则返回ans的分钟数。每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。值 2 代表腐烂的橘子。
2025-06-24 15:39:00
223
原创 200. 岛屿数量
这道题我们遍历网格,当发现陆地时,就说明我们踏上了一个岛屿,我们就把它做上标记(标记可以是任何不是1的值),然后递归地往四个方向相邻的陆地走,把这个岛屿上的所有陆地都做上标记。最后把岛屿数量加1。给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。注意往四个方向走的时候需要判断数组是否越界。此外,你可以假设该网格的四条边均被水包围。输入:grid = [
2025-06-23 22:01:25
144
原创 124. 二叉树中的最大路径和
二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次。该路径 至少包含一个 节点,且不一定经过根节点。需要注意的是dfs返回的是当前子树的最大链和,并且不能为负,如果为负的话这条链路之和对它的父节点没有增益效果,则返回0.我觉得这道题和求二叉树的直径是类似的,只不过直径是求路径最长,这道题是求路径上的节点值之和最大。给你一个二叉树的根节点 root ,返回其 最大路径和。路径和 是路径中各节点值的总和。不过也是在遍历的过程中收集答案。
2025-06-23 20:32:43
136
原创 236. 二叉树的最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。有可能找到一个目标(p或q),那么就需要往父类节点返回结果,直到遇到一个父类节点的另一个子节点也有返回值,那么这个父类节点就是最近公共祖先。因为到找到p了,q要么在它的子类节点,要么不在。输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1。左右子树只有一个找到目标,
2025-06-23 20:06:21
273
原创 437. 路径总和 三
题目中的路径不需要从根节点开始,也不需要在叶子节点结束,其实就相当于一条子路径,如果我们知道从根节点到它的起点的前缀和以及从根节点到它的终点的前缀和,那么这条子路径上节点值的和就是两者之差。而不需要恢复s,是因为s是基本数据类型,是通过值传递的方式传递到每一层的递归函数的,所以在函数内的修改不会影响到上一层的s,所以不需要恢复,而map是引用数据类型,在这一层的修改会影响到上一层的map,所以需要恢复现场。路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
2025-06-23 16:46:08
181
原创 105. 从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。前序遍历序列的第一个元素就是根节点,然后在中序遍历序列中找到根节点的位置,它的前面就是左子树的中序遍历,后面部分就是右子树的中序遍历。这样我们就分别得到了左子树和右子树的前序遍历和中序遍历。这是和原问题一样的子问题,可以用递归问题解决。根据左子树的大小可以将前序遍历分为左子树的前序遍历和右子树的前序遍历。
2025-06-22 21:44:23
185
原创 114. 二叉树展开为链表
采用头插法的方式建立链表,那么建立链表的顺序依次为6-5-4-3-2-1,也就意味着我们需要以右子树–左子树–根节点的顺序遍历二叉树,遍历到一个节点就把他以头插法的方法添加到当前链表中。不妨以head表示当前链表的头部,初始为null。展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null。展开后的单链表应该与二叉树 先序遍历 顺序相同。
2025-06-22 20:17:00
209
原创 199. 二叉树的右视图
给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。层序遍历,然后记录每一层的最后一个元素就是右视图中的节点。
2025-06-22 13:13:08
142
原创 230. 二叉搜索树中第K小的元素
给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 小的元素(从 1 开始计数)。由于中序遍历就是在从小到大遍历节点值,所以遍历到的第 k 个节点值就是答案。
2025-06-22 12:52:50
159
原创 98. 验证二叉搜索树
注意preVal的初始值为long型的最小值,因为题目的节点值可以取到int型的最小值,如果第一个遍历的节点值刚好等于int型的最小值就会出现误判(和preVal的初始值相等了,导致返回false)。利用二叉搜索树的中序遍历是严格的升序序列,如果中序遍历过程中当前节点值小于等于上一个节点值,那么就说明不是严格递增的,自然也就不是二叉搜索树了。给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。
2025-06-21 22:21:10
252
原创 108. 将有序数组转换为二叉搜索树
找到数组的中间元素,作为平衡二叉树的root节点,中间元素左半边子数组转换为的平衡二叉树就是root节点的左子树,右半边子数组转换为的平衡二叉树就是root节点的右子树。所以就将原问题转换为两个子问题,又root节点+左半部分数组转换的平衡二叉树+右半部分数组转换的平衡二叉树,故可用递归方法解决。给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。
2025-06-21 21:53:37
176
原创 102. 二叉树的层序遍历
这道题思路比较简单,就是用一个队列来存储数据,一个node出队就把他的左右子树入队,用n来记录当前层的节点数量。给你二叉树的根节点 root ,返回其节点值的 层序遍历。(即逐层地,从左到右访问所有节点)。主要是有一些常用方法需要记住。
2025-06-20 22:18:09
201
原创 543. 二叉树的直径
我们可以计算在每个node处拐弯的最长路径,并用这个最长路径来更新答案。而每个node处拐弯的最长路径可以用左子树的最大链长(node到叶子节点的路径长度)和右子树的最大链长来表示。而求树的最大链长和求树的最大深度类似,可以用递归函数解决。二叉树的 直径 是指树中任意两个节点之间最长路径的 长度。这条路径可能经过也可能不经过根节点 root。注意:null节点的最大链长应该返回-1,这样叶子节点的最大链长才为0;给你一棵二叉树的根节点,返回该树的 直径。两节点之间路径的 长度 由它们之间边数表示。
2025-06-20 21:25:17
205
原创 101. 对称二叉树
那么左右两个子树什么时候是镜像对称的呢?给你一个二叉树的根节点 root , 检查它是否轴对称。一个二叉树是轴对称等价于它的左右子树是镜像对称的。2、左子树的右子树与右子树的左子树镜像对称。3、左子树的左子树与右子树的右子树镜像对称。1、左右子树根节点相等。
2025-06-19 21:07:22
144
原创 104. 二叉树的最大深度
将大问题转换为子问题,二叉树的最大深度等于左右子树的最大深度+1;二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。给定一个二叉树 root ,返回其最大深度。
2025-06-19 20:29:02
184
原创 94.二叉树的中序遍历
二叉树的中序遍历为先左子树->根节点->右子树,对于左子树和右子树也需要按照这个顺序访问,所以适合用递归的方法解决。同时需要掌握前序和后序遍历。给定一个二叉树的根节点 root ,返回 它的 中序 遍历。
2025-06-19 20:21:56
112
原创 23. 合并K个升序链表
用mergeList(初始为null)表示已经合并的有序链表,只需要遍历链表数组,将每个链表合并到mergeList得到新的有序链表。上面是属于暴力做法,时间复杂度比较高。改进的思路是把lists一分为二,先合并前一半链表,再合并后一半链表,最后再将这两部分合并。输入:lists = [[1,4,5],[1,3,4],[2,6]]请你将所有链表合并到一个升序链表中,返回合并后的链表。给你一个链表数组,每个链表都已经按升序排列。输出:[1,1,2,3,4,4,5,6]将它们合并到一个有序链表中得到。
2025-06-19 14:10:34
150
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人