代码随想录训练营
文章平均质量分 56
打开算法题
愤怒的小阿淇这就开摆
这个作者很懒,什么都没留下…
展开
-
代码随想录第一天 704二分查找 27移除元素
然后我们定义快指针fastIndex遍历整个数组,此时我们需要判断快指针是否跟要移除的元素相同,如果不相同则nums[slowIndex] = nums[fastIndex];原因二:当我们判断if(nums[mid] < target)时,我们需要更新左边界,此时需要将left = mid + 1;二分的逻辑也很简单,取中间位置的下标,判断下标处的值是否等于目标值,如果下标处的值小于target,则将左边界更新为mid + 1,反之右边界更新为mid + 1。这样理解可能会更好一些。原创 2024-06-05 21:02:51 · 462 阅读 · 0 评论 -
代码随想录训练营第二天 977有序数组的平方 209长度最小的子数组 59螺旋矩阵II
取这个数组的中间值,然后以此为基准,判断这个基准的左边的元素是否小于基准值,右边的元素是否大于基准值,如果两边都为否,也就是说左边的值大于基准值,右边的值小于基准值,则交换两者的位置。当第一行的元素放入后,上边界++,当最后一列的元素放入后,右边界--,当最后一行的元素放入后,下边界--,当第一列元素放入后,左边界++;此时维护一个范围让这个区间的元素的总和一直大于target,慢指针指向这个区间的最左边,快指针指向区间的最右边。双指针:使用快慢指针,首先定义一个慢指针为0,定义快指针一直遍历整个数组。原创 2024-06-06 21:33:25 · 338 阅读 · 0 评论 -
代码随想录训练营第三天 203移除链表元素 707设计链表 206翻转链表
细节,我们在遍历的时候直接判断cur -> next 是否为空,不为空则判断cur -> next 的值是否为要移除的元素,是则cur -> next = cur -> next -> next;否则cur = cur -> next;首先定义一个虚拟头结点,然后让虚拟头节点指向head。这个虚拟头节点的next就是我们要返回的答案,因此我们不能用这个虚拟头节点直接去移动,需要在定义一个cur节点指向虚拟头节点。原创 2024-06-07 11:06:55 · 153 阅读 · 0 评论 -
代码随想录训练营第四天 24两两交换链表中的节点 19删除链表的倒数第n个节点 02链表相交 142环形链表
本题的思路就是用虚拟头节点指向第二个节点,然后再指向第一个节点,然后再指向第三个节点。本题的关键,要暂存几个节点:首先我们虚拟头结点指向第二个节点的时候,第一个节点就没人指向,所以需要暂存,当我们第二个节点指向第一个节点的时候,第三个节点也没人指向,也需要暂存。首先定义快慢指针都指向链表的头部,判断fast是否为空,并且fast->next是否为空,如果都不为空的话,快指针节点比慢指针节点多走一步,如果是有环的话快慢指针节点肯定会在环内相遇。此时从头节点和相遇节点以相同的步长遍历,相交的地方就是入环处。原创 2024-06-08 21:39:43 · 214 阅读 · 0 评论 -
代码随想录训练营第五天 242有效的字母异位词 349两个数组的交集 202快乐数 1两数之和
遍历整个数组,当发现当前遍历的数值和target相减之后的值出现在map中,说明这两个数值的下标为返回结果,将两个数值的下标添加进vector<int> res中。= 1 && set.find(n) == set.end()),只有n不等于1才需要进行循环,等于1就直接返回true了,条件二只有set中没出现过n值,证明还没陷入死循环,接着执行循环中的内容。然后遍历第二个数组num2,当发现num2中出现的值在map中出现过,并且返回结果的数组res中没有这个值,就将这个值添加进res中,原创 2024-06-11 21:54:05 · 441 阅读 · 0 评论 -
代码随想录训练营第六天 454四数相加II 383赎金信 15三数之和 18四数之和
先判断我们当前遍历的位置的值是否大于0,如果大于0直接返回res,因为排过序后当前值大于0后面的值也大于0。接在在right > left的循环里判断三数之和是否大于0,大于0right--,如果小于0left++,如果等于0,将这三个值插入res中,然后判断left的值和left+1的值是否相同,相同也要跳过。首先对数组进行排序,这点很关键,可以剪枝。定义unordered_map map,将第一个和第二个数组中的元素相加并填入map中,记录相加之后元素的值对应出现的个数。原创 2024-06-12 22:42:47 · 500 阅读 · 0 评论 -
代码随想录训练营第七天 344反转字符串 541反转字符串II 替换数字
于是我们遍历的时候直接i += 2 * k。这样我们就直接指向要反转的第一个元素。然后判断i + k是否超过了边界,如果没有超过直接反转前k个元素即可,若超过了就反转剩下的元素。双指针,一根指向字符串的头部,一根指向字符串的尾部。两个指针向中间移动,交换两根指针指向的值。反转可以用reverse(s.begin() + i, s.begin() + i + k);先找出这个字符串中出现数字的个数,然后乘5,然后将字符串扩容。题目要求的是遍历到2k个字符然后反转2k字符的前k个字符。原创 2024-06-13 21:38:54 · 237 阅读 · 0 评论 -
代码随想录训练营第八天 151反转字符串中的单词 右旋字符串
使用双指针,一根用来移动寻找每个单词的头,一根用于指向每个单词的末尾。然后将头指针和尾指针的字符添加到结果字符串中,其中头指针遇到空格时要跳过。先把首尾的空格去掉:找到第一个不是空格的字符,找到最后一个不是空格的字符。substr字符串为新的字符串t。将整个字符串反转,然后再对前n个反转和对n之后的字符反转。最后返回的时候最后一定会多一个空格,需要将空格去掉。原创 2024-06-14 20:49:41 · 165 阅读 · 0 评论 -
代码随想录训练营第九天232用栈实现队列 225用队列实现栈 20有效的括号 1047删除字符串中的所有相邻重复项
然后遍历整个字符串,如果是{ [ (这个三种括号的话就将它们插入st中,如果不是这三种括号的话则需要判断是什么类型的括号,首先要判断st是否为空,如果为空的话直接就返回false,然后看括号是否与栈顶的括号相匹配,如果是匹配的话则将栈顶的元素弹出,如果不匹配将该元素插入st中。使用两个栈来实现队列,一个栈A用来实现接收添加的元素,另外一个栈B用来记录栈订单元素来实现队列的peek操作,其中便是将A栈中的元素逆序存放在B栈中,A的栈顶元素就是B的栈底元素,A中的栈顶元素就是B中的栈底元素。原创 2024-06-16 16:35:55 · 350 阅读 · 0 评论 -
代码随想录训练营第十二天
当i大于0的时候,当在que中的第一个元素等于i指向元素的前一位时,证明该元素要弹出了,窗口移动让该元素弹出队列。当que中的元素不为空的时候,如果que的尾元素小于要新添加进来的元素时,我们将这些元素都弹出,这样能保持que的递减。当我们遇到+ - * / 的时候就需要将栈中的最后两个元素取出来,然后进行对应的操作并将结果也放入栈中,如果是数字的话将字符转换为数字放入栈中。deque 内 仅包含窗口内的元素 ⇒ 每轮窗口滑动移除了元素 nums[i−1] ,需将 deque内的对应元素一起删除。原创 2024-06-18 12:35:08 · 274 阅读 · 0 评论 -
代码随想录训练营第十三天
因为在中序遍历中,遍历顺序是左中右,而且先访问的是二叉树的顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点,这样就造成了处理顺序和访问顺序的不一致。就是先定义一个栈,把二叉树的每一层的元素都放入栈中,然后对栈进行操作,把栈中的元素取出放入到结果数组中。前序遍历的话顺序是根左右,因此一来变先将节点的值添加进res数组中,然后先向左递归再向右递归,结果都存在res数组中。在将每一层的元素放入数组中的时候,一定要将size提前声明并赋值好,不然在操作的时候que.size()是会变化的。原创 2024-06-19 19:20:37 · 356 阅读 · 0 评论 -
代码随想录训练营第十四天 226翻转二叉树 101对称二叉树 104二叉树的最大深度 111二叉树的最小深度
其中需要注意的是在如果左子树为空,右子树不为空的情况下最小深度是1 + 右子树的深度,反之,右子树为空,左子树不为空的情况下返回的是1 + 左子树的深度。思路:使用后序遍历的方式,遍历顺序是左右中。一直遍历到底部,然后取左右子节点中较大的深度再加一返回给上层,最后传递到根节点的值就是最大深度。注意本题最小深度是从根节点到最近叶子节点的最短路劲上的节点数量,注意是叶子节点,什么是叶子节点,左右孩子都为空的节点才是叶子节点。递归法:使用中序遍历的操作,中左右,在遍历到中间节点的时候对它左右节点进行交换。原创 2024-06-19 22:55:49 · 292 阅读 · 0 评论 -
代码随想录训练营第十五天 110平衡二叉树 257二叉树的所有路径 404左子树之和 222完全二叉树的节点
现在要标记的是左右子树的差值是否大于1,那么如果当前传入节点为根节点的二叉树已经不是儿二叉平衡树的话,还返回高度的话就没有意义了,因此可以直接返回-1来标记该树已经不是平衡二叉树了。我们使用前序遍历的方式,那么当我们找到一个左叶子的时候,res加上该叶子的值即可。当当前节点的左右节点都为的空的情况下证明这是一条完整的路径了,可以直接添加“->”然后加入res中。首先我们要定义返回值和传入的参数,传入的参数就是当前传入节点,返回值是传入节点为根节点的树的高度。是指该树所有节点的左右子树的深度相差不超过 1。原创 2024-06-20 22:14:59 · 319 阅读 · 0 评论 -
代码随想录训练营第十六天 513找树左下角的值 112路径总和I 113路径总和II 106从中序和后序遍历序列构造二叉树
采用中序遍历的方式,中左右,中间节点先添加到路径,向左遍历的时候targetSum的值-=节点的值传递给下一层递归逻辑。参数和返回值:参数需要有一个来记录此时的节点的深度,传入下一层递归的时候进行比较,同时这个参数也是要进行回溯的,当回溯的时候深度就要-1;终止条件:当前遍历的节点的左右节点都为空并且当前节点的值等于targetSum的值,则将该这条路径添加到res数组中。终止条件:当前遍历的节点的左右节点都为空并且节点的值等于targetSum的值则返回true;最后递归处理中序和后序的左右区间。原创 2024-06-24 21:29:09 · 281 阅读 · 0 评论 -
代码随想录训练营第十七天 654最大二叉树 617合并二叉树 700二叉树搜索树的搜索
终止条件:因为传入了两个树,那么就有两个树遍历的节点t1和t2,如果t1==null,那么两个树合并之后就是t2,同理t2==null,合并之后就是t1。将两个树的当前节点进行相加。然后根节点的左指向和右指向就进行递归。先用一个pre来记录当前遍历节点的前一个节点,判断当前节点的值是否大于pre的值。中:当前的pre不为空的情况下进行判断。先向左遍历:找到第一个节点,然后用bool left接住返回值。终止条件:当前节点是的值为目标值的时候,返回当前节点。单层递归逻辑:向左和向右子树遍历。原创 2024-06-24 21:50:01 · 301 阅读 · 0 评论 -
代码随想录训练营第十八天 530二叉搜索树的最小绝对差 501二叉搜索树中的众数 236二叉树的最近公共祖先
如果count>maxcount的值话,则需要将res中的值全部都清空,再把cur的值存放到res中。maxcount更新为count的值。在中序的时候将当前节点和前一个节点的值相减取绝对值然后和res进行比较。如果count的值和maxcount的值相等的话就将cur的值存放在res中,如果pre为空的话证明当前节点是左下角的那个元素,count记录为1;如果pre的值和cur的值相同,count++;定义一个pre节点来存放当前节点的前一个节点。定义一个pre节点来存放当前节点的前一个节点。原创 2024-06-24 22:36:53 · 290 阅读 · 0 评论 -
代码随想录训练营第二十天 235二叉搜索树的最近公共祖先 701二叉搜索树中的插入操作
注意本题是二叉搜索树,只要发现当前节点的值比p节点和q节点的值都大的话,那么最近公共祖先的位置一定的当前节点的左子树中,同理如果都小的话就在当前节点的右子树。当当前节点的值大于p并小于q的时候证明该节点就要返回的节点。先找到右子树左下角的元素,然后让该元素的左指针指向要删除节点的左子树。终止条件就是当前遍历的节点为空,那么就需要新建val节点然后被上一层遍历的节点接住。3.要删除的节点的左节点为空,右节点不为空。4.要删除的节点的左节点不为空,右节点为空。5.要删除的节点的左右节点都不为空。原创 2024-06-25 22:38:04 · 200 阅读 · 0 评论 -
代码随想录训练营第二十一天 669修建二叉搜索树 108将有序数组转换为二叉搜索树 538把二叉搜索树转换为累加树
如果当前节点的val值小于low边界,说明当前这个节点是要删除的节点,但是不能直接返回null,因为在这个节点的右子树中可能存在区间内的值,因此需要继续向右子树遍历,观察右子树中的每个节点值都在区间内。因为题目提到了要求是平衡的二叉搜索树,因此我们直接取数组的中间元素作为root,然后根据mid来划分左右数组区间,依次向左和向右递归两个数组区间。同理当前节点的值大于high边界同上一样的但是相反的操作。采用后序遍历的方式 一开始先向右遍历,然后中再向前。如果root本身为null的话直接返回null;原创 2024-06-26 21:53:35 · 339 阅读 · 0 评论 -
代码随想录训练营第二十二天 77组合
需要用一个sum来记录当前所有元素加起来的值是多少,然后和n进行比较即可。本题需要用一个string数组来记录每个数字对应的字符串。终止条件,当中间变量用来存储单个结果的大小等于k,则将中间变量存放到结果数组中。先将输入字符串的字符转换为数字。然后在找到数字对应的字符串后进行for循环。回溯的时候单个组合要pop_back(),sum要pop掉的那个值。中间变量的大小等于输入字符串的大小则存放入res数组中。for循环遍历的是字符串中每个数字对应的英文字母。递归是为了找到下一个位置的数字对应的英文字母。原创 2024-06-27 22:48:06 · 296 阅读 · 0 评论 -
代码随想录训练营第二十三天 39组合总和 40组合总和II 131分割回文串
本题要注意的就是树层去重的逻辑。树枝上不需要去重,因为树枝上的元素对应的是不同的元素。而树层上的元素必须要去重,因为在树枝上前一个相同的元素的遍历会包含当前元素的所有遍历结果,因此如果在同一层中当前的元素和前一个元素相同并且前一个元素没有被使用过的情况下,该元素直接跳过。当sum的值等于target的时候将组合添加到组合集合中。for循环中注意本题中的元素是可以重复选取的,因此下层递归中的startIndex还是i。在递归的逻辑中是将startIndex的位置向后移动一位。本题要注意的是去重的逻辑。原创 2024-06-29 17:12:42 · 219 阅读 · 0 评论 -
代码随想录训练营第二十四天 78子集 90子集II
用一个count值来记录当前遍历到IP地址的第几个字段了,如果当前已经遍历到第三个字段的时候,就需要考虑剩下的字符是否符合要求,如果符合要求的话就将剩下的结果添加到path中,如何将path添加到res结果数组中。如果要是全排列的话,每次要从0开始遍历,为了跳过已入栈的元素,需要使用used。终止条件:当前要收集的起始位置已经大于等于数组的大小的时候证明已经搜集到完成了。本题和子集很相似,但是要注意的是本题有重复的元素,但是结果中不能包含重复的子集。本题很简单,就是在每次遍历的地方都要搜集结果。原创 2024-06-30 16:45:15 · 346 阅读 · 0 评论 -
代码随想录训练营第二十五天 491非递减子序列 46全排列 47全排列II
在for循环中我们要注意的是需要有一个set结构来记录之前存在的数字。for循环中需要用一个bool类型的数组来记录哪些元素是使用过的。当当前遍历的元素的下标对应used数组中的值为true时说明当前元素已经被使用过了,直接continue。题目要求是递增子序列中至少有两个元素,因此在当path中存在的元素超过1的时候就将path放入结果数组中。终止条件:当path的大小等于nums的大小时,将path添加进res数组中。终止条件:当path的大小等于nums的大小时,把path添加进res数组中。原创 2024-07-03 22:46:51 · 254 阅读 · 0 评论 -
代码随想录训练营第二十八天 122买卖股票的最佳时间II 55跳跃游戏 45跳跃游戏II 1005K次取反后最大化的数组和
当前可以移动距离尽可能的走远,当走到最远的时候还没到达终点的时候,步数加一同时更新下一步的最远距离。一旦覆盖了终点,得到的就是最远步数。这题十分简单,就是把相邻天数的金额相减,如果发现大于0就加到res中,返回res即可。我们需要两个变量一个是这一步的最大覆盖距离,另一个是下一步覆盖的最远距离。看数组中每一位是否能覆盖到整个数组,如果覆盖到返回true;如果此时K的值不为0且为奇数,再进行排序,将最小的元素取反。先排序,遍历数组,将数组中为负的元素全部取正。原创 2024-07-04 22:04:59 · 190 阅读 · 0 评论 -
代码随想录训练营第二十九天 134加油站 135分发糖果 860柠檬水找零 406根据身高重建队列
需要三个变量,一个变量start记录结果也就是出发的第一个加油站,一个变量curSum来记录此时加油耗油后剩余的油量,如果发现curSum小于0的话就直接从当前加油站的下一个加油站作为第一个加油站重新计算;先从左向右遍历记录右孩子比左孩子多的情况,然后再从右向左遍历记录左孩子比右孩子高分的情况。找零的时候先找十块的,没有十块的再找五块。按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。然后遍历数组,根据k的值插入到结果数组中。原创 2024-07-05 22:57:00 · 405 阅读 · 0 评论 -
代码随想录训练营第三十天 452用最少数量的箭引爆气球 435无重叠区间 763划分字母区间
思路:先根据每个元素的第一个值进行排序,然后从第一个元素开始遍历,这里要注意我们初始化结果值的时候直接初始化为1,因为无论如何都是需要一把箭引爆气球。开始遍历的时候当前元素的左边界如果大于前一个元素的右边界的话说明此时需要加一把箭才能引爆气球,如果不是则跟新当前元素的右边界为当前右边界和前一个元素的右边界的最小值。将右边界right更新了当前元素的最远值。首先也是要排序,如果当前元素的左边界小于前一个元素的右边界,说明重叠了需要去掉一个,然后将右边界跟新为当前元素右边界和前一个元素右边界的较小值。原创 2024-07-09 21:07:40 · 287 阅读 · 0 评论 -
代码随想录训练营第三十一天 56合并区间 738单调递增的数字
如果我们发现前一个元素的值大于当前值,前一个数字-1,然后将标志位flag值为当前元素的下标。当前元素的左边界如果小于结果数组最后一个元素的右边界的时候,将结果数组最后一个元素的右边界跟新为当前元素右边和最后一个元素的右边界的最大值。然后定义一个二维数组存放结果,先将第一个元素存放到结果数组中,然后从第一个元素开始遍历整个数组。注意的是遍历要从后向前遍历,因为前面的数字会根据后面的数字进行判断和操作。如果不是以上情况就将当前元素添加到结果数组中。要注意flag的初始化为数字的位数。思路:首先还是排序;原创 2024-07-09 21:15:39 · 247 阅读 · 0 评论 -
代码随想录训练营第三十三天 509斐波那契数列 70爬楼梯 746使用最小花费爬楼梯
递推公式:dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])在下标为0的最小花费是0,只有它需要往上跳的时候才要加上cost[0],同理在下标为1的位置也是如此。初始化:dp[0] = 0;递推公式:dp[i] = dp[i - 1] + dp[i - 2];递推公式:dp[i] = dp[i - 1] + dp[i - 2]初始化dp[0] = 0;dp[1] = 1;初始化dp[0] = 1;dp[1] = 1;原创 2024-07-09 20:06:04 · 181 阅读 · 0 评论 -
代码随想录训练营第三十四天 62不同路径 63不同路径II
由题目可以知道dp[i][j]是什么推导来的,由于机器人智能向下或者向右移动一步,因此只能左边和上面移动而来。首先确定dp[i][j]是什么定义:表示下标为i,j的位置上有dp[i][j]条路径。初始化:第一行和第一列初始化为1。因为第一行和第一列的位置都是只有一条路径能到达。1.初始化的时候遇到障碍之后剩下没有置为1的位置就不能置为1了。2.在遍历过程中遇到障碍的位置dp[i][j]置为0;遍历顺序:从dp[1][1]开始遍历。原创 2024-07-09 19:53:44 · 247 阅读 · 0 评论 -
代码随想录训练营第三十五天 416分割等和子集
首先要先了解一下01背包问题:01背包问题就是有n和物品,每个物品有两个属性 一个是重量一个是价值;现在有一个背包,问每个物品只能用一次,能够将哪些物品装入背包容量为w的背包使得其价值总和最大。原创 2024-07-15 19:47:40 · 690 阅读 · 0 评论 -
代码随想录训练营第三十六天 1049最后一块石头的重量II 494目标和
接下来就是如何初始化dp[j]呢,因为重量都不会是负数,所以dp[j]都初始化为0就可以了,这样在递归公式dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);相对于 01背包,本题中,石头的重量是 stones[i],石头的价值也是 stones[i] ,可以 “最多可以装的价值为 dp[j]” == “最多可以背的重量为dp[j]”01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);原创 2024-07-15 21:24:52 · 690 阅读 · 0 评论 -
代码随想录训练营第三十七天 完全背包问题 518零钱兑换问题II 377组合总和IV
其中还需要在写递推公式之前还需要进行判断,因为可能会造成数组越界的问题,首先j - nums[i]必须是大于等于0的,同时在测试用例有两个数组相加之后超过了int的数据,所以需要判断dp[j] < INT_MAX - dp[j - num[i]].什么是完全背包,就是在01背包的基础上每个物品可以放无数次,在代码中和01背包不一样的地方只有在遍历顺序上不一致,在遍历背包的顺序上 01背包是从后往前遍历,在完全背包中是从前往后遍历。这次进阶版的改为一步一个台阶,两个台阶,三个台阶,...直到m个台阶。原创 2024-07-16 22:36:11 · 238 阅读 · 0 评论 -
代码随想录训练营第三十八天 322零钱兑换
凑足总额为j - coins[i]的最少个数为dp[j - coins[i]],那么只需要加上一个钱币coins[i]即dp[j - coins[i]] + 1就是dp[j](考虑coins[i])从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。dp[j] 可以由dp[j - i * i]推出, dp[j - i * i] + 1 便可以凑成dp[j]。原创 2024-08-10 09:50:49 · 714 阅读 · 0 评论 -
代码随想录训练营第40天 198打家劫舍 213打家劫舍II 337打家劫舍III
如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷一定是选一个最大的,所以:val2 = max(left[0], left[1]) + max(right[0], right[1]);在自定义的函数里返回值为一个vector,其中有两个值,分别为dp[0]和dp[1], dp[0]表示当前节点不偷所得到的金钱,dp[1]表示当前节点偷所得到的金钱。就是在上一题的基础上控制一下数组的范围,因为是环形的,首尾元素不能同时取,因此要划分为两个区间[0, n - 2] , [1, n - 1];原创 2024-07-17 23:13:45 · 348 阅读 · 0 评论 -
代码随想录训练营第四十一天 121买卖股票的最佳时机 122买卖股票的最佳时机II 123买卖股票的最佳时机III
这里股票能够买卖多次了,因此在持有的状态中可能之前就有利润了,那么第i天持有股票即dp[i][0],如果是第i天买入股票,所得现金就是昨天不持有股票的所得现金 减去 今天的股票价格 即:dp[i - 1][1] - prices[i]。dp[0][0]:持有股票那么为-price[0];dp[i][1]:表示第一次持有股票的最大现金;dp[i][0]表示第i天持有股票的最大现金。原创 2024-07-18 21:59:32 · 441 阅读 · 0 评论 -
代码随想录训练营四十二天 188买卖股票的最佳时机IV 309买卖股票的最佳时机含冷冻期 714买卖股票的最佳时机含手续费
同样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]);一定是选最大的,所以 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]呢?原创 2024-08-10 10:57:07 · 544 阅读 · 0 评论 -
代码随想录训练营第四十三天 300最长递增子序列 674最长连续递增序列
为什么一定表示 “以nums[i]结尾的最长递增子序” ,因为我们在做递增比较的时候,如果比较 nums[j] 和 nums[i] 的大小,那么两个递增子序列一定分别以nums[j]为结尾 和 nums[i]为结尾, 要不然这个比较就没有意义了,不是尾部元素的比较那么 如何算递增呢。但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;dp[i] 是有0到i-1各个位置的最长递增子序列 推导而来,那么遍历i一定是从前向后遍历。原创 2024-08-10 22:09:57 · 731 阅读 · 0 评论 -
代码随想录训练营第四十四天 1143最长公共子序列 1035不相交的线 53最大子数组和 392判断子序列
t[j - 1]),此时相当于t要删除元素,t如果把当前元素t[j - 1]删除,那么dp[i][j] 的数值就是 看s[i - 1]与 t[j - 2]的比较结果了,即:dp[i][j] = dp[i][j - 1];if (s[i - 1] == t[j - 1]),那么dp[i][j] = dp[i - 1][j - 1] + 1;从递推公式可以看出dp[i][j]都是依赖于dp[i - 1][j - 1] 和 dp[i][j - 1],所以dp[0][0]和dp[i][0]是一定要初始化的。原创 2024-08-11 09:50:45 · 675 阅读 · 0 评论 -
代码随想录训练营第四十五天 115不同的子序列 583两个字符串的删除操作 72编辑距离
第一题:思路:1.确定dp数组(dp table)以及下标的含义dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。为什么i-1,j-1 这么定义我在中做了详细的讲解。2.确定递推公式这一类问题,基本是要分析两种情况当s[i - 1] 与 t[j - 1]相等时,dp[i][j]可以有两部分组成。一部分是用s[i - 1]来匹配,那么个数为dp[i - 1][j - 1]。原创 2024-08-11 10:13:58 · 897 阅读 · 0 评论 -
代码随想录训练营第四十七天 647回文子串
如果j - i > 1的情况,那么可以有递推公式推出,如果dp[i + 1][j - 1]的值为true的话说明i + 1到j - 1这个区间的元素是回文子串,那么再加上两边的两个元素同样还是回文子串,res++;= s[j],那么就要分别考虑从 i 到 j - 1 和从 i + 1到 j之间回文子序列的最大值;注意初始化的时候,如果 i == j的时候将 dp[i][j] 初始化为1;dp[i][j]的含义:表示从i到j之间的子串是否是回文子串。dp[i][j]的含义:表示从i到j之间的最长回文子序列;原创 2024-07-23 22:18:57 · 393 阅读 · 0 评论 -
代码随想录训练营第四十八天 739每日温度 496下一个更大元素I 503下一个更大元素II
加入T[4],T[4] == T[3] (当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况),此时依然要加入栈,不用计算距离,因为我们要求的是右面第一个大于本元素的位置,而不是大于等于!我们要保持一个递增单调栈(从栈头到栈底),所以将T[0]弹出,T[1]加入,此时result数组可以记录了,result[0] = 1,即T[0]右面第一个比T[0]大的元素是T[1]。加入T[1] = 74,因为T[1] > T[0](当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况)。原创 2024-08-11 12:08:02 · 662 阅读 · 0 评论