- 博客(42)
- 收藏
- 关注
原创 代码随想录打卡 Day49 | part 10 动态规划
和 dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);同样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[0][1]表示第0天不持有股票,不持有股票那么现金就是0,所以dp[0][1] = 0;
2023-08-24 16:59:49
150
原创 代码随想录打卡 Day 48 | 动态规划 part09
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,初始化:dp[0] = nums[0], dp[1] = max(nums[0], nums[1])你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。,今晚能够偷窃到的最高金额。
2023-08-23 16:55:35
137
原创 代码随想录打卡 Day46 | 动态规划part08
递推公式:如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。第一题、unordered_set中 find() 和 end() 的用法。初始化: dp[0]肯定要是true,否则递推公式都是错的了。第一题、单词拆分 LeetCode 139。unordered_set成员方法。dp数组:dp[i]成员方法 功能。
2023-08-23 08:57:03
114
原创 代码随想录打卡Day45 | 动态规划part07
考虑到递推公式的特性,dp[j]必须初始化为一个最大的数,否则就会在min(dp[j - coins[i]] + 1, dp[j])比较的过程中被初始值覆盖。想不清楚的就是平方数也能够该怎么表示出来,其实在遍历物品的时候,用i * i <= n,然后在递推公式中用dp[j - i * i]就可以了。这道题要求最少硬币数,因此递推公式dp[j] = min(dp[j - coins[i]] + 1;递推公式:dp[j] = min(dp[j - i * i] + 1, dp[j])
2023-08-21 16:39:14
97
原创 代码随想录打卡Day 44 | 动态规划 part06
心得:完全背包:完全背包和01背包的区别在于物品时无限的,可以重复使用。因此在代码中的体现就是内圈的for要从小到大。因为初始化后,从大到小的for因j递减,前面的j还是初始的值,不会累加。而小到大的for因i递增,后面的j就会和前面的j累加在一起。
2023-08-17 17:06:58
110
原创 代码随想录打卡Day43 | 动态规划part05
剩下的部分和 LeetCode416分割等和子集 很类似,target就用数组sum的一半,然后dp[j]尽可能靠近target。最后的结果用 sum-dp[target] 就是另一堆的石块,在减去 dp[target]就是结果。本题其实就是尽量让石头分成重量相同的两堆,相撞之后剩下的石头最小,第一题、最后一块石头的重量 LeetCode1049。
2023-08-16 16:51:29
134
原创 代码随想录打卡Day 42 | 动态规划04
此时dp[j]有两个选择,一个是取自己dp[j] 相当于 二维dp数组中的dp[i-1][j],即不放物品i,一个是取dp[j - weight[i]] + value[i],即放物品i,指定是取最大的,毕竟是求最大价值,所以递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);因为对于二维dp,dp[i][j]都是通过上一层即dp[i - 1][j]计算而来,本层的dp[i][j]并不会被覆盖!
2023-08-15 22:59:27
86
原创 代码随想录打卡Day41| 动态规划 part03
从递归公式上来讲,dp[以j为头结点左子树节点数量] * dp[以j为头结点右子树节点数量] 中以j为头结点左子树节点数量为0,也需要dp[以j为头结点左子树节点数量] = 1, 否则乘法的结果就都变成0了。首先一定是遍历节点数,从递归公式:dp[i] += dp[j - 1] * dp[i - j]可以看出,节点数为i的状态是依靠 i之前节点数的状态。dp[i] 是依靠 dp[i - j]的状态,所以遍历i一定是从前向后遍历,先有dp[i - j]再有dp[i]。一个是j * (i - j) 直接相乘。
2023-08-14 14:34:46
95
原创 代码随想录打卡Day 39| 动态规划 part02
因此要多加一个判断条件,if(obstacle[i][j] == 0),当然,前面的初始化也需要骄傲,避免障碍出现在第一行和第一列的情况。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。不用想的太复杂,其实本质上就是遇到障碍的时候,不递推就可以了,相当于障碍就被跳过了。网格的左上角 (起始点在下图中标记为 “Start” )。网格的左上角 (起始点在下图中标记为 “Start” )。网格中的障碍物和空位置分别用。
2023-08-10 14:16:44
99
原创 代码随想录打卡Day38 | 动态规划 part01
数组初始化:不考虑dp[0]如何初始化,只初始化dp[1] = 1,dp[2] = 2,然后从i = 3开始递推,这样才符合dp[i]的定义。还有就是dp[i - 2],上i-2层楼梯,有dp[i - 2]种方法,那么再一步跳两个台阶不就是dp[i]了。首先是dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,那么再一步跳一个台阶不就是dp[i]了。第三步:初始化dp[0] = 0, dp[1] =1。你有多少种不同的方法可以爬到楼顶呢?第一题、斐波那契数 LeetCode509。
2023-08-09 16:58:14
119
原创 代码随想录打卡Day37 | 贪心算法part06
需要保证数字是单调递增的,因此需要从后向前遍历。逻辑是假如后一位比前一位小,前一位减1,后一位变成9。当且仅当每个相邻位数上的数字 x 和 y 满足 x
2023-08-09 10:05:10
77
原创 代码随想录打卡Day36 | 贪心算法part05
给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi]。像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。输入: intervals = [[1,2],[2,3],[3,4],[1,3]]划分结果为 "ababcbaca"、"defegde"、"hijhklij"。注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s。解释: 移除 [1,3] 后,剩下的区间没有重叠。
2023-08-08 14:19:19
123
原创 代码随想录打卡Day35 | 贪心算法 part04
但使用vector是非常费时的,C++中vector(可以理解是一个动态数组,底层是普通数组实现的)如果插入元素大于预先普通数组大小,vector底部会有一个扩容的操作,即申请两倍于原先普通数组的大小,然后把数据拷贝到另一个更大的数组上。所以使用vector(动态数组)来insert,是费时的,插入再拷贝的话,单纯一个插入的操作就是O(n^2)了,甚至可能拷贝好几次,就不止O(n^2)了。不用想那么复杂, 收到5就5++,10就10++,5--,20就优先10--5--,再5减三个。
2023-08-07 23:19:22
82
原创 代码随想录打卡Day34| 贪心算法part03
i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算curSum。区间和1 + 区间和2 < 0 同时 区间和2>0,只能说明区间和1 < 0, 那么就会从假设的箭头初就开始从新选择其实位置了。那么为什么一旦[0,i] 区间和为负数,起始位置就可以是i+1呢,i+1后面就不会出现更大的负数?如果出现更大的负数,就是更新i,那么起始位置又变成新的i+1了。
2023-08-07 15:25:47
97
原创 代码随想录打卡Day32 | 贪心算法part02
在每一天,你可以决定是否购买和/或出售股票。返回 你能获得的 最大 利润。i 每次移动只能在 cover 的范围内移动,每移动一个元素,cover 得到该元素数值(新的覆盖范围)的补充,让 i 继续移动下去。给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。每次移动取最大跳跃步数(得到最大的覆盖范围),每移动一个单位,就更新最大覆盖范围。不一定非要明确一次究竟跳几步,每次取最大的跳跃步数,这个就是可以跳跃的覆盖范围。这个范围内,别管是怎么跳的,反正一定可以跳过来。
2023-08-04 17:02:50
121
原创 代码随想录打卡Day 31| 贪心算法 part1
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j]。链接:https://leetcode.cn/problems/assign-cookies。局部最优解可以有两种方式:大饼干先喂胃口大的孩子,或者小饼干先喂胃口小的孩子。例如,有一堆钞票,你可以拿走十张,如果想达到最大的金额,你要怎么拿?每次拿最大的就是局部最优,最后拿走最大数额的钱就是推出全局最优。指定每次拿最大的,最终结果就是拿走最大数额的钱。来源:力扣(LeetCode)
2023-08-03 22:54:24
130
1
原创 代码随想录打卡Day30 | 回溯算法part06
一行一行的试不同的位置。因此可以用row == n作为终止条件。判断位置是否合法的isValid函数中,只需要判断已有的列,45度角和135度角有没有元素。构造一个由'.'组成的字符串。n皇后问题是回溯算法解决的经典问题,但是用回溯解决多了组合、切割、子集、排列问题之后,遇到这种二维矩阵还会有点不知所措。确定完约束条件,来看看究竟要怎么去搜索皇后们的位置,其实搜索皇后的位置,可以抽象为一棵树。
2023-08-03 17:02:13
71
原创 代码随想录打卡 Day29| 回溯算法part05
限制答案集要两个以上,直接放在res.push_back前;限制条件递增,直接在递归的for里用nums[i] >= path.back();给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素。你可以按 任意顺序 返回答案。数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。第一题、递增子序列 LeetCode491。
2023-08-02 15:40:10
135
原创 代码随想录打卡Day 27| 回溯算法 part03
在处理组合问题的时候,递归参数需要传入startIndex,表示下一轮递归遍历的起始位置,这个startIndex就是切割线。
2023-08-01 16:26:19
87
原创 代码随想录打卡Day24| 回溯算法part01
例如:{1, 2} 和 {2, 1} 在组合上,就是一个集合,因为不强调顺序,而要是排列的话,{1, 2} 和 {2, 1} 就是两个集合了。心得:回溯的精髓在与递归的时候在for循环里,所以每一次递归终止条件触发,回到上一层递归,还能执行上一层的for循环,从而把数都遍历掉。回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。注意图中,我特意举例集合大小和孩子的数量是相等的!回溯是递归的副产品,有了递归才会有回溯。第一步:确定回溯函数的返回值和参数。
2023-07-27 17:03:12
96
原创 代码随想录打卡Day22| 二叉树part08
利用二叉搜索树的特点,cur节点要么介于p,q之间,要么大于或小于p和q(这道题每个节点值不同)。介于中间就直接返回root, 大于或小于就分别左子树递归和右子树递归。涉及到删除节点就会调整二叉树的结构,比较复杂。这里的思路是根据左右孩子是否为空分各种情况。在二叉搜索树中插入一个新的节点,其实就是放在叶子节点上。因此遇到NULL的时候进行插入操作。第二题、二叉搜索树中的插入操作 LeetCode701。第三题、删除二叉搜索树的节点 LeetCode450。
2023-07-25 16:15:23
54
原创 代码随想录打卡Day21| 二叉树part07
当然也可以不用额外的数组,直接遍历节点然后直接计算。使用双指针法,一个pre指针指向前一个节点。可以和前一天的最后一题类似,放入数组中然后找出相邻两个数的最小差。第一题、二叉搜索树中的最小绝对差 LeetCode530。
2023-07-23 00:30:34
119
原创 代码随想录打卡Day20| 二叉树part06
需要先找到最大值并分割数组,再构造左右数组并进行递归。第一题、最大二叉树 LeetCode654。注意注释中错误的部分。
2023-07-22 13:55:14
135
1
原创 代码随想录打卡Day18| 二叉树05
首先可以使用迭代法层序遍历,记录每一层第一个数,用i==0时计算。第一题、找树左下角的值 LeetCode513。
2023-07-18 23:32:49
107
1
原创 代码随想录打卡Day17| 二叉树part04
第二题、二叉树的所有路径 LeetCode257。第一题、平衡二叉树 LeetCode 110。
2023-07-17 16:59:01
138
1
原创 代码随想录打卡Day16| 二叉树part03
也可以利用完全二叉树的特性,遍历左子树的完全二叉树,不需要遍历所有的节点。也可使用层序遍历:记住depth自加的位置,不是在同一层内的遍历里。第二题 二叉树的最小深度 LeetCode 111。第三题:完全二叉树的节点数 LeetCode222。第一题、二叉树的最大深度 LeetCode104。N叉数的最大深度 LeetCode 559。递归:可以直接在一个函数里面递归。
2023-07-17 11:01:53
137
1
原创 代码随想录打卡Day15| 二叉树 part02
心得:层序遍历的各种变体,要灵活思维,翻转答案,保留不同的答案。第一题:LeetCode 102 二叉树的层序遍历。6、每个树行中找到最大值 LeetCode 515。4、二叉树的层平均值 LeetCode637。5、N叉树的层序遍历 LeetCode 429。实现二叉树的层序遍历,即广度优先遍历。2、二叉树的层序遍历-2。
2023-07-14 08:44:59
166
1
原创 代码随想录打卡Day14|二叉树 part1
前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。那么再看看中序遍历,中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了。分析一下为什么刚刚写的前序遍历的代码,不能和中序遍历通用呢,因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,所以刚刚才能写出相对简洁的代码,前序遍历,中序遍历和后序遍历。
2023-07-13 11:16:39
93
1
原创 代码随想录打卡Day13| LeetCode 239、 LeetCode 347
使用队列来解决这一道题,首先遇到的问题是怎么把知道队列里的最大值,我们需要保证能把最大值放在队列出口处才能知道最大值。因此每一个push进去新的元素,都要和前面的元素数值进行比较。、LeetCode 347、前k个高频元素。、LeetCode239 滑动窗口最大值。今天的内容是关于队列稍微复杂一些的应用。
2023-07-12 13:16:48
101
1
原创 代码随想录打卡Day11|LeetCode20、LeetCode1047、LeetCode150
有时经常会想学的这些数据结构有什么用,也开发不了什么软件,大多数同学说的软件应该都是可视化的软件例如APP、网站之类的,那都是非常上层的应用了,底层很多功能的实现都是基础的数据结构和算法。这个命令最后进入a目录,系统是如何知道进入了a目录呢 ,这就是栈的应用(其实可以出一道相应的面试题了)。如果还记得编译原理的话,编译器在 词法分析的过程中处理括号、花括号等这个符号的逻辑,也是使用了栈这种数据结构。题意其实就像我们在写代码的过程中,要求括号的顺序是一样的,有左括号,相应的位置必须要有右括号。
2023-07-10 15:57:24
145
1
原创 代码随想录打卡Day10|栈与队列 LeetCode232、LeetCode225
思路类似,但用队列模拟栈不需要使用两个队列。只需要将队列的出口元素弹出再重新进入队列,直到需要的元素即可。开始关于栈与队列的内容。栈是先进后出,队列是先进先出。用一个进栈和一个出栈实现队列pop先进先出的功能。今天学习的内容是分别用栈实现队列和用队列实现栈。第二题、LeetCode225、用队列实现栈。、LeetCode232 用栈实现队列。整体的方法这两道题都是差不多的。
2023-07-10 14:37:40
88
1
原创 代码随想录打卡day09| KMP算法 LeetCode 28、 LeetCode459
本节开始了解KMP算法,目前对整个算法的实现还是比较的懵,弄懂了最长相同前后缀的意思。剩下的内容等之后理解更多了再来补充。
2023-07-10 13:57:18
72
1
原创 代码随想录打卡Day08|LeetCode344、LeetCode541、剑指Offer05、LeetCode151、剑指Offer58-2
要在while循环之前,因为是在单词前加空格,而不是之后,否则会报错。思路可以放开一些,前一道题刚学了局部翻转一些字符串然后全部翻转的操作,这道题可以先翻转n以内的字符串,再翻转其余字符串,最后把整个字符串翻转回来,就可以得到需要的结果。这道题目让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。从后往前替换成新的数组。先删除字符串里多余的空格,思路是删除所有空格之后,在每一个单词之后添加空格。再反转整个字符串,反转之后再依次把每个单词反转回来,得到结果。
2023-07-09 12:30:22
143
1
原创 代码随想录打卡Day07|LeetCode453、LeetCode383、LeetCode15、LeetCode18
四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值,依然是循环内有left和right下标作为双指针,找出nums[k] + nums[i] + nums[left] + nums[right] == target的情况,三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3)。的双指针解法是一层for循环num[i]为确定值,然后循环内有left和right下标作为双指针,找到nums[i] + nums[left] + nums[right] == 0。
2023-07-08 10:47:19
152
1
原创 代码随想录打卡Day6|LeetCode 242、LeetCode 349、LeetCode 202、LeetCode 1.
查找[first,last)范围内,与toval等价的第一个元素,返回一个迭代器。即从nums2的int型数组中依次将值赋值给num,将num带入for语句代码块中执行。使用哈希表中的set来解决,没有用数组是因为不同于上一题是连续的数(字母),第二时find函数,是C++ 标准模板库函数,查找一定范围内元素的个数。假如一个数重复出现,说明其不是快乐数,return false;使用unordered_set可以保证输出的数组是不重复的。第二题、LeetCode349,两个数组的交集合。
2023-07-05 23:38:17
124
原创 代码随想录打卡Day04| LeetCode 24、LeetCode 19、 LeetCode 160、LeetCode 142
找到相交链表的相交点,除了遍历套着遍历,可以想象为找到两个链表的长度,然后相减得到差值。在循环时要分别判断奇数节点数和偶数的区别,并注意要先判断cur-next而不是cur-next-next来避免出现空指针异常。注意要保存上面示意图中节点1和3,避免2被操作后找不到1和3。这样,就可以一起遍历curA和curB,不用循环套循环。第四题、LeetCode142:环形链表的入环第一个节点。第一题、LeetCode 24 两两交换链表中的节点。对链表的操作有了更深的认识。
2023-07-04 22:16:05
152
原创 (补)代码随想录打卡Day03| LeetCode 203; LeetCode 707; LeetCode 206
链表中不能用头节点来遍历,否则头结点的指针一直在变,最后无法返回头节点,需要定义一个临时的指针来遍历整个列表。第二种方法是设置虚拟头节点,这样不需要判断是否为头节点。只需要最后把链表的头节点设置回去,并删除虚拟头节点。2、加表头:要先设置加入节点的next,否则就找不到next了(先设置前一个结点的next的话)4、在第index个节点前加:需要遍历到其前一个节点(体现了虚拟表头的妙处),并同时注意2。设计一个链表需要注意的点比较多,C++中需要注意private里面的size和虚拟链表头。
2023-07-03 23:35:54
95
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人