自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 代码随想录训练营第41天 | 343. 整数拆分 ● 96.不同的二叉搜索树

所以递推公式:dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j))。之所以还要比较dp[i],是因为在遍历j的过程中,dp[i]是在不断更新的。一个是j * dp[i - j],相当于是拆分(i - j)。可以明确的是m一定大于等于2,既然m大于等于2,也就是 最差也应该是拆成两个相同的可能是最大值。dp[i]:分拆数字i,可以得到的最大乘积为dp[i]。其实可以从1遍历j,然后有两种渠道得到dp[i].一个是j * (i - j) 直接相乘。

2023-10-28 02:10:55 177

原创 代码随想录训练营第39天 | 62.不同路径 ● 63. 不同路径 II

想要求dp[i][j],只能有两个方向来推导出来,即dp[i - 1][j] 和 dp[i][j - 1],那么dp[i][j] = dp[i - 1][j] + dp[i][j - 1],因为dp[i][j]只有这两个方向过来。因为从(0, 0)的位置到(i, 0)的路径只有一条,所以dp[i][0]一定为1,dp[0][j]也同理。递推公式为dp[i][j] = dp[i - 1][j] + dp[i][j - 1]。有障碍的话,其实就是标记对应的dp table(dp数组)保持初始值(0)就可以了。

2023-10-27 01:59:41 97

原创 代码随想录训练营第38天 | 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯

一定是选最小的,所以dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])。首先是dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,那么再一步跳一个台阶不就是dp[i]了么。dp[i - 1] 跳到 dp[i] 需要花费 dp[i - 1] + cost[i - 1]。dp[i - 2] 跳到 dp[i] 需要花费 dp[i - 2] + cost[i - 2]。由于从0和1起跳,所以dp[0]=0, dp[1]=1。

2023-10-27 00:03:41 135

原创 代码随想录训练营第37天 | 738.单调递增的数字 ● 968.监控二叉树

后向前遍历(332,遍历顺序为2-3-3),一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先让strNum[i - 1]--,然后strNum[i]以及后面的所有元素都设为9。过于hard了,如果考到,那就是和我八字不合,再见!738.单调递增的数字。时间复杂度:O(n)空间复杂度:O(n)

2023-10-26 12:47:04 87

原创 代码随想录训练营第36天 | 435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间

这么做是为了方便处理最后一个元素,不需要额外写代码,而且把只有一个元素的边界条件也处理掉了。做法可以参考射箭引爆气球,先按左边界进行升序排列,然后对下一个元素进行判断:如果重叠,那么更新元素的右边界;如果不重叠,那么非交叉区间的个数加一。即intervals[i]的左边界 <= intervals[i - 1]的右边界,则一定有重叠。这道题也是更新右边界的操作,由于不再是统计个数,而是把区间添加到结果中,需要稍微有些不同。主要是移除区间的个数等于总区间数减去非交叉区间的个数这点很难想到。

2023-10-26 02:48:03 92

原创 代码随想录训练营第35天 | 860.柠檬水找零 ● 406.根据身高重建队列 ● 452. 用最少数量的箭引爆气球

但如果把气球排序之后,从前到后遍历气球,被射过的气球仅仅跳过就行了,没有必要让气球数组remove气球,只要记录一下箭的数量就可以了。按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。如果真实的模拟射气球的过程,应该射一个,气球数组就remove一个元素,这样最直观,毕竟气球被射了。所以实际操作和代码实现非常不一样,实际操作上,射了当前的气球就没了,但是代码上还是存在列表中。空间复杂度:O(1)空间复杂度:O(n)

2023-10-25 10:21:15 127

原创 代码随想录训练营第34天 | 1005.K次取反后最大化的数组和 ● 134. 加油站● 135. 分发糖果

再确定左孩子大于右孩子的情况(从后向前遍历):如果 ratings[i] > ratings[i + 1],此时candyVec[i](第i个小孩的糖果数量)就有两个选择了,一个是candyVec[i + 1] + 1(从右边这个加1得到的糖果数量),一个是candyVec[i](之前比较右孩子大于左孩子得到的糖果数量)。如果将负数都转变为正数了,K依然大于0,此时的问题是一个有序正整数序列,如何转变K次正负,让数组和达到最大。如果剩油量总和大于零,那么有解,当循环结束,返回当前的起始位置即可。

2023-10-25 02:03:30 94

原创 代码随想录训练营第32天 | 122.买卖股票的最佳时机II ● 55. 跳跃游戏 ● 45.跳跃游戏II

相当于(prices[3] - prices[2]) + (prices[2] - prices[1]) + (prices[1] - prices[0])。如果移动下标达到了当前这一步的最大覆盖最远距离了,还没有到终点的话,那么就必须再走一步来增加覆盖范围,直到覆盖范围覆盖了终点。假如第 0 天买入,第 3 天卖出,那么利润为:prices[3] - prices[0]。如果按照这样实现:选一个低的买入,再选个高的卖,再选一个低的买入,会感觉比较难。这个范围内,别管是怎么跳的,反正一定可以跳过来。

2023-10-24 10:46:05 80

原创 代码随想录训练营第31天 | 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子序和

在计算是否有峰值的时候,知道遍历的下标 i ,计算 prediff(nums[i] - nums[i-1]) 和 curdiff(nums[i+1] - nums[i]),如果。局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。由于只需要返回最大和,而不需要返回子序列,所以在遍历过程中,不断更新最大的和即可。边界条件:只有两个数字的情况。

2023-10-24 06:41:47 87

原创 代码随想录训练营第29天 | 491.递增子序列、46.全排列、47.全排列 II

但排列问题需要一个used数组,标记在一棵树枝也就是深度方向已经选择的元素,用于去重。这里的写法是,used数组中放的是元素的index,而不是元素本身。当收集元素的数组path的大小达到和nums数组一样大的时候,说明找到了一个全排列,也表示到达了叶子节点。去重的逻辑如下,同一父节点不重复这个难以想到,这个可以使用set来去重,每次for循环之前都清空。本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了。时间复杂度:O(n * 2^n)空间复杂度:O(n)空间复杂度:O(n)

2023-10-01 22:21:34 84

原创 代码随想录训练营第28天 | 93.复原IP地址、78.子集、90.子集II

时间复杂度:O(3^4),IP地址最多包含4个数字,每个数字最多有3种可能的分割方式,则搜索树的最大深度为4,每个节点最多有3个子节点。本题明确要求只会分成4段,所以不能用切割线切到最后作为终止条件,而是分割的段数已经达到4作为终止条件。空集合也是子集,这是在第一次调用递归函数时加入,不需要自己手动加入。如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,时间复杂度:O(n * 2^n)时间复杂度:O(n * 2^n)这个题涉及到去重,所以。空间复杂度:O(4)空间复杂度:O(n)空间复杂度:O(n)

2023-09-29 19:50:32 77

原创 代码随想录训练营27天 | 39. 组合总和、40.组合总和II、131.分割回文串

需要注意的一点是,如果当前的字符串不是回文串,那么for循环应该continue,而不是return中断,因为下一个可能构成回文串。也就是在for循环的时候,判断前一个元素和当前元素是否相同,如果相同,则continue。切割线切到了字符串最后面,说明找到了一种切割方法,此时就是本层递归的终止条件。已经知道下一层的sum会大于target,就没有必要进入下一层递归了,以及本层的for循环也可以结束了。时间复杂度:O(n * 2^n),注意这只是复杂度的上界。时间复杂度:O(n * 2^n)

2023-09-28 21:47:55 96

原创 代码随想录训练营第25天 | 77.组合、216.组合总和III、17.电话号码的字母组合

那么可取的元素个数为:n+1 - startIndex,那么由 (n+1 - startIndex) >= (k - path.size()),得到:startIndex <= n+1 - (k-path.size()),那么遍历时,其实位置最多遍历到 : n+1 - (k - path.size()) ,那么 for 循环的条件为range(startIndex, n+2 - (k-path.size)),这样才能最大取到 n+1 - (k- path.size())时间复杂度:O(n * 2^n)

2023-09-28 03:55:03 104

原创 代码随想录训练营第23天 | 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

递归法:实现细节上,如果使用left和right的来原地取数,可以不用重新定义左右区间数组,而是用下标来操作原数组。如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点。如果root(当前节点)的元素大于high的,那么应该递归左子树,并返回左子树符合条件的头结点。如果数组的长度是偶数,那么中间节点取左或右的都行,构造的二叉树都满足条件。, 中节点的处理逻辑就是让cur的数值加上前一个节点的数值,并且更新pre指针。迭代法:不需要用到栈和队列,因为是有序的。

2023-09-27 11:18:01 109 1

原创 代码随想录训练营第22天 | 235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

235. 二叉搜索树的最近公共祖先。

2023-09-27 05:17:49 100 1

原创 代码随想录算法训练营第21天 | 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

一个关键问题是,如果在左子树遇到了q或者p,而右子树没有p或者q,就返回左子树的q或者q,那么如果p或者q就在它的下一层的左右子树上,就不去查找了吗?在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。判断逻辑是 如果递归遍历遇到q,就将q返回,遇到p 就将p返回,那么如果 左右子树的返回值都不为空,说明此时的中节点,一定是q 和p 的最近祖先。要注意的是任意两点的差值,而不是节点和左右子节点的差值。

2023-09-27 00:34:33 107 1

原创 代码随想录训练营20天 | 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。如果root->val > val,搜索左子树,如果root->val < val,就搜索右子树,最后如果都没有搜索到,就返回NULL。二叉搜索树中,左子树的所有节点的值,都必须小于中间节点的值;右子树的所有节点的值,都必须大于中间节点的值。注意每个子节点都是原地修改了自己的值,最终返回的是root1,而不是当前的子节点node1,这里我写错了,看了半天没发现怎么回事。递归法:难度不大,采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。

2023-09-07 07:55:46 103 1

原创 代码随想录算法训练营第18天 | 513.找树左下角的值、112. 路径总和 、113.路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树

最关键的一点是,某条路径,如果满足条件了,要进行深拷贝再加入到results中,不然回溯的时候会被改变,导致results中的结果也会改变。而且需要注意在更新左子树和右子树的路径时,path本身要不变,不然相当于左子树的路径和右子树的路径加在一块了,因此不要用append的操作。递归法:不要去累加然后判断是否等于目标和,那么代码比较麻烦,可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。以 后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后序数组。

2023-09-06 08:52:21 115 1

原创 代码随想录算法训练营第17天 | 110.平衡二叉树、257. 二叉树的所有路径、404.左叶子之和

递归法做:确定单层递归的逻辑:当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。递归法:参数:当前传入节点。左叶子的明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点。需要注意的是,由于函数是计算左叶子节点之和,如果当前节点为叶子节点,那么其左叶子节点之和为0,而不是当前节点的数值。如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子。

2023-09-05 10:43:56 83 1

原创 代码随想录算法训练营第16天 | 104.二叉树的最大深度、559.n叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数

二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数。深度从1开始,则根节点的深度为1。使用前序遍历,从上往下求深度。二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数或者节点数。高度从1开始,则叶子节点的高度为1。使用后序遍历,从下往上求高度。

2023-09-05 06:53:10 299 1

原创 代码随想录算法训练营第15天 | 二叉树的层序遍历、翻转二叉树、对称二叉树

最简单的是广度优先搜索的层次遍历的迭代法,把每一层的元素都放在一个列表里,然后判断反转后的列表是否和之前的相等。记住,如果某一层的左节点或右节点为空,那么就在列表中放入Null值,不然会判断错误。还有,直接从root的左右节点开始判断,而不是从root节点开始判断,因为root一定是可反转的。正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右,一个树的遍历顺序是右左。对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了。

2023-09-03 05:54:18 85

原创 代码随想录算法训练营第14天 | 二叉树的递归遍历和迭代遍历

后序遍历,先序遍历是中左右,后续遍历是左右中,那么我们只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了。中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了。前中后序遍历的区别:看中间节点的顺序,前序遍历就是先遍历中间节点,后序遍历就是最后才遍历中间节点。深度优先遍历:前中后序遍历,使用栈的结构。广度优先遍历:一层一层的去遍历。

2023-09-01 04:47:08 110 1

原创 代码随想录算法训练营第13天 | 239. 滑动窗口最大值,347.前 K 个高频元素

大顶堆(优先级队列)可以存放这个窗口里的k个数字,这样就可以知道最大的最大值是多少了, 但是问题是这个窗口是移动的,而大顶堆每次只能弹出最大值,我们无法移除其他数值,这样就造成大顶堆维护的不是滑动窗口里面的数值了。放进去窗口里的元素,然后随着窗口的移动,队列也一进一出,移除上一步的最大值。队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的。大顶堆(堆头是最大元素),小顶堆(堆头是最小元素),从小到大排就是小顶堆,从大到小排就是大顶堆。

2023-07-12 15:37:33 104 1

原创 代码随想录算法训练营第11天 | 20. 有效的括号,1047. 删除字符串中的所有相邻重复项,150. 逆波兰表达式求值

向零截断,那么用 x // y就不行,因为当其中有一个负数时,会有问题,应该用 int(x / y);分为左括号和右括号,最后进的左括号,最先需要右括号来匹配,于是符合后进先出的思想。栈中放右括号,但遍历到左括号时,相应的右括号入栈;当遍历到相等的右括号时,栈中的右括号出栈。另外,在提交代码时,选python2会报case不通过,选python3却没问题。如果遍历过程中,栈中元素为空,或者字符串中括号和栈中的括号不相等,则是无效的。遍历结束后,栈中元素不为空,则无效,为空则都匹配上了,为有效。

2023-07-10 14:21:51 95 1

原创 代码随想录算法训练营第十天 | 232.用栈实现队列,225. 用队列实现栈

要模拟队列的先进先出,那就得来两次后进先出,[1,2,3]后进先出得到[3,2,1],再后进先出就输出了 1、2、3,所以需要用两个栈或着说队列,一个输入栈,一个输出栈。使用python的双端队列deque,因为先进先出的操作用popleft实现,复杂度为O(1),而一般的列表,pop(0)的复杂度为O(n)。这道题要求实现队列,就要求 push的时间复杂度为O(1),而pop和peek的时间复杂度为O(n)。栈就用列表来实现,因为列表的pop() 操作就是给出最后一个元素,属于后进先出。

2023-07-10 12:01:59 79 1

原创 代码随想录算法训练营第八天 | 344.反转字符串,541. 反转字符串II,剑指Offer 05.替换空格,151.翻转字符串里的单词,剑指Offer58-II.左旋转字符串

题目链接:https://leetcode.cn/problems/reverse-words-in-a-string/python的语法:a, b = b, a,非常方便。:O(n),因为字符串是不可变类型,所以操作字符串需要将其转换为列表,所以空间复杂度是O(n)是反转字符串1的拓展。把s[i: i+k]这个子字符串截取出来,并进行反转即可。具体步骤为:反转区间为前n的子串;这道题本意不是用python来解的,不然直接用切片解决问题,简单快速。:O(n),因为要转成列表,所以需要额外的空间。

2023-07-08 18:02:33 70

原创 代码随想录算法训练营第七天 | 454.四数相加II,383. 赎金信,15. 三数之和,18. 四数之和

如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下标就应该向左移动,这样才能让三数之和小一些。首先将数组排序,然后有一层for循环,i从下标0的地方开始,同时定一个下标left 定义在i+1的位置上,定义下标right 在数组结尾的位置上。首先定义 一个map,key放a和b两数之和,value 放a和b两数之和出现的次数。遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。

2023-07-08 15:20:26 79

原创 代码随想录算法训练营第六天 | 242.有效的字母异位词,349. 两个数组的交集,202. 快乐数,1. 两数之和

O(logn),有点难分析,记住得到下一个平方和的复杂度为 O(logn),查找给定数字的下一个值的成本为 O(logn),因为我们正在处理数字中的每位数字,而数字中的位数由logn 给定。在遍历数组的时候,只需要向map去查询是否有和目前遍历元素匹配的数值,如果有,就找到的匹配对,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。自己用map实现的代码比较繁琐,先用map把数字的index都保存,再去判断是否存在,额外考虑了两数相等的情况。数组就是一种简单的哈希表,可以。

2023-07-05 22:14:07 82 1

原创 代码随想录算法训练营第四天 | 24. 两两交换链表中的节点,19.删除链表的倒数第N个节点,面试题 02.07. 链表相交,142.环形链表II

使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。这里的指针,不是整数,而是链表。从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。快慢指针相遇前,指针走的次数小于链表长度,快慢指针相遇后,两个index指针走的次数也小于链表长度,总体为走的次数小于 2n。19.删除链表的倒数第N个节点。

2023-07-04 18:38:11 83

原创 代码随想录算法训练营第三天 | 203.移除链表元素,707.设计链表,206.反转链表

循环的判断条件不是 cur.next, 而是while cur,因为cur可能变为None,None是没有next的,会报错。和双指针法是一样的逻辑,同样是当cur为空的时候循环结束,不断将cur指向pre的过程。为了使用统一的方法进行删除,就设置一个虚拟结点,删除之后,再return虚拟节点的子节点,作为新的头节点。涉及全部遍历的为O(n),和 index 的相关操作为 O(index), 其余为 O(1)O(n),递归法:O(n), 要递归处理链表的每个节点。添加的为O(n),其他为O(1)

2023-07-03 21:03:56 66 1

原创 代码随想录算法训练营第二天 | 977.有序数组的平方,209.长度最小的子数组,59.螺旋矩阵II

每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。窗口的起始位置如何移动(左指针):如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)。需要再定义一个k,用于往result里面填充元素,而且先从终止位置填充最大值,再依次填充到起始位置。窗口的结束位置如何移动(右指针):窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。满足 sum ≥ s 的长度最小的连续子数组,这就像一个窗口,所以这么叫了。时间复杂度:O(n)。

2023-07-03 18:02:07 59 1

原创 代码随想录算法训练营第一天 | 704. 二分查找、27. 移除元素

(1)之前没有注意到有左闭右闭、左闭右开的写法的区别,于是再写时,对于循环条件是否加等号,left = mid 还是 left = mid + 1,存在疑惑了。为了方便起见,以后都写左闭右闭:while循环时,left <= right,left = mid + 1,right = mid - 1。(2)mid的写法,如果是 (left + right) // 2,会存在溢出,得写成 left + (right - left) // 2。时间复杂度:暴力解:O(n ^ 2),双指针:O(logn)

2023-07-03 17:45:34 75 1

空空如也

空空如也

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

TA关注的人

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