- 博客(109)
- 收藏
- 关注
原创 C++ STL容器相关操作的复杂度分析
本文总结了常见C++容器的操作时间复杂度。序列容器中,vector支持O(1)随机访问但中间操作O(n);deque头尾操作O(1);list任意位置插入删除O(1)。关联容器set/map基于红黑树实现O(logn)操作,哈希实现的unordered系列平均O(1)。适配器stack/queue操作O(1),priority_queue插入删除O(logn)。所有时间复杂度均考虑了动态扩容的均摊情况。
2025-08-18 20:23:56
301
原创 LeetCode Hot 100 最长回文子串
上文的所有讨论是建立在子串长度大于 2 的前提之上的,我们还需要考虑动态规划中的边界条件,即子串的长度为 1 或 2。对于一个子串而言,如果它是回文串,并且长度大于 2,那么将它首尾的两个字母去除之后,它仍然是个回文串。注意:在状态转移方程中,我们是从长度较短的字符串向长度较长的字符串进行转移的,因此一定要注意动态规划的循环顺序。根据这样的思路,我们就可以用动态规划的方法解决本题。也就是说,只有 s[i+1:j−1] 是回文串,并且 s 的第 i 和 j 个字母相同时,s[i:j] 才会是回文串。
2025-08-11 09:59:12
349
原创 LeetCode Hot 100 最长公共子序列
0:j] 的最长公共子序列,应取两项中的长度较大的一项,因此 dp[i][j]=max(dp[i−1][j],dp[i][j−1])。[0:i] 为空,空字符串和任何字符串的最长公共子序列的长度都是 0,因此对任意 0≤j≤n,有 dp[0][j]=0;[0:j] 的最长公共子序列,因此 dp[i][j]=dp[i−1][j−1]+1。[0:j] 为空,同理可得,对任意 0≤i≤m,有 dp[i][0]=0。因此动态规划的边界情况是:当 i=0 或 j=0 时,dp[i][j]=0。
2025-08-11 09:57:47
1205
原创 Unity 遮挡显示效果 Shader
本文介绍了用于实现游戏遮挡显示效果的Shader方案。该技术通过两个Pass实现:第一个Pass正常渲染物体(ZTestLEqual),第二个Pass在被遮挡时显示轮廓(ZTestGreater+顶点膨胀)。Shader参数包括主纹理、基础颜色、遮挡颜色和轮廓宽度。关键技术点包括深度测试机制、法线膨胀轮廓和透明混合模式。使用时需注意性能影响、模型法线要求和透明度处理。这种方案适用于需要显示被遮挡物体的游戏场景,如角色被墙壁遮挡时的X光效果。
2025-08-10 21:25:47
1158
原创 LeetCode Hot 100 不同路径
由于我们每一步只能从向下或者向右移动一步,因此要想走到 (i,j),如果向下走一步,那么会从 (i−1,j) 走过来;需要注意的是,如果 i=0,那么 f(i−1,j) 并不是一个满足要求的状态,我们需要忽略这一项;我们用 f(i,j) 表示从左上角走到 (i,j) 的路径数量,其中 i 和 j 的范围分别是 [0,m) 和 [0,n)。为了方便代码编写,我们可以将所有的 f(0,j) 以及 f(i,0) 都设置为边界条件,它们的值均为 1。初始条件为 f(0,0)=1,即从左上角走到左上角有一种方法。
2025-08-10 09:52:10
384
原创 LeetCode Hot 100 最小路径和
由于路径的方向只能是向下或向右,因此网格的第一行的每个元素只能从左上角元素开始向右移动到达,网格的第一列的每个元素只能从左上角元素开始向下移动到达,此时的路径是唯一的,因此每个元素对应的最小路径和即为对应的路径上的数字总和。显然,dp[0][0]=grid[0][0]。当 i>0 且 j>0 时,dp[i][j]=min(dp[i−1][j],dp[i][j−1])+grid[i][j]。当 i>0 且 j=0 时,dp[i][0]=dp[i−1][0]+grid[i][0]。给定一个包含非负整数的。
2025-08-10 09:51:04
174
原创 LeetCode Hot 100 乘积最大子数组
考虑当前位置如果是一个负数的话,那么我们希望以它前一个位置结尾的某个段的积也是个负数,这样就可以负负得正,并且我们希望这个积尽可能「负得更多」,即尽可能小。如果当前位置是一个正数的话,我们更希望以它前一个位置结尾的某个段的积也是个正数,并且希望它尽可能地大。对应的序列是 {5,30,−3,4,−3},按照前面的算法我们可以得到答案为 30,即前两个数的乘积,而实际上答案应该是全体数字的乘积。加入第 i−1 个元素结尾的乘积最大或最小的子数组的乘积中,二者加上 a。(i) 之后选取最大的一个作为答案。
2025-08-09 17:36:16
388
原创 LeetCode Hot 100 最长递增子序列
j] 中以 nums[j] 结尾的最长上升子序列,所以如果能从 dp[j] 这个状态转移过来,那么 nums[i] 必然要大于 nums[j],才能将 nums[i] 放在 nums[j] 后面以形成更长的上升子序列。我们从小到大计算 dp 数组的值,在计算 dp[i] 之前,我们已经计算出 dp[0…定义 dp[i] 为考虑前 i 个元素,以第 i 个数字结尾的最长上升子序列的长度,注意 nums[i] 必须被选取。dp[i]=max(dp[j])+1,其中0≤j<i且num[j]<num[i]
2025-08-09 17:33:52
251
原创 LeetCode Hot 100 零钱兑换
我们注意到这个问题有一个最优的子结构性质,这是解决动态规划问题的关键。假设我们知道 F(S),即组成金额 S 最少的硬币数,最后一枚硬币的面值是 C。为了避免重复的计算,我们将每个子问题的答案存在一个数组中进行记忆化,如果下次还要计算这个问题的值直接从数组中取出返回即可,这样能保证每个子问题最多只被计算一次。当然可以,利用动态规划,我们可以在多项式的时间范围内求解。],针对给定的子集计算它们组成的金额数,如果金额数为 S,则记录返回合法硬币总数的最小值,反之返回 −1。你可以认为每种硬币的数量是无限的。
2025-08-08 10:24:37
356
原创 LeetCode Hot 100 单词拆分
我们定义 dp[i] 表示字符串 s 前 i 个字符组成的字符串 s[0..i−1] 是否能被空格拆分成若干个字典中出现的单词。公式化来说,我们需要枚举 s[0..i−1] 中的分割点 j ,看 s[0..j−1] 组成的字符串 s。对于检查一个字符串是否出现在给定的字符串列表里一般可以考虑哈希表来快速判断,同时也可以做一些简单的剪枝,枚举分割点的时候倒着枚举,如果分割点 j 到 i 的长度已经大于字典列表里最长的单词的长度,那么就结束枚举,但是需要注意的是下面的代码给出的是不带剪枝的写法。
2025-08-08 10:23:26
330
原创 LeetCode Hot 100 打家劫舍
如果只有两间房屋,则由于两间房屋相邻,不能同时偷窃,只能偷窃其中的一间房屋,因此选择其中金额较高的房屋进行偷窃,可以偷窃到最高总金额。偷窃第 k 间房屋,那么就不能偷窃第 k−1 间房屋,偷窃总金额为前 k−2 间房屋的最高总金额与第 k 间房屋的金额之和。偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。在两个选项中选择偷窃总金额较大的选项,该选项对应的偷窃总金额即为前 k 间房屋能偷窃到的最高总金额。,一夜之内能够偷窃到的最高金额。
2025-08-07 08:55:24
196
原创 LeetCode Hot 100 跳跃游戏II
如果有多个位置通过跳跃都能够到达最后一个位置,那么我们应该如何进行选择呢?直观上来看,我们可以「贪心」地选择距离最后一个位置最远的那个位置,也就是对应下标最小的那个位置。因此,我们可以从左到右遍历数组,选择第一个满足要求的位置。我们的目标是到达数组的最后一个位置,因此我们可以考虑最后一步跳跃前所在的位置,该位置通过跳跃能够到达最后一个位置。找到最后一步跳跃前所在的位置之后,我们继续贪心地寻找倒数第二步跳跃前所在的位置,以此类推,直到找到数组的开始位置。从下标为 0 跳到下标为 1 的位置,跳。
2025-08-05 11:28:17
158
原创 LeetCode Hot 100 划分字母区间
上述做法使用贪心的思想寻找每个片段可能的最小结束下标,因此可以保证每个片段的长度一定是符合要求的最短长度,如果取更短的片段,则一定会出现同一个字母出现在多个片段中的情况。由于同一个字母只能出现在同一个片段,显然同一个字母的第一次出现的下标位置和最后一次出现的下标位置必须出现在同一个片段。由于每个片段访问结束的标志是访问到下标 end,因此对于每个片段,可以保证当前片段中的每个字母都一定在当前片段中,不可能出现在其他片段,可以保证同一个字母只会出现在同一个片段。返回一个表示每个字符串片段的长度的列表。
2025-08-05 11:27:16
310
原创 LeetCode Hot 100 跳跃游戏
对于当前遍历到的位置 x,如果它在 最远可以到达的位置 的范围内,那么我们就可以从起点通过若干次跳跃到达该位置,因此我们可以用 x+nums[x] 更新 最远可以到达的位置。根据题目的描述,只要存在一个位置 x,它本身可以到达,并且它跳跃的最大长度为 x+nums[x],这个值大于等于 y,即 x+nums[x]≥y,那么位置 y 也可以到达。我们遍历到位置 1,由于 1≤3,因此位置 1 可达,加上它可以跳跃的最大长度 2 得到 3,没有超过最远可以到达的位置;无论怎样,总会到达下标为 3 的位置。
2025-08-04 16:02:32
321
原创 LeetCode Hot 100 买卖股票的最佳时机
显然,如果我们真的在买卖股票,我们肯定会想:如果我是在历史最低点买的股票就好了!太好了,在题目中,我们只要用一个变量记录一个历史最低价格 minprice,我们就可以假设自己的股票是在那天买的。因此,我们只需要遍历价格数组一遍,记录历史最低点,然后在每一天考虑这么一个问题:如果我是在历史最低点买进的,那么我今天卖出能赚多少钱?在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5。假设给定的数组为:[7, 1, 5, 3, 6, 4]
2025-08-04 16:01:09
214
原创 LeetCode Hot 100 每日温度
天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用。,表示每天的温度,返回一个数组。
2025-08-02 10:27:45
220
原创 LeetCode Hot 100 柱状图中最大的矩形
个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1。求在该柱状图中,能够勾勒出来的矩形的最大面积。最大的矩形为图中红色区域,面积为 10。
2025-08-02 10:26:39
141
原创 LeetCode Hot 100 最小栈
-> 返回 -3.minStack.getMin();--> 返回 -2.minStack.top();操作,并能在常数时间内检索到最小元素的栈。
2025-08-01 17:00:58
212
原创 LeetCode Hot 100 寻找两个正序数组的中位数
如果 A[k/2−1]<B[k/2−1],则比 A[k/2−1] 小的数最多只有 A 的前 k/2−1 个数和 B 的前 k/2−1 个数,即比 A[k/2−1] 小的数最多只有 k−2 个,因此 A[k/2−1] 不可能是第 k 个数,A[0] 到 A[k/2−1] 也都不可能是第 k 个数,可以全部排除。由于 A[2]=B[3],根据之前的规则,排除 A 中的元素,因此排除 A[2],即数组 A 的下标偏移变为 3,同时更新 k 的值: k=k−k/2=1。大的有序数组的中间位置的元素,即为中位数。
2025-07-31 09:30:25
945
原创 LeetCode Hot 100 寻找旋转排序数组中的最小值
我们考虑数组中的最后一个元素 x:在最小值右侧的元素(不包括最后一个元素本身),它们的值一定都严格小于 x;在二分查找的每一步中,左边界为 low,右边界为 high,区间的中点为 pivot,最小值就在该区间内。如下图所示,这说明 nums[pivot] 是最小值右侧的元素,因此我们可以忽略二分查找区间的右半部分。如下图所示,这说明 nums[pivot] 是最小值左侧的元素,因此我们可以忽略二分查找区间的左半部分。原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。
2025-07-31 09:29:07
221
原创 LeetCode Hot 100 搜索旋转排序数组
整数数组nums按升序排列,数组中的值。在传递给函数之前,nums在预先未知的某个下标k)上进行了,使数组变为(下标计数)。例如,在下标3处经旋转后可能变为。给你的数组nums和一个整数target,如果nums中存在这个目标值target,则返回它的下标,否则返回-1。你必须设计一个时间复杂度为O(log n)的算法解决此问题。
2025-07-30 18:41:15
295
原创 LeetCode Hot 100 在排序数组中查找元素的第一个和最后一个位置
二分查找中,寻找 leftIdx 即为在数组中寻找第一个大于等于 target 的下标,寻找 rightIdx 即为在数组中寻找第一个大于 target 的下标,然后将下标减一。两者的判断条件不同,为了代码的复用,我们定义 binarySearch(nums, target, lower) 表示在 nums 数组中二分查找 target 的位置,如果 lower 为 true,则查找第一个大于等于 target 的下标,否则查找第一个大于 target 的下标。给你一个按照非递减顺序排列的整数数组。
2025-07-30 18:39:45
210
原创 LeetCode Hot 100 分割回文串
对于当前枚举的 j 值,我们使用双指针的方法判断 s[i..j] 是否为回文串:如果 s[i..j] 是回文串,那么就将其加入答案数组 ans 中,并以 j+1 作为新的 i 进行下一层搜索,并在未来的回溯时将 s[i..j] 从 ans 中移除。假设我们当前搜索到字符串的第 i 个字符,且 s[0..i−1] 位置的所有字符已经被分割成若干个回文串,并且分割结果被放入了答案数组 ans 中,那么我们就需要枚举下一个回文串的右边界 j,使得 s[i..j] 是一个回文串。分割成一些 子串,使每个子串都是。
2025-07-28 10:45:36
405
原创 LeetCode Hot 100 N皇后
摘要:n皇后问题要求在n×n棋盘上放置n个不互相攻击的皇后(皇后可攻击同行、同列或对角线上的子)。本文介绍了基于集合的回溯解法,使用位运算记录列和两个对角线方向的占用情况。算法通过递归搜索有效位置,当找到合法布局时生成棋盘表示。示例展示了4皇后问题的两种解法,输出格式为包含'Q'(皇后)和'.'(空位)的字符串矩阵。该方法利用位掩码高效检测冲突,时间复杂度为O(n!),空间复杂度为O(n)。
2025-07-28 10:43:39
187
原创 3D碰撞检测系统 基于SAT算法+Burst优化(Unity)
本文介绍了基于Unity的3D碰撞检测系统实现方案,重点阐述了分离轴定理(SAT)算法在凸体碰撞检测中的应用。系统采用Burst编译器进行高性能优化,通过将C#代码编译为Native代码提升运算效率。核心算法包括:面检测阶段遍历所有面法线作为潜在分离轴;边检测阶段利用Minkowski差特性优化计算;接触点生成采用ClipPlane和裁剪算法。文章详细说明了数据结构设计、内存管理和性能优化策略,如使用unmanaged类型、NativeBuffer和指针操作减少GC开销。最终实现了一个精确、高效的3D凸体碰
2025-07-27 21:32:04
2700
原创 LeetCode Hot 100 单词搜索
搜索下一单元格: 朝当前元素的 上、下、左、右 四个方向开启下层递归,使用 或 连接 (代表只需找到一条可行路径就直接返回,不再做后续 DFS ),并记录结果至 res。剪枝: 在搜索中,遇到“这条路不可能和目标字符串匹配成功”的情况,例如当前矩阵元素和目标字符不匹配、或此元素已被访问,则应立即返回,从而避免不必要的搜索分支。返回 false : (1) 行或列索引越界 或 (2) 当前矩阵元素与目标字符不同 或 (3) 当前矩阵元素已访问过 ( (3) 可合并至 (2) )。
2025-07-27 16:42:29
268
原创 LeetCode Hot 100 组合总和
2 和 3 可以形成一组候选,2 + 2 + 3 = 7。注意 2 可以使用多次。如果至少一个数字的被选数量不同,则两种组合是不同的。7 也是一个候选, 7 = 7。,并以列表形式返回。中可以使数字和为目标数。对于给定的输入,保证和为。
2025-07-26 09:32:13
212
原创 LeetCode Hot 100 腐烂的橘子
在给定的 网格 中,每个单元格可以有以下三个值之一:每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 。示例 1:输入:grid = [[2,1,1],[1,1,0],[0,1,1]]输出:4示例 2:输入:grid = [[2,1,1],[0,1,1],[1,0,1]]输出:-1解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个方向上。示例 3:输入:
2025-07-24 12:43:42
331
原创 LeetCode Hot 100 岛屿数量
为了求出岛屿的数量,我们可以扫描整个二维网格。如果一个位置为 1,则以其为起始节点开始进行深度优先搜索。在深度优先搜索的过程中,每个搜索到的 1 都会被重新标记为 0。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。我们可以将二维网格看成一个无向图,竖直或水平相邻的 1 之间有边相连。(水)组成的的二维网格,请你计算网格中岛屿的数量。最终岛屿的数量就是我们进行深度优先搜索的次数。此外,你可以假设该网格的四条边均被水包围。方法一:深度优先搜索。
2025-07-24 12:42:47
316
原创 LeetCode Hot 100 从前序与中序遍历序列构造二叉树
递推参数: 根节点在前序遍历的索引 root 、子树在中序遍历的左边界 left 、子树在中序遍历的右边界 right。在中序遍历中搜索根节点 node 的索引 ,可将 中序遍历 划分为 [ 左子树 | 根节点 | 右子树 ]。根据中序遍历中的左(右)子树的节点数量,可将 前序遍历 划分为 [ 根节点 | 左子树 | 右子树 ]。通过以上三步,可确定 三个节点 :1.树的根节点、2.左子树根节点、3.右子树根节点。中序遍历性质: 节点按照 [ 左子树 | 根节点 | 右子树 ] 排序。
2025-07-21 10:07:49
466
原创 手把手教会你使用Unity新版输入系统
Unity 2025新版输入系统全面升级,提供跨平台、事件驱动的现代化输入处理框架。核心特性包括InputActions抽象输入动作、可视化配置的InputActionAssets、多设备支持的控制方案和灵活绑定机制。系统支持复合输入、交互定义、设备切换和触觉反馈等高级功能,同时优化了性能表现。开发流程涵盖创建配置InputActionAsset、代码调用及性能优化建议,并提供了常见问题解决方案。新版系统虽有一定学习曲线,但能显著提升开发效率和游戏质量,建议通过实践项目逐步掌握其功能。
2025-07-20 20:12:21
2049
原创 LeetCode Hot 100 二叉树展开为链表
本文提出了将二叉树展开为单链表的算法。展开后的链表应使用TreeNode结构,其中right指针指向下一个节点,left指针始终为null,且链表顺序与二叉树先序遍历相同。提供的解决方案采用递归方法:后序遍历二叉树,每次处理节点时将其左右子树展开,然后将右子树接到左子树末尾,最后将处理好的左子树作为当前节点的右子树。算法时间复杂度为O(n),空间复杂度为O(n)。示例展示了不同输入情况下的输出结果。
2025-07-20 10:31:18
293
原创 LeetCode Hot 100 二叉树的右视图
摘要:本文提出一种二叉树的右视图解决方案。使用广度优先搜索(BFS)遍历二叉树,在每层访问时记录最右侧节点的值。算法首先检查根节点是否为空,然后通过队列逐层处理节点,优先将右子节点入队,确保每层第一个节点即为最右侧可见节点。该方法时间复杂度为O(n),空间复杂度为O(n),其中n为节点数量。示例结果显示对于特定输入能正确输出右视图节点序列[1,3,4]和[1,3,4,5]。
2025-07-20 10:30:11
137
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅