leetcode-104-二叉树的最大深度(maximum depth of binary tree)
**查询树的深度,一般有两种方法
第一种,递归,长度=当前长度(1)+左右子树的max长度
第二种,一层层遍历,建立两个list,now和next,now的初始值为root,length为0,每次循环将,now的left与right加入next,然后让now=next,并且length++,直到now为null为止
leetcode-98-验证二叉搜索树(validat binary search tree)-java
二叉搜索树是左侧子树全部比root小,右侧全比root大
验证二叉搜索树,二种方法
1 中序遍历,左侧大于右侧
2 递归 令左侧 大于min 小于root 右侧 大于root 小于min
leetcode-101-对称二叉树(symmetric tree)-java
树的话,验证对称,可以用递归
也可以迭代,在一个队列中加入两次root,每次取出两个,比较双方,然后一次塞入左的左,右的右,左的右,右的左
leetcode- 102二叉树的层次遍历(binary tree level order traversal)-java
二叉树层次遍历
迭代
建立一个queue,一个rowlist,
一个现在层次的节点数num=1,一个下一层next=0
将root加入queue
当queue不为空
从queue取出头,num–,将值加入rowlist,将left,right加入queue尾部,next++
当num为0 则num=next,next=0,结果加入rowlist,rowlist新建一个
递归
利用递归进行dfs,每次递归一个node的时候记录它的深度,然后在类中设置result变量,在result的第i层(i为节点深度),插入节点的值(先递归左孩子)
leetcode-108-将有序数组转换为二叉搜索树(convert sorted array to binary search tree)-java
二叉搜索树变为数组用中序遍历
数组变为平衡的二叉搜索树用递归
中间的为root
左边的比他小的数为左子树,右边的为右子树
leetcode-94-二叉树的中序遍历(binary tree inorder traversal)-java
解法1
同样用栈,用循环
循环条件是curt不为null或者stack不为空
首先将curt自身及所有左子树逐个加入stack
然后弹出stack顶部,将其加入result
最后curt为弹出的那个节点的右子树
因为弹出的那个节点,左子树要么没有,要么已经被处理,所以只考虑右子树
右子树如果没有,则下一次循环,直接curt = stack.pop();,相当于处理它的上层
如果有右子树,那么先处理该节点的右子树,再处理上层
解法2
中序递归方法,建立一个public void inorder(List result,TreeNode root)方法
leetcode-103-二叉树的锯齿形层次遍历(binary tree zigzag level order traversal)-java
解法1
使用典型的二叉树层次化遍历的方法,设置一个队列逐个放入层次化的二叉树,设置num,next变量控制层数,然后设置isLTR变量,表明该层的数据从左往右还是从右往左,如果从右往左,则每层遍历的节点由于是从左往右,则塞入linkedList的顺序是插入头部,导致最右的数据在list最左边
解法2
经典的递归算法,层次遍历二叉树时,可以根据参数depth,知道要加入到List < List < Integer > > 的哪个list的哪里
leetcode-105- 从前序与中序遍历序列构造二叉树(construct binary tree from preorder and inorder traversal)-java
从前序遍历可以得到该段的root,从中序遍历找到root,root的左右是root的左右节点,就可以按这个方法递归出这个节点的左右子节点
上述的做法有个缺点,每次都要去中序遍历中,查找中间节点的位置,因为数字不重复,可以将中序遍历放入hashmap,把中序遍历数组的每个元素的值和下标存起来,这样寻找根节点的位置就可以直接得到了。
leetcode-116- 填充同一层的兄弟节点(populating next right pointers in each node
解法1
递归,传来自己与自己的next,设置next关系,然后让儿子处理儿子与侄子的关系
解法2
循环,pre为每一行的第一个节点,cur从pre开始,不断到同一行的next,如果没有next了,到下一行的第一个
每次处理cur的儿子与侄子的关系
leetcode-230-二叉搜索树中第K小的元素(kth smallest element in a bst)-java
解法1(成功,1ms,极快)
在solution中设置一个变量result,每个方法一旦发现现在第一小的数是自己,则把result=root.val
kthSmallest2方法,返回这个root下找到了几个数
同时right=kthSmallest2(root.right,k-left-1);,对右边的节点用k-left-1作为第几小的k
解法2
很有趣的题,但是很简单,实际上就是对树的中序遍历,关于第K小,因为是二叉搜索树,所以最左边的就是最小的,那么中序遍历的情况下,第一次回溯到中序就是最小的一个节点,每遍历一个元素就k–,当 k=1的时候,该节点就是第K小了。
通过循环的方式进行中序遍历,得到k变为1时,返回节点的val
leetcode-297-二叉树的序列化与反序列化 (seriliaze and deseriliaze binary tree)-java
使用先序遍历,null只加进去一次,不把null的左右加进去
1
2 3
4 5
变成1,2,4,null,null,5,null,null,3,null,null
反序列化,每次得到第一个str,然后删掉第一个。如果是null,就返回null。如果不是null,就创建节点,然后递归调用函数,设置左右节点。
leetcode-236-二叉树的最近公共祖先-java
解法2(别人的)
这种方法非常直观。先深度遍历改树。当你遇到节点 p 或 q 时,返回一些布尔标记。该标志有助于确定是否在任何路径中找到了所需的节点。最不常见的祖先将是两个子树递归都返回真标志的节点。它也可以是一个节点,它本身是p或q中的一个,对于这个节点,子树递归返回一个真标志。
从根节点开始遍历树。
如果当前节点本身是 p 或 q 中的一个,我们会将变量 mid 标记为 true,并继续搜索左右分支中的另一个节点。
如果左分支或右分支中的任何一个返回 true,则表示在下面找到了两个节点中的一个。
如果在遍历的任何点上,左、右或中三个标志中的任意两个变为 true,这意味着我们找到了节点 p 和 q 的最近公共祖先。
就是如果节点不是p或q的父节点,三个标志都为false。
只是一个的父节点,1个标志为true。
正好是2个的最近父节点,2个标志为true。
2个的非最近父节点,一定只有一个标志为true,因为2个节点一定在它的left或right侧。
解法3(别人的)
使用父指针迭代
如果每个节点都有父指针,那么我们可以从 p 和 q 返回以获取它们的祖先。在这个遍历过程中,我们得到的第一个公共节点是 LCA 节点。我们可以在遍历树时将父指针保存在字典中。
从根节点开始遍历树。
在找到 p 和 q 之前,将所有节点的父指针存储在字典中。
一旦我们找到了 p 和 q,我们就可以使用父亲字典获得 p 的所有祖先,并添加到一个称为祖先的集合中。
同样,我们遍历节点 q 的祖先。如果祖先存在于为 p 设置的祖先中,这意味着这是 p 和 q 之间的第一个共同祖先(同时向上遍历),因此这是 LCA 节点。
leetcode-124-二叉树中的最大路径和-java
初始化 max_sum 为最小可能的整数并调用函数 max_gain(node = root)。
实现 max_gain(node) 检查是继续旧路径还是开始新路径:
边界情况:如果节点为空,那么最大权值是 0 。
对该节点的所有孩子递归调用 max_gain,计算从左右子树的最大权值:left_gain = max(max_gain(node.left), 0) 和 right_gain = max(max_gain(node.right), 0)。
检查是维护旧路径还是创建新路径。创建新路径的权值是:price_newpath = node.val + left_gain + right_gain,当新路径更好的时候更新 max_sum。
对于递归返回的到当前节点的一条最大路径,计算结果为:node.val + max(left_gain, right_gain)。
即max_gain(node)方法,会返回node节点-它的某一侧的节点的最大长度。
某一侧节点-node-另一侧节点,这种情况的路径,会在方法内部更新max_sum字段,更新最大长度。
leetcode-208-实现Trie (前缀树)-java
TrieNode类,有isEnd字段,TrieNode[] nodes= new TrieNode[26]
Trie里有TrieNode类型的root,如果确实有一个字符 abc 那么root.nodes[0]不为null,而且最后一个nodes[2].isEnd为true
插入时,就node.nodes[now-‘a’] = new TrieNode(),新增一个节点,最后node.isEnd = true
查找时,不断node = node.nodes[now-‘a’],如果没有,则返回false,如果都有,就看最后node.isEnd是否为true