登录社区云,与社区用户共同成长
邀请您加入社区
摘要: 本文深入解析二叉搜索树(BST)的核心特性——有序性,通过LeetCode 98(验证BST)和235(BST最近公共祖先)两道经典题目,揭示BST的解题逻辑。98题强调全局有序性,需通过中序遍历或递归区间法验证;235题则利用BST有序性实现高效自顶向下搜索。文章对比了BST与普通二叉树的操作差异,提供Python/Java/C++三语言代码实现,并延伸至BST家族题(搜索、插入、删除、
这道题的关键是:一棵非空树的最大深度等于左右子树最大深度的较大值加一;空树深度为 0。理解这一点后,再结合边界条件检查,代码就能保持清晰且稳定。
在老师的指导下,我完成了力扣(LeetCode)数组相关的 4、11、14、15、46 这五道题。老师要求我每道题做完后做三件事:先把思路口述一遍,再看代码里有没有重复和冗余,最后分析时间复杂度。昨天的练题让我认识到,Python 语法只是工具,真正难的是把判断、循环、列表、递归这些知识组合起来解决实际问题。第 15 题三数之和让我明白,光有思路不够,细节决定成败:排序后左右指针怎么移动、什么时候
1.两数之和。
Python基础补牢,不涉及算法,供大家快速查漏补缺
本文提出了一种高效计算矩阵中所有k×k子矩阵最小绝对差的方法。通过将二维滑动窗口拆解为一维问题,先预处理每行的1×k窗口,再合并k个行窗口得到子矩阵元素。对元素去重排序后,利用相邻元素差值最小的特性快速求解。算法时间复杂度为O(mnk + (m-k+1)(n-k+1)k²logk),空间复杂度O(mn)。关键点在于维度拆解和排序优化,既简化了计算过程,又保证了效率。代码实现中需要注意索引边界、重复
给你一个整数数组nums,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。是数组中的一个连续部分。6连续子数组 [4,-1,2,1] 的和最大,为 6。nums = [1]123这个太简单了,和洛谷的p1115一样,那个用c++写了题解可以去主页看。不要想得太复杂!!!
本文详细讲解了二叉树路径遍历问题的解法,重点分析了回溯算法的应用。通过前序遍历收集路径节点,遇到叶子节点时拼接路径字符串。文章提供了C++、C和Python三种实现,其中C++和Python显式回溯,C语言通过按值传递隐式回溯。时间复杂度为O(N^2),空间复杂度为O(N)。特别解析了C语言实现中的两个精妙点:指针偏移实现字符串追加和按值传递实现隐式回溯。该问题是理解回溯算法和二叉树遍历的经典案例
【代码】DeepSeekLeetCode 2188.完成比赛的最少时间 public int minimumFinishTime。
fmt.Println(shortestSequence([]int{1,1,2,2}, 2))// 输出: 2。fmt.Println(shortestSequence([]int{1,1,3,4}, 4))// 输出: 1。fmt.Println(shortestSequence([]int{4,2,1,2,3,3,2,4,1}, 4)) // 输出: 3。输入: rolls = [4,2,1
对于候选值 `target`,计算每个 `nums[i]` 提升到包含 `target` 所有 1 位的最小代价,取最小的 `m` 个代价之和,若不超过 `k` 则该位可行。当 `v == 0` 时返回 `0`,否则返回最高位的位置+1(例如 `bits.Len(uint(6))` = `3`,因为 `6 = 110`)当 `j = 0` 时,`mask = 0`,代价为 `0`- `diff =
2. 窗口维护顺序:先更新单调队列,再收缩窗口(可能删除 pref[left]),然后查询,最后插入 pref[right+1],确保查询时 Trie 中只包含当前窗口内的合法左边界。· 在窗口滑动过程中,用 Trie 存储当前窗口内所有合法左边界 l 对应的 pref[l],每次查询 pref[r+1] 与 Trie 中所有值的最大异或值。· 用前缀异或 pref[i+1] = pref[i]
1. 前缀异或(Prefix XOR):子数组 [l, r] 的异或值 = prefix[r+1] ^ prefix[l],将子数组异或问题转化为"两个前缀值的异或最大值"问题。2. 01字典树(Binary Trie):将所有前缀异或值按二进制位插入 Trie,查询时贪心选择相反的位,即可快速找到与当前值异或最大的前缀值。· 15位遍历:因为 nums[i] < 2^15,异或值也在15位范围内
3. 计数:对于每个 `right`,所有以 `right` 结尾、左端点在 `[0, l]` 的子数组都满足"至多 lim 个不同元素且每个都 ≥ m 次"// y 的出现次数从 m 降到 m-1。`恰好 k 个不同元素 = 至多 k 个不同元素 - 至多 k-1 个不同元素`示例 1:`nums = [1,2,1,2,2], k = 2, m = 2`示例 2:`nums = [3,1,2,4
滑动窗口维护不满足 `f(lim)` 条件的最小窗口 `[l, r]`,则以 `r` 结尾、左端点在 `[0, l−1]` 的子数组都满足 `f(lim)`。3. 统计贡献:`l` 是不满足条件的最小左端点,那么以 `r` 结尾、左端点在 `[0, l−1]` 的 `l` 个子数组都满足 `f(lim)`- `f(2)` 统计至少 2 个不同且至少 2 个 ≥ 2 次:贡献来自 `[1,2,1,2
已通过所有题目示例和 `[1, 10000]` 范围的暴力验证,`[1, 10^15]` 的结果为 `907441159188136`。- `s < 100`:排除 11 的倍数(`11, 22, ..., 99`),即 `s % 11!- 好数:数位严格递增(如 `123`、`10`)或严格递减(如 `321`)的整数。所有一位数都是好数。分别计算 `[0, r]` 和 `[0, l-1]` 中
时间复杂度:`O(D³ × log r)`,其中 `D = 10` 为数字范围,状态数为 `pos × sum × prev × st ≈ 16 × 145 × 10 × 4`- `s < 100`:不是 11 的倍数即为好数(因为两位数中 `11, 22, ..., 99` 不是好数)- `st`:单调状态(`0`=初始/前导零, `1`=递增, `2`=递减, `3`=非单调)3. 用 `ca
3. 添加新点的作用:新点 `(a, b)` 相当于连接行 `a` 和列 `b`。如果 `a` 和 `b` 分别属于两个不同的连通块,就能将这两个块合并激活。2. 坐标区分:由于 x 和 y 的取值范围都是 `[-1e9, 1e9]`,直接合并会冲突。1. 模型转化:将每个点 `(x, y)` 看作连接 行节点 `x` 和 列节点 `y` 的一条边。- 时间复杂度:`O(n · α(n))`,其中
已通过所有题目示例和 `[1, 10000]` 范围的暴力验证,`[1, 10^15]` 的结果为 `907441159188136`。- `s < 100`:排除 11 的倍数(`11, 22, ..., 99`),即 `s % 11!- 好数:数位严格递增(如 `123`、`10`)或严格递减(如 `321`)的整数。分别计算 `[0, r]` 和 `[0, l-1]` 中的奇妙数个数,相减即
总得分可以表示为 weights[0] + weights[n-1] 加上每个切割点(段与段之间的边界)的贡献 weights[i] + weights[i+1],其中 i 是切割位置。相邻和:[4,8,6],取最大 1 个 = 8,最小 1 个 = 4,差值 = 4 → 输出 4。· 特殊处理 k == 1 或 k == n 的情况,此时只有一种分法,差值为 0。相邻和:[4],k-1=1,最大
1. 当前数组 [3,4,-1],最小值 -1 不在最左,移动 3 到末尾 → [4,-1,3](1次)· 此时需要额外的 (n - i) 次操作(将当前位置之后的所有元素移动到末尾)· 如果当前值的索引小于上一个值的索引,说明需要绕一圈(将前面的元素移到末尾)处理 3 → 4:索引0 < 索引1,需要额外 (3-2)=1 次操作。// 如果当前索引小于前一个索引,说明需要额外操作。· 当按值从小
如果数据规模较大(例如 n, m <= 10^5),可以使用 LCA + 差分数组 优化路径统计,将单次路径复杂度降为 O(log n)。以下是 LeetCode 2646“最小化旅行的价格总和”的 C++ 实现,思路与 Java 版本一致,采用 DFS 统计节点访问次数 + 树形 DP。// 父半价,子必须不半价。// 返回 pair: first = 当前节点不半价的最小总价, second
自底向上 DFS:对于每个节点,若其子树返回需要翻转,则翻转该边,同时当前节点的翻转状态也被取反。`dfs(b, a, ...)` 返回 `true`子节点 `b` 需要被翻转,必须通过翻转边 `(a,b)` 解决。= target[a]`节点 `a` 当前是否需要被翻转。根节点返回 `true` → `[-1]`根没有父边,无法被翻转,说明无解。rev`翻转边后,节点 `a` 的颜色也被改变。/
对于候选值 `target`,需要判断是否存在大小为 `m` 的子集,使得总操作次数不超过 `k`。- `diff = target & ~nums[i]`:`target` 为 1 但 `nums[i]` 为 0 的位。- 时间:O(\log(\max) \cdot n \log n),其中 \max = \max(nums) + k。取最小的 `m` 个代价之和,若不超过 `k` 则该位可行。
给定 `n` 个房屋,编号从 `1` 到 `n`,排成一条直线。对于每个 `k`(`1 <= k <= n`),返回距离恰好为 `k` 的有序房屋对 `(house1, house2)` 的数量。- 环(Ring):由 `x` 到 `y` 及连接它们的额外边形成的环,长度为 `ringLen = y - x + 1`- 左链(Left Line):`[1, x)` 部分,长度为 `leftLine
否则需要精确计算操作2的最小代价。// 记录所有1的位置。- 距离 Dylan 为 1 的位置(`i-1` 和 `i+1`)上的 `1` 可以直接交换过来,代价为 1。- 如果 `maxChanges` 足够大,其余 `k-c` 个 `1` 都可以用操作1(代价2)获得。1. 连续1的处理:最多3个连续1可以直接利用(代价0或1),这是 `c` 的上限。- 最多有 3 个位置(`i-1, i, i
否则更新最小差值:`dfs(i+1, i, k-1, min(mi, nums[i] - nums[j]))`用 `HashMap` 缓存状态,key 编码为 `mi << 18 | i << 12 | j << 6 | k`。2. 状态压缩 key:`mi << 18 | i << 12 | j << 6 | k`,用位运算编码四个状态变量。- 如果 `j == n`(第一次选):`dfs(i+
1. 容斥原理:`dp[i][j][0] = (dp[i-1][j][0] + dp[i-1][j][1]) - dp[i-limit-1][j][1]`状态定义:`dp[i][j][k]` 表示使用了 `i` 个 0 和 `j` 个 1,且最后一个数字为 `k`(0 或 1)的稳定二进制数组数量。// 可以由 dp[i-1][j][0] 和 dp[i-1][j][1] 转移而来。- `zero=
2. `arr2` 非递增:`arr2[i-1] >= arr2[i]` → `nums[i-1] - prev_j >= nums[i] - j` → `prev_j <= j + nums[i-1] - nums[i]`设 `dp[i][j]` 表示前 `i` 个元素,且 `arr1[i] = j` 时的方案数。1. `arr1` 非递减:`arr1[i-1] <= arr1[i]` → `p