自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 代码随想录算法训练营第二十九天|491.递增子序列、46.全排列、47.全排列 II

这一题的去重不仅要看当前元素是否使用过,还要在当前元素和上一个元素重复的时候查看:现在是否已经处理过重复元素序列中的第一个元素了。因为前面的 nums[i] == nums[i - 1],这个去重逻辑是不影响正常的没有使用过的元素的。不是很难,因为要找出所有的排列并且所有元素都不重复,只需要用一个used数组来记录当前正在用的元素,并在遍历的时候排除这个元素就可以了。这里的去重也是用used数组实现,但要注意因为只对同层去重,所以每一层的used数组都是独立的,要写在回溯方程里面。

2024-02-12 14:59:53 397

原创 代码随想录算法训练营第二十八天|93.复原IP地址、78.子集、90.子集II

要注意判断是否去重是用 i > startIndex 而不是 i > 0,如果是0的话就会错误的漏掉很多元素。题解的解法没太看懂,自己在切割回文串的代码基础上写了一个很慢的解法。有时间了再多看视频题解研究一下。也不是很难,在上一题的基础上加入了去重。这里还是数层去重(横向),所以直接套用以前的去重逻辑就好了。不是很难,就是要注意在回溯的一开始就把path加入result。

2024-02-12 11:55:43 372

原创 代码随想录算法训练营第二十七天|39. 组合总和、40.组合总和II、131.分割回文串

39:代码随想录和普通组合问题的区别在于对index的使用。允许重复元素的话只需要维护一个index,并且在递归时不需要手动+1。剪枝的操作有点难度,尽管弄明白了什么时候做剪枝,但代码实现上有些坑。如果不对数组排序,那在剪枝的时候就不能用break直接退出,而是用continue跳过当前元素,因为后面可能还有符合条件的元素;相对的,如果对数组排序的话,就应在和大于target的时候直接break退出forloop,因为如果当前元素已经大于target,那之后每个元素和都会比target大。

2024-02-09 09:12:03 381 1

原创 代码随想录算法训练营第二十五天|216.组合总和III、17.电话号码的字母组合

剪枝的操作除了写在forloop的起始条件里也可以写在递归的一开始。最后还是要记住startIndex是用来控制横向遍历的,i是用来控制纵向的。其次是单个字符形式的数字转换成int,直接利用字符的ASCII码的性质,用字符减去 '0' 就可以得到相应的数字。首先是数字和字母的映射,直接把各个数字代表的字符串放入一个String[ ]里,用下标来代表数字就好了。在forloop开始的时候,i 用来遍历当前集合的每一个元素(选取每一个元素作为初始值)字符串的操作几天没做又忘记了...

2024-02-04 13:10:09 372 1

原创 代码随想录算法训练营第二十四天|回溯理论基础、77. 组合

跟着题解的思路走,比较容易理解,自己重新写的时候把forloop里给递归传入的新startIndex写成了startIndex + 1(正确的应该是 i + 1)。这就导致代码会跳过一些有效叶子节点并重复加入已经遍历过的节点。正式开始学习回溯,不把过程抽象为树的话确实是很抽象难以理解。把过程看作树,forloop就相当于横向遍历,递归则是纵向遍历。剪枝的操作虽说在图上能理解,但是到代码层面的话理解起来还是有些吃力。

2024-02-03 05:31:07 344 1

原创 代码随想录算法训练营第二十三天|669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

想清楚这个后,用昨天的思路来做能解决 要删除的节点的子树完全在区间内的简单情况,但如果要删除的节点的子树里还有区间外的节点(比如 [3,1,4,null,2] 3-4),就要。这题也不是很难,通过反中序(右中左)来遍历,然后记录一个全局变量来储存当前节点应该加多少,就可以比较容易地做出了。题本身不是很难,思路就是用前序遍历来构造BST,因为给的数组是有序的,所以直接找中点然后递归构造左右子树就好了。整体思路和昨天做过的删除节点一样,要通过修改上一层的指针来达到删除下一层的结果。,然后再返回修建好的子树。

2024-02-02 10:55:39 344

原创 代码随想录算法训练营第二十二天|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

一下子难度就来了,而且这种通过直接更新节点左右指针来达成目的的方法还需要更多理解和练习。一开始自己写的处理四种不复杂情况的代码还是拘泥于迭代遍历时的更新方法,类似于这种: previous.left = current.left。如果pq都比当前节点大,那就只搜索右子树,如果都小,则只搜索左子树,如果一个大一个小则代表找到了最小公共祖先。但其实这道题和上一道实现增加/删除的方法是一样的,通过更新根节点的左右指针来达成操作。不是很难的一道题,重点是要熟练掌握BST(二叉搜索树)的特性。

2024-02-01 14:49:40 350 1

原创 代码随想录算法训练营第二十一天|530、501、236

递归中的root只可能是 null,p,q,pq的最低公共祖先 这四种情况中的一个。这是因为根据basecase,当递归从最底下的空节点开始返回时,如果没有碰上pq中的任意一个,那root就会是null不变并向上返回(代表并没有找到pq),如果碰上p或q,就会往上返回p或q,直到在某个节点,当这个节点的子树返回上来的left和right都不为null的时候则找到最小公共祖先,将这个节点向上返回到根节点。跟着题解的 同时记录当前count和最大count的方法做的,但在写单层处理逻辑的时候卡了很久。

2024-01-31 08:52:37 312

原创 代码随想录算法训练营第二十天|654、617、700、98

递归做起来更简单一点,递归的时候不要忘记是用来给左右指针赋值的,不赋的话就递归相当于啥也没干。两天没写层序遍历有点忘了,需要注意除了一开始判断两个树是否有一个为空,其他的条件判断都应该在whileloop里面赋值的时候做。易于理解一点的递归就是题解中的,按照左中右的顺序进行处理,这样只用维护一个最小值,中序遍历所有节点时,同样的思路但不放进数组,用递归遍历的同时检查,却一做就出错。很简单,递归的做法要注意返回递归的值,要不然白递归。用中序遍历把元素放进数组然后遍历比较的方法比较简单。

2024-01-30 12:47:56 405 1

原创 代码随想录算法训练营第十八天|513、112、113、106、105

其次就是对于return值是boolean的递归方程的运用。目前为止一直在写有返回值的递归,所以一开始还是在想该怎么让递归最后返回的是符合条件的值。我一开始是在base case前就直接减去当前节点的值(因为也包含了根节点),再在返回上一层的时候加回子节点的值,这样弄错了一个关键点:把手动回溯和让每层递归自动回溯混合使用了。在这个版本里,我在basecase前就使sum减去当前节点的值(这是令递归自动回溯),却又在下面的if判断里手动加回了子节点的值(手动回溯),这样一混用就导致sum的值总是错的。

2024-01-29 13:54:35 314

原创 代码随想录算法训练营第十七天|110、257、404

但要注意在发现任意一个子树不符合要求返回 -1 的时候,也要检查当前的左右高度(子节点们返回的值)是否是 -1,如果是的话代表当前节点下方已经出现了不符合条件的子树,需要继续往回返回 -1。因为左右子树的遍历是从根节点的左右子节点开始的,然后本题又得从父节点来查左子节点,所以如果根节点左侧只有一个叶子节点,左右子树的遍历会漏算这个有效节点。所以就需要额外定义一个整数变量,并在查找到左叶子时更新他,最后和左右sum一起返回,处理特殊情况的同时也能正确的在每一层给左右sum赋值。

2024-01-27 13:31:21 307

原创 代码随想录算法训练营第十六天|104、559、111、222

题目本身不难,但完全理解递归还是有一点抽象的。递归的解法可以理解为通过不断查找当前节点的左右节点来到最底层,最底层再递归到下一层是null节点,return 0 回到上一层(最底层的叶子节点),此时depth变量还是0,但是通过返回depth + 1的方式来代表底层已被记录,并且将这个结果(现在是1)返回到上一层,重复+1来记录每一层。要记住,第一次return的时候相当于是在最底层的下面的null节点,返回的数是0,再次返回的时候相当于是在最底层,就要+1来记录这一层了,不+1来记录的话返回的永远是0。

2024-01-26 14:08:04 324 1

原创 代码随想录算法训练营第十四天|144、145、94(二叉树的递归遍历,迭代遍历,统一迭代)

当前节点不是null,就不应该退出while-loop,因为遍历完所有根节点左边的子节点之后栈会弹出并记录根节点,此时栈是空的,但根节点右边的子节点还没开始遍历(如果没有任何右子节点则会满足退出条件)。跟着题解的递归思路想一遍就比较清晰了,没什么难度,重点还是把递归搞清楚。一开始完全看不懂,然后自己在纸上跟着题解画图写步骤一步一步来弄明白了。前序比较容易理解,在纸上画几个例子跟着过一下就差不多了。

2024-01-24 10:41:16 590

原创 代码随想录算法训练营第十三天|239、347

举例说明:[1,3,1,2,0,5],k=3。当初始窗口开始滑动的时候队列为 3,1 并且需要加入2,我一开始是用queue,只能与头(也就是3)作比较,2<3,于是2就在1没有被移除的情况下加入了,使得队列变成 3,1,2 ,这就导致当窗口再次移动至[1,2,0],队列里移除3之后,队列(1,2)的头变成了1,这时再用peek取最大值的话就会获得错误的答案。所以加入2的正确方法是从尾开始先跟1比较,2>1,移除1,再跟3比较,2<3,加入2,这样就能保证队列中正确的排序。第一道hard题,花了很久。

2024-01-23 13:52:21 342 1

原创 代码随想录算法训练营第十一天|20、1047、150

遍历和筛选逻辑写的没什么困难,但是没有选择用StringBuilder,然后又对String object直接操作不熟花了一些时间:我以为两个String相加的顺序无法和栈pop的顺序对齐,只能获得反过来的字符串。一开始没有想到直接new一个用来放Integer的栈,遍历到数字就转换并且放入,遍历到运算符就用已经在栈里的整数来运算,而是new了一个String的栈,然后运算的时候转换成整数,再把结果转回String,最后return的时候再转换成整数,不出意料的花了很多很多时间。

2024-01-20 11:57:02 329

原创 代码随想录算法训练营第十天|232、225

一上来自己想到了用两个栈交替加入元素,再交替取出/查找,写了半天最后才意识到完全没有实现队列的先进先出......题目本身不难,用一个队列实现的话只需要在每次查询时重新排列一下就可以达到栈的效果。看到题解上说一个栈进一个栈出,就有思路了。代码实现起来不难,需要注意只有。

2024-01-20 09:07:25 331

原创 代码随想录算法训练营第八天|字符串 344、541、卡码网54、151、卡码网55

traversed用来记录已经处理过多少元素以供后续处理尾巴,这个数字会忽略array的实际长度限制,只记录理论上下一步应该开始的位置(跳过k个元素之后的结束位置),所以如果传入后续处理尾巴的代码的traverse已经比右指针大了,则说明尾巴的元素数不足或者刚好够需要跳过的数量,则不对尾巴做任何处理。又练习了在ACM模式写题。题目的说明写的很烂,实际可以理解为:反转k个元素->跳过k个元素->反转k个元素->跳过k个元素... 如果跳过k个元素之后剩下的元素不足k个,则反转剩下的所有。

2024-01-18 14:15:02 356 1

原创 代码随想录算法训练营第七天|哈希表 454、383、15、18

关键点是要搞明白return true和false的分界点在哪里。一开始我写的是只要数组里有不等于0的数就return false,但这样忽略了magazine里特定字母数大于所需要的数量(这种情况下由于有冗余,特定字母的计数会是大于0的),正确的false条件是某所需字母的位置的数字小于0。但有个很关键的点就是计算有效结果数时是允许数值相同的元素的,也就是说哈希表中每一个符合条件的key出现的每一次(也就是value)都是有效的,在统计结果时要将所有key的value相加而不是每找到一个key就+1。

2024-01-17 15:06:22 524

原创 代码随想录算法训练营第六天|哈希表 242、349、202、1

首先是用value来统计元素出现的次数,然后再在遍历的过程中找哈希表中有没有 target - nums[i] 的结果,但这样就无法记录题目所需要的元素的下标。是之前做过的一道题,记得用字母的ascii码来计算在数据结构里的位置然后记录出现次数的做法,但是具体的实现有点忘了。又思考了15分钟无解,遂看题解:原来是通过用两个set,第一个存放数组1的元素,第二个存放用set1和数组2比较后两边都有的元素,形成一个result set,最后建立一个新数组来return result set里的元素。

2024-01-16 10:34:02 357

原创 代码随想录算法训练营第四天|链表 24、19、160、142

这个位置不一定是环的起点。假设链表的头部到环的入口点的距离为a,环的入口点到fast和slow相遇的点的距离为b,相遇点到环的入口点的距离为c。看到之后想到了用双指针来做,但是具体的细节忘了,查了一下后发现之前是用a和b遍历两个链表,当一方先遍历完后去遍历另一个链表,这样在双方都交换过至少一次之后双指针就会同步从而在接下来的遍历中找到相交点。正确的做法是:current站在前一个结点操作后面两个节点,temp节点跟在current后面辅助操作,temp1要去到需要操作的节点的后面一个节点来保存剩下的链表。

2024-01-15 11:48:21 500

原创 代码随想录算法训练营第三天|链表 203、707、206

对递归的基础掌握还是比较欠缺,看完视频题解之后大致理解并且能跟着双指针的思路写出来。这次第一眼看到想到了用current和previous两个dummy来操作,但是实际上还需要一个。来记录剩下的链表,如果不这么做的话在第一次反转之后就会丢失剩下的链表。也是之前做过的一道题,但是也忘光了。

2024-01-14 08:42:02 286 1

原创 代码随想录算法训练营第一天 | 704、27

作为 if 的判断条件。这就导致更新slow指针变得非常麻烦,而且还需要一个额外的 if 来判断是否让fast赋值给slow。这次想思路的时候大致是:快慢指针一起遍历,遇到目标值时慢指针停下,快指针继续遍历到下一个非目标值并替换。在执行的时候,我用了。看了一圈网上用Java写的取中点公式,发现都没有处理这个问题,于是又花了很多时间研究。半年前做过几道快慢指针的题,但这次重新看的时候感觉当时没有抓住精髓。看到题的第一反应是:如果数组里有偶数个元素,中点怎么算?

2024-01-11 12:17:41 324

空空如也

空空如也

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

TA关注的人

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