![](https://img-blog.csdnimg.cn/20190918140129601.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
数据结构算法训练
文章平均质量分 87
数据结构算法训练,整理刷题思路。
Orion嵌入式随想录
嵌入式学习分享,学习路径、理论笔记、实践项目等。
展开
-
算法训练 | 动态规划Part9 | 188.买卖股票的最佳时机IV、309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费
本题只需要在计算卖出操作的时候减去手续费就可以了,代码几乎是一样的。中有两个状态,持有股票后的最多现金,和不持有股票的最多现金。的进阶版,这里要求至多有k次交易。,本题加上了一个冷冻期在。原创 2024-06-25 12:18:42 · 177 阅读 · 0 评论 -
算法训练 | 动态规划Part8 | 121.买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III
那么第i天持有股票即dp[i][0],如果是第i天买入股票,所得现金就是昨天不持有股票的所得现金 减去 今天的股票价格 即:dp[i - 1][1] - prices[i]。一定是选最大的,所以 dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1]);那么dp[i][1]究竟选 dp[i-1][0] - prices[i],还是dp[i - 1][1]呢?操作一:第i天买入股票了,那么dp[i][1] = dp[i-1][0] - prices[i]原创 2024-06-25 00:16:32 · 812 阅读 · 0 评论 -
算法训练 | 动态规划Part7 | 198.打家劫舍、213.打家劫舍II、337.打家劫舍III
可以看出,递推公式的基础就是dp[0] 和 dp[1],从dp[i]的定义上来讲,dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1]);对于情况三,取nums[1] 和 nums[3]就是最大的。如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。原创 2024-06-22 20:04:49 · 873 阅读 · 0 评论 -
算法训练 | 动态规划Part6 | 322.零钱兑换、279.完全平方数、139.单词拆分
dp数组如何初始化:从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。确定递推公式:凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])所以dp[j] 要取所有 dp[j - coins[i]] + 1 中最小的。原创 2024-06-21 21:11:38 · 502 阅读 · 0 评论 -
算法训练 | 动态规划Part5 | 518.零钱兑换 II、377.组合总和 Ⅳ 、70.爬楼梯 (进阶)
确定递推公式:dp[i](考虑nums[j])可以由 dp[i - nums[j]](不考虑nums[j]) 推导出来。因为只要得到nums[j],排列个数dp[i - nums[j]],就是dp[i]的一部分。dp数组如何初始化:既然递归公式是 dp[i] += dp[i - j],那么dp[0] 一定为1,dp[0]是递归中一切数值的基础所在,如果dp[0]是0的话,其他数值都是0了。下标非0的dp[i]初始化为0,因为dp[i]是靠dp[i-j]累计上来的,dp[i]本身为0这样才不会影响结果。原创 2024-06-19 16:54:24 · 595 阅读 · 0 评论 -
算法训练 | 动态规划Part4 | 3. 416.分割等和子集、1049.最后一块石头的重量 II、494.目标和
1049. 最后一块石头的重量 II - 力扣(LeetCode)代码随想录。原创 2024-06-18 20:54:09 · 878 阅读 · 0 评论 -
算法训练 | 动态规划Part2 | 62.不同路径、63.不同路径 II
确定遍历顺序:这里要看一下递推公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1],dp[i][j]都是从其上方和左方推导而来,那么从左到右一层一层遍历就可以了。确定遍历顺序:从递归公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 中可以看出,一定是从左到右一层一层遍历,这样保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值。机器人从(0 , 0) 位置出发,到(m - 1, n - 1)终点。原创 2024-06-15 16:17:03 · 700 阅读 · 0 评论 -
算法训练 | 动态规划Part1 | 509.斐波那契数、70.爬楼梯、746.使用最小花费爬楼梯
dp数组如何初始化:看一下递归公式,dp[i]由dp[i - 1],dp[i - 2]推出,既然初始化所有的dp[i]是不可能的,那么只初始化dp[0]和dp[1]就够了,其他的最终都是dp[0]dp[1]推出。根据dp数组的定义,到达第0台阶所花费的最小体力为dp[0],那么有同学可能想,那dp[0] 应该是 cost[0],例如 cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 的话,dp[0] 就是 cost[0] 应该是1。原创 2024-06-14 14:10:52 · 898 阅读 · 0 评论 -
算法训练 | 贪心算法Part5 | 435.无重叠区间、763.划分字母区间、56. 合并区间、738.单调递增的数字
例如:98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]--,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。当确定区间 1 和 区间2 重叠后,取 区间1 和 区间2 右边界的最小值,因为这个最小值之前的部分一定是 区间1 和区间2 的重合部分,如果这个最小值也触达到区间3,那么说明 区间 1,2,3都是重合的。此时问题就是要求非交叉区间的最大个数。区间,1,2,3,4,5,6都按照右边界排好序。原创 2024-06-13 14:37:04 · 742 阅读 · 0 评论 -
算法训练 | 贪心算法Part4 | 860.柠檬水找零、406.根据身高重建队列、452.用最少数量的箭引爆气球
如果真实的模拟射气球的过程,应该射一个,气球数组就remove一个元素,这样最直观,毕竟气球被射了。但仔细思考一下就发现:如果把气球排序之后,从前到后遍历气球,被射过的气球仅仅跳过就行了,没有必要让气球数组remove气球,只要记录一下箭的数量就可以了。情况一,情况二,都是固定策略,都不用我们来做分析了,而唯一不确定的其实在情况三。按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。情况二:账单是10,消耗一个5,增加一个10。原创 2024-06-12 12:18:59 · 321 阅读 · 0 评论 -
算法训练 | 贪心算法Part3 | 1005.K次取反后最大化的数组和、134.加油站、135.分发糖果
局部最优:取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,保证第i个小孩的糖果数量既大于左边的也大于右边的。i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算curSum。此时局部最优:只要右边评分比左边大,右边的孩子就多一个糖果,全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果。原创 2024-06-11 14:29:53 · 731 阅读 · 0 评论 -
算法训练 | 贪心算法Part2 | 122.买卖股票的最佳时机II、55.跳跃游戏、45.跳跃游戏II
假如第 0 天买入,第 3 天卖出,那么利润为:prices[3] - prices[0]。相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。如果移动下标达到了当前这一步的最大覆盖最远距离了,还没有到终点的话,那么就必须再走一步来增加覆盖范围,直到覆盖范围覆盖了终点。要从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最少步数。原创 2024-06-09 11:22:47 · 448 阅读 · 0 评论 -
算法训练 | 贪心算法Part1 | 455.分发饼干、376.摆动序列、53.最大子序和
实际操作上,其实连删除的操作都不用做,因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)这就是贪心所贪的地方,让峰值尽可能的保持峰值,然后删除单一坡度上的节点。在计算是否有峰值的时候,遍历的下标 i ,计算 prediff(nums[i] - nums[i-1]) 和 curdiff(nums[i+1] - nums[i]),如果。大尺寸的饼干既可以满足胃口大的孩子也可以满足胃口小的孩子,那么就应该优先满足胃口大的。原创 2024-06-08 23:49:16 · 1128 阅读 · 0 评论 -
算法训练 | 回溯算法Part6 | 51.N皇后、37.解数独
递归单层搜索逻辑:需要的是一个二维的递归 (一行一列),一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,一行一列确定下来之后,递归遍历这个位置放9个数字的可能性!注意这里return false的地方,,因为如果一行一列确定下来了,这里尝试了9个数都不行,说明这个棋盘找不到解决数独问题的解,那么会直接返回, 这也就是为什么没有终止条件也不会永远填不满棋盘而无限递归下去。单层搜索的逻辑:递归深度就是row控制棋盘的行,每一层里for循环的col控制棋盘的列,一行一列,确定了放置皇后的位置。原创 2024-06-06 13:48:05 · 295 阅读 · 0 评论 -
算法训练 | 回溯算法Part5 | 491.递增子序列、46.全排列、47.全排列 II
因为排列问题,每次都要从头开始搜索,例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。递归函数参数:元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了。当收集元素的数组path的大小达到和nums数组一样大的时候,说明找到了一个全排列,也表示到达了叶子节点。排列具有顺序,不可以直接把取过的前面全部去除,只需要记住当前使用的元素,前面的仍然可以用。单层搜索逻辑:同一父节点下的同层上使用过的元素就不能再使用了。原创 2024-06-05 12:30:49 · 451 阅读 · 0 评论 -
算法训练 | 回溯算法Part4 | 93.复原IP地址、78.子集、90.子集II
题目链接:https://leetcode.cn/problems/restore-ip-addresses/原创 2024-06-04 15:36:23 · 388 阅读 · 0 评论 -
算法训练 | 回溯算法Part3 | 39.组合总和、40.组合总和II、131.分割回文串
同一树层,used[i - 1] == false 才能表示,当前取的 candidates[i] 是从 candidates[i - 1] 回溯而来的。此外还定义了int型的sum变量来统计单一结果path里的总和,其实这个sum也可以不用,用target做相应的减法就可以了,最后如何target==0就说明找到符合的结果了,但为了代码逻辑清晰,依然用了sum。因为本题没有组合数量要求,仅仅是总和的限制,所以递归没有层数的限制,只要选取的元素总和超过target,就返回。(这两个参数可以放到函数参数里)原创 2024-06-03 11:27:41 · 1011 阅读 · 0 评论 -
算法训练 | 回溯算法Part2 | 216.组合总和III、17.电话号码的字母组合
遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。(sum参数也可以省略,每次targetSum减去选取的元素数值,然后判断如果targetSum为0了,说明收集到符合条件的结果了,为了直观便于理解,加一个sum参数。例如 k = 2,n = 4的话,就是在集合[1,2,3,4,5,6,7,8,9]中求 k(个数) = 2, n(和) = 4的组合。注意这个index不是。原创 2024-06-02 15:55:22 · 788 阅读 · 0 评论 -
算法训练 | 回溯算法Part1 | 77.组合、组合优化
回溯法解决的问题都可以抽象为树形结构.因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度就构成了树的深度。举一个例子,n = 4,k = 4,那么第一层for循环的时候,从元素2开始的遍历都没有意义了。图中每一个节点(图中为矩形),就代表本层的一个for循环,那么每一层的for循环从第二个数开始遍历的话,都没有意义,都是无效遍历。path这个数组的大小如果达到k,说明我们找到了一个子集大小为k的组合了,在图中path存的就是根节点到叶子节点的路径。原创 2024-05-31 11:30:36 · 520 阅读 · 0 评论 -
算法训练 | 二叉树Part9 | 669.修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树
这里定义的是左闭右闭区间,在不断分割的过程中,也会坚持左闭右闭的区间,这又涉及到我们讲过的循环不变量。接着划分区间,root的左孩子接住下一层左区间的构造节点,右孩子接住下一层右区间构造的节点。确定递归终止条件:这里定义的是左闭右闭的区间,所以当区间 left > right的时候,就是空节点了。确定单层递归的逻辑:注意要右中左来遍历二叉树, 中节点的处理逻辑就是让cur的数值加上前一个节点的数值。但在二叉搜索树的中可不是单纯的节点3和左孩子节点0就决定的,还要考虑节点0的右子树。原创 2024-05-30 11:23:52 · 875 阅读 · 0 评论 -
算法训练 | 二叉树Part8 | 235.二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点
剩下的情况,就是cur节点在区间(p->val <= cur->val && cur->val <= q->val)或者 (q->val <= cur->val && cur->val <= p->val)中,那么cur就是最近公共祖先了,直接返回cur。第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点。原创 2024-05-29 10:19:06 · 1010 阅读 · 0 评论 -
算法训练 | 二叉树Part7 | 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数
一个指针指向前一个节点,这样每次cur(当前节点)才能和pre(前一个节点)作比较。而且初始化的时候pre = NULL,这样当pre为NULL时候,我们就知道这是比较的第一个元素。结果更新:频率count 大于 maxCount的时候,不仅要更新maxCount,而且要清空结果集(以下代码为result数组),因为结果集之前的元素都失效了。存入众数结果:频率count 等于 maxCount(最大频率),当然要把这个元素加入到结果集中(以下代码为result数组)在二叉搜素树中序遍历的过程中直接计算。原创 2024-05-28 19:40:48 · 288 阅读 · 0 评论 -
算法训练 | 二叉树Part6 | 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
确定终止条件:因为是传入了两个树,那么就有两个树遍历的节点t1 和 t2,如果t1 == NULL 了,两个树合并就应该是 t2 了(如果t2也为NULL也无所谓,合并之后就是NULL)。确定终止条件:题目中说了输入的数组大小一定是大于等于1的,所以我们不用考虑小于1的情况,那么当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。确定递归函数的参数和返回值:递归函数的参数传入的就是根节点和要搜索的数值,返回的就是以这个搜索数值所在的节点。原创 2024-05-28 18:16:47 · 969 阅读 · 0 评论 -
算法训练 | 二叉树Part5 | 513.找树左下角的值、112.路径总和、106.从中序与后序遍历序列构造二叉树
中序数组都切成了左中序数组和右中序数组了,那么后序数组就可以按照左中序数组的大小来切割,切成左后序数组和右后序数组。以后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后序数组。首先要切割中序数组,切割点在后序数组的最后一个元素,就是用这个元素来切割中序数组的,所以必要先切割中序数组。可以使用前序遍历(当然中序,后序都可以,因为本题没有 中间节点的处理逻辑,只要左优先就行),保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。在树的最后一行找到最左边的值。原创 2024-05-27 22:10:49 · 1007 阅读 · 0 评论 -
算法训练 | 二叉树Part4 | 10.平衡二叉树、257.二叉树的所有路径、404.左叶子之和
因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点。只有当前遍历的节点是父节点,才能判断其子节点是不是左叶子。确定单层递归的逻辑:·当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和右子树左叶子之和,相加便是整个树的左叶子之和。确定递归函数的参数和返回值:判断一个树的左叶子节点之和,那么一定要传入树的根节点,递归函数的返回值为数值之和,所以为int。原创 2024-05-27 16:27:01 · 710 阅读 · 0 评论 -
算法训练 | 二叉树Part3 | 104.二叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数
确定单层递归的逻辑:先求它的左子树的深度,再求右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度。确定单层递归的逻辑:先求它的左子树的节点数量,再求右子树的节点数量,最后取总和再加一 (加1是因为算上当前中间节点)就是目前节点为根节点的节点数量。确定递归函数的参数和返回值:参数就是传入树的根节点,返回就返回以该节点为根节点二叉树的节点数量,所以返回值为int类型。在处理节点的过程中,最小深度是从根节点到最近叶子节点的最短路径上的节点数量。原创 2024-05-24 17:19:22 · 1058 阅读 · 1 评论 -
算法训练 | 二叉树Part2 | 层序遍历、226.翻转二叉树、101.对称二叉树
确定递归函数的参数和返回值:参数就是要传入节点的指针,不需要其他参数了,通常此时定下来主要参数,如果在写递归的逻辑中发现还需要其他参数的时候,随时补充。对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了其实我们要比较的是两个树(这两个树是根节点的左右子树),所以在递归遍历的过程中,也是要同时遍历两棵树。确定递归函数的参数和返回值:因为我们要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数是左子树节点和右子树节点。原创 2024-05-22 17:49:05 · 875 阅读 · 1 评论 -
算法训练 | 二叉树Part1 | 递归遍历、迭代遍历、统一迭代
学习分享个人主页。原创 2024-05-21 17:31:38 · 610 阅读 · 1 评论 -
算法训练 | 栈与队列Part3 | 239.滑动窗口最大值、347.前 K 个高频元素
大顶堆(堆头是最大元素),小顶堆(堆头是最小元素),直接用priority_queue(优先级队列)就可以了,底层实现都是一样的,从小到大排就是小顶堆,从大到小排就是大顶堆。push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止。这个维护元素单调递减的队列就叫做单调队列,即单调递减或单调递增的队列。模拟队列,放进去窗口里的元素,随着窗口的移动,队列也一进一出,每次移动之后,队列将最大值放在出口处。原创 2024-05-20 12:13:43 · 573 阅读 · 0 评论 -
算法训练 | 栈与队列Part2 | 20.有效的括号、1047.删除字符串中的所有相邻重复项、150.逆波兰表达式求值
遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false。已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false。栈的目的是存放遍历过的元素,当遍历当前的这个元素的时候,去栈里看一下是不是遍历过相同数值的相邻元素。从栈中弹出剩余元素,因为从栈里弹出的元素是倒序的,所以再对字符串进行反转一下,就得到了最终的结果。在删除相邻重复项的时候,其实就是要知道当前遍历的这个元素,在前一位是不是遍历过一样数值的元素。原创 2024-05-18 22:39:30 · 660 阅读 · 0 评论 -
算法训练 | 栈与队列Part1 | 232.用栈实现队列、225.用队列实现栈
在push数据的时候,只要数据放进输入栈就好,但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。队列是先进先出的规则,把一个队列中的数据导入另一个队列中,数据的顺序并没有变,并没有变成先进后出的顺序。原创 2024-05-17 15:36:30 · 310 阅读 · 0 评论 -
算法训练 | 字符串Part2 | 28.实现 strStr()、459.重复的子字符串
(len - (next[len - 1] + 1)) 也就是: 12(字符串的长度) - 8(最长公共前后缀的长度) = 4, 4正好可以被 12(字符串的长度) 整除,所以说明有重复的子字符串(asdf)。数组长度为:len。如果len % (len - (next[len - 1] + 1)) == 0 ,则说明数组的长度正好可以被 (数组长度-最长相等前后缀的长度) 整除 ,说明该字符串有重复的子字符串。= -1,则说明字符串有最长相同的前后缀(就是字符串里的前缀子串和后缀子串相同的最长长度)。原创 2024-05-16 11:53:36 · 431 阅读 · 0 评论 -
算法训练 | 字符串Part1 | 344.反转字符串、541.反转字符串II、卡码网:54.替换数字、151.翻转字符串里的单词、卡码网:55.右旋转字符串
在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。对于字符串,定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。整体翻转的操作放在下面,先局部反转,要控制好局部反转的长度,如果先局部反转,那么先反转的子串长度就是 len - n。在反转链表中,使用了双指针的方法。通过整体倒序,把两段子串顺序颠倒,两个段子串里的的字符在倒叙一把,负负得正,这样就不影响子串里面字符的顺序了。原创 2024-05-15 16:04:19 · 770 阅读 · 0 评论 -
算法训练 | 哈希表Part2 | 454.四数相加II、383.赎金信、15.三数之和、18.四数之和
四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值,依然是循环内有left和right下标作为双指针,找出nums[k] + nums[i] +nums[left] + nums[right] == target的情况,三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3)。的双指针解法是一层for循环num[i]为确定值,然后循环内有left和right下标作为双指针,找到nums[i] + nums[left] + nums[right] == 0。原创 2024-05-14 15:36:13 · 651 阅读 · 0 评论 -
算法训练 | 哈希表Part1 | 242.有效的字母异位词、349.两个数组的交集、202.快乐数、1.两数之和
需要给出一个元素,判断这个元素是否出现过,如果出现过,返回这个元素的下标。那么判断元素是否出现,这个元素就要作为key,所以数组中的元素作为key,有key对应的就是value,value用来存下标。在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。原创 2024-05-13 21:09:10 · 979 阅读 · 0 评论 -
算法训练 | 链表Part2 | 24.两两交换链表中的节点、19.删除链表的倒数第N个节点、106.链表相交、142.环形链表II
可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。fast 走两个节点,slow走一个节点,其实相对于slow来说,fast是一个节点一个节点的靠近slow的,有环的话,一定会在环内相遇,而不是永远的错开。当 n为1的时候,公式就化解为。原创 2024-05-11 16:38:03 · 1081 阅读 · 3 评论 -
算法训练 | 链表Part1 | 203.移除链表元素 、707.设计链表、206.反转链表
然后,遍历链表并打印每个节点的值。链表由一系列节点组成,每个节点包含两部分:一部分是存储数据的元素,另一部分是一个指针,指向该节点所在链表中的下一个节点。删除非头节点:判断cur与curnext均不为空,且curnext节点元素为删除数值,则cur指向curnextnext。移除头结点和移除其他节点的操作是不一样的,链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点。链表的头节点是元素1, 反转之后头结点就是元素5 ,这里并没有添加或者删除节点,仅仅是改变next指针的方向。原创 2024-05-11 00:27:03 · 1258 阅读 · 1 评论 -
算法训练 | 数组Part2 | 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II
目录977.有序数组的平方暴力解法双指针法209.长度最小的子数组暴力解法滑动窗口59.螺旋矩阵II转圈模拟嵌入式学习分享个人主页:Orion嵌入式随想录 - 小红书 (xiaohongshu.com)题目链接:. - 力扣(LeetCode)文章讲解:代码随想录视频讲解: 双指针法经典题目 | LeetCode:977.有序数组的平方_哔哩哔哩_bilibili解题思路先平方后排序解题步骤循环内平方循环后快速排序代码注意sort(A.begin(), A.end());快速排序方法return nums;原创 2024-05-09 21:33:42 · 779 阅读 · 0 评论 -
算法训练 | 数组Part1 | 704. 二分查找、27. 移除元素
if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1。原创 2024-05-08 19:13:31 · 1108 阅读 · 0 评论