
算法学习
文章平均质量分 78
学习常规算法
玩复杂点
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素。
注意此时right指针初始定义为nums.length,该指针指向数组最右元素的右边一个位置,故右为开区间,当left = right时已经无意义,故为left < right,当nums[mid] > target时,mid已经确定不是了,故此时right = mid,因为右为开区间,正好把mid排除在外。当遇到不为目标值时,两个指针一起向后走,当遇到为目标值时,慢指针不走,快指针继续向后遍历,然后用快指针指向的值覆盖慢指针此时指向的目标值元素。元素的顺序可以改变。的元素,并返回移除后数组的新长度。原创 2023-02-15 20:03:33 · 551 阅读 · 2 评论 -
代码随想录算法训练营第二天| 977. 有序数组的平方、209. 长度最小的子数组、59.螺旋矩阵II
示例 1: 输入:nums = [-4,-1,0,3,10] 输出:[0,1,9,16,100] 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]如果不存在符合条件的子数组,返回 0。输入:s = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。示例 2: 输入:nums = [-7,-3,2,3,11] 输出:[4,9,9,49,121]209.长度最小的子数组。977.有序数组的平方。原创 2023-02-16 17:14:13 · 196 阅读 · 0 评论 -
代码随想录算法训练营第三天| 203.移除链表元素、707. 设计链表、206.反转链表
null的条件,head=null直接返回结果,链表涉及到删除结点的情况一般都在循环的cur指针后定义一个pre指针,跟着cur一步步走,用来删除结点时用。注意该题目说的第0个结点,指的就是index=0的结点,该题目中的head实际上就是一个虚拟的结点,head.next就是index为0的结点,在写这几个方法时,先写在index位置加入值为val的结点这个方法,然后在第一个位置插入和末尾插入的方法调用该方法即可,一个个来,慢慢写,整体不难,注意结点结构的定义与链表结构的定义。双链表情况二刷再看。原创 2023-02-17 23:37:52 · 86 阅读 · 0 评论 -
代码随想录算法训练营第四天| 24.两两交换链表中的结点、19.删除链表的倒数第N个结点、面试题02.07.链表相交、142.环形链表II
定义一个快指针和一个慢指针,快指针一次走两个结点,慢指针 一次走一个结点,因为快比慢相对而言每次多走一个结点,故在循环的时候不会错过,肯定会遇上,当快指针和慢指针相等时,说明存在环,快指针走了x+y+n(z+y)个结点,慢指针走了x+y个结点,2倍的慢指针结点数=快指针结点数,最后联立化简后得到x=(n-1)(z+y)+z,可以知道z与x这两个距离的结点个数是相同的。给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。原创 2023-02-19 00:09:57 · 109 阅读 · 0 评论 -
代码随想录算法训练营第六天| 242.有效的字母异位词、349.两个数组的交集、202.快乐数、1.两数之和
1.对于看一个元素是否在一个集合里面这种题,一般都要想到哈希表,哈希表有三种数组,set,map,要根据情况确定选择哪一种,这里因为字母总共有26个,数目是确定的,故可以选择数组来操作,开辟一个大小为26的数组,一个索引代表一个字母,先遍历第一个字符串,出现一个字母,在对于的数组下标处+1,然后再遍历第二个字符串,将对应位置的值-1,如果最后数组里每一个位置都为0,则证明连个字符串每个字母的数量是一致的,符合字母异位词,如果存在不为0的值,则不是。给定两个数组,编写一个函数来计算它们的交集。原创 2023-02-20 22:25:05 · 99 阅读 · 0 评论 -
代码随想录算法训练营第七天| 454. 四数相加II、383. 赎金信、15.三数之和、18.四数之和
本题符合看元素是否在一个集合中的题,需要用哈希表,要存储数组的值的大小与数量,优先想到用hashmap来存储,为了提高效率,两个数组两个数组的遍历,首先遍历前两个数组,将结果相加得到前两个数组的和,存到map中去记组合数为1,如果map中本来存在与该和相等的情况,则记相应的组合数加1,后两个数组循环遍历,依次得到后两个元素和的值,拿着前面存好的map去找,与该值相加正好为0的值,即0-temp,如果有,则res加上有的这个值对应的组合数,最终循环结束,得到最终的res。454.四数相加II。原创 2023-02-22 17:34:53 · 112 阅读 · 0 评论 -
代码随想录算法训练营第八天| 344.翻转字符串、541.翻转字符串II、剑指Offer 05.替换空格、151.翻转字符串里的单词、剑指Offer58-II.左旋转字符串
总结:用i来遍历整个字符串数组,以2k个元素来跳跃,当从i起第k个元素索引小于数组最后一个元素的索引,说明剩余的还有大于k个元素,则将前k个元素反转,如果从i起第k个元素索引大于数组最后一个元素的索引,说明剩余的元素不足k个了,则将剩余的元素全部反转。总结:翻转字符串这个操作是很简单的,收尾两个指针,每次交换索引位置的元素值,即可,用一个temp变量暂存中间值即可,后面有很多字符串题目用到此题目方法。输入:["h","e","l","l","o"]输出:["o","l","l","e","h"]原创 2023-02-23 11:16:54 · 80 阅读 · 0 评论 -
代码随想录算法训练营第九天| 28.找出字符串中第一个匹配项的下标、459. 重复的子字符串。
该题目用到了kmp算法,其核心为构造一个next数组,数组中每一个值,代表以当前下标位置的元素为结尾的字符串的最大前后缀匹配串长度,aba,next(2)=1,即aba的最大前后匹配串长度为1,当模式串abaa指针指向最后一个a时与文本串不匹配,则需要将指针后移动至,倒数第二个a的next值的位置,这里需要自己体会,不好描述,这题需要仔细体会代码,理解深度还不够,二刷再好好体会。示例 2: 输入: haystack = "aaaaa", needle = "bba" 输出: -1。输入: "abab"原创 2023-02-24 17:34:40 · 106 阅读 · 0 评论 -
代码随想录算法训练营第十天| 232.用栈实现队列、225. 用队列实现栈。
栈是先进后出的,而队列是先进先出的,需要用两个栈来模拟队列的基础操作,队列的入队,直接用一个stackIn的入栈来模拟,但是队列的出队时,必须要先出最先入队的那个,但是对于一个栈来说,这个元素在栈底,肯定是出不来的,此时,就需要吧栈里的全部元素腾出来,都依次放入stackOut栈中去,此时最里面的那个元素变成了最外面,就能直接执行pop操作来模拟出队了,逻辑是不错的,只要stackOut中有元素,就出,出完了,再出的话就去stackIn中取。push(x) -- 将一个元素放入队列的尾部。原创 2023-02-25 22:13:09 · 77 阅读 · 0 评论 -
代码随想录算法训练营第十一天| 20.有效的括号、1047.删除字符串中的所有相邻重复项、150.逆波兰表达式求值。
每遍历一个左括号,就往栈里打入一个相同的右括号,用于后面好匹配,如果整个字符串,还没遍历完,如果不是所有左括号的情况,说明只剩下右括号了,下面就开始对照栈中了,看看是否匹配,此时如果栈中空了,此时说明右括号多了,如果,如果此时栈中的第一个括号与当前遍历的括号不符,就说明属于第二种情况,这两种都返回false,如果匹配上了,就把栈中的那个括号弹出来,最后所有字符串都遍历完了,再看栈中是否还有,如果还有,说明是左括号多了,也不符合情况,只有此时栈里也空了,才返回true。根据 逆波兰表示法,求表达式的值。原创 2023-02-26 23:53:36 · 81 阅读 · 0 评论 -
代码随想录算法训练营第十三天| 239. 滑动窗口最大值、347.前 K 个高频元素
本题非常巧妙,定义一个单调递减的队列,要保证进来的元素,始终队头是最大的一个元素,我们不需要记录滑动窗口里每个值,每个大值前面的小数不需要记录,每次入队,队尾元素小于进队元素,就弄出,不记录,当队列中队头的元素从滑动窗口中出来的时候才需要弹出,不记录的小元素从窗口出来时,因为没有记录所以也没事。你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。输入: nums = [1,1,1,2,2,3], k = 2。给定一个非空的整数数组,返回其中出现频率前 k 高的元素。原创 2023-02-27 23:36:35 · 128 阅读 · 0 评论 -
代码随想录算法训练营第十四天| 144. 二叉树的前序遍历、94. 二叉树的中序遍历、145. 二叉树的后序遍历。
用一个指针记录我们遍历的每个节点,先顺着往左下,见一个节点先压入栈中,知道没左节点,此时该返回中节点了,也就是之前我们压入栈中的最新的那个节点,存到数组里去,然后指针指向其右边节点继续压入栈中重复之前操作。后序遍历二叉树用迭代法的时候,因为前序是中左右的顺序,把前序遍历方法左右节点压入栈中的顺序颠倒下就变成中右左的顺序了,得到最终的数组后,再调用reverse方法将数组反转,得到左右中的顺序,即正好为后序遍历的顺序。给你一棵二叉树的根节点 root ,返回其节点值的。144. 二叉树的前序遍历。原创 2023-02-28 23:57:01 · 132 阅读 · 0 评论 -
代码随想录算法训练营第十五天| 102. 二叉树的层序遍历、226. 翻转二叉树、101. 对称二叉树。
本题利用递归法遍历二叉树,即可完成对应操作,前序和后序都可,但是中序不行,整体思路就是,先交换本次遍历结点的左右子树,交换完毕后,再向下继续遍历,或者后序也没问题,中序的话就有问题了,比如上面第一个数,遍历 到最左边一后返回到2,然后交换2的1和3两个节点,然后再回到根4节点,然后交换2和7节点顺序,之后要遍历根4节点的右节点,但是发现右节点2子树,是刚刚交换过的子树,故此时不太行。给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。给你二叉树的根节点 root ,返回其节点值的。原创 2023-03-01 23:55:15 · 100 阅读 · 0 评论 -
代码随想录算法训练营第十六天| 104. 二叉树的最大深度、111. 二叉树的最小深度、222. 完全二叉树的节点个数。
二叉树的深度与高度是有区别的,高度是指任意一节点到叶子节点的节点个数,适合用从下往上计数,适合后序遍历,深度是指任意一节点到根节点的节点个数,是从上往下计数的,适合前序遍历,一个二叉树的最大深度与最大高度实际上数值是一样的,所以我们可以用求最大高度的方法,来得出最大深度,后序简单。的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。叶子节点是指没有子节点的节点。原创 2023-03-03 00:04:09 · 98 阅读 · 0 评论 -
代码随想录算法训练营第十七天| 110. 平衡二叉树、257. 二叉树的所有路径、404. 左叶子之和。
这里我们考虑用后序遍历的递归方法解决,算出每个节点的左孩子的值,返回给上一层的节点,最后累计加一起,这里需要注意,每个左叶子的判断我们需要通过其父节点才能判断出来,父节点的左孩子不为空,且左孩子的左右指针为空,此时这个父节点的左孩子才为左叶子节点,用一个midsum记录这个左孩子的值,代表这个父节点的左叶子节点的值,然后向上一层返回出这个midsum+该父节点的左右孩子的左叶子节点的值也就是leftsum 和 rightsum,好好体会便可以了解。给定二叉树的根节点 root ,返回所有左叶子之和。原创 2023-03-03 23:48:41 · 73 阅读 · 0 评论 -
代码随想录算法训练营第十八天| 513.找树左下角的值、112. 路径总和、113. 路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树。
总结:1.递归法,用Deep和res记录当前最大的深度与目前得到的最深一层的最左侧的节点值,无论后序还是中序,都是优先遍历到最左侧节点,所以当同一层的非最左边的节点被遍历到的时候,此时的deep是等于记录的最大Deep的,不大于它,因为在他之前已经同一层的最左侧叶子节点已经被遍历到了被记录了。给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。原创 2023-03-06 09:55:53 · 74 阅读 · 0 评论 -
代码随想录算法训练营第二十天| 654. 最大二叉树、617. 合并二叉树、700. 二叉搜索树中的搜索、98. 验证二叉搜索树。
验证是否为搜索二叉树,可根据搜索二叉树中序遍历正好是按从小到大的顺序遍历出来的,这一性质来进行判断,在中序遍历的过程中,用一个max节点来记录上一个节点的值,如果该节点的值小于等于max的值(也就是其上一个节点的值),说明这棵树按照中序遍历,出来的结果不是依次增大的,不满足搜索二叉树的性质,所以返回false,每次都要更新max节点的值,以保证max始终是前一个节点。- [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5]。- 空数组,无子节点。原创 2023-03-06 23:28:42 · 99 阅读 · 0 评论 -
代码随想录算法训练营第二十一天| 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先。
要想到搜索二叉树用中序遍历,遍历出来的结果是按照节点值的顺序升序排列的,找到两个节点的最小的差值,必定在顺序挨着的两个节点直接产生,则用pre记录前一个节点,result记录目前的最小差值,每次用遍历到的节点与前一个节点作差后与result比较,如果比result还小,就更新result,同时更新pre节点,使其一直更新为遍历节点的前一个节点。中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(原创 2023-03-08 21:51:02 · 95 阅读 · 0 评论 -
代码随想录算法训练营第二十二天| 235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点。
后面就是根据遍历到的节点的值与目标值比较,来判断直接去右子树还是左子树遍历,如果去左边递归,就代表前面的几种情况返回的值赋给该节点的左孩子,右边递归,返回的值就赋给该节点的右孩子。如果当前节点大于p和q两个节点的值,对于搜索二叉树来说,那么pq两个节点的祖先一定在该节点的左子树上,则去左边遍历,如果当前节点小于pq两个节点的值,则说明pq两者的祖先一定在该节点的右子树上,遍历到第一个结点,如果其值在p与q之间(无论大于谁小于谁,或者等于谁且大于或小于谁)那么它一定是二者的最小公共最先,直接返回该节点即可。原创 2023-03-10 17:13:06 · 82 阅读 · 0 评论 -
代码随想录算法训练营第二十三天| 669. 修剪二叉搜索树、108. 将有序数组转换为二叉搜索树、538. 把二叉搜索树转换为累加树。
如果该节点的值小于区间的最小值,则说明该节点与其左子树都不能要了,直接删除,返回以右孩子为根再开一个这个函数的结果,最后返回的也就是以这个右孩子为根的树,相当于间接把原本的该节点和其左子树删除掉了,如果该节点的值大于区间的最大值,则该节点包括其右子树的所有节点不能要了,直接删除,以左孩子为根,再开一个这个函数,同样相当于把该节点和其右子树都删除掉了,符合左右区间的话,则该节点不用删除,像其左右子树递归查看,最终返回根节点。所以结果应当返回修剪好的二叉搜索树的新的根节点。节点的右子树仅包含键。原创 2023-03-11 00:07:58 · 131 阅读 · 0 评论 -
代码随想录算法训练营第二十四天| 回溯理论基础、77. 组合。
path列表存放每一种选择,当path的长度达到k时,可以将该path加入到最终的result中去了,这里每次遍历一个元素之后,下次这个元素就不再遍历了,因为这里返回的是组合,不是排列,排列是元素一样,顺序不一样,算两种结果,而组合,就是顺序不一致也是只算一个结果,而且不能是两个元素都是重复的,遇到这种在一堆数中找组合的问题,就想到回溯,套用上面回溯模板即可。第一次取1,集合变为2,3,4 ,因为k为2,我们只需要再取一个数就可以了,分别取2,3,4,得到集合[1,2] [1,3] [1,4],以此类推。原创 2023-03-11 20:07:17 · 251 阅读 · 0 评论 -
代码随想录算法训练营第二十五天| 216.组合总和III、17.电话号码的字母组合。
首先传的“23”digits肯定要有,我们做的字符串数组也要传,再传一个num,用来确定我们当前是遍历到“23”中的第几个位置开始选择字母,先传0,代表先从2,=对应的字母中去选择abc,2终止条件,如果num=digits.length(),相当于传的digits已经都选完了,故可以返回了,for循环也是模版,遍历完没次选择个数字对应的字母,每种情况都是把选出的该字母加入,然后再递归将num+1,挑digits中的下一个数字代表的字母列表中选出另一个字母,递归后面再回溯,把加的字母再弹出来。原创 2023-03-12 16:57:29 · 115 阅读 · 0 评论 -
代码随想录算法训练营第二十七天| 39. 组合总和、40.组合总和II、131.分割回文串。
从数组中找出和为target的所有不同组合,还是回溯问题,终止条件,当sum> target时,说明已经不用继续递归了,这种选择已经不行了,return终止即可,==target时,说明已经到达了收获结果的时候,收获结果再return,然后是基本的for循环,每次path加元素,sum加上该元素,然后递归,注意这里元素能无限次选,故递归中的开始位置i可以不+1操作,之后再回溯sum-元素,path移除元素。如果至少一个数字的被选数量不同,则两种组合是不同的。,并以列表形式返回。解集不能包含重复的组合。原创 2023-03-14 21:18:44 · 75 阅读 · 0 评论 -
代码随想录算法训练营第二十八天| 93. 复原 IP 地址、78. 子集、90. 子集 II。
包含重复元素,故要考虑去重,还是同层的情况,如果本次元素与上一个元素一致,则看本元素是在上一个元素的下面,还是说又重新开的一个子集情况的第一个,如果是后者,则直接返回,因为上一个以和这个元素相等的元素打头的子集已经把所有可能的情况都选上了,再以这个元素打头选子集,会重复的,这个也是要在每个节点都收集结果,每个节点出来都是一个子集。区别于之前每次收获结果的时候必须到叶子节点,这次每个结点都是一个结果,都要加入结果集,其余的都是常规的回溯模版。给你一个整数数组 nums ,数组中的元素。原创 2023-03-15 21:04:24 · 99 阅读 · 0 评论 -
代码随想录算法训练营第二十九天| 491. 递增子序列、46. 全排列、47. 全排列 II。
排列问题出现了,区别于之前的组合问题与子集问题,排列问题因为【1,2】与【2,1】结果是不一样的,故每次递归选每个元素时,前面的元素是可以选的,除了已经选过的,故函数里不需要再设置起始位置start了,因为是全排列,所以需要在每个叶子节点收获结果,当path中大小与数组大小一致,说明选择完全,出了一种排列,收集即可,用used数组,记录哪个元素被选过,for挑选元素时,如果该值的元素被选过,则说明需要直接跳过,选没被选过,使其对应used=true,加入path,递归,回溯。返回所有不重复的全排列。原创 2023-03-17 15:49:59 · 89 阅读 · 0 评论 -
代码随想录算法训练营第三十一天| 455. 分发饼干、376. 摆动序列、53. 最大子数组和。
这里利用count去记录连续的序列和,如果count为负数,那么再与后一个元素去累加时,因为这时序列和是负数,所以还不如舍去,从头开始记录下一个元素的值,注意不是遇到负数就舍弃,而是目前的序列和为负数舍弃,即使,下一个元素是负数,但是,只要序列和是正的,那么再加到下下一个元素时,值肯定是会比下下一个元素大的,就可能存在更大值的情况,用result记录目前的最大序列和,如果count大于目前的最大序列和,就直接更新,避免错过最大和。虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。原创 2023-03-19 22:33:02 · 119 阅读 · 0 评论 -
代码随想录算法训练营第三十二天| 122. 买卖股票的最佳时机 II、55. 跳跃游戏、45. 跳跃游戏 II。
每次遍历一个元素看它能到达的位置,看它下一跳能否大于最大范围,大于最大范围,则更新最大范围,如果这个下一跳范围能超过数组末尾,则就跳这一步,count+1,并返回,如果已经遍历到当前的最大范围,curindex,则说明中间没有到末尾的那一步,则必须跳这一步了,count+1,更新目前的最大范围为跳过之后这个节点能到的最大范围。不用关注到底哪一步怎么跳,只需要看每步之后能跳的最大范围,在这个范围里,再看有没有能更新最大范围的,如果最终能将范围扩大到数组的末尾,则证明会存在一种方法可以跳到最后。原创 2023-03-20 22:41:39 · 63 阅读 · 0 评论 -
代码随想录算法训练营第三十四天| 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果。
每次到一个加油站,就统计本身的加油站给的油和去到下一个加油站需要的油的差值,正数,说明可以由这个加油站到下一个加油站,负数,说明到不了下一个,我们开始遍历每个加油站,curSum记录遍历过的加油站的这个差值的和,如果curSum为负数,也就是说,到不了下一个站,则这个加油站包括之前的每个加油站都不能开始,去循环一圈,因为到这里卡住了,到不了下一个站,故需要从下一个加油站开始,继续统计curSum,这里用index记录下一个加油站的位置。开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油。原创 2023-03-21 23:16:30 · 91 阅读 · 0 评论 -
代码随想录算法训练营第三十五天| 860. 柠檬水找零、406. 根据身高重建队列、452. 用最少数量的箭引爆气球。
用3个变量分别记录目前手里5,10,20元钱的数量,遍历账单数组,遇到给5元的,直接收下,遇到10元的,检查目前记录手中5元数量的变量,如果没有5元零钱,则找零不了这个10元。则直接返回false,如果还有5元,则记录5元的变量-1,记录10元的变量+1,遇到20元的,这里分两种情况找零了,一个10元+一个5元,还有是3个5元。编号为 5 的人身高为 7 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。编号为 0 的人身高为 5 ,没有身高更高或者相同的人排在他前面。原创 2023-03-23 10:19:40 · 65 阅读 · 0 评论 -
代码随想录算法训练营第三十六天| 435. 无重叠区间、763. 划分字母区间、56. 合并区间。
因为每个字母只能出现在一个片段中,那么我们需要将遍历的每个字母的最远位置的字母也加入到我们的片段里来,等到最远的一个字母也加入进来了(中间的字母的最远位置字母也都在这个区间里被加入进来了),一个片段生成。先将区间的左边界按照从小到大的顺序排序,然后对每个区间进行遍历,如果该区间的左边界小于上一个区间的右边界,则说明重复,需要删除一个区间,count++,此时将该区间的右边界重新赋值为两个区间的右边界的最小值,用来与下一个区间的左边界比较,如果还重叠则继续删,重复上述操作,直到遍历结束,返回count。原创 2023-03-23 23:30:20 · 85 阅读 · 0 评论 -
代码随想录算法训练营第三十七天| 738. 单调递增的数字、968. 监控二叉树。
i > 0;i--){//从后往前遍历,如果当前元素比其前面的元素小,则前面的元素-1,本元素需要赋值为9start = i;i++){原创 2023-03-24 23:39:17 · 202 阅读 · 0 评论 -
代码随想录算法训练营第三十八天| 509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯。
动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。所以动态规划中每一个状态一定是由上一个状态推导出来的对于动态规划问题,我将拆解为如下五步曲,这五步都搞清楚了,才能说把动态规划真的掌握了!确定dp数组(dp table)以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组。原创 2023-03-26 10:52:48 · 135 阅读 · 0 评论 -
代码随想录算法训练营第三十九天| 62. 不同路径、63. 不同路径 II。
题目中2位置只能由其左边一个位置和其上面一个位置走一步到达,故到达2位置的不同路径数就等于到其左和到其右位置的不同路径数之和,我们发现中间的值,都是需要从最左边的边界和最上面的边界来逐一推导出来的,故左边和上边的边界都需要初始化值,因为只能向右走和向下走,所以走到所以的左边界的位置和走到所以右边界的位置的不同路径数都只有1种情况,所以将这些位置的值都初始化为1,然后根据动态五部曲依次求结果即可。//1.dp[i][j]表示为走到i行j列有多少中路径//3.数组初始化i < m;i++){原创 2023-03-26 23:11:07 · 320 阅读 · 0 评论 -
代码随想录算法训练营第四十一天| 343. 整数拆分、96. 不同的二叉搜索树。
0,1都是不可拆分的,默认为0即可,2可以拆成1*1=1,故从n=3开始遍历,j记录每次拆分的第一个数,一个数的拆分情况,我们把它划分为2个数,3个数以及3个数以上这两种情况,后面这个情况我们用类似递归的思想来去实现,1.分成两个数的情况,比如第一个数为j,则第二个数则为i-j,将这两个数相乘,2.三个以及三个数的情况,第一个数的划分不变,剩下数整体再划分,以两个数或者三个数以及三个数以上的两种情况来划分。原创 2023-03-27 19:50:58 · 106 阅读 · 0 评论 -
代码随想录算法训练营第四十二天| 416. 分割等和子集。
这题可以把其抽象为背包问题,如果数组能将大小为数组总和一半的背包正好装满,值也为数组总和一半,说明可以分割成两个子集,这里数组的每个元素代表每个商品,其值既是大小,又是价值。用一维数组来实现背包问题,d[j]代表背包大小为j,能装的最大价值,一维数组在内循环之所以用逆序遍历,是因为如果正序,会把原理上上一层的数据给更改为新的数值,每个dp[j]都是由上一层的值来确定的,这里因为省去了数组的维数,每个层的数据共享了一层的位置,所以需要逆序遍历,这样上一层的数据再利用的时候才不会被修改。int sum =0。原创 2023-03-28 23:05:50 · 216 阅读 · 0 评论 -
代码随想录算法训练营第四十三天| 1049. 最后一块石头的重量 II、494. 目标和、474. 一和零。
两个石头可以消重量,要使得最终剩余石头的最小重量,那么就把石头尽可能分成两个总重量一样的数组,且这个重量数要尽可能大,最终可以使得消除后剩余重量最小,先求出石头的总重量,然后除以2,我们就需要求大小为sum/2的背包,能装的最大价值,求出之后,总重量减去俩两倍的该最大价值,即为结果。sum += i;//dp[j] 为背包大小为j,可以装的最大价值i++){j--){left 为需要赋值为正数的数组,right为需要赋值为负数的数组,由left+right=sum;原创 2023-03-29 23:18:02 · 236 阅读 · 0 评论 -
代码随想录算法训练营第四十四天| 518. 零钱兑换 II、377. 组合总和 Ⅳ。
本题要根据不同的硬币去凑大小为amount的金额数,查看所有凑成总金额的硬币组合数,每个面的硬币有无限个,这就是完全背包问题,,区别于01背包,所有的面额有无数个,可以随便去,当时我们的内循环,j也就是背包大小,之所以逆序来循环,就是为了避免前面的硬币能重复取得问题,故这里我们可以重复取,所以内循环j也是正序遍历即可。dp[0] = 1;i++){j++){这里所说的组合,说的是顺序不同的序列被视作不同的组合,所以这里指的是从nums中找出并返回总和为target的元素序列的个数,这是找排列。原创 2023-03-31 17:11:43 · 290 阅读 · 0 评论 -
代码随想录算法训练营第四十五天| 70. 爬楼梯(进阶版)、322. 零钱兑换、279. 完全平方数。
是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。如果没有任何一种硬币组合能组成总金额,返回。你有多少种不同的方法可以爬到楼顶呢?,表示不同面额的硬币;你可以认为每种硬币的数量是无限的。计算并返回可以凑成总金额所需的。70. 爬楼梯(进阶版)有两种方法可以爬到楼顶。1. 1 阶 + 1 阶。的完全平方数的最少数量。279. 完全平方数。原创 2023-03-31 23:39:32 · 324 阅读 · 0 评论 -
代码随想录算法训练营第四十六天| 139. 单词拆分。
这题字符串可以想象成背包,字典中的每个单词可以想象成物品,题目中说是字符串可以拆分为一个或多个在字典中出现的单词,字典中的一个单词可以多次利用,看一个字符串能否由字典中的单词组成,所以这是完全背包,遍历背包时需要正序遍历,dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。原创 2023-04-02 22:46:41 · 327 阅读 · 0 评论 -
代码随想录算法训练营第四十八天| 198. 打家劫舍、213. 打家劫舍 II、337. 打家劫舍 III。
dp[i]代表范围到第i家包括,包括第i家,能偷的最大金额,如果偷这个i家的,则只能看范围到该家的前面两家的能偷的最大金额,加上该家的金额,如果不偷这家的,则需要看范围到该家的前一家的能偷的最大金额。比较这两种可能性的最大值将其赋给dp[i]。//如果只有一家,则肯定偷就完事了,返回这家的金额//dp[i]代表考虑前i家包括第i家,能偷的最大金额数//只有一家,则必偷,dp[0]直接等于这一家的金额//有两家,为了避免报警,则选一个最大金额的偷。原创 2023-04-04 10:28:17 · 174 阅读 · 0 评论