Algorithm Advance
文章平均质量分 53
always on the way
夜澜听雨声
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
动态规划_爬楼梯
所以我的原则是:不考虑dp[0]如何初始化,只初始化dp[1] = 1,dp[2] = 2,然后从i = 3开始递推,这样才符合dp[i]的定义。还有就是dp[i - 2],上i-2层楼梯,有dp[i - 2]种方法,那么再一步跳两个台阶不就是dp[i]了么。首先是dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,那么再一步跳一个台阶不就是dp[i]了么。从递推公式dp[i] = dp[i - 1] + dp[i - 2];所以dp[i] = dp[i - 1] + dp[i - 2]。原创 2025-04-02 22:52:37 · 290 阅读 · 0 评论 -
贪心_摆动序列
dp[i][0] = max(dp[i][0], dp[j][1] + 1),其中0 < j < i且nums[j] < nums[i],表示将 nums[i]接到前面某个山谷后面,作为山峰。dp[i][1] = max(dp[i][1], dp[j][0] + 1),其中0 < j < i且nums[j] > nums[i],表示将 nums[i]接到前面某个山峰后面,作为山谷。设 dp 状态dp[i][1],表示考虑前 i 个数,第 i 个数作为山谷的摆动子序列的最长长度。原创 2025-04-02 22:42:37 · 332 阅读 · 0 评论 -
回溯_组合总和III
返回 所有可能的有效组合的列表。该列表不能包含相同的组合两次,组合可以以任何顺序返回。我们说过,回溯法虽然是暴力搜索,但也有时候可以有点剪枝优化一下的。每个数字 最多使用一次。原创 2025-03-29 14:49:48 · 349 阅读 · 0 评论 -
动态规划_斐波那契数
从递归公式dp[i] = dp[i - 1] + dp[i - 2];中可以看出,dp[i]是依赖 dp[i - 1] 和 dp[i - 2],那么遍历的顺序一定是从前到后遍历的。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。因为题目已经把递推公式直接给我们了:状态转移方程 dp[i] = dp[i - 1] + dp[i - 2];F(n) = F(n - 1) + F(n - 2),其中 n > 1。dp[i]的定义为:第i个数的斐波那契数值是dp[i]确定dp数组以及下标的含义。原创 2025-03-26 21:42:01 · 467 阅读 · 0 评论 -
贪心_分发饼干
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。假设你是一位很棒的家长,想要给你的孩子们一些小饼干。大尺寸的饼干既可以满足胃口大的孩子也可以满足胃口小的孩子,那么就应该优先满足胃口大的。然后从后向前遍历小孩数组,用大饼干优先满足胃口大的,并统计满足小孩数量。原创 2025-03-26 21:19:25 · 279 阅读 · 0 评论 -
回溯_组合
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按 任何顺序 返回答案。原创 2025-03-26 20:30:19 · 255 阅读 · 0 评论 -
二叉树_把二叉搜索树转换为累加树
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。其实这就是一棵树,大家可能看起来有点别扭,换一个角度来看,这就是一个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13],是不是感觉这就简单了。那么知道如何遍历这个二叉树,也就迎刃而解了,从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个二叉树,然后顺序累加就可以了。原创 2025-03-25 11:32:52 · 425 阅读 · 0 评论 -
二叉树_将有序数组转换为二叉搜索树
首先取数组中间元素的位置,不难写出int mid = (left + right) / 2;,这么写其实有一个问题,就是数值越界,例如left和right都是最大int,这么操作就越界了,在二分法 (opens new window)中尤其需要注意!给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。所以可以这么写:int mid = left + ((right - left) / 2);利用其有序性,迭代的方式还是比较简单的,解题思路在递归中已经分析了。原创 2025-03-25 11:11:17 · 191 阅读 · 0 评论 -
二叉树_修剪二叉搜索树
给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。可以证明,存在 唯一的答案。所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。利用其有序性,迭代的方式还是比较简单的,解题思路在递归中已经分析了。原创 2025-03-25 10:21:44 · 275 阅读 · 0 评论 -
二叉树_删除二叉搜索树中的节点
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。利用其有序性,迭代的方式还是比较简单的,解题思路在递归中已经分析了。首先找到需要删除的节点;如果找到了,删除它。原创 2025-03-24 22:30:44 · 249 阅读 · 0 评论 -
二叉树_二叉搜索树中的插入操作
给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。返回插入后二叉搜索树的根节点。输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。你可以返回 任意有效的结果。利用其有序性,迭代的方式还是比较简单的,解题思路在递归中已经分析了。原创 2025-03-24 21:56:09 · 251 阅读 · 0 评论 -
二叉树_二叉搜索树的最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]利用其有序性,迭代的方式还是比较简单的,解题思路在递归中已经分析了。给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。原创 2025-03-24 21:40:01 · 291 阅读 · 0 评论 -
二叉树_二叉树的最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。原创 2025-03-23 21:06:19 · 174 阅读 · 0 评论 -
二叉树_二叉搜索树中的众数
给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。所以如果本题没有说是二叉搜索树的话,那么就按照上面的思路写!如果树中有不止一个众数,可以按 任意顺序 返回。结点左子树中所含节点的值 小于等于 当前节点的值。结点右子树中所含节点的值 大于等于 当前节点的值。既然是搜索树,它中序遍历就是有序的。左子树和右子树都是二叉搜索树。原创 2025-03-23 20:38:11 · 347 阅读 · 0 评论 -
二叉树_二叉搜索树的最小绝对差
给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值。差值是一个正数,其数值等于两值之差的绝对值。原创 2025-03-23 19:52:25 · 191 阅读 · 0 评论 -
二叉树_验证二叉搜索树
中序遍历,一直更新maxVal的节点,一旦发现maxVal >= root->val,就返回false,注意元素相同时候也要返回false。可以递归中序遍历将二叉搜索树转变成一个数组,然后只要比较一下,这个数组是否是有序的,注意二叉搜索树中不能有重复元素。我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点。给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。原创 2025-03-22 16:51:07 · 293 阅读 · 0 评论 -
二叉树_二叉搜索树中的搜索
你需要在 BST 中找到节点值等于 val 的节点。返回以该节点为根的子树。如果节点不存在,则返回 null。对于二叉搜索树可就不一样了,因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法。例如要搜索元素为3的节点,我们不需要搜索其他节点,也不需要做回溯,查找的路径已经规划好了。对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向。给定二叉搜索树(BST)的根节点 root 和一个整数值 val。原创 2025-03-22 16:25:26 · 317 阅读 · 0 评论 -
二叉树_合并二叉树
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。(opens new window)中的迭代法已经讲过一次了,求二叉树对称的时候就是把两个树的节点同时加入队列进行比较。给你两棵二叉树: root1 和 root2。注意: 合并过程必须从两个树的根节点开始。返回合并后的二叉树。原创 2025-03-22 15:53:38 · 396 阅读 · 0 评论 -
二叉树_最大二叉树
给定一个不重复的整数数组 nums。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后缀上 构建右子树。创建一个根节点,其值为 nums 中的最大值。返回 nums 构建的 最大二叉树。原创 2025-03-18 22:03:30 · 353 阅读 · 0 评论 -
二叉树_从中序与后序遍历序列构造二叉树
给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树。此时应该发现了,如上的代码性能并不好,因为每层递归定义了新的vector(就是数组),既耗时又耗空间,但上面的代码是最好理解的,为了方便读者理解,所以用如上的代码来讲解。此时有一个很重的点,就是中序数组大小一定是和后序数组的大小相同的(这是必然)。原创 2025-03-18 20:52:26 · 221 阅读 · 0 评论 -
二叉树_路径总和
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum。如果存在,返回 true;否则,返回 false。本题要找出树的最后一行的最左边的值。此时大家应该想起用层序遍历是非常简单的了,反而用递归的话会比较难一点。叶子节点 是指没有子节点的节点。还可以简化为struct如下。原创 2025-03-16 17:46:50 · 189 阅读 · 0 评论 -
二叉树_找树左下角的值
本题要找出树的最后一行的最左边的值。此时大家应该想起用层序遍历是非常简单的了,反而用递归的话会比较难一点。给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。假设二叉树中至少有一个节点。原创 2025-03-16 17:08:29 · 237 阅读 · 0 评论 -
二叉树_左叶子之和
给定二叉树的根节点 root ,返回所有左叶子之和。原创 2025-03-16 16:43:47 · 220 阅读 · 0 评论 -
二叉树_二叉树的所有路径
那么在如上代码中,貌似没有看到回溯的逻辑,其实不然,回溯就隐藏在traversal(cur->left, path + “->”, result);每次函数调用完,path依然是没有加上"->" 的,这就是回溯了。其实关键还在于 参数,使用的是 string path,这里并没有加上引用& ,即本层递归中,path + 该节点数值,但该层递归结束,上一层path的数值并不会受到任何影响。答案:因为更改了path的值,会导致没有回溯->,左边有节点的时候,会先加一个->,导致右边节点会多加一个-> .原创 2025-03-16 15:20:35 · 323 阅读 · 0 评论 -
二叉树_平衡二叉树
这个函数通过栈模拟的后序遍历找每一个节点的高度(其实是通过求传入节点为根节点的最大深度来求的高度)因为对于回溯算法已经是非常复杂的递归了,如果再用迭代的话,就是自己给自己找麻烦,效率也并不一定高。当然此题用迭代法,其实效率很低,因为没有很好的模拟回溯的过程,所以迭代法有很多重复的计算。然后再用栈来模拟后序遍历,遍历每一个节点的时候,再去判断左右孩子的高度是否符合。例如:都知道回溯法其实就是递归,但是很少人用迭代的方式去实现回溯算法!虽然理论上所有的递归都可以用迭代来实现,但是有的场景难度可能比较大。原创 2025-03-11 20:52:23 · 235 阅读 · 0 评论 -
二叉树_完全二叉树的节点个数
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层(从第 0 层开始),则该层包含 1~ 2h 个节点。给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。使用队列进行迭代遍历、原创 2025-03-11 20:10:21 · 169 阅读 · 0 评论 -
二叉树_二叉树的最小深度
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明:叶子节点是指没有子节点的节点。给定一个二叉树,找出其最小深度。使用队列进行迭代遍历、原创 2025-03-11 20:01:36 · 209 阅读 · 0 评论 -
二叉树_二叉树的最大深度
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。给定一个二叉树 root ,返回其最大深度。使用栈进行迭代遍历进行翻转、原创 2025-03-11 10:41:14 · 200 阅读 · 0 评论 -
二叉树_对称二叉树
给你一个二叉树的根节点 root , 检查它是否轴对称。使用栈进行迭代遍历进行翻转、原创 2025-03-11 10:27:35 · 203 阅读 · 0 评论 -
二叉树_翻转二叉树
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。使用栈进行迭代遍历进行翻转、原创 2025-03-11 09:54:34 · 242 阅读 · 0 评论 -
二叉树_遍历
【代码】二叉树_遍历。原创 2025-03-10 16:34:36 · 224 阅读 · 0 评论 -
栈与队列_总结
所以大家经常说的大顶堆(堆头是最大元素),小顶堆(堆头是最小元素),如果懒得自己实现的话,就直接用priority_queue(优先级队列)就可以了,底层实现都是一样的,从小到大排就是小顶堆,从大到小排就是大顶堆。有的同学经常会想学的这些数据结构有什么用,也开发不了什么软件,大多数同学说的软件应该都是可视化的软件例如APP、网站之类的,那都是非常上层的应用了,底层很多功能的实现都是基础的数据结构和算法。那么这个维护元素单调递减的队列就叫做单调队列,即单调递减或单调递增的队列。原创 2025-03-05 14:58:24 · 818 阅读 · 0 评论 -
栈与队列_前 K 个高频元素
所以大家经常说的大顶堆(堆头是最大元素),小顶堆(堆头是最小元素),如果懒得自己实现的话,就直接用priority_queue(优先级队列)就可以了,底层实现都是一样的,从小到大排就是小顶堆,从大到小排就是大顶堆。所以大家经常说的大顶堆(堆头是最大元素),小顶堆(堆头是最小元素),如果懒得自己实现的话,就直接用priority_queue(优先级队列)就可以了,底层实现都是一样的,从小到大排就是小顶堆,从大到小排就是大顶堆。有的同学一想,题目要求前 K 个高频元素,那么果断用大顶堆啊。什么是优先级队列呢?原创 2025-03-05 11:38:03 · 361 阅读 · 0 评论 -
栈与队列_滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。那么这个维护元素单调递减的队列就叫做单调队列,即单调递减或单调递增的队列。C++中没有直接支持单调队列,需要我们自己来实现一个单调队列。其实队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的。不要以为实现的单调队列就是 对窗口里面的数进行排序,如果排序的话,那和优先级队列又有什么区别了呢。原创 2025-03-05 10:43:46 · 224 阅读 · 0 评论 -
栈与队列_逆波兰表达式求值
逆波兰式(Reverse Polish Notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)。给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。返回一个表示表达式值的整数。原创 2025-03-04 21:36:39 · 380 阅读 · 0 评论 -
栈与队列_ 删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 s,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在完成所有重复项删除操作后返回最终的字符串。在 s 上反复执行重复项删除操作,直到无法继续删除。原创 2025-03-04 21:10:53 · 377 阅读 · 0 评论 -
栈与队列_有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。每个右括号都有一个对应的相同类型的左括号。左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。原创 2025-03-04 20:22:14 · 186 阅读 · 0 评论 -
栈与队列_用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。boolean empty() 如果栈是空的,返回 true;否则,返回 false。void push(int x) 将元素 x 压入栈顶。int pop() 移除并返回栈顶元素。int top() 返回栈顶元素。原创 2025-03-04 20:11:51 · 301 阅读 · 0 评论 -
栈与队列_用栈实现队列
你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。请你仅使用两个栈实现先入先出队列。否则,返回 false。void push(int x) 将元素 x 推到队列的末尾。int pop() 从队列的开头移除并返回元素。int peek() 返回队列开头的元素。原创 2025-03-03 22:23:46 · 229 阅读 · 0 评论 -
字符串_总结
一些同学会使用for循环里调用库函数erase来移除元素,这其实是O(n^2)的操作,因为erase就是O(n)的操作,所以这也是典型的不知道库函数的时间复杂度,上来就用的案例了。在151.翻转字符串里的单词 (opens new window)中要求翻转字符串里的单词,这道题目可以说是综合考察了字符串的多种操作。是考察字符串的好题。在344.反转字符串 (opens new window),我们使用双指针法实现了反转字符串的操作,双指针法在数组,链表和字符串中很常用。在字符串:反转个字符串还有这个用处?原创 2025-03-03 21:45:19 · 934 阅读 · 0 评论
分享