自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(48)
  • 收藏
  • 关注

原创 代码随想录算法训练营day60||42. 接雨水 ||84.柱状图中最大的矩形

首先我们确定是使用单调栈的思路,那么使用单调栈的话存放顺序是什么?从栈顶到栈底的存放顺序是从小到大,递增的顺序,当遍历到比栈顶元素大的元素的时候,就进行操作,这样就模拟了一个凹槽,两边大中间小,此时我们计算凹槽能够容纳的面积就是接雨水的面积。这里涉及到了单调栈的重要性质,就是单调栈里的顺序,是从小到大还是从大到小。注意:这里的三个元素并不是连续的三个柱子组成的面积!遇到相同高度的元素,将原来栈里元素弹出,将新元素入栈。因为我们要求宽度的时候,如果遇到高度相同的柱子,需要使用最右边的柱子来计算宽度。

2022-11-15 22:44:21 210 1

原创 代码随想录算法训练营day58||739. 每日温度 ||496.下一个更大元素 I ||503.下一个更大元素II

大致思路与上一题一样但是比上一题更绕一些,首先我们创建一个result的数组的大小与nums1的大小相同,全部初始化为-1,默认没有找到更大元素,如果后面找到了就进行操作,如果没找到就保持-1,然后我们还是用单调栈的方法遍历nums2数组,同样是三种情况,nums[i]nums[st.top()],这里使用的是递增顺序,只有递增的顺序,加入一个元素i,才知道是栈顶元素在数组中右边比栈顶元素大的是i.

2022-11-15 11:46:04 261

原创 代码随想录算法训练营day56||72. 编辑距离||647. 回文子串 ||516.最长回文子序列

示例 1: 输入:word1 = "horse", word2 = "ros" 输出:3 解释: horse -> rorse (将 'h' 替换为 'r') rorse -> rose (删除 'r') rose -> ros (删除 'e')1.dp[i][j]及其下标的定义:以下标i-1为结尾的字符串word1和以下标j-1为结尾的字符串word2的最小编辑距离是dp[i][j].不操作:dp[i][j]=dp[i-1][j-1]换:dp[i][j]=dp[i-1][j-1]+1。

2022-11-14 09:45:25 252

原创 代码随想录算法训练营day52||674. 最长连续递增序列||718. 最长重复子数组||1143.最长公共子序列

dp[i][j]:以下标i-1为结尾的A,和以下标j-1为结尾的B,最长重复子数组长度为dp[i][j].(特别注意:以下标i-1为结尾的A,标明一定是以A[i-1]为结尾的字符串。1.dp[i][j]及其下标的含义:长度为[0,i-1]的字符串text1与长度为[0,j-1]的字符串text2的最长公共子序列为dp[i][j]。但dp[i][0]和dp[0][j]要初始化,因为为了方便递推公式dp[i][j]=dp[i-1][j-1]+1。所以dp[i][0]和dp[0][j]初始化为0.

2022-11-12 21:41:45 565

原创 代码随想录算法训练营day55||392.判断子序列||115.不同的子序列||583. 两个字符串的删除操作

if(s[i-1]!=t[j-1]),此时相当于t要删除元素,t如果把当前元素t[j-1]删除,那么dp[i][j]的数值就是看s[i-1]与t[j-2]的比较结果,即:dp[i][j]=dp[i][j-1];-dp[i][j]=dp[i-1][j]+1 和 dp[i][j]=dp[i][j-1]+1 和 dp[i][j]=dp[i-1][j-1]+2。递推公式可以看出dp[i][j]依赖于dp[i-1][j-1]和dp[i][j-1],所以一定要初始化dp[0][0]和dp[i][0].

2022-11-12 21:41:18 118

原创 代码随想录算法训练营day53||1035.不相交的线||53. 最大子序和

直线不能相交,就说明在字符串A中找到一个与字符串B相同的子序列,而且这个子序列不能改变相对顺序,只要相对顺序不改变,链接相同数字的直线就不会相交。一定是取最大的,所以dp[i] = max(dp[i - 1] + nums[i], nums[i]);从递推公式可以看出来dp[i]是依赖于dp[i - 1]的状态,dp[0]就是递推公式的基础。根据dp[i]的定义,很明显dp[0]应为nums[0]即dp[0] = nums[0]。递推公式中dp[i]依赖于dp[i - 1]的状态,需要从前向后遍历。

2022-11-12 20:40:13 553

原创 代码随想录算法训练营day30||332.重新安排行程 ||第51题. N皇后||37. 解数独

1.确定参数和返回值:因为这个不是找到一个棋盘就进行返回,而是找出所有的棋盘,所以返回值为void。因为递归遍历棋盘的高度,for遍历棋盘的宽度,所以要传入棋盘的长宽n,还需要确定当前递归层数的row。想要解出这道题,最主要的就是知道二维递归,棋盘的横向赋值和纵向赋值遍历都是通过递归来实现的,也就是说要写两层递归函数里要写两层for循环来安插数字,如果知道这一点这一题就迎刃而解了。想要解出这道题,重点在于抽象棋盘,将棋盘抽象成一颗树形结构,for循环遍历棋盘的行,递归遍历棋盘的列。

2022-11-10 17:01:42 383

原创 代码随想录算法训练营day51|| 309.最佳买卖股票时机含冷冻期 ||714.买卖股票的最佳时机含手续费 ||300.最长递增子序列

思路:这题相对于买卖股票最佳时机2多了一个冷冻期的条件,买卖股票最佳时机2每天只用考虑两个状态,买入股票状态和卖出股票的状态。这题多了一个条件就需要多出一些状态求解,这题就需要总的每天可能分为四个状态:1.持有股票 2.第i天之前不持有股票(前一天是冷冻期,或者前一天超过冷冻期并且不持有股票) 3.第i天卖出股票 4.当天为冷冻期为什么不把状态二和状态三结合在一起呢?因为状态四是冷冻期,状态四之前的一天一定是状态三,股票卖出的当天。但是如果将状态二和三结合在一起了,那么就无法保证状态四的前一天是刚好卖出股票

2022-11-09 18:02:44 279

原创 代码随想录算法训练day50||123.买卖股票的最佳时机III ||188.买卖股票的最佳时机IV

这道题相较于上一道买卖股票最佳时机2,多了最多只能进行两笔交易的限制,刚拿到这题时我就想用一个count计数器来统计,每次卖出一次,count++,当count最大等于2.这个一想是不是觉得很简单,但是仔细一想每次卖出股票都没有确切的时间,根本不能确定是这一天卖出股票的收益是最大的,因为很可能下一天的股票价格更大,这个在遍历之前是未知的,所以这个方法是不合理的。1.确定dp[i][j]及其下标的含义:到第i天时状态j下最多剩余为dp[i][j].2.递推公式:dp[i][0]=dp[i-1][0].

2022-11-09 11:32:47 114

原创 代码随想录算法训练day37||738.单调递增的数字||714. 买卖股票的最佳时机含手续费 ||968.监控二叉树

当且仅当每个相邻位数上的数字x和y满足x strNum[i]的情况,让strNum[i-1]--,然后strNum[i]赋值为9,可以保证这两位是最大单调递增整数。全局最优:得到小于等于N的最大单调递增整数。但是这里局部最优推全局最优,还需要遍历顺序,和标记从哪一位开始统一改为9.此时是从前往后还是从后往前。

2022-11-08 17:00:48 85

原创 代码随想录算法训练day32||122.买卖股票的最佳时机II ||55. 跳跃游戏 ||45.跳跃游戏II

思路:本题首先要清楚两点:想获得利润至少要两天为一个交易单元。这道题目可能我们只会想,选一个低的买入,在选个高的卖,在选一个低的买入.....循环反复。如果想到其实最终利润是可以分解的,那么本题就很容易了!55. 跳跃游戏思路:跳跃游戏最主要的点就是想到统计每个点覆盖的最远范围,每次统计当前能够到达的点的最远距离,不断更新这个最远范围,如果这个最远范围最终>=最后一个下标的位置,那么可以到达返回true,如果统计完后这些位置的最大值小于最后一个位置返回FALSE。这道题如果考虑的是每次应该跳几步,

2022-11-08 15:46:50 109

原创 代码随想录算法训练营day49||121. 买卖股票的最佳时机||122.买卖股票的最佳时机II

所以在持有股票的情况会有所不用,如果是第i-1天之前就持有股票,那么dp[i][0]=dp[i-1][0],但是如果是第i天买入股票,第i天之前可能就进行了买入卖出赚取了利润,所以我们还要加上之前的利润,dp[i][0]=dp[i-1][1]-prices[i].这是确定卖出股票的天数,如果股票是在第i-1天之前卖出股票的收益最大,那么dp[i][1]=dp[i-1][1].如果股票是在第i天卖出的收益最大,那么dp[i][1]=dp[i-1][0]+prices[i].输入:[7,1,5,3,6,4]

2022-11-08 10:58:55 154

原创 代码随想录算法训练营day36||435. 无重叠区间||763.划分字母区间 ||56. 合并区间

我刚开始想到的是按照右区间从小到大进行排序,右区间越小留给下一个区间的空间就越大,但是我转头一想,这道题不是合并区间吗,那我应该尽可能多的去合并更多的空间,我就按照左区间的从小到大进行排序,遍历时就从前往后进行遍历,如果设置start和end来记录重叠的左边界和右边界,如果下一区间的左区间小于这一个区间的右边界的话说明两者重叠,end值更新为较大的那个右边界,如果判断两个区间没有重叠则将当前记录的start,end压入result数组。给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

2022-11-08 09:20:20 106

原创 代码随想录算法训练营||135. 分发糖果||406.根据身高重建队列||452. 用最少数量的箭引爆气球 ||435. 无重叠区间

这一题的关键思想在于得到分数高的孩子得到的糖果比左边孩子多也比右边孩子多,但是我们考虑的时候不能遍历孩子的时候,不能一边考虑左边孩子的同时一边考虑右边孩子,这样容易顾此失彼,我们可以先考虑和左边孩子的比较,从左向右遍历,如果当前孩子的值大于左边孩子,那么当前孩子得到的糖果等于左边这个孩子+1.如果不大于左边孩子,那么赋值为1, 左边遍历完后,我们从右向左开始遍历,如果左边孩子的值大于右边,那么比较当前的值和右边孩子+1的大小,取最大的那个。全局最优:相邻的孩子中分数高的糖果多。

2022-11-07 20:50:51 80

原创 代码随想录算法训练营day48||198.打家劫舍 ||213.打家劫舍II||337.打家劫舍 III

题目描述:你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。示例 1: 输入:[1,2,3,1] 输出:4 解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。偷窃到的最高金额 = 1 + 3 = 4。

2022-11-07 12:08:38 227

原创 代码随想录算法训练||139.单词拆分 ||多重背包

3.初始化:dp[0]初始化为true,其他地方初始化为false,为什么dp[0]要初始化为true,你想啊:如果区间【0,i】中的单词能够在wordDict中找到,还得满足dp[0]为true,dp[i]才能为true.这就保证了必须不漏掉第一个单词。2.确定递推公式:背包容量为i(长度为i的子串),i>j,如果dp[j]=true,区间[i,j]之间的子串能够在wordDict中找到,那么返回true.1.确定dp[i]及其下标的定义:dp[i]背包容量为i能否拆分成几个能够查到的单词。

2022-11-06 23:06:03 73

原创 代码随想录算法训练day45||70. 爬楼梯 ||322. 零钱兑换||279.完全平方数

解决1:将除了dp[0]初始化为0,其他初始化为INT_MAX,如果遍历结束后dp[amount]等于INT_MAX的话说明不能够凑出总金额。3.初始化:由递推公式可以看出初始化dp所有值时不能全部初始化为0,全部初始化为INT_MAX,dp[0]=0;示例 1: 输入:coins = [1, 2, 5], amount = 11 输出:3 解释:11 = 5 + 5 + 1。这一题和上一题基本完全相同,只不过这一题的物品是完全平方数,上一题的物品是给定的coins数组。你可以认为每种硬币的数量是无限的。

2022-11-05 09:38:07 68

原创 代码随想录算法训练day44||518. 零钱兑换 II ||377. 组合总和 Ⅳ

输入: amount = 5, coins = [1, 2, 5] 输出: 4 解释: 有四种方式可以凑成总金额: 5=5 5=2+2+1 5=2+1+1+1 5=1+1+1+1+1。反过来的话是求排序问题(如果是纯背包问题那就不用在意这个,因为纯背包问题就是为了凑出背包容量,不用管顺序,只需要凑出就行).2.递推公式:组合问题常用公式:dp[j]+=dp[j-coins[i]];1.dp[i]及其下标的定义:填满容量为i的背包最多有dp[i]种方法。背包容量是从小到大,反过来是01背包。

2022-11-04 23:24:17 84

原创 代码随想录算法训练营day44||494. 目标和 ||474.一和零||完全背包

我看了卡哥的题解思路是将这个数组中的数,变成左右两堆的数,当这两堆数满足left-right=target时,代表求出了一个满足条件的方案,这样子就避免了像我那样每次遍历数组中的数还得考虑是放入正号还是负号,这道题统一就是left堆放正号,right堆放负号。2.递推公式:dp[i][j]=max(dp[i][j],dp[i-nums[k].first][j-nums[k].second]]+1).1.dp[i][j]及其下标的定义:0容量为i,1容量为j的背包最多能装下dp[i][j]个子集.

2022-11-04 23:06:34 112

原创 代码随想录算法训练||1049. 最后一块石头的重量 II ||背包问题二维dp和一维dp的区别

这题最重要的地方就是想到将所有石头切分成两堆大小尽可能相同的石头。两堆尽可能相同的石头相减的结果就是最终结果,如果想到了这一点那么这一道题就跟 416. 分割等和子集 的解法差不多了。动规五部曲:1.dp[j]及其下标的定义:dp[j]当前容量为j的背包所容纳的最大容量的石头2.dp[i]的递推公式:dp[j]=max(dp[j],dp[j-stones[i]]+stones[i])3.dp[i]的初始化,全部初始化为0。

2022-11-04 22:24:22 98

原创 算法训练||70. 爬楼梯||746. 使用最小花费爬楼梯||62.不同路径||63. 不同路径 II

j从1开始遍历,拆分j的情况,在遍历j的过程中已经计算过了,那么从1遍历j,比较(i-j)*j和dp[i-j]*j取最大的。递推公式:dp[i]=max(dp[i],max(i-j)*j,dp[i-j]*j));一个是j*(i-j)直接相乘。1.dp[i][j]及其下标的含义:到横坐标为i纵坐标为j的地方有dp[i][j-1]种方法。2.递推公式:dp[i]=min(dp[i-1],dp[i-2])+cost[i];2.递推公式:dp[i][j]=dp[i-1][j]+dp[i][j-1];

2022-10-31 11:31:22 68

原创 算法训练||134. 加油站

1.本题可以使用暴力解法,首先判断是否能够走完整的一圈,如果剩余油的总量大于消耗油的总量,那么可以走完。两层for循环,第一层下标i作为起始位置,第二层for循环用于遍历一圈,如果哪一个点开始可以完整的遍历一圈,那么这个点就是加油站的起点。2.本题可以可以使用贪心的写法,先统计出到每个站点的油净含量(加油量-消耗量),for循环从0号加油站开始遍历,如果遇到中途,汽车油总量小于0,加油起始位置就从start=i+1开始,最后start的值就是开始的位置。

2022-10-25 23:25:10 51

原创 算法训练||122.买卖股票的最佳时机II |55. 跳跃游戏 |45.跳跃游戏II |1005.K次取反后最大化的数组和

public:// 只有一个元素,就是能达到i++) { // 注意这里是小于等于cover// 说明可以覆盖到终点了}}};

2022-10-24 23:26:22 790

原创 算法训练day31||376. 摆动序列

看到这个的时候我就很懵,但是看了题解之后发现,只要把这个题抽象成一个图形就不再困难了,抽象成一个山坡图,如果我们要求最大摆动序列,我们只用删除所有山坡上的元素。实际操作中,其实联删除操作都不用,题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了 (相当于删除单一坡度上的节点,然后统计长度)为什么一开始result就从1开始,每一次统计一个峰值就result+1,但是你看初始时,如果只有两个数,只加1 的话就会缺一个1.

2022-10-21 23:45:34 82

原创 算法训练||39. 组合总和|40.组合总和II131. 分割回文串

先说说什么时候需要startIndex,当我们求的组合是从一个集合中取元素的时候,我们就需要startIndex,在组合中[2,5]和[5,2]相同,所以当我们上一次组合有了[2,5]之后,for遍历startIndex就得必须从5开始了。这道题相比于上一道题多了去重的操作(可以使用used数组,还可以使用set集合来进行去重操作,但是不管使用哪一个去重操作,都需要进行sort排序),加上每一位数字都不能够重复使用,所以递归startIndex+1开始遍历。切割问题的回溯过程类似于组合问题的回溯过程。

2022-10-19 23:24:13 83

原创 算法训练day25||216.组合总和III |17.电话号码的字母组合

定义一个全局变量vectorpath用于存下遍历从根节点到叶子节点,定义一个vectorresult存在满足条件的path,返回值是void ,参数是k,n,还有startIndex,startIndex代表是下一次for循环的起始位置,为什么需要startIndex,因为组合的数字的不能重复的数字,来避免重复。二、遍历的时候将数字转化为对应的字符串,然后for循环遍历,for循环里面包含递归逻辑。2.数字的长度代表递归遍历的层数,for循环用于遍历数字映射出的字符串。

2022-10-15 16:41:06 188

原创 算法训练day24||第77题. 组合

这题求组合大家很容易就可以想到for循环,但是两层三层for循环还好,如果是十几层几十层for循环实现起来就很麻烦了,虽然想要暴力解法,但是暴力解法也写不出来。这时就可以使用回溯写法,回溯法就用递归来解决嵌套层数的问题。递归来做层序遍历(可以理解是开k层for循环),每一次的递归中嵌套一个for循环,那么递归就可以用于解决多层嵌套循环的问题了。回溯法解决的问题都可以抽象为树形结构(N叉树),用树形结构来理解回溯就容易多了每次从集合中选取元素,可选择的范围随着选择的进行而收缩,调整可选择的范围。

2022-10-14 10:33:27 205

原创 算法训练day23||669. 修剪二叉搜索树|108.将有序数组转换为二叉搜索树

我刚开始是写如果一个结点小于给定返回则直接返回他的右子树,但是这样忽略了,右子树中也存在有不满足条件的节点,然后我继续写不断从上到下遍历右子树,如果遍历到满足的节点就返回,这里我忽略了,二叉搜索树的特性,二叉搜索树左下角的节点是最小的,要操作也是应该从下到上删除操作,看完卡哥思路,看到了他这里如果遍历到的节点值小于给定范围的时候,并没有直接返回右子树,而是继续遍历右子树,这样就可以保证去除操作,进行到最底层了。1.确定返回值和参数:返回值是构造好的根节点,参数是nums数组,left,right下标。

2022-10-13 17:02:46 101

原创 算法训练day22||235. 二叉搜索树的最近公共祖先|701.二叉搜索树中的插入操作|450.删除二叉搜索树中的节点

找到节点很简单,重点讲下删除结点:找结点可能遇到这几种情况:1.找不到结点 2.找到的节点左右子树为空 3.找到的节点左子树为空右子树不为空 4.找到的结点右子树为空左子树不为空 5.找到的节点两个子树都不为空(最复杂的情况),对应的去进行相应的操作就可以。递归中确定单层逻辑:如果遍历到的当前节点的值比p,q两个节点大,那么就像当前节点的左子节点进行递归,如果遍历到节点比p,q两个节点都小,那么就向当前节点的右子树进行遍历。本题是标准的搜索一条边的写法,遇到递归函数的返回值,如果不为空就立即返回。

2022-10-12 21:17:11 109

原创 算法训练day21||530.二叉搜索树的最小绝对差|501.二叉搜索树中的众数|236. 二叉树的最近公共祖先

方法1:如果这是一个普通的二叉树,那么我们可以使用一个map来通过遍历将二叉树结点的值和出现的次数存起来,然后因为不能在map里面直接按照value进行排序,所以我们将创建一个vectorvec ,并将map直接赋值给他,然后通过sort()进行排序(具体怎么排序就要通过操作sort的第三个参数cmp,通过写特定的函数),然后将排序后的前n个评率出现相同的元素装进数组。使用后序遍历,回溯的过程,就是从低向上遍历结点,一旦发现满足第一种情况的节点,就是最近公共结点了。

2022-10-12 11:18:44 119

原创 算法训练day20||654.最大二叉树

有一个点大家可能会疑惑,比如二叉树1只有一个结点,二叉树2有很多层结点,递归循环只进行了一层,表面看二叉树1只接上了左右两个子节点,但是左右两个子节点会将之前的左右子树都带上,而且不用担心的是,原先的二叉树1,对应结点的地方都为空,所以直接继承了二多的节点,而不会出错。找到切割点后进行切割数组,然后向左右进行递归构造,向左右进行递归构造的条件是,左右数组的大小至少大于1.二叉搜索树的概念:根节点的左子树里的节点的值都小于根节点的值,根节点的右子树里的所有节点的值都大于根节点,左右子树也满足这一特性。

2022-10-11 13:15:11 92

原创 算法训练day18||404.左叶子之和|513.找树左下角的值|112. 路径总和|

思路:对二叉树运用前序遍历,用一个count(count=count-当前节点的值)作为计数器,一直遍历到叶子结点,如果遍历到当前叶子结点时计数器count=0,遍历结束,return true.如果计数器count!=0,那么就向上回溯,返回上一个结点,并且将count也返回上一个节点时候的值,求出左叶子之和的关键在求叶子结点的条件,并且这是左叶子节点,但是在当前节点的时候无法确定自己是不是左叶子结点,所以求左叶子结点,一定要通过操作该结点的父节点。给定一个二叉树,在树的最后一行找到最左边的值。

2022-10-10 11:42:51 106

原创 算法训练day17||110.平衡二叉树

null&&node->left->left==null&&node->left->right==null),左叶子结点在当前节点是不可判断的,只有在他的上一个结点才可以判断是否是左叶子节点。使用后序遍历求左叶子之和。本题涉及到回溯的算法,运用前序遍历,用一个vector容器来装当前遍历的路径,当你遍历到叶子节点的时候,就证明这条路径已经走到头了,这时候需要使用回溯,向上一个结点走,看是否能够走右边方向,如果不能就继续将上一个结点走,每次向上一个结点走的时候,都将当前节点的值从容器中弹出(这就叫回溯)。

2022-10-08 23:32:02 83

原创 算法训练day16||104.二叉树的最大深度|111.二叉树的最小深度|222.完全二叉树的节点个数

遍历二叉树,如果遍历的节点的左子树和右子树外侧高度相同那么就是满二叉树,如果是满二叉树就直接计算出节点数目,如果不是就遍历当前节点的左子树和右子树,判断左子树和右子树是不是满二叉树,以此类推,计算出结果。求二叉树的最大高度(后序遍历)等同于求二叉树的最大深度(前序遍历),求二叉树的最大高度就要用到后序遍历,为什么要用后续遍历呢?如果是一颗普通的二叉树,不管是用前中后续遍历或者是层序遍历都可以完成统计操作,但是本题求的是一颗完全二叉树的遍历,那我们就利用完全二叉树的特性。

2022-10-08 14:13:42 120

原创 算法训练day15||二叉树的层序遍历|226.翻转二叉树|101. 对称二叉树

定义一个队列,将二叉树树顶节点压入队列中,用while循环,循环条件是当队列不为空,每次循环都记下队列里当前节点的个数(也就是当前这层的节点个数),记下该层的节点数之后,再使用一个for循环将队列中,刚刚记下的那层的节点一个个弹出,每次弹出一个结点,判断这个结点是否存在左右子节点,若存在则将其压入队列。是不会的,因为每操作一层结点,都会统计这一层结点的数目,也就是当前队列中的节点个数,然后用for循环刚好弹出统计的元素个数,利用到了队列先进先出的特点。递归三部曲,先交换,再向左递归,再向右递归。

2022-10-08 13:15:06 104

原创 算法训练day14||二叉树的递归遍历|二叉树的迭代遍历|二叉树的统一迭代法

思路:压入第一个节点进栈中,然后进行while循环操作,循环条件是栈不为空,将栈中第一个节点弹出,存到result数组中,如果弹出的节点有右子节点,就将他的右子节点压入栈中,随后判断是否有左子节点,有就将左子节点压入栈中。=null,就压入栈中,向左遍历。2.确定终止条件:写完递归算法,运行出现栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存站必然会溢出。前序按照压入右节点,左节点,中间结点,null的顺序压入。

2022-10-06 17:58:46 112

原创 算法训练day13||150. 逆波兰表达式求值|239. 滑动窗口最大值|347. 前 K 个高频元素

所以由此可以想到我们遍历数组时将当前遍历到的数组元素加入窗口时进行判断,如果窗口中的最后一个元素小于刚刚压入的元素,就将最后一个元素弹出,循环往复。遍历字符数组,如果遍历到数字就将数字压入到栈中,如果遍历到运算符,就将栈顶的两个元素进行出栈操作,进行运算后的结果压入到栈中。push():判断数组当前遍历到的元素是否大于窗口(双向队列)中的尾部元素,如果大于就将尾部元素弹出,弹出操作结束后就将遍历到的当前元素压入。pop():判断窗口中的第一个元素(队首元素)是否是数组中的第一个元素,如果是就将其弹出。

2022-10-05 20:36:42 221

原创 算法训练Day11||232.用栈实现队列|225.用队列实现栈| 20.有效括号

入队操作不是连续的,而是入队和出队操作间断进行的,那么出队操作就要进行一些逻辑判断操作,如果第二个栈不为空,就将第二个栈中的元素直接弹出,如果第二个栈为空,就将第一个栈中的所有元素压入第一个栈中。获取队首元素:与出队操作大致相同,将一个栈中元素压入另一个栈中,然后通过stack.top()获取其中的元素。出队操作:将其中一个栈中的元素压入另一个栈中,再将元素从另一个栈中弹出,这样就是实现了先进先出的操作。出栈操作:先将最后一个入队元素之前的元素(n-1个元素)全部弹出,并加入队列的尾部,然后进行弹出操作。

2022-10-05 19:02:45 102

原创 算法训练day9||459.重复的子字符串

假设字符串ababab前缀是t,后缀是s,因为这是最长相等前缀后缀,那么t=s,所以t[0]=s[0],t[1]=s[1],因为s[0]=t[2],s[1]=t[3],所以t[0]=t[2],t[1]=t[3],以此类推可以得出最长相等前缀后缀不包含的那部分就是重复子串。如果字符串是重复的子字符串s, 那么s+s的中间(抛去首尾位置的字符)必然有一个s字符串,为什么呢?暴力写法的注意点:1.j如果完整的遍历完到=s.size()的位置,并且s.size()%(i+1)==0,说明存在重复子串。

2022-10-02 23:20:58 112

原创 算法训练day9|| 28.找出字符串中第一个匹配项的下标(kmp算法)

这个题解,我不清楚是怎么想到这样的一个方法的,虽然我觉得这个方法很妙,但是我可以也可以用代码写出一个构建next数组的方法,只不过时间复杂度是o(n^2),所以我暂且认为写出这样的算法是因为作者的算法能力很强,在尝试过程中写出的。因为前缀表中记录了模式串中每个元素的最长相同前缀后缀的长度,每次在匹配文本串和模式串时遇到不相同的情况时,如果有前缀表的话可以不从头开始匹配,而是根据前缀表对应的值返回上到特定的地方进行匹配。先构建一个前缀表(next数组),然后匹配模式串和文本串的时候使用next数组。

2022-09-30 12:32:18 312

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除