![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
数据结构和算法
文章平均质量分 70
Jack199274
这个作者很懒,什么都没留下…
展开
-
Grind75第13天 | 208.实现Trie、54.螺旋矩阵、721.账户合并
一个容易理解的例子是:给出若干个pair对(张三和张五,李四和李六),pair对表示这俩人是亲戚关系,那么可以构建亲戚图谱(合并操作)。再给出一个pair对(张三和李六),问他们俩是不是亲戚(查询是否有相同的根)。按照以下的遍历顺序去处理,注意到从左到右和其他的三个方向不一样,从左到右把一行的所有元素都遍历了,而其他方向的遍历则少一个元素。并查集的代码是作为模板直接用的,有三个部分:初始化,查找父节点(寻根),合并。时间复杂度:O(nlogn),其中 n是不同邮箱地址的数量,logn 是路径压缩的复杂度。原创 2024-01-18 11:43:44 · 435 阅读 · 0 评论 -
Grind75第12天 | 67.二进制求和、937.最接近原点的k个点、295.数据流的中位数
还需要注意的是,如果python实现,那么大根推是把数值取反,那么不仅插入时取反,在pop后加以使用时也要取反:(1)以上addNum的两种情况都需要把堆顶元素取反后再插入;对于当前位置的两个数字x和y,加和后的carry = carry + x + y,然后更新当前位置的数字为 carry % 2,下一步的carry = carry // 2。B保存较小的一半,顶点是其中最大的。因为从第k+1元素开始,判断是否小于顶点,如果小于,则弹出顶点,插入当前的元素,这样就保证一直维持k个最小的元素。原创 2024-01-17 08:31:56 · 932 阅读 · 0 评论 -
Grind75第11天 | 310.最小高度树、127.单词接龙、230.二叉搜索树中第k小的元素
替换方案是:在遍历队列元素时,通过把单词的某个字符替换为26个字母中的一个,并且替换后的单词需要在word_list里面,这样的替换单词就是相邻节点。为了找到这些点,我们从边缘开始,先找到所有出度为1的节点,然后把所有出度为1的节点进队列,以它们为包围圈,不断地BFS,最后找到的就是两边同时向中间靠近的节点。从题目的例子可以看到,最小高度树的根节点,好像是入度比较大的节点,这是一个大概的认识。时间复杂度:O(n),其中 n 是为节点的个数。空间复杂度:O(n),其中 n是为节点的个数。原创 2024-01-16 12:27:29 · 475 阅读 · 0 评论 -
Grind75第10天 | 133.克隆图、994.腐烂的橘子、79.单词搜索
然后进行 BFS 遍历,对上、下、左、右四个方向的结点进行污染,同时加入队列,作为第1层的节点。这个题和【542.01矩阵】有点像,都是先把某个特定值的点加入到队列中,作为第0层,然后进行广度优先搜索,遍历第1层,第2层...DFS:从A开始克隆,遍历两个邻居B和D,遍历到B时,不管D了,继续遍历B的邻居A和C。其中A遍历过了,跳过。BFS:从A开始克隆,遍历两个邻居B和D,B和D都遍历完了,再遍历B的邻居A和C。BFS 结束后,新鲜橘子的数量仍未减为零,说明存在无法被污染的橘子,返回为-1,否则分钟数。原创 2024-01-15 12:15:11 · 989 阅读 · 0 评论 -
Grind75第9天 | 733.图像渲染、542.01矩阵、1235.规划兼职工作
到弹出值为1的点时,它相邻的且未访问过的点(值也是1),距离都为2,即 dist[i][j] + 1。需要注意的是,如果算法开始之前,当前的颜色已经和需要染的颜色相同了,就直接返回,因为如果相邻点和当前颜色相同,那么就和需要染的颜色相同,不需要再染,如果相邻点和当前颜色不相同,那么没法染。使用队列,每次搜索到一个方格时,如果其与初始位置的方格颜色相同,就将该方格的染色,并把上下左右4个方位加入队列。时间复杂度:O(nlogn),排序的复杂度是 O(nlogn),遍历+二分查找的复杂度合计是O(nlogn)原创 2024-01-14 10:05:27 · 588 阅读 · 0 评论 -
Grind75第8天 | 278.第一个错误的版本、33.搜索旋转排序数组、981.基于时间的键值存储
如果一个版本为错误版本(isBadVersion为True),那么第一个错误版本在该版本左侧(包括该版本);如果一个版本为正确版本,那么第一个错误版本在该版本的右侧(不包括该版本)。这个题,麻烦还是在于条件判断时,要不要加 == 符号,比如有时候是 = nums[left] 这个条件里加了等号,比如 [3,1],查找1,这个例子可以验证必须加等号。二分查找,统一写左闭右闭区间:while循环时,left原创 2024-01-13 12:40:57 · 468 阅读 · 0 评论 -
Grind75第7天 | 543.二叉树的直径、199.二叉树的右视图、297.二叉树的序列化和反序列化
543.二叉树的直径题目链接:https://leetcode.com/problems/diameter-of-binary-tree解法:做这个题,首先要搞清楚二叉树深度的定义。二叉树的深度在leetcode里,定义为从根节点到叶子结点的最长路径的节点数(注意不是边的数量)。所以如果只有一个根节点,那么深度为1。这个题,对于每个节点,都求出直径,再取所有节点直径的最大值。那么对于每个节点求直径,需要求出左子树的深度和右子树的深度,二者相加就是当前节点的直径。而树的深度为 max(左子原创 2024-01-12 10:14:27 · 366 阅读 · 0 评论 -
Grind75第6天 | 5.最长回文子串、76.最小覆盖子串、438.找到字符串中所有字母异位词
但是,这个并不一定是全局的最长回文子串。这个题和76.最小覆盖子串的思路差不多,都是用滑动窗口,都参考了labuladong的题解。对字符串进行遍历,在 i 这个位置,首先往左寻找与当期位置相同的字符,直到遇到不相等为止。遍历结束后,得到了最长回文子串的左坐标和长度,就可以得到最长回文子串了。时间复杂度:O(n+m),n和m分别为s和t的长度。空间复杂度:O(c),c为字符集的大小,即2*26。时间复杂度:O(n+m),n和m分别为s和t的长度。空间复杂度:O(c),c为字符集的大小,即26。原创 2024-01-11 11:50:24 · 447 阅读 · 0 评论 -
Grind75第5天 | 409.最长回文串、3.无重复字符的最长子串、8.字符串转换整数
容易错的地方是,python对负数求商和余数时,得到的结果非常反常识,比如 divmod(-128, 10) 得到的是 -13 和 2,这个结果与 -128 // 10, -128 % 10 得到的是一样的。我们发现,回文串如果是偶数长度,那么所有字符的个数为偶数个,回文串如果是奇数长度,那么除了中间的子串为一个奇数长度的单字符外,其他字符都是偶数个。空间复杂度:O(128),本题中没有明确说明字符集,因此可以默认为所有 ASCII 码在 [0,128) 内的字符。时间复杂度:O(n)空间复杂度:O(1)原创 2024-01-10 07:10:46 · 442 阅读 · 0 评论 -
Grind75第4天 | 141.环形链表、876.链表的中间节点、125.验证回文串
每次移动时,fast向后走两次,slow向后走一次,直到 fast 无法向后走两次(fast本身是null或者fast.next是null,就没法走了)。使用快慢指针,当一个链表有环时,快慢指针都会无限移动下去,并且快指针会追上慢指针,也就是说两个指针相等。还有空间复杂度为O(1)的写法,不需要事先去掉非字母数字的字符。节点数为偶数时,终止循环时,slow是中间两节点的后一个节点。节点数为奇数时,终止循环时,slow就是中间节点。空间复杂度:O(1),slow和fast是常数空间。空间复杂度:O(n)原创 2024-01-09 09:49:11 · 441 阅读 · 0 评论 -
Grind75第3天 | 155.最小栈、224.基本计算器、21.合并两个有序链表
pop() 方法: 判断将 pop() 出去的元素值是否是 min_stack 栈顶元素值(即最小值),如果是则将 min_stack 栈顶元素一起 pop(),这样可以保证 min_stack 栈顶元素始终是 stack 中的最小值。push() 方法: 每当push()新值进来时,如果小于等于 min_stack 栈顶值,则 push() 到 min_stack,即更新了栈顶最小值。最后如果两个链表长度不等,那么必有一个链表为空,一个不为空,那么把不为空的链表直接添加到dummy链表中。原创 2024-01-08 10:34:56 · 502 阅读 · 0 评论 -
Grind75第2天 | 238.除自身以外数组的乘积、75.颜色分类、11.盛最多水的容器
因此需要两个列表:L 和 R,对于nums中的索引i,L[i] 表示索引i左侧所有数字的乘积,R[i] 表示索引i右侧所以数字的乘积,那么L[i] * R[i] 就是除自身以外数组的乘积。基本的思路是,双指针为i和j,容器的盛水量由短板决定 min(h[i], h[j]) * (j - i)。双指针从两端往中间移动,移动的过程中,(j - i)一定是变小的,那么为了得到更大的容积,就需要短板变大,所以只能移动短板。Baseline:baseline的解法是统计0,1,2三个元素的个数,然后在原数组中修改。原创 2024-01-07 12:26:24 · 519 阅读 · 0 评论 -
TikTok真题第11天 | 1249.移除无效的括号、23.合并K个升序链表、773.滑动谜题
还有一种做法是直接在遍历字符的过程中,记录左括号,并且即时删除无效的右括号,最后遍历结束再删除左括号。如果栈不为空,那么该位置有效,且把前面左括号(栈顶元素)改为有效。(1)第一种方法是优先队列,即构造小根堆(队首元素最小),然后把所有链表添加到优先队列中,那么从队首到队尾是根据val进行升序排列的。这个题用栈来处理,用栈来记录左括号的位置,同时用一个向量来记录左括号和右括号是否有效(有效则不需要删除)。如果遇到左括号,那么栈中弹入,同时该位置为无效(需要删除),待后面遇到右括号再置为有效。原创 2024-01-01 10:43:25 · 443 阅读 · 0 评论 -
TikTok真题第10天 | 1541.平衡括号字符串的最少插入次数、1209.删除字符串中所有相邻重复项、1530.好叶子结点对的数量
由于栈中的元素是后进先出,那么最后拼接答案时,取出来的元素的顺序和原字符串的顺序是反的,比如abcd,在stack中是[a,b,c,d],那么stack.top() 取出来是[d, c, b, a],所以取出元素进行拼接后,需要翻转一下结果。如果当前为右括号,且左括号不为空,那么首先左括号数量减1(相当于栈中弹出左括号),表示消消乐,然后如果下一个还是右括号,就继续往下走 (idx+=2),如果下一个不是右括号,那么需要插入右括号 (result++)。空间复杂度:O(H),H为树的高度。原创 2023-12-31 12:07:05 · 1507 阅读 · 0 评论 -
TikTok真题第9天 | 163.缺失的区间、1861.旋转箱子、2217.找到指定长度的回文数
基本逻辑是,依次遍历nums中的所有的元素,判断这个元素(right)和上一个元素(left)的差值是否>=2,如果是,那么缺失区间为[left+1, right-1]。比如上一个为1,当前为3,那么缺失的区间为[2,2],如果上一个为1,当前为4,那么缺失的区间为[2,3]。如果当前是空的,那么最低位置不变,因为没有石头落下去占据最低位置,也没有障碍挡住石头下落。(1)如果回文数的长度为 intLength,那么第q位回文数的左半部分(回文数是奇数,那么包含中间的那个数)的计算公式如下。原创 2023-12-30 10:35:25 · 838 阅读 · 0 评论 -
TikTok真题第8天 | 418.屏幕可显示句子的数量、395.至少有K个重复字符的最长子串、1010.总持续时间可以被60整除的歌曲对
2)一行的开头刚好是一个word的中间,如果前一个为空格,则start不变,如果不为空格,则start需要减1。当前time的模为 time % 60,对应的数的模为:60 - time % 60,比如time=62,那么对应的数可以是58,118,模=60 - 62 % 60 = 58。这是 time 不为60的倍数的情况。和两数之和类似,区别在于两数之和中,存储的是 当前的num,寻找的是target-num,而这里存储的是当前time的模,寻找的是模和当前的模可以相加为target(60)的数。原创 2023-12-29 11:10:10 · 1022 阅读 · 0 评论 -
TikTok真题第7天 | 2422.使用合并操作将数组转换为回文序列、200.岛屿的个数、694.不同岛屿的个数
整块岛屿的形状就是每个小岛的形状的列表。而形状定义为相对于左上角第1个小岛的位置的偏移量,这样左上角第一个小岛的位置是(0, 0),下方的小岛则是(-1, 0)。这样,通过DFS或者BFS,可以得到这块岛屿上所有小岛的形状,从而得到整块岛屿的形状列表。总体思想是,从1个小岛开始,通过遍历所有垂直和水平方向的节点,把相邻的小岛连接起来变成一整块岛屿,同时标上特殊值用来记录该节点已经访问过了。BFD的O(min(M,N) ),在最坏的情况下(全部为陆地),队列的大小可以达到 min(M,N)。原创 2023-12-28 06:27:04 · 1210 阅读 · 0 评论 -
TikTok真题第6天 | 146.LRU缓存、333.最大的二分搜索树、621.任务调度器
如果当前node是二叉搜索树,就记录节点的个数,并返回节点个数,如果不是二叉搜索树,那就验证左右子树是否为二叉搜索树,分别记录节点的个数,然后取二者中的最大值进行返回。而删除最久未使用的node时,需要在哈希表和双向链表中都删除,那么可以由双向链表得到最久未使用的node,从而得到node的key,再从哈希表中删除,这是哈希表和双向链表之间的联系。如果当前节点不是 BST 的节点,那么更新 BST 的节点数 res 为左右子节点的各自的 BST 的节点数的较大值。空间复杂度:O(h),树的深度。原创 2023-12-27 08:14:42 · 701 阅读 · 0 评论 -
TikTok真题第5天 | 386. 字典序排数、785.判断二分图、886.可能的二分法
比如第二个条件,n=234时,如果number=199了,那么199 / 10 = 19, 19 / 10 = 1, 1+1=2,也是后面的字典序整数就是:2, 20, 200,..., 21,...。第一层从1开始,遍历到9,而后面层的循环,也就是递归,从0遍历到9。空间复杂度:O(n),存储节点颜色的数组需要 O(n) 的空间,并且在深度优先搜索的过程中,栈的深度最大为 n,需要 O(n)的空间。这个题是上一个题的加强版,也是用染色法或者并查集解决,所以在做此题之前,先把上一个题干掉了。原创 2023-12-26 12:34:58 · 908 阅读 · 0 评论 -
TikTok真题第4天 | 1366. 通过投票对团队排名、1029.两地调度、562.矩阵中最长的连续1线段
解法:这道题就是统计每个队伍在每个排名的投票数,队伍为A、B、C,则排名有1、2、3,按照投票数进行降序排列。如果有队伍在每个排名的投票数都一样,那么按照字母序进行排列。可以用哈希表也可以用数组处理(因为最多有26个队伍,即26个字母)。细节在于按照字母序排列,为了统一为按照数字降序排列,可以把队伍(字母)转为 (Z - 队伍),这样的话,如果队伍是A,那么数字为26,字母为Z,那么数字为0,字母序排列=数字降序排列。参考题解:1.2.边界条件:无。原创 2023-12-25 12:40:59 · 1468 阅读 · 0 评论 -
TikTok真题第3天 | 856.括号的分数、2115. 从给定原材料中找到所有可以做出的菜、394.字符串解码
拓扑排序(Topological Sorting)是图论中的一个概念,用于对有向无环图(Directed Acyclic Graph,简称 DAG)的所有顶点进行排序。接下来遍历字符,如果是左括号,则压入0,如果是右括号,则弹出栈顶元素score:(1)如果栈顶元素是0,说明前一个是左括号,那么构成 (),则分数为1;(2)如果栈顶元素为1,说明前一个还是右括号,那么构成的是 )),说明是(A)这种类型,那么分数为 2*score。使用栈来解决,后进先出,后面加入的左括号,先弹出和右括号去匹配。原创 2023-12-24 12:23:27 · 866 阅读 · 0 评论 -
TikTok真题第2天 | 799.香槟塔、2096. 从二叉树一个节点到另一个节点每一步的方向、255. 会议室 II
每一个杯子保留的是溢出之前的值,所以最后返回结果时,通过 row=query_row,glass=query_glass来取对应杯子装的香槟,并和1.0比较求最小值。遍历时,如果小根堆中最早结束的会议,结束时间小于等于当前的会议的开始时间,那么把最早结束的会议弹出,弹入当前会议,表示不需要开新会议室,而是占用之前的。使用的二维数组,可以更清晰的确定杯子的位置,但是提高了空间复杂度。使用优先队列(最小堆),先对所有的区间按照开始时间进行排序,再使用小根堆保存每个会议的结束时间,最早的结束时间排在前面。原创 2023-12-23 12:25:40 · 414 阅读 · 0 评论 -
TikTok真题第1天 | 666.路径和IV、 207.课程表、210.课程表||
这里按前一种,把先修课作为vector的索引,得从先修课开始选,根据先修课再去遍历以它为前置条件的课程,直到搜索到某门课不是任何课程的先修课,说明从当前课开始dfs的路径,是有限无环的。(2)左右子树的表示:对于某一个节点来说,如果它的深度为depth,位置编号为 pos,那么它的左子节点的深度为depth+1,位置编号为 pos × 2 - 1,那么key就是 (depth+1) * 10 + pos*2-1。bfs:需要提前计算所有课的入度和先修课的邻接表,入度为0的课意味着没有任何先修课,可以先选。原创 2023-12-22 11:37:42 · 421 阅读 · 0 评论 -
代码随想录训练营第30天 | 332.重新安排行程、51. N皇后、37. 解数独
时间复杂度:O(mlogm),其中 m 是边的数量。对于每一条边我们需要 O(logm) 地删除它,最终的答案序列长度为 m+1,而与 n 无关。这道题真的挺复杂的,代码写出来以后,看似明白了,待自己模拟运行一遍,就会发现其实理解还有待加强。算法的复杂度那是相当的高。这个题,卡哥的思路会超时。辛辛苦苦看懂了卡哥的思路,结果超时了,直接崩溃。看了leetcode官方的思路,非常简洁,但是里面的深意还是不太懂。O(m),其中 m 是边的数量。我们需要存储每一条边。332.重新安排行程。原创 2023-11-28 09:05:08 · 78 阅读 · 0 评论 -
代码随想录训练营第60天 | 503.下一个更大元素II ● 42. 接雨水● 84.柱状图中的最大矩形
503.下一个更大元素II解法:由于是循环数组,可以直接把两个数组拼接在一起,然后使用单调栈求下一个最大值。写法上,可以巧妙一些,循环的长度为2*len(nums),通过 i%len(nums)来实现两次遍历数组。边界条件:无时间复杂度:O(n)空间复杂度:O(n)42. 接雨水每一列雨水的高度,取决于,该列 左侧最高的柱子和右侧最高的柱子中最矮的那个柱子的高度。使用双指针来计算。为了得到两边的最高高度,使用了双指针来遍历,每到一个柱子都向两边遍历一遍,这其实是有重复计算的。原创 2023-11-05 00:17:43 · 179 阅读 · 0 评论 -
代码随想录训练营第58天 | 739. 每日温度 ● 496.下一个更大元素 I
这个题和上一个题差不多,可以分两步走,第一步完全和上一题相同,找到nums2中的下一个最大元素,只不过这题是取元素本身而不是差值。第二步再找到nums1中元素在nums2中的index,再取出下一个最大元素即可。为了减少空间复杂度,可以并为一步(一次for循环)来解决,也就是如果找到了下一个最大元素,再进一步判断当前的元素是否在nums1里面,是就放到result里。这里是单调栈是递增的,栈为一个[],那么栈头就是列表最右端,栈尾是最左端,于是栈头到栈尾递增,其实是列表从左到右递减。空间复杂度:O(n)原创 2023-11-04 11:54:03 · 114 阅读 · 0 评论 -
代码随想录训练营第57天 | 647. 回文子串 ● 516.最长回文子序列
那么dp[i][j]一定是取最大的,即:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])。所以条件是 if s[i] == s[j] and (j -i i <= 2 or dp[i+1][j-1]),则dp[i][j] = True。dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是,则dp[i][j]为true,否则为false。如果s[i]与s[j]相同,那么dp[i][j] = dp[i + 1][j - 1] + 2.原创 2023-11-04 06:46:16 · 161 阅读 · 0 评论 -
代码随想录训练营第56天| ● 583. 两个字符串的删除操作 ● 72. 编辑距离
(1) dp[i-1][j-1],即先将 word1 的前 4 个字符 hors 转换为 word2 的前 2 个字符 ro,然后将第五个字符 word1[4](因为下标基数以 0 开始) 由 e 替换为 s(即替换为 word2 的第三个字符,word2[2])当word1[i - 1] 与 word2[j - 1]相同的时候,dp[i][j] = dp[i - 1][j - 1];于是不相等时,dp[i][j] = min(dp[i][j-1] + dp[i-1][j]) + 1。原创 2023-11-03 04:29:21 · 200 阅读 · 0 评论 -
代码随想录训练营第55天 | ● 392.判断子序列 ● 115.不同的子序列
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]表示以下标i-1为结尾的字符串s和以下标j-1为结尾的字符串t 相同子序列的长度,所以如果dp[s.size()][t.size()] 与 字符串s的长度相同说明:s与t的最长相同子序列就是s,那么s 就是 t 的子序列。空间复杂:O(mn)原创 2023-11-03 03:17:55 · 163 阅读 · 0 评论 -
代码随想录训练营第53天 | 1143.最长公共子序列 ● 1035.不相交的线 ● 53. 最大子序和
如果text1[i - 1] 与 text2[j - 1]不相同,那就看看text1[0, i - 2]与text2[0, j - 1]的最长公共子序列 和 text1[0, i - 1]与text2[0, j - 2]的最长公共子序列,取最大的。如果text1[i - 1] 与 text2[j - 1]相同,那么找到了一个公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;即:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]).原创 2023-11-02 05:13:04 · 83 阅读 · 0 评论 -
代码随想录训练营第52天 | 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组
根据dp[i][j]的定义,dp[i][j]的状态只能由dp[i - 1][j - 1]推导出来。即当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;根据dp[i][j]的定义,dp[i][0] 和dp[0][j]其实都是没有意义的!所以dp[i][0] 和dp[0][j]初始化为0。300.最长递增子序列。原创 2023-11-02 03:47:53 · 65 阅读 · 0 评论 -
代码随想录训练营第51天 | 309.最佳买卖股票时机含冷冻期 ● 714.买卖股票的最佳时机含手续费
所以:dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee)之前的题目,不持有一定是最大值,但是这里有手续费,减去手续费后,可能还不如不卖...,所以最后一个不一定是最大值。如果第i天不持有股票即dp[i][1]的情况, 依然可以由两个状态推出来。难点就是划分状态,递推公式倒是好推导。714.买卖股票的最佳时机含手续费。1.不持有股票的递推公式。时间复杂度:O(n)空间复杂度:O(n)时间复杂度:O(n)空间复杂度:O(n)原创 2023-11-01 06:27:27 · 57 阅读 · 0 评论 -
代码随想录训练营第50天 | 123.买卖股票的最佳时机III ● 188.买卖股票的最佳时机IV
选最大的,所以 dp[i][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][1]);所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])。dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。dp[0][3] 表示第一天完成了三次操作:买-卖-买,所以是-prices[0]。dp[0][4] 表示第一天完成了四次操作:买-卖-买-卖,所以是0。原创 2023-11-01 03:46:54 · 62 阅读 · 0 评论 -
代码随想录训练营第49天 | 121. 买卖股票的最佳时机 ● 122.买卖股票的最佳时机II
同样dp[i][1]取最大的,dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0])。那么dp[i][0]应该选所得现金最大的,所以dp[i][0] = max(dp[i - 1][0], -prices[i]);如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来。如果第i天不持有股票即dp[i][1], 也可以由两个状态推出来。如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来。空间复杂度:贪心 O(1),动规O(n)原创 2023-10-31 06:50:11 · 103 阅读 · 0 评论 -
代码随想录训练营第48天 | 198.打家劫舍 ● 213.打家劫舍II ● 337.打家劫舍III
如果偷第i房间,那么dp[i] = dp[i - 2] + nums[i] ,即:第i-1房一定是不考虑的,找出 下标i-2(包括i-2)以内的房屋,最多可以偷窃的金额为dp[i-2] 加上第i房间偷到的钱。从dp[i]的定义上来讲,dp[0] 一定是 nums[0],dp[1]就是nums[0]和nums[1]的最大值即:dp[1] = max(nums[0], nums[1])。然后dp[i]取最大值,即dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);原创 2023-10-31 02:47:57 · 84 阅读 · 0 评论 -
代码随想录训练营第46天 | 139.单词拆分● 背包问题总结
139.单词拆分解法:单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。拆分时可以重复使用字典中的单词,说明就是一个完全背包!1.确定dp数组以及下标的含义。2.确定递推公式如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。当然,内层循环也可以直接遍历字典。原创 2023-10-30 04:09:37 · 43 阅读 · 0 评论 -
代码随想录训练营第45天 | 70. 爬楼梯 (进阶)● 322. 零钱兑换 ● 279.完全平方数
凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])考虑到递推公式的特性,dp[j]必须初始化为一个最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。1阶,2阶,.... m阶就是物品,楼顶n就是背包。递推公式:dp[j] = min(dp[j - coins[i]] + 1, dp[j]);原创 2023-10-30 00:59:53 · 116 阅读 · 0 评论 -
代码随想录训练营第44天 | 完全背包● 518. 零钱兑换 II ● 377. 组合总和 Ⅳ
在完全背包中,对于一维dp数组来说,其实两个for循环嵌套顺序是无所谓的,但是为了不搞错,统一写成物品外循环、背包内循环的方式。dp[0]一定要为1,dp[0] = 1是 递归公式的基础。第i件物品的重量是weight[i],得到的价值是value[i]。由于是组合,那么一定是物品外循环、背包内循环,由于是完全背包,所以背包内循环是从前到后遍历。其本质是本题求的是排列总和,而且仅仅是求排列总和的个数,并不是把所有的排列都列出来。所以唯一需要注意的,就是遍历顺序,背包外循环,物品内循环,其他没了。原创 2023-10-29 05:15:05 · 38 阅读 · 0 评论 -
代码随想录训练营第43天 | 1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零
只要搞到nums[i],凑成dp[j]就有dp[j - nums[i]] 种方法。在初始化的时候dp[0] 一定要初始化为1,因为dp[0]是在公式中一切递推结果的起源,如果dp[0]是0的话,递推结果将都是0。所以递推公式:dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1)。回想一下01背包的递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);最后需要求的就是dp[m][n]。原创 2023-10-29 03:52:17 · 72 阅读 · 0 评论 -
代码随想录训练营第42天 | 01背包问题● 416. 分割等和子集
因为只要有子集之和等于 sum / 2,那么剩下的子集一定也等于 sum / 2。01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);所以递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i])。本题,相当于背包里放入数值,那么物品i的重量是nums[i],其价值也是nums[i]。空间复杂度:二维 O(n), 一维O(1)时间复杂度:O(n^2)时间复杂度:O(n^2)空间复杂度:O(n)原创 2023-10-28 08:47:22 · 61 阅读 · 0 评论