![](https://img-blog.csdnimg.cn/20201014180756928.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
树
abant2
世界上最菜的arcem
展开
-
leetcode 2196 非拓扑排序建树
此题乍一看很像拓扑排序,但仔细想一想,就算用拓扑排序排好了,建树按那个顺序是建不起来的。细想,这题其实挺简单的,因为你只需要每次连一条边,用map存节点即可。唯一问题就是根节点怎么找,由于是连通图,只需要看看谁没有爸爸即可,我们存起来所有有爸爸的,剩下的就是根节点。class Solution {public: TreeNode* createBinaryTree(vector<vector<int>>& descriptions) { uno.原创 2022-03-12 16:07:03 · 123 阅读 · 0 评论 -
leetcode 297 二叉树的序列化和反序列化
此题虽然标注是困难,但还是不难的一个题。首先要想如何表示节点而不引起歧义,这里的做法是用括号括住每个节点的数值。然后就是正常的bfs编码解码即可。解码时可以先去掉括号,然后处理很简单。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), lef.原创 2021-09-15 11:03:30 · 72 阅读 · 0 评论 -
leetcode 538 累加二叉树计算
这个题的难点在于遍历顺序,要采取右,中,左的遍历,遍历过程中不断累加节点数值即可。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : v.原创 2021-08-02 18:44:02 · 100 阅读 · 0 评论 -
leetcode 105 前中序遍历构造二叉树
此题是剑指offer第7题前中序构造,需要用子数组。如果直接用下标的话,很容易出bug。但这里尝试了只用下标的,细节较多,要分清楚两个数组的开始和结束位置。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(.原创 2021-07-25 15:05:45 · 39 阅读 · 0 评论 -
二叉树的迭代遍历
二叉树的迭代遍历其实蛮简单的,核心就是栈。中序和后序遍历,需要考虑根节点是否看过,需要在栈中存pair,判断是否遍历过。对于前序遍历则不需要。三种遍历方式代码都蛮像的。前序:class Solution {public: vector<int> preorderTraversal(TreeNode* root) { stack<TreeNode*> s; vector<int> ans; if(!root)r原创 2021-07-24 20:47:46 · 77 阅读 · 0 评论 -
leetcode 437 树形前缀和,区间和问题
此题和leetcode 560题极为相似,只不过那个题是线性的,这个是树形的,加了一个回溯。此题就是考虑前缀和历史,每个前缀和都记录下来。如果差值出现,就可以记录总和。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), .原创 2021-07-22 23:45:31 · 100 阅读 · 0 评论 -
leetcode 98 验证二叉搜索树
解法一:前序遍历 树形dp前序遍历是最常见的遍历方式,此处也是可以使用的。我们每次记录左子树和右子树的最大值和最小值。返回后,我们只需判断左子树和最大值是否小于中间值,或右子树的最小值是否大于最小值即可。typedef long long ll;class Solution {typedef vector<ll> V;public: V dfs(TreeNode *n) { if(!n)return V{1, (ll)INT_MAX+1, (ll)I.原创 2021-07-22 20:55:00 · 46 阅读 · 0 评论 -
leetcode 421 字典树找最大异或值
class Solution {struct node{ int end = 0; node *next[2];};struct Trie{ node *start = new node(); void insert(int num) { node *curr = start; for(int i=30;i>=0;i--) { int nxt = num >= (1&l原创 2021-07-18 13:26:13 · 70 阅读 · 0 评论 -
leetcode 310 最小高度树
这个题是一个看着就没法做的题,但是用拓扑排序(bfs)可以很好的解决。如果直接从题目角度考虑,每个当根做一遍dfs,那百分百超时的。此题的做法是比较难想的,就是从外层节点往里走,走到最中心就是了。具体做法和拓扑排序很相似:记录度数组,每次取出度为1的节点,最后一批度为1的节点就是我们要找的根。class Solution {typedef pair<int, int> P;public: vector<int> findMinHeightTrees(int n, .原创 2021-07-17 15:40:40 · 59 阅读 · 0 评论 -
leetcode 543 二叉树的直径
最长两个节点的路径一定会路过一个根节点加上他的子树,所以一遍dfs即可。每个点返回高度,根据返回的高度算当前节点最大值,更新全局最大值即可。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) .原创 2021-07-16 22:45:18 · 47 阅读 · 0 评论 -
leetcode 617 合并二叉树
此题是一个比较巧妙的题,如果两边又一边为空,合并的就是另一边,这个是基本原理。代码如下,默认root1是要返回的,将root1的left和right都重置成最好的返回即可。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr),原创 2021-06-26 17:35:20 · 42 阅读 · 1 评论 -
leetcode 101 对称二叉树 bfs+dfs
解法一:递归法每次按相反顺序插入细节:用!判断是否为空指针。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), lef原创 2021-06-26 16:31:53 · 65 阅读 · 0 评论 -
leetcode 104 二叉树的最大深度
正常的做法是dfs,一个一个遍历/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode() : val(0), left(nullptr), right(nullptr) {} * TreeNode(int x) : val(x), left(nullptr), righ原创 2021-06-26 16:57:58 · 49 阅读 · 0 评论 -
LCP 34 二叉树染色 树形dp
此题和打家劫舍问题有一点相似,但还是差的挺多的。主要是dp状态的定义,是以当前节点结尾的相连i个元素的最大可能值。更新时,如果不涂节点,返回两边最大值的和,如果涂的话,用两边的可能性组合进行更新,比打家劫舍还是要难的。/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int原创 2021-05-19 19:20:58 · 92 阅读 · 0 评论 -
leetcode 337 打家劫舍3 树形dp入门
经典的选或者不选问题。这个问题应该是自底向上的一个过程,因为我们最终只看根节点状态就可以知道结果,而不用统计所有底部信息,是较为方便的。之后我们考虑dp数组怎么存,一种使用树形数组存,另外就是dfs过程中存。对于这个题,dfs是一种很方便的方式,前序遍历就很方便,左右处理完后,中间看两边取或者不取的状态的最优值,这个和普通的打家劫舍定义不太一样。普通的一个数就记录了,这边要两个数,还是比较有趣的,也不用看上一个,思想相当于后序遍历。/** * Definition for a binary tree原创 2021-05-19 18:26:21 · 164 阅读 · 0 评论 -
线段树
实现三个功能:1 add:在l到r区间所有数加一个数2 update:在l到r区间所有数更新成一个相同的数3 query:得到l到r区间的和一般add和update不会同时做,一般一次只需要一个功能。思路:可以利用二分划分区间,类似多重背包,任何一个数,利用二进制,可以在logn找到它。线段树也是一样,利用二分可实现快速查找。上图是一个满二叉树,需要2n-1个空间。但如果你的数组长度不是2的指数,其实是无法构成一颗满二叉树的。可能需要补几个元素,让他们为0.满二叉树:一直一样的范围会分到底,原创 2021-05-03 16:53:59 · 77 阅读 · 0 评论 -
leetcode 493 满足大小关系的对 分治
注:此题与327题很相似。解法一:分治直接考虑,如果是两个有序数组,O(N)能不能做,用单指针明显可以,同327题。故直接分治解决。typedef long long ll;class Solution {public: void msort(vector<int>& nums, int& sum, int l, int r) { if(l == r)return; int mid = l + (r-l)/2;原创 2021-04-15 12:22:11 · 77 阅读 · 0 评论 -
leetcode 327 特殊分治 双指针 线段树
解法一:分治 O(NlogN)这个题用分治做其实很难想。对于求区间和问题,前缀数组很有用。但这个题要求所有区间范围,如果枚举需要O(N2)O(N^2)O(N2),其实也可以接受。用分治的话,其实就是想明白了一件事,只要确保i < j,i,j在哪个位置其实是不影响结果的,因为我们只需要求区间个数。这就很好办了,分治就是划分,然后处理两个有序数组。利用分治可以很容易得到所有上述数组,用O(N)时间计算区间个数+合并即可。在计算区间个数时,可以用到双指针。对第二个有序数组,咱们可以用双指针确定它的最小原创 2021-04-14 20:58:30 · 104 阅读 · 0 评论 -
leetcode 208 pbds 字典树
此题暂时用了pbds实现字典树,非常方便。但是速度比自己实现的要慢一些。将来手打是应该学会的,但那是后面的事情了。#include<ext/pb_ds/assoc_container.hpp>#include<ext/pb_ds/trie_policy.hpp>using namespace __gnu_pbds;class Trie {private: trie<string, null_type, trie_string_access_traits&l原创 2021-04-14 15:01:28 · 288 阅读 · 0 评论 -
leetcode 1825 pbds维护中间数组
直接暴力走就完事了,每次求平均数O(k),基本也就是无敌吧。#include <ext/pb_ds/assoc_container.hpp>#include <ext/pb_ds/tree_policy.hpp>using namespace __gnu_pbds;typedef pair<int, int> P;typedef long long ll;class MKAverage {tree<P, null_type, less<P>原创 2021-04-12 14:51:53 · 332 阅读 · 0 评论 -
leetcode 480 滑动窗口维护中位数
这个题是很有趣的一个题,目标是维护中位数,所以需要两个堆的数据结构。最大堆存较小的那部分,最小堆存较大的那部分,堆顶的就是中位数。这里有一个难点就是什么时候prune,以及什么时候维持平衡。重点是一定要始终让一个堆最大,否则prune会出很多问题,此处让最大堆始终比最小堆多一个,在添加和删除后直接维持一次平衡然后prune就行,但这个prune必须保证先prune最大堆,再prune最小堆。主程序部分直接用双指针模板就好。from heapq import *from collections imp原创 2021-02-04 22:52:15 · 192 阅读 · 0 评论 -
leetcode 222 二分完全二叉树
解法一:dfs暴力求解# Definition for a binary tree node.# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = Noneclass Solution: def countNodes(self, root: TreeNode) -> int: self.原创 2020-11-24 14:08:25 · 93 阅读 · 0 评论 -
剑指offer 04 单调矩阵
本题中的矩阵,每行每列都是单调递增的,解法一:二分这道题很容易让人想到二分。二分如果要选左边的元素,那么需要用ceil函数来确定中间,这是一个坑。然后二分的思路就是确定候选区间,先根据第一个元素选出右区间,再根据最后一个元素选出左区间,在区间内二分即可。from math import ceilclass Solution: def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:原创 2021-03-05 15:20:42 · 385 阅读 · 0 评论 -
剑指offer 37 序列化二叉树
这个题有些bug,但还是一道ok的题目。给一颗二叉树,可以将其序列化,并且还原回树。这也是一种压缩或者表示的手段。注意:叶子节点的后面跟着None。而这两种方法都可以用bfs解决。序列化时,我们可以用bfs,如果是None,就不入队,否则入队,然后不断让儿子入队,最终完成。解码时,我们需要遍历数组,不断地将数组赋给父节点。由于每个父亲最多两个儿子,就按顺序给就行,代码如下:from queue import Queue# Definition for a binary tree node.# cl原创 2021-03-05 16:42:09 · 52 阅读 · 0 评论 -
剑指offer 07 前序+中序重建二叉树
此题并不是一道简单的题,我采用的方法先从前序的第一个根节点开始,根据中序中的位置划分左子树右子树,再分别递归处理。我这种写法比传索引差一些。传索引会非常省时间。实际可以采用传索引的方法。# Definition for a binary tree node.# class TreeNode:# def __init__(self, x):# self.val = x# self.left = None# self.right = None原创 2021-03-12 14:04:37 · 42 阅读 · 0 评论 -
剑指offer 08 中序遍历 找下一个节点
节点有几种分类?有爹:当前节点是左儿子:直接找爹当前节点是右儿子:这种情况是比较复杂的,要不断往上找,直到一个父节点是左子树,选中这个爹。如果没有父节点是左子树,恭喜你,你就是最后一个节点。无爹:说明此节点是根节点,找右子树最左边的节点,直到绝后就停止...原创 2021-03-12 14:08:19 · 57 阅读 · 0 评论 -
leetcode 331 前序遍历 单调栈 出度入度
本题要验证前序遍历是否合理,由于是个递归的题目,很容易想到用栈处理,不断处理最内层再规约就好,代码也很简单。但这并不是最优答案,同样的解法咱们可以直接用从后向前的方法,不需要栈,直接合并。最后是两个#号,直接按照老方法合并即可,这样可以实现O(1)的空间复杂度。class Solution: def isValidSerialization(self, preorder: str) -> bool: stack = [] s = preorder.split原创 2021-03-12 21:38:11 · 200 阅读 · 0 评论