
leetcode
文章平均质量分 79
Kl_WJ
菜鸡本鸡
展开
-
LeetCode刷题day29||491.递增子序列&&46.全排列&&47.全排列 II--回溯
因为排列问题,每次都要从头开始搜索,例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。首先排列是有序的,也就是说 [1,2] 和 [2,1] 是两个集合,这和之前分析的子集以及组合所不同的地方。而used数组,其实就是记录此时path里都有哪些元素使用了,一个排列里一个元素只能使用一次。还要强调的是去重一定要对元素进行排序,这样我们才方便通过相邻的节点来判断是否重复使用了。原创 2022-11-08 22:48:46 · 284 阅读 · 1 评论 -
LeetCode刷题day28||93. 复原 IP 地址&&78.子集&&90.子集II--回溯
如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点。从图中可以看出,同一树层上重复取2 就要过滤掉,同一树枝上就可以重复取2,因为同一树枝上元素的集合才是唯一子集。其实子集也是一种组合问题,因为它的集合是无序的,子集{1,2} 和 子集{2,1}是一样的。这道题目和78.子集 区别就是集合里有重复元素了,而且求取的子集要去重。原创 2022-11-07 21:51:30 · 284 阅读 · 0 评论 -
LeetCode刷题day27||39. 组合总和&&40.组合总和II&&131.分割回文串--回溯
上面的代码还存在一定的优化空间, 在于如何更高效的计算一个子字符串是否是回文字串。大家如果熟悉动态规划这种算法的话, 我们可以高效地事先一次性计算出, 针对一个字符串s, 它的任何子串是否是回文字串, 然后在我们的回溯函数中直接查询即可, 省去了双指针移动判定这一步骤.对于sum已经大于target的情况,其实是依然进入了下一层递归,只是下一层递归结束判断的时候,会判断sum > target的话就返回。所以我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重。原创 2022-11-01 22:39:05 · 373 阅读 · 0 评论 -
LeetCode刷题day25||216.组合总和III&&17.电话号码的字母组合--回溯
图中可以看出遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”]。,无非就是多了一个限制,本题是要找到和为n的k个数的组合,而整个集合已经是固定的了[1,…图中,可以看出,只有最后取到集合(1,3)和为4 符合条件。原创 2022-10-31 22:03:52 · 455 阅读 · 0 评论 -
LeetCode刷题day24||回溯算法理论基础&&77. 组合--回溯
大家可以从图中看出for循环可以理解是横向遍历,backtracking(递归)就是纵向遍历,这样就把这棵树全遍历完了,一般来说,搜索叶子节点就是找的其中一个结果了。树中就可以看出,一般来说搜到叶子节点了,也就找到了满足条件的一条答案,把这个答案存放起来,并结束本层递归。回溯法并不是什么高效的算法——因为回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案。回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。回溯是递归的副产品,只要有递归就会有回溯。所以回溯也有要终止条件。原创 2022-10-30 11:29:07 · 922 阅读 · 0 评论 -
LeetCode刷题day23||669. 修剪二叉搜索树&&108.将有序数组转换为二叉搜索树&&538.把二叉搜索树转换为累加树--二叉树
一棵二叉搜索树,换一个角度来看,这就是一个有序数组[2, 5, 13],求从后到前的累加数组,也就是[20, 18, 13]因为是要遍历整棵树,做修改,其实不需要返回值也可以,我们也可以完成修剪(其实就是从二叉树中移除节点)的操作。如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点。如果root(当前节点)的元素大于high的,那么应该递归左子树,并返回左子树符合条件的头结点。但是有返回值,更方便,可以通过递归函数的返回值来移除节点。大于high的情况类比。原创 2022-10-27 22:23:33 · 788 阅读 · 0 评论 -
LeetCode刷题day22||235. 二叉搜索树的最近公共祖先&&701.二叉搜索树中的插入操作&&450.删除二叉搜索树中的节点--二叉树
本题是二叉搜索树,二叉搜索树是有序的,那得好好利用一下这个特点。只要按照二叉搜索树的规则去遍历,遇到空节点就插入节点就可以了。中则一定可以说明该节点cur就是q 和 p的公共祖先。只要从上到下去遍历,遇到。原创 2022-10-27 09:53:20 · 272 阅读 · 0 评论 -
LeetCode刷题day21||530.二叉搜索树的最小绝对差&&501.二叉搜索树中的众数&&236. 二叉树的最近公共祖先--二叉树
如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。情况一 和 情况二 代码实现过程都是一样的,也可以说,实现情况一的逻辑,顺便包含了情况二。因为遇到 q 或者 p 就返回,这样也包含了 q 或者 p 本省就是 公共祖先的情况。节点本身p(q),它拥有一个子孙节点q§。原创 2022-10-26 09:53:33 · 405 阅读 · 0 评论 -
LeetCode刷题day20||654.最大二叉树&&617.合并二叉树&&700.二叉搜索树中的搜索&&98.验证二叉搜索树--二叉树
参数就是传入的是存放元素的数组,返回该数组构造的二叉树的头结点,返回类型是指向节点的指针。样例中最小节点 可能是int的最小值,如果这样使用最小的int来比较也是不行的。构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。节点10大于左节点5,小于右节点15,但右子树里出现了一个6 这就不符合了。这就决定了,二叉搜索树,递归遍历和迭代遍历和普通二叉树都不一样。遍历一个树逻辑是一样的,只不过传入两个树的节点,同时操作。不能单纯的比较左节点小于中间节点。确定递归函数的参数和返回值。原创 2022-10-24 22:19:53 · 387 阅读 · 0 评论 -
LeetCode刷题day15||513.找树左下角的值&&112. 路径总和&&113. 路径总和&&106. 从中序与后序遍历序列构造二叉树&&105. 从前序与中序遍历序列构造二叉树--二叉树
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)路径总和ii要遍历整个树,找到所有路径,所以递归函数不要返回值。我们要找一条符合条件的路径,所以递归函数需要返回值,及时返回。第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点。如果使用递归法,其实就是深度最大的叶子节点一定是最后一行。第五步:切割后序数组,切成后序左数组和后序右数组。第一步:如果数组大小为零的话,说明是空节点了。原创 2022-10-20 10:59:13 · 178 阅读 · 0 评论 -
LeetCode刷题day14||110.平衡二叉树&&257. 二叉树的所有路径&&404. 左叶子之和--二叉树
注意在函数定义的时候void traversal(TreeNode* cur, string path, vector& result) ,定义的是string path,每次都是复制赋值,不用使用引用,否则就无法做到回溯的效果。那么在如上代码中,貌似没有看到回溯的逻辑,其实不然,回溯就隐藏在traversal(cur->left, path + “->”, result);每次函数调用完,path依然是没有加上"->" 的,这就是回溯了。从根节点到叶子的路径,所以需要前序遍历。节点高度,用后序遍历。原创 2022-10-18 21:14:02 · 340 阅读 · 0 评论 -
LeetCode刷题day13||104. 二叉树的最大深度&&559. N 叉树的最大深度&&111. 二叉树的最小深度&&222.完全二叉树的节点个数--二叉树
3.确定单层递归的逻辑:先求它的左子树的深度,再求的右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度。确定单层递归的逻辑:先求它的左子树的节点数量,再求的右子树的节点数量,最后取总和再加一 (加1是因为算上当前中间节点)就是目前节点为根节点的节点数量。1.确定递归函数的参数和返回值:参数就是传入树的根节点,返回就返回这棵树的深度,所以返回值为int类型。,所以本题中我们通过后序求的根节点高度来求的二叉树最大深度。原创 2022-10-17 22:03:21 · 159 阅读 · 0 评论 -
LeetCode刷题day12||二叉树层序遍历&&226.翻转二叉树&&101. 对称二叉树--二叉树
对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了其实我们要比较的是两个树(这两个树是根节点的左右子树),所以在递归遍历的过程中,也是要同时遍历两棵树。这个迭代法,其实是把左右两个子树要比较的元素顺序放进一个容器,然后成对成对的取出来进行比较,那么其实使用栈也是可以的。这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不方便,因为中序遍历会把某些节点的左右孩子翻转了两次!队列先进先出,符合一层一层遍历的逻辑,而是用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。原创 2022-10-15 16:18:20 · 272 阅读 · 0 评论 -
LeetCode刷题day11||二叉树基础理论&&二叉树的递归遍历&&二叉树的迭代遍历--二叉树
链式存储的二叉树节点的定义方式。int val;} };原创 2022-10-13 21:12:39 · 206 阅读 · 0 评论 -
LeetCode刷题day10||150. 逆波兰表达式求值&&239. 滑动窗口最大值&&347.前 K 个高频元素--栈与队列
大顶堆(堆头是最大元素),小顶堆(堆头是最小元素),如果懒得自己实现的话,就直接用priority_queue(优先级队列)就可以了,底层实现都是一样的,从小到大排就是小顶堆,从大到小排就是大顶堆。需要一个队列,这个队列呢,放进去窗口里的元素,然后随着窗口的移动,队列也一进一出,每次移动之后,队列告诉我们里面的最大值是什么。小顶堆,因为要统计最大前k个元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前k个最大元素。deque是可以两边扩展的,而且deque里元素并不是严格的连续分布的。原创 2022-10-11 22:45:15 · 217 阅读 · 0 评论 -
LeetCode刷题day09||232.用栈实现队列&&225. 用队列实现栈&&20. 有效的括号&&1047. 删除字符串中的所有相邻重复项--栈与队列
两个stack,stack1存数据,之后压入另一个stack2。实现queue先进先出功能。原创 2022-10-10 22:10:15 · 338 阅读 · 0 评论 -
LeetCode刷题day08||459.重复的子字符串--字符串
步骤一:因为 这是相等的前缀和后缀,t[0] 与 k[0]相同, t[1] 与 k[1]相同,所以 s[0] 一定和 s[2]相同,s[1] 一定和 s[3]相同,即:,s[0]s[1]与s[2]s[3]相同。步骤三: 因为 这是相等的前缀和后缀,t[2] 与 k[2]相同 ,t[3]与k[3] 相同,所以,s[2]一定和s[4]相同,s[3]一定和s[5]相同,即:s[2]s[3] 与 s[4]s[5]相同。next 数组记录的就是最长相同前后缀,next[len - 1]!数组长度为:len。原创 2022-10-05 22:21:36 · 141 阅读 · 0 评论 -
LeetCode刷题day07||28. 找出字符串中第一个匹配项的下标--字符串
因为找到了最长相等的前缀和后缀,匹配失败的位置是后缀子串的后面,那么我们找到与其相同的前缀的后面从新匹配就可以了。下标5之前这部分的字符串(也就是字符串aabaa)的最长相等的前缀 和 后缀字符串是 子字符串aa。KMP算法:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。构造next数组其实就是计算模式串s,前缀表的过程。子串aaba,最长相同前后缀的长度为1。子串aa,最长相同前后缀的长度为1。子串a,最长相同前后缀的长度为0。使用next数组做匹配。原创 2022-10-05 08:48:51 · 301 阅读 · 0 评论 -
LeetCode刷题day06||344. 反转字符串&&541. 反转字符串II&&剑指Offer 05.替换空格&&151.翻转字符串里的单词&&剑指Offer58-II.左旋转字符串--字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素向后移动。然后从后向前替换空格,也就是双指针法,i指向新长度的末尾,j指向旧长度的末尾。因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。原创 2022-09-28 22:53:42 · 619 阅读 · 0 评论 -
LeetCode刷题day05||454. 四数相加 II&&383. 赎金信&&15. 三数之和&&18. 四数之和--哈希表
四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值,依然是循环内有left和right下标作为双指针,找出nums[k] + nums[i] + nums[left] + nums[right] == target的情况,三数之和的时间复杂度是O(n^2)。四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑有重复的四个元素相加等于0的情况。target不是确定的数,比如三数之和的0,这是需要改变剪枝逻辑。原创 2022-09-28 10:33:03 · 218 阅读 · 0 评论 -
LeetCode刷题day04||242. 有效的字母异位词&&349. 两个数组的交集&&202. 快乐数&&1. 两数之和--哈希表
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。原创 2022-09-27 08:13:08 · 203 阅读 · 0 评论 -
LeetCode刷题day03||24. 两两交换链表中的节点&&19. 删除链表的倒数第 N 个结点&&160.链表相交&&142.环形链表II--链表
求出两个链表的长度,并求出两个链表长度的差值,然后让两链表末尾对齐。删除节点的关键是找到其。同:160.链表相交。原创 2022-09-25 15:02:08 · 168 阅读 · 0 评论 -
LeetCode刷题day02||203.移除链表元素&&707.设计链表&&206.反转链表--链表
将头结点向后移动一位就可以,这样就从链表中移除了一个头结点。注释 – 单向链表的定义。分为单链表和双链表方式。原创 2022-09-24 16:21:25 · 238 阅读 · 0 评论 -
LeetCode刷题day01||长度最小的子数组&&水果成篮&&螺旋矩阵 II-数组
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。类似双指针的窗口滑动,难点在于存储每棵树窗口的大小不是单纯和数组下标有关,而是数组的值有关(也就是果树的种类),考虑一一映射关系(输入:s = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。双指针滑动,双指针,[left,right]满足条件后,left右移动,right继续遍历,窗口往前滑动。原创 2022-09-23 15:49:03 · 88 阅读 · 0 评论