自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 代码随想录day24|复原IP地址,子集,子集II

因为是子集问题,所以[2,1],[1,2]是重复的,所以i要等于starIndex(排列问题才会从0开始选取startIndex之前的元素)往后选取不能选取之前的元素. 这题有点不一样,是要把遍历过程所有结果添加入子集,所以path.add的位置会发生变化。这里其实和分割回文串的思路是一样的,也是找不同的切割方式.不一样的地方就在于这里是判断是否是有效的IP地址并且有切割次数的限制。和之前的组合II题目一样,要取重复元素的最大集合,所以得从第一个重复元素开始从前往后递归搜集结果集,后面相同的元素就都跳过。

2023-12-07 05:00:40 425

原创 代码随想录day23| 组合总和,组合总和II,分割回文子串

/ 这里最外层的for就是找以不同i结尾的切割规则作为结果集的第一个元素,从前往后寻找以不同切割规则为结果集开头的不同切割规则的组合. //比如以头一个元素为切割线,后面的不同切割线的组合情况.下一层就是以头两个元素为切割线,后面不同切割线的组合情况。//所以本题怎么理解去重很重要。这里要理解,相同的值是没关系的,但是不能以相同的值开头收集集合,相同的值开头收集到的数值一定是会存在重复的,因为后面相同的值为开头收集到的结果集一定是前面的子集.直接这么说很抽象,来看代码,会有详细注释。

2023-11-27 04:32:45 384

原创 代码随想录day22|组合III,字母组合

回溯的思路组合都差不多,主要是得理解和找到这个startIndex,index的界定和设定 前几题的循环都是在同一个连续集合进行循环遍历的,所以需要statIndex来指定下一层遍历的开始位。但这道题是不同的集合之间进行组合,所以需要index来指定遍历到哪一个集合了,指定的是下一层遍历的集合的位置。和day21的题目基本相似,把相关参数变换一下就能做出来.

2023-11-27 04:16:15 373

原创 代码随想录day21|回溯算法入门:组合

那么我们的开始位置其实就是i,然后往i+1的位置往后递归,当收集到k个时,加入结果集,递归函数结束。回弹到上一层时,需要把最后加入的数字弹出,然后进入这一层的下一个循环i++.这其实和二叉树有一道打印出所有路径的题目很像,dfs前序遍历,然后从叶子节点往上逐层弹出上一个加入的节点。其实所有的回溯算法和这个原理是一样的。这里收集到k个其实就是遍历到了叶子节点,所以往上弹出最后一个到K-1的状态。回溯算法其实就是暴力for循环,但是单纯for循环无法做到一些需要回溯的场景,今天做的就是这一道入门题 组合。

2023-11-23 21:37:51 354

原创 代码随想录19|二叉树中的插入操作,删除二叉搜索树中的节点,二叉树的最近公共祖先

/可以利用二叉搜索树的特性,在寻找目标节点p,q的过程中可以减少节点遍历。中序遍历,一定是升序无重复的 //所以只需要中序遍历两两比较再插入就可以.这种思路需要调整二叉树结构,尝试用过morris自己做不出来. //那么题目也允许另一种思路,在合适的null节点处插入节点,所以可以利用搜索二叉树的特性往下遍历到null节点,最后在这个null节点添加新节点就行。//我们可以找被删除节点的前驱节点,因为这个前驱节点是当前节点的左子树下最大的一个节点,我们就可以直接把右孩子放在这个节点的右节点上。

2023-11-22 07:24:58 23 1

原创 代码随想录day20 |修剪二叉搜索树,将有序数组转换为二叉搜索树,把二叉搜索树转换为累加树

还有一点就是删除节点的右子树或者左子树可能还会存在超出界限的节点,所以超出下界的节点还得往右子树递归,上界则往左子树.这里迭代法比较难思考出来,因为从上往下不是找被删除的界限节点,而是找到符合要求的根节点,从根节点往下修剪。反序 右中左遍历即可.因为二叉搜索树的中序遍历(左中右)是升序无重复,那么最右边是这颗树的最大值(搜索树),所以从后往前遍历累加即可.超出下界,删除这个节点的这节点的左子树,上界则是这个节点和这个节点的右子树.所以直接返回这个节点的另一颗树,就可以删除。把二叉搜索树转换为累加树。

2023-11-22 07:02:25 21 1

原创 代码随想路day18|二叉树中的众数,二叉搜索树的最小绝对差,二叉树的最近公共祖先,morris遍历

若有左树,则找到这个节点的前驱节点。就是左子节点的最右的一个节点。这个mostRight指针要遍历到这个前驱节点两次,第一次先把这个前驱节点的右指针从null指向cur,然后cur左移,继续重复遍历.第二次遍历到这个前驱节点,证明cur已经往上层返回了,把这个右指针再改回指向null.最后cur再右移动。//其实你列举下来就会发现,其实过程就是找到目标结点之后,往上返回路径,找到两条路径的相遇节点。//第二种情况是两个节点不在同一层,但在同一边的子树,那么最先遍历到的目标节点本身就是最近公共祖先.

2023-11-19 23:42:17 29 1

原创 代码随想录第17天|二叉搜索树中的搜索,验证二叉搜索树,合并二叉搜索树,最大二叉树

其实就是同时遍历两棵二叉树,将两个都不为空的节点值相加生成一颗新的节点,如果有一颗相同节点位置的树节点为空,另一棵不为空,那么就直接返回/指向另一颗不为空的树节点就行,因为空和不为空的节点值相加,其实就是不为空的节点本身.做一个优化,在递归迭代的过程中就可以去比较是不是单调递增的,因为中序遍历的过程种就可以比较. 做一个双指针优化,用一个指针指向上一个节点,这样中序遍历的过程中就可以比较;因为它本来就是二叉搜索树了,所以如果当前节点比目标值小,则往大的方向找,也就是往右子树找,反之则往左子树找.

2023-11-18 19:32:55 23 1

原创 代码随想录day16|树左下角,路径总和,从中后序遍历序列构造二叉树

可以注意到后序的最后一个节点一定是根节点,那么根据这个根节点,可以切出此时中序中根节点的左右子树,那么知道了根节点的左右子树, 这时,又可以根据中序数组中的左右子树的长度,再切割后序数组中的根节点的左右子树. 接着又可以根据这个根节点的左右子树的最后一个节点,知道下一层的左右节点分别是什么,然后再到中序数组中切割,再通过中序数组的信息反过来切割后序数组,以此往复递推。前中后序遍历都可以,通过找到最大深度的叶子节点获取它的值,所以需要两个全局变量,maxDepth记录最大深度和maxVlue记录最大值。

2023-11-16 02:15:19 25 1

原创 代码随想录15天|平衡二叉树,二叉树的所有路径,左叶子之和

下面的后序遍历第一种其实就告诉你答案,因为如果中节点先遍历,那么如果是目标节点就直接返回,这时候右子树就无法进入,如果右子树也存在叶子节点,就会导致少结果.那你会问左子树呢?在判断这个中节点是不是目标节点的时候会判断这个节点的左节点的左右节点是否为空,那么这个时候实际上就已经把左节点/左子树便利了。更详细地看代码注解.这里主要是要理解回溯的过程,就是每次找到到达根节点的路径之后,要往回返回的同时,记录的节点要往回弹出.那么这道题得用后序遍历,因为要先收集左右子树的深度,然后最后在中间节点做数据对比来返回.

2023-11-15 00:20:44 30 1

原创 代码随想录day14|二叉树最大最小深度,完全二叉树节点数量

状态:其实就是要熟悉各种遍历方式,前中后递归遍历,非递归和层序遍历。这里可以利用完全二叉树的特性。

2023-11-11 21:14:40 46 1

原创 代码随想录day13|层序遍历,对称二叉树,翻转二叉树

那这个次数就由未开始for循环的队列的size来记录 因为for循环开始后,会加入节点的下一层的左右孩子,队列的size会不断改变,所以要先先记录队列的size来保证循环次数正确。中序是左中右,试想一下,我们先把左子树的所有孩子交换后,我们这时候把根节点的左右孩子交换再去遍历右子树, 那这时候根节点的右子树就变成了之前的左子树,那右子树的孩子就没交换还是处理的左子树,之前处理的左子树的孩子也会交换回来。通过队列来实现,对于每个节点依次在队列后面加入它的左节点和右子节点.那么怎么知道当前层有多少个节点呢?

2023-11-09 23:06:52 43 1

原创 代码随想录|二叉树的遍历

状态:只会递归的遍历,迭代遍历要多重复思考。

2023-11-08 20:53:12 28 1

原创 代码随想录第十一天|leecode 239,347

用单调队列为最优解,用堆实现时间复杂度则为O(Nlogn)。我们始终要维护队列的头部元素始终是当前窗口的最大值,并且保持窗口内保持单调递减,比他小的元素可以直接从后面退掉。从后面退掉更容易实现。这个主要是要知道用堆来实现.那么可以改变优先队列中的对比器来用大顶堆或者小顶堆来实现。leecode 239 滑动窗口的最大值。Leecode 347 前k个高频元素。状态:比较难,主要理解思路。

2023-11-07 18:29:41 17

原创 代码随想录第十天| leecode 20,1047,150

思路:和找有效括号的思路是一样的,因为找有效括号有一部分逻辑也是相当于消除相邻的重复括号,所以这道题的代码会更精简。用栈是显而易见的,那么其实这里可以用一个字符串模拟栈的行为,这样就不用最后再通过栈里的元素来转换成字符串。做这道题之前有一些特性需要明白,括号是符合先进后出的原理的,也就是后进先出. 比如({[]}),先进入的(肯定是包含在最外面的,最后进入的左[括号一定是最先出现右括号的,所以是先进后出。遇到元素压入栈中,算术表达式就将栈的头两个元素拿出来计算再把计算完的值压入栈中。

2023-11-06 13:24:41 21

原创 代码随想录第九天|Leecode 232,leecode 225

核心思想就是在每个元素加入的时候就让他们以倒序的顺序在队列中存在. 因为队列有两端开口,可以在push处这么实现(stack就不行--上一题),更容易实现也少了两次边界条件的判断(pop+peek). 将最后一位之前的全部元素pop出来再重新加入队列的尾部。进行size-1次pop,下一个就是需要放在头部的元素(倒序)。核心思想就是将前一个栈的元素全部压入第二个栈中,这样就实现了元素倒序。状态:对stack,queue的实例化和方法不熟悉。要注意Queue是接口,有很多实现这个接口的类。

2023-11-03 20:20:48 17

原创 代码随想录day09|KMP

比如j-1的位置为1,那么意味着可以跳过一位字符来比较,所以当j指向下标1,那么其实就是需要被比较的字符的位置,0被跳过了。//所以这意味着我们把字符串的前几个字符移到尾部都是相同的,那么在这个基础上再看下一个匹不匹配,如果匹配就直接j+1,不匹配还需要再往j-1的位置递推。//所以当i,j位置的值不相同怎么办?//移动匹配 因为如果一个字符串s,是由一个子串s‘重复组成的话,那么这个主串的长度一定是s’的整数倍。// 当i,j位置的字符相同时,他们同时往后遍历,每相同一个,他们的相同前后缀长度也会加一。

2023-11-03 11:31:27 22

原创 代码随想录底第七天| leecode 344,541,122,151

第二种思路就是把这个过程分成三步:第一步先去除所有多余的空格,第二步就是翻转整个字符,第三步就是再对每一个单词进行翻转。这里和其实就和数组中移除元素题目的思想是一样的(移除空格),但是这里不能用相向指针,因为顺序不能打乱。但是对于c++来说,可以直接给字符串进行扩容,然后用双指针从后往前,能把空间复杂度降为O1,对于java来说,字符串不可变,所以用stringbuilder进行拼接。所以有第二中思路可以让它变为O1.但是对于java来说都是On,因为java中字符串不可变。LR122 路径加密。

2023-11-02 10:27:24 19

原创 代码随想录第六天|leecode 454,383,15,18

主要逻辑是先遍历前两个数组,然后将每一种组合的和都记录到hashmap中,然后再遍历后两组数组,也是将后两组数组的数据两两相加,然后算出需要找的值,也就是找需要什么数才能相加为0.在hashmap中找这个值,有则用count加上这个值出现的次数(也就是value),也就是当前的值能找到几种组合。看到三数之和,最先想到的是哈希法,但是这里边界条件很多,并且要求去重,所以哈希法并不合适很难实现,因为他要从数组前后去遍历,去重很复杂。其实和三数之和的思路是一样的,用双指针来解决。状态:第一次见还是没思路。

2023-11-01 11:06:36 414

原创 代码随想录第五天| leecode 242,349,202,1

那么用set的逻辑就是将第一个数组去重变为一个hashset,然后用第二个数组和这个hashset对比,如果有相同的数值,就将这个值加入到结果的resultHashset中,最后将这个resultHashset变成数组返回。那么用数组的逻辑就是分别遍历完两个数组之后,在他们对应的哈希数组中记录次数,最后对比这两个哈希数组,如果两个哈希数组相同索引位置的值都大于0,则加入结果集list,最后将结果集list变化为数组返回。因为这里我们在遍历每一个元素的时候,需要去寻找数组中之前是否存在过当前位置需要的数。

2023-10-31 13:19:25 28 1

原创 代码随想录第四天|leecode 24,19,02.07,142

相遇时: slow指针走过的节点数为: x + y fast指针走过的节点数:x + y + n(y + z), 化简后x = (n - 1) (y + z) + z. 这里也有个关键点,在慢指针进入圈的第一圈就一定会被快指针追上。因为快指针是慢指针移动速度的两倍,假设慢指针走满一圈,那这个时候快指针已经走了两圈。关键点是要弄明白(n+(leng-n))=((length-n)+n).所以让快指针先移动n步,然后再让快慢指针同时移动length-n的长度(就是让快指针遍历剩下长度的链表)。

2023-10-30 10:39:02 23

原创 代码随想录第三天|leecode203,707,206

但是一定要注意删除添加以及特殊条件判断的边界条件。不然可能导致一系列问题。相关注意事项在代码中标注。单链表和双链表的添加删除不同,一个遍历到目标地址的前一个,一个遍历到目标地址的当前。关键是要添加一个虚拟头节点,操作比较方便。因为是单向列表,如果头节点刚好是删除的元素的话,就没办法操作了,所以要新建一个虚拟头节点来指向头节点。状态:逻辑不算难,基本都能自己写一次过。Leecode 206 翻转链表。Leecode707 设计链表。双指针思想很容易做出来。

2023-10-28 00:01:23 48

原创 代码随想录算法训练营第二天 | leecode977,209,59

因为当n为奇数的时候,因为右开的原则,如果直接用count<n^2来判断,在最后一轮,剩下的一格会处于四条边的开规则里面。这个i作为窗口终点往后移动,当满足大于目标值的集合时才停下,然后慢慢移动前面的指标来缩小窗口,找到当前终点位置的最小窗口,然后再重新往后移动直到终点位置到达数组尾部。这道题的思路主要是在这个非递减递减顺序排序的数组中,负数的平方值是递减的,而非负数的平方值是递增的,所以平方的大小从两端往中间是递减的。这道题主要是找到循环不变量,每一条边的规则都要是一样的,遵循左闭右开或者左闭右闭。

2023-10-26 19:51:50 230

原创 代码随想录算法训练营第一天| 704. 二分查找、35插入.69x的平方根.|27. 移除元素

因为当start和end相等的时候,while循环就应该结束了,然后这个目标数就是start或者end了,因为每个数都有它的平方根,和数组的情况不一样。然后这里的中间位置变量mid要向上取值,因为start没有加一,当只剩下两个数时,(end-start)/2会永远是0,那么start和mid就会永远相同,区间不会再缩小,会陷入死循环,所以mid要向上取整。对于leecode69 x的平方根这一题,我是看题解才明白内部用二分法的逻辑的,这里也要主意中间位置的取值以及while的条件。

2023-10-25 22:12:57 329

空空如也

空空如也

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

TA关注的人

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