自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 day33-动态规划__62.不同路径__63. 不同路径 II __343. 整数拆分__343. 整数拆分

62.不同路径这一题由于题目一开始限定了每次我们只能向下走或者向右走,那么其实这道题的动规逻辑就相当清晰了。那么该初始化为多少呢。显然每次只能向左或者向右走,那么最上边和最左边只能是1所以dp[i][0] = 1,dp[0][j] = 1时间复杂度: O(N)空间复杂度: O(N²)当然这题,由于后面状态始终依靠左边和上面得出,是可以优化为滚动数组版本的63. 不同路径 II这道题是在上一题的基础上,加上了障碍物这个元素那么显然,只需要在上述分析下修改一下即可。

2025-04-14 21:40:37 1106

原创 day32-动态规划__509. 斐波那契数__70. 爬楼梯__746. 使用最小花费爬楼梯

在同学接触到动态规划的题目时,对于简单的动态规划问题,同学们常常轻易通过,而对于复杂的动态规划,却没有一个很好的思路,那么我们究竟有没有一种统一的思考步骤来解决动态规划问题呢?很多同学认为,dp的难,难在不能很好的总结出递推公式(状态转移方程),但其实这个只是动规里面的一个难点,只需要想清楚了dp数组及其下标的含义,我们在推导递推公式时,也会事半功倍。2层的最小花费 + cost[i-2] -> dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]).

2025-04-12 12:31:59 1228

原创 day31-贪心__56. 合并区间__ 738.单调递增的数字__968.监控二叉树 (可跳过)

那现在我们来考虑如何进行贪心呢,首先由于题目所给的是int类型的数字,这种数字不方便我们去遍历访问他的每一位以及后续的修改操作,所以这里,我们考虑将其先转换为string类型。然后,我们来看一下,如果是“233”这个例子,我们会发现它对应的最大递增是“229",并且对于"231",按照题目的要求,它对应的也是"229"。之后,如果前一段的右端点<=后一段的左端,则进行合并操作,然后加入答案。现在我们考虑从后向前的考虑,这样我们能考虑到每一位的递增关系,并且确保它的局部最优叠加的总和是全局最优。

2025-04-11 19:13:52 368

原创 day30-贪心__452. 用最少数量的箭引爆气球__435. 无重叠区间__763.划分字母区间

当然是right == i 的时候,即我们已经走到了当前遍历过字母的最远位置,这时我们需要记录答案,而由于这道题要求我们保存的是每一段的元素个数,所以我们除了right之外,还需要一个left,用来记录我们开始时的左端点。每一次都去判断前一段的右端点,是否大于等于后一段的左端点。对于这道题来说,初看的时候,我们会认为复杂繁琐,但是如果我们对每一个vector 按照左端点或者按照右端点进行排序之后,我们去射击气球时,每次射击都尽可能的设计区间的重叠部分,这样就能保证我们花费的箭最少。(使用类似桶排序的方式)

2025-04-11 18:39:30 638

原创 day29-贪心__134. 加油站__135. 分发糖果__860.柠檬水找零__406.根据身高重建队列

首先,我们可以通过gas[i] - cost[i]得到第i个站点的净加油量(耗油量),那么如果我们现在考虑一个从某点a到某点b,那么如果a-》b范围之间的gas[i] - cost[i]存在负数,那么说明无法从a作为起点到达b,那么我们就必须考虑从b+1,开始作为起点。当顾客给二十元时,这个时候就有了两种处理方案,一种是找三张5元,另一种是一张10元,一张5元。当后一个元素大于当前元素时,该位置的糖果数量就是单独考虑左侧时的糖果数量和后一个元素的糖果数量+1取最小值,这样能保证我们最终得到的糖果是最少的。

2025-04-10 23:07:18 456

原创 day28-贪心 __122.买卖股票的最佳时机II__55. 跳跃游戏__45.跳跃游戏II__1005.K次取反后最大化的数组和

这道题问我们能否跳到最终的位置,每次的nums[i] 就是站在i下标下,我们能够跳跃的最大距离,所以如果我们在下标为i的位置,我们能够跳跃的范围就是(i,nums[i] + i),如果我们想要从i这一步到达终点的话,我们只需要判断nums[i] + i是否大于等于nums[i] + i。还是用上一题的思路,有一个关键概念是覆盖范围,我们每一次都要找到覆盖范围中最大的下一次覆盖范围,这样的话能保证,我们每一次跳跃都能保证下一次能跳的更远,这样多个下一次最远的叠加就能够使我们跳跃到终点。

2025-04-08 10:54:38 375

原创 day27-贪心 __455.分发饼干__376. 摆动序列__53. 最大子序和

这道题,我们能很直观的看出,只需要把当前最大的饼干,分给胃口最大且小于当前最大饼干的小朋友,每一次都这样做,就能得到最终的答案。例如,手中有五张面值不同的钱币,分别为100,50,20,10,5。这里也能看出来,贪心算法的适用范围是有限的,因为在很多问题中,局部最优的累加并不能得到全局最优。这道题,我们能想到,如果前面的最大和是正数的话,那么加上当前位置的元素值,就是当前位置的最大和,如果前面的最大和是负数的话,那么当前位置的最大和,就等于当前位置的元素即可。贪心算法其实就是符合人类直觉思维的方法。

2025-04-07 10:50:47 228

原创 day25-回溯__491.递增子序列 __46.全排列__47.全排列 II

这一题的排列和上一题的不同,就是所给数组中存在了重复元素,也就意味着,我们不仅要考虑排列问题在同一树枝的去重问题,还需要考虑,在同一树层的去重问题,这些之前在组合问题中都解决过了。我们之前通过startIndex来保证完成组合问题,那么意味着,如果我们每次回溯都从0开始,并且去除掉同一树枝已经使用过的元素,这样的话就能把组合问题改为排列问题了。只有满足这两个条件的元素,我们才会将其加入path,并且要求的是元素个数大于等于2的子集,所以每次path.size()大于2时,我们就要将其加入。

2025-04-06 22:05:08 340

原创 day24-回溯 __ 93.复原IP地址 __ 78.子集 __90.子集II

这道题,如果昨日的分割字符串学懂了,应该是难度不大的。我们由于ip地址的表示方式是4段的点分十进制,意味着,我们只需要在每一个合理的段中,添加一个".",分割处四段ip地址段。这样的话我们需要添加三个’.'。子集问题类问题,与我们之前写过的组合类问题很类似,只是现在我们可以每次手机path的时候,同时收集一下ans。所以,我们就可以用分割回文串类似的算法来解决这道题。只需要修改一下回溯的边界条件,以及将判断回文串的代码改为判断ip段是否合理的代码即可解决这道题。这题的去重和之前组合总和问题去重也类似。

2025-04-04 18:01:14 250

原创 day23-回溯 39. 组合总和 __ 40.组合总和II __131.分割回文串

这道题要求我们将整个字符串分割成多个回文串的集合,我们可以进行回溯操作,每次判断传入的startInde-i这个范围内的字符串是否为回文串,如果是,就继续将startIndex设置为i+1向下递归,如果不是就跳过继续判断startIndex-i+1范围内的字符串是否是回文串。在这题组合总和中,我们不能重复使用同一个元素了,但是在所选集合中,存在重复的元素,那么就有可能出现这样的情况,在递归树层上,我们选择了重复的元素,在后序递归的过程中,这两个重复的元素会产生相同的结果。我们先回顾一下昨日的。

2025-04-03 10:23:50 398

原创 day22-回溯__77. 组合__216.组合总和III __ 17.电话号码的字母组合

但是这一题,我们每次选择数字的地方是不同的,要根据题目所给的digits得到,比如,题目如果给的digits=“23”,那么我们选择第一个数字是’2’,那么我们需要去’2’对应的字母里面选,而第二次需要去’3’对应的字母里面选。所以一般而言,我们会在回溯函数的参数中传入一个startIndex,即本层回溯的起始点,这样当前层回溯的起始点都比上一层大1,这样的话也就隐式的包含了顺序的思想,而不会出现[1,2,4]与[2,1,4]这种情况。这题虽然看上去和之前一样,同样是一个组合问题。

2025-04-02 09:42:24 338

原创 day21-二叉树-__669. 修剪二叉搜索树__108.将有序数组转换为二叉搜索树__538.把二叉搜索树转换为累加树

我们要将其所给的有序数组,每次找到数组中间的那个元素(可向下取整,也可向上取整,不过要一直使用同一种取整方式),作为这一次递归的根节点,然后以当前节点下标划分左右区间(区间划分时,要一直采取同一种划分策略,左闭右开,左闭右闭,左开右开都可以),然后当前递归节点的左子树,用左区间去递归,而右子树,用右区间去递归。这里,我们不妨思考一下,如果给的是一个有序数组,那么我们是否只需要从后往前遍历,每次让当前元素值加上后一个元素值就可以得到,题目要求的数组了!显然,这种方式便于理解,但是实现起来比较的麻烦。

2025-04-01 11:14:37 441

原创 day17-二叉树-__654.最大二叉树__617.合并二叉树__700.二叉搜索树中的搜索__98.验证二叉搜索树

所以用这种方法是不对的。这时候我们就要想到二叉搜索树的另一个性质,二叉搜索树的中序遍历,是一个有序数组。所以,我们只需要对这棵二叉搜索树进行中序遍历并同时收集其遍历节点的val保存到一个vector中,然后判断,这个vector是否有序即可,能写出如下代码。如果是这种情况,上诉代码就会返回True,但是这却不是一颗二叉搜索树(10的右子树里存在小于10的元素6,这是不允许的)。由于这是一颗二叉搜索树,所以我们可以利用其性质进行快速搜索,而不需要像普通树一样,一个节点一个节点的遍历。

2025-03-31 22:29:23 317

原创 day20-二叉树-__235. 二叉搜索树的最近公共祖先__701.二叉搜索树中的插入操作__450.删除二叉搜索树中的节点

5.左右孩子节点都不为空,则将删除节点的左子树头节点(左孩子)放到删除节点的右子树的左面节点的左孩子 上,返回删除节点右孩子为新的根节点。3.删除节点的左孩子为空,右孩子不为空,删除该节点,右孩子补位,返回右孩子为根节点。4.删除节点的右孩子为空,左孩子不为空,删除该节点,左孩子不为,返回左孩子为根节点。2.删除节点的左右孩子都为空(叶子节点),直接删除节点,返回NULL为根节点。所以当当前节点小于p,q时,我们访问当前节点的右子树。或者找到最后一个小于待插入节点的节点,插入到它的右子树。

2025-03-31 22:02:42 388

原创 day18-二叉树-__530.二叉搜索树的最小绝对差 __501.二叉搜索树的众数__236.二叉树的最近公共祖先

使用中序遍历二叉搜索树,用pre记录遍历前一个节点,cur记录当前遍历的节点。这样用cur->val - pre->val的方式,每次都能得到一个差值,如果这个差值小于当前的最小差值,就更新最小差值,并更新pre。但是,上述方法并没有很好的使用到这是一颗二叉搜索树的结论,所以这里我们可以利用二叉搜索数的性质,想到类似于上面一题的双指针解法。对于这道题,我们也能很自然的想到,只需要使用一个map在遍历二叉树的同时,统计二叉树的每个节点的出现次数。这道题的递归法其实很好思考,由于所给的树是二叉搜索树,所以其。

2025-03-31 21:24:53 287

原创 day6-代码随想录__hash__ 哈希表理论基础 ___ 242.有效的字母异位词__349. 两个数组的交集__202. 快乐数__202. 快乐数

先以数组为例具体解释。

2025-03-17 21:37:51 671

原创 day4-代码随想录||链表||24.两两交换链表中的节点 ||19.删除链表的倒数第N个节点||面试题02.07 链表相交||142.环形链表

我们可以先分别遍历两个链表,记录两个链表的节点数量,那么链表公用的部分一定不会出现在,较长链表的前面abs(sizeA-sizeB)部分。之后就很简单的,长链表指针从tmp处开始移动,短链表指针从头开始移动,判断他们是否相等(注意:这里的相等是指针相等,而不是值相等,意味着指向的内存相等,所以就能判断找到了公用链表头)。这道题是一道交换节点的题目,由于要直接对链表进行操作(增删改),而不是单纯的遍历,所以需要添加虚头节点,使得对头节点的操作和后续节点的操作一致。同样的,因为是删除操作,需要虚头节点。

2025-03-15 17:14:55 480

原创 day3-代码随想录||链表||203.移除链表元素 707.设计链表 206.反转链表

找第一个不为val的节点的目的是: 由于单链表的特性(单向指向),删除节点需要先找到待删除节点的前一个节点,这样比较好操作。关键点在于这题给的链表,他的head节点本身就是一个有实际含义的节点,而不是一个空节点。一道设计类的题,看似不难,其实存在很多细节,容易写错,由于卡尔大神写的是单链表版本的,我写了一个双向链表的版本。这道题相对简单,就是创建一个pre节点用于记录前一个节点的位置,一个cur节点不断向后移动即可。对非头节点的处理:这里就比较简单,如果相等就删除cur所指的节点,不过不等cur向后走。

2025-03-15 00:35:30 349

原创 LeetCode---1423. 可获得的最大点数---2134. 最少交换次数来组合所有的 1 II

思路:这题如果正常遇见的话是想不到滑动窗口的,但是灵神将他分类在滑动窗口中,我就开始想使用滑动窗口做。考虑到对于一个数组来说他最终要求所有1都连续,那么也就是说,我们只需要维护一个大小为数组中所有1个数的数组,然后用这个窗口不断滑动,找到在该窗口下,窗口中含有1的最小值,即最终要返回的答案。思想:这题使用滑动窗口的话,需要反向思考要求求出从数组的两端弹出k个元素的最大值,就可以反向思考为找出数组中间窗口大小为size-k个元素的窗口的最小值,这样除了这个窗口之外的剩余元素就是最大的。空间复杂度:O(n)

2024-10-09 23:28:13 198

原创 LeetCode-2379. 得到 K 个黑块的最少涂色次数-1652. 拆炸弹-1052. 爱生气的书店老板-2841. 几乎唯一子数组的最大和-2461. 长度为 K 子数组中最大和

思路:基本上就是简单的滑动窗口,只是要记录一个map映射,用来保存当前窗口内有多少对不同的map映射,用来和m进行比较,只有当map映射数满足大于等于m时,采取尝试更新最终的maxSum。那么,要保证有一个长度为k的全为‘B’的字符串,就只需要把对应map中,键‘W’全改为‘B’即可。但是官方题解给出了一种更好的方式来求解,即将原来的code数组,扩容成原来的两倍,并且将code数组原来的数据直接赋值给后面一半,这样当访问数组第i+k个元素时,就不存在越界问题了。之后的操作就是普通的滑动窗口了。

2024-10-02 15:58:34 228

原创 LeetCode---1456. 定长子串中元音的最大数目---643. 子数组最大平均数 I---1343. 大小为 K 且平均值大于等于阈值的子数组数目---2090. 半径为 k 的子数组平均值

思想:维护一个长度为k的定长滑动窗口,每次对窗口执行后移操作,要检查移除窗口的元素是否为元音字母,以及加入窗口的元素是否为元音字母,然后更新当前窗口中的元音字母数量YUAN。之后检查YUAN与最终返回的maxYUAN的关系并赋值即可。空间:O(1)-只维护一个窗口右指针,无额外开销。时间:O(n)-对数组进行遍历操作。思路:基本与上一题一致。

2024-10-01 23:47:41 257

原创 LeetCode---53.最大子数组的和

申请一个dp数组,dp[i]代表数组第i个位置的最大子数组的和,初始化dp[0] = nums[0],那么dp[1]就等于max(dp[0]+nums[1],nums[1]),由此可以推得状态方程为: dp[i] = max(dp[i-1]+nums[i],nums[i])。直接使用一个currentS来记录当前子数组的和,而每次都记录当前位置的子数组最大和,递推表达式为 currentS = max(nums[i], currentS + nums[i])。空间复杂度:O(n),dp数组所需花费。

2024-09-30 09:39:50 224 1

原创 LeetCode---76.最小覆盖子串

第二步:开始不断尝试收缩左边界,看是否影响windowCount包含整个子串,如果不影响则继续收缩,影响就先停止收缩。然后通过左移r,来使windowCount重新包含整个子串,重复该过程,直至完全收缩。在每次重新包含整个子串时都要对最小长度进行更新,并且记录该子串的起始位置。分别定义两个map。第一个map记为tCount,用于保存子串t的映射;第二个map记为windowCount用于保存当前窗口内的字符映射。初始化双指针l,r分别为0,用于记录当前窗口边界。O(m),保存子串t的哈希映射。

2024-09-29 09:13:49 222

原创 LeetCode---239.滑动窗口的最大值

思想:使用单调栈+滑动窗口的方式,首先先初始化一个单调递增栈这个单调递增栈的大小为k,这样可以第一个窗口中的最大值,会位于当前单调递增栈的栈顶,可以直接记录进入最终返回的vector,然后开始进行滑动窗口,设置l,r两个变量记录窗口的左右边界,分别初始化为0和k-1。申请一个双端队列,用于维护当前窗口,每次加入一个窗口元素时,都先去除掉队列中小于当前插入元素的元素,这样能够维护队列的单调性,保证最大元素一直在队头,当循环变量i到达k-1之后,每一次都需要对最终的返回vector进行插入双端队列的队头元素。

2024-09-28 20:24:39 351

原创 LeetCode---438.找到字符串中所有字母异位词---560.和为k的子数组

通过前缀和的概念,我们能够在一次遍历中有效地计算出和为 kk 的子数组数量。哈希表用于存储每个前缀和的出现次数,使得我们能够快速查找并更新结果。这个方法的高效性在于它避免了使用双重循环的 O(n2)O(n2) 复杂度,将其降低到 O(n)O(n)。public:// 处理和为 k 的情况// 更新当前前缀和// 检查是否存在前缀和为 currentSum - k 的情况// 更新当前前缀和的计数return ans;

2024-09-26 09:40:59 1650

原创 LeetCode---3.无重复字符的最长字串

思路:使用滑动窗口的写法来写,设置一个map来存储当前窗口中已经出现的字符以及其对应的映射,初始窗口起点和最大长度均为0,然后外层循环中不断推进窗口的右端点,并且逐一更新窗口的最大值和当前存储map映射。如果在推进窗口右端点的时候,遇到重复的字符,则直接将窗口的左端点移到重复字符的下一个字符处,重新开始计算窗口。时间复杂度:O(n) (一开始以为是O(nlogn),然后突然意识到map是基于hash的,所以查找的时间复杂度应该是O(1),所以时间复杂度是O(1))

2024-09-25 19:52:40 295

原创 LeetCode---42.接雨水

如果 height[i]>height[top],则得到一个可以接雨水的区域,该区域的宽度是 i−left−1,高度是 min(height[left],height[i])−height[top],根据宽度和高度即可计算得到该区域能接的雨水量。显然这种方式的复杂度是O(N)。思想:由于要得到能接的雨水总量,一定是每一个bar位置所能接的雨水的总和,而对于每一个bar而言,其能接水的量无非就是该bar左右两边的bar的最小值减去当前bar的高度,决定了这个bar的位置能接多少水。

2024-09-24 09:58:58 865

原创 LeetCode---11.盛最多水的容器---15.三数之和

思路:先将数组进行排序之后,循环遍历数组,设置左右指针,左指针设置为当前i位置的下一个位置,设置右指针为数组的最后一个位置。开始内层循环,当三个指针的和sum为0时,保存进最终的ans数组,并且继续增大l,减小r,看是否有其他组数据能和当前i组成的和为0。为了避免重复保存,应该分别在i,l,r对应位置的元素与上一个位置的元素相同时,执行跳过操作。由于短板效应,每次测试完当前情况下的面积后,就将l,r所指向的两个板中较短的那一个板向内移动,因为只有这样,才最有可能使得下一次所盛放的水的比上一次的多。

2024-09-23 16:22:28 294

原创 Leetcode---128最长连续序列---283移动零

使用快慢指针的思想,遇到非零则快慢指针同时向后,遇到零快指针(i)向后。时间:O(nlogn)128-最长连续序列。

2024-09-22 10:06:48 212

原创 PAT --- B1035 --- 插入与归并

不知道为什么这里会出现段错误,没看出什么地方发生地址越界了。

2024-09-04 09:49:07 262

原创 算法学习---字符串相关

二者的结果都会返回一个对应的布尔值。2) 链接 str1 = str1 + str2 或者 str1 = str2 + str1。2) 含空格输入 --- 使用cin.getline(数组名,数组长度)的方式进行按行输入。3) 判等与判断大小 str1 == str2 str1>str2。1) length()或者size()---返回字符串的长度。3)strcat---将一个字符串追加到另一个字符串的末尾。2)strcpy --- 将一个字符串复制到另一个字符串。

2024-05-09 16:12:58 1088 2

空空如也

空空如也

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

TA关注的人

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