- 博客(23)
- 收藏
- 关注
原创 牛客Top101 8/25
如果是线型递归,子问题直接回到父问题不需要回溯,但是如果是树型递归,父问题有很多分支,我需要从子问题回到父问题,进入另一个子问题。因此回溯是指在递归过程中,从某一分支的子问题回到父问题进入父问题的另一子问题分支,因为有时候进入第一个子问题的时候修改过一些变量,因此回溯的时候会要求改回父问题时的样子才能进入第二子问题分支。但是这样递归不能保证括号一定合法,我们需要保证左括号出现的次数比右括号多时我们再使用右括号就一定能保证括号合法了,因此每次需要检查左括号和右括号的使用次数。
2023-08-25 08:31:20 82
原创 牛客Top101 8/24
矩阵中多处聚集着1,要想统计1聚集的堆数而不重复统计,那我们可以考虑每次找到一堆相邻的1,就将其全部改成0,而将所有相邻的1改成0的步骤又可以使用深度优先搜索(dfs):当我们遇到矩阵的某个元素为1时,首先将其置为了0,然后查看与它相邻的上下左右四个方向,如果这四个方向任意相邻元素为1,则进入该元素,进入该元素之后我们发现又回到了刚刚的子问题,又是把这一片相邻区域的1全部置为0,因此可以用递归实现。都是求元素的全排列,字符串与数组没有区别,一个是数字全排列,一个是字符全排列,因此大致思路与。
2023-08-24 08:36:27 84
原创 牛客Top101 8/22
处理优先级问题,那必定是乘号有着优先运算的权利,加号减号先一边看,我们甚至可以把减号看成加一个数的相反数,则这里只有乘法和加法,那我们优先处理乘法,遇到乘法,把前一个数和后一个数乘起来,遇到加法就把这些数字都暂时存起来,最后乘法处理完了,就剩余加法,把之前存起来的数字都相加就好了。本题需要使用快速排序的思想,快速排序:每次移动,可以找到一个标杆元素,然后将大于它的移到左边,小于它的移到右边,由此整个数组划分成为两部分,然后分别对左边和右边使用同样的方法进行排序,不断划分左右子段,直到整个数组有序。
2023-08-22 08:49:01 100
原创 牛客Top101第十三天
元素入栈指的是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;我们可以发现,数字1是根节点,并将二叉树分成了(247)和(3568)两棵子树,而子树的的根也是相应前序序列的首位,比如左子树的根是数字2,右子树的根是数字3,这样我们就可以利用前序遍历序列找子树的根节点,利用中序遍历序列区分每个子树的节点数。如输入[1,2,4,5,3],[4,2,5,1,3]时,通过前序遍历的结果[1,2,4,5,3]和中序遍历的结果[4,2,5,1,3]可重建出以下二叉树:所以对应的输出为[1,3,5]。
2023-08-18 08:26:43 68 1
原创 牛客Top101第十二天
我们也可以利用二叉搜索树的性质:对于某一个节点若是p与q都小于等于这个这个节点值,说明p、q都在这个节点的左子树,而最近的公共祖先也一定在这个节点的左子树;而若是对于某个节点,p与q的值一个大于等于节点值,一个小于等于节点值,说明它们分布在该节点的两边,而这个节点就是最近的公共祖先,因此从上到下的其他祖先都将这个两个节点放到同一子树,只有最近公共祖先会将它们放入不同的子树,每次进入一个子树又回到刚刚的问题,因此可以使用递归。直接得到从根节点到两个目标节点的路径,这样我们利用路径比较就可以找到最近公共祖先。
2023-08-17 08:48:10 50 1
原创 牛客Top101第十一天
上述一个函数算深度,一个函数遍历所有节点的方法,用了两个递归,做了很多不必要的运算,这就是自顶向下的弊端。那我们可以考虑自底向上,因为其实我们判断某个节点是否符合平衡二叉树特性的时候,需要的不是左右子树的完整深度,而是深度差,只要深度差绝对值不超过1,就可以满足。因为我们需要将二叉树镜像,意味着每个左右子树都会交换位置,如果我们从上到下对遍历到的节点交换位置,但是它们后面的节点无法跟着他们一起被交换,因此我们可以考虑自底向上对每两个相对位置的节点交换位置,这样往上各个子树也会被交换位置。
2023-08-16 08:50:49 46 1
原创 牛客Top101第十天
前序遍历的时候我们采用的是“根左右”的遍历次序,如果这棵二叉树是对称的,即相应的左右节点交换位置完全没有问题,那我们是不是可以尝试“根右左”遍历,按照轴对称图像的性质,这两种次序的遍历结果应该是一样的。二叉搜索树是一种特殊的二叉树,它的每个节点值大于它的左子节点,且大于全部左子树的节点值,小于它右子节点,且小于全部右子树的节点值。而二叉树的递归,则是将某个节点的左子树、右子树看成一颗完整的树,那么对于子树的访问或者操作就是对于原树的访问或者操作的子问题,因此可以自我调用函数不断进入子树。
2023-08-15 08:48:51 45 1
原创 牛客Top101第九天
不过,当右边被访问了,又回到了根,我们的根怎么知道右边被访问了呢?用一个前序指针pre标记一下,每个根节点只对它的右节点需要标记,而每个右节点自己本身就是一个根节点,因此每次访问根节点的时候,我们可以用pre标记为该节点,回到上一个根节点时,检查一下,如果pre确实是它的右子节点,哦那正好,刚刚已经访问过了,我现在可以安心访问这个根了。从上述前序遍历的解释中我们不难发现,它存在递归的子问题:每次访问一个节点之后,它的左子树是一个要前序遍历的子问题,它的右子树同样是一个要前序遍历的子问题。
2023-08-14 08:27:55 38
原创 牛客Top101第八天
双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指针(特殊情况甚至可以多个),两个指针或是同方向访问两个链表、或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针),从而达到我们需要的目的。例如,"1.1"的版本号小于"1.1.1"。因为"1.1"的版本号相当于"1.1.0",第3位修订号的下标为0,小于1。版本号是由修订号组成,修订号与修订号之间由一个"."连接。修订号从左到右编号,下标从0开始,最左边的修订号下标为0,下一个修订号下标为1,以此类推。
2023-08-12 19:47:41 47 1
原创 牛客Top101第六天
分治即“分而治之”,“分”指的是将一个大而复杂的问题划分成多个性质相同但是规模更小的子问题,子问题继续按照这样划分,直到问题可以被轻易解决;“治”指的是将子问题单独进行处理。分治即“分而治之”,“分”指的是将一个大而复杂的问题划分成多个性质相同但是规模更小的子问题,子问题继续按照这样划分,直到问题可以被轻易解决;“治”指的是将子问题单独进行处理。这里我们也可以用相同的方法划分,划分之后相邻一个元素的子数组就可以根据大小统计逆序对,而不断往上合并的时候,因为已经排好序了,我们逆序对可以往上累计。
2023-08-11 08:42:17 57 1
原创 牛客Top101第五天
1.不是什么题都需要dummy虚拟结点,虚拟节点的用处是为了避免头节点的特殊处理,因此应判断该题是否需要头节点的特殊处理才决定是否dummy,牛客代码简洁明了。
2023-08-10 08:43:18 43 1
原创 牛客Top101第四天
1.分治法的思想非常好,结合递归使用。1.第二种方法很妙,注意并不需要新建链表,而是可以直接遍历修改链表元素即可。1.栈这个数据结构要合理使用。
2023-08-09 08:43:26 48 1
原创 牛客Top101第三天
知识点:双指针双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指针(特殊情况甚至可以多个),两个指针或是同方向访问两个链表、或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针),从而达到我们需要的目的。我们无法逆序遍历链表,就很难得到链表的倒数第�k个元素,那我们可以试试反过来考虑,如果当前我们处于倒数第�k的位置上,即距离链表尾的距离是�k,那我们假设双指针指向这两个位置,二者同步向前移动,当前面个指针到了链表头的时候,两个指针之间的距离还是�k。
2023-08-08 08:46:12 459
原创 牛客Top101第二天
为了快速比较�k个数字得到最小值,我们可以利用Java提供的PriorityQueue或者C++SLT提供的优先队列或者Python提供的PriorityQueue可以实现,它是一种参照堆排序的容器,容器中的元素是有序的,如果是小顶堆,顶部元素就是最小的,每次可以直接取出最小的元素。对子问题继续划分,直到子问题只有1个元素。还原的时候呢,将每个子问题和它相邻的另一个子问题利用上述双指针的方式,1个与1个合并成2个,2个与2个合并成4个,因为这每个单独的子问题合并好的都是有序的,直到合并成原本长度的数组。
2023-08-07 08:37:59 36
原创 牛客101 第一天
1.使用头插法,和 制造哨兵伪节点讨论。2.链表模拟过程,有时候会直接变成一个圈。3.注意temp->next = pre->next 而不是cur。
2023-08-05 10:38:30 41 1
原创 暑期力扣第十七天
1.要回顾一下动态规划的用法,总结一下所有算法,不要做一个专题只想一种方法。2.二分查找的方式很妙,不再是以坐标为基准,而是以最大元素到和取mid验证。3.做题时可以考虑封装函数结合使用。1.注意这种解法,二分查找验证这个数行不行 n×logn。
2023-08-04 08:44:37 38 1
原创 暑期力扣第十六天
上述三种解法,第一种没有利用矩阵的性质,所以时间复杂度最差;第二种解法只利用了一部分性质(每一行是一个有序数列,而忽视了列之间的关系);第三种解法则利用了全部性质,所以时间复杂度最佳。这也启示我们要认真把握题目中的条件与性质,更有利于我们解题。
2023-08-03 08:47:37 47
原创 暑期力扣第十五天
1.对于这种情况,将当前二分区间的左边界加一,右边界减一,然后在新区间上继续二分查找。2.注意再需要缩小区间或无法判断,尤其是出现重复元素时,考虑这++--策略.1.两种方法殊途同归,都利用了二分查找,在二维矩阵上寻找目标值。值得注意的是,若二维数组中的一维数组的元素个数不一,方法二将会失效,而方法一则能正确处理。2.注意lambda表达式、库函数binary_search、upper_bound函数的运用(在知晓原理可省时间)。3.二维数组的定位 / 和 %。
2023-08-02 08:52:09 94
原创 暑期力扣第十四天
循环条件是leftright?我们可以假设left=right,此时mid=left=right。假设条件为false,执行right=mid-1。此时right=mid-1,而left=mid,left>right。也就是说,只有当left=right的时候才有可能出现left>right (因为执行的可能是left=mid)。而left=right时早已终止循环了。所以不可能出现left>right的情况。
2023-08-01 08:48:58 53 1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人