给你一棵以 root 为根的二叉树,二叉树中的交错路径定义如下:
选择二叉树中 任意 节点和一个方向(左或者右)。
如果前进方向为右,那么移动到当前节点的的右子节点,否则移动到它的左子节点。
改变前进方向:左变右或者右变左。
重复第二步和第三步,直到你在树中无法继续移动。
交错路径的长度定义为:访问过的节点数目 - 1(单个节点的路径长度为 0 )。
请你返回给定树中最长 交错路径 的长度。
输入:root = [1,null,1,1,1,null,null,1,1,null,1,null,null,null,1,null,1]
输出:3
解释:蓝色节点为树中最长交错路径(右 -> 左 -> 右)。
输入:root = [1,1,1,null,1,null,null,1,1,null,1]
输出:4
解释:蓝色节点为树中最长交错路径(左 -> 右 -> 左 -> 右)。
示例 3:
输入:root = [1]
输出:0
提示:
每棵树最多有 50000 个节点。
每个节点的值在 [1, 100] 之间。
class Solution {
//记 f(u)f(u) 为从根到节点 uu 的路径上以 uu 结尾并且 uu 是它
// 父亲的左儿子的最长交错路径,g(u)g(u) 为从根到节点 uu 的路径
// 上以 uu 结尾并且 uu 是它父亲的右儿子的最长交错路径
Map<TreeNode, Integer> f = new HashMap<>();
Map<TreeNode, Integer> g = new HashMap<>();
//作为盛放(节点,结果)的集合,二者可以相互转换
Queue<TreeNode[]> q = new LinkedList<>();
//这里用来作为队列,一次性放置两个节点(孩子节点,父节点)
public int longestZigZag(TreeNode root) {
bfs(root);
int max = 0;
//所有节点的结果都放入f,g中,寻找最大值即可
for(TreeNode node : f.keySet()){
max = Math.max(max, Math.max(f.get(node), g.get(node)));
}
return max;
}
void bfs(TreeNode root){
f.put(root, 0);
g.put(root, 0);
q.add(new TreeNode[]{root, null});//放入根节点
while(!q.isEmpty()){
//取出
TreeNode[] now = q.poll();
TreeNode child = now[0], parent = now[1];
f.put(child, 0);//先初始化
g.put(child, 0);
if(parent != null){//更新f,g的值
if(parent.left == child){
f.put(child, g.get(parent) + 1);//利用刚才的结果
}
if(parent.right == child){
g.put(child, f.get(parent) + 1);
}
}
//判断child节点是否有子节点,加入队列
if(child.left != null){
q.add(new TreeNode[]{child.left, child});
}
if(child.right != null){
q.add(new TreeNode[]{child.right, child});
}
}
}
}
class Solution {
int max;
public int longestZigZag(TreeNode root) {
if(root == null) return 0;
max = 0;
dfs(root, false, 0);
dfs(root, true, 0);
return max;
}
void dfs(TreeNode root, boolean flag, int len){
//其中flag表示当前点的走向,false向左,true向右
max = Math.max(max, len);//每次遍历的时候都要比较一下
if(!flag){
//当前为左,下次应向右
if(root.left != null){
dfs(root.left, true, len + 1);//变为true
}/*else {
//若没有左子树,则只能向右,下个节点仍然是向左
dfs(root.right, false, 1);
}*/
//并不是一个二选一的过程,都是有可能存在的情况的
if(root.right != null){
dfs(root.right, false, 1);//设定root.right仍是向左,
//因为已经向左走了一段,此时长度为1;
}
}else {
//当前走向向右
if(root.right != null){
dfs(root.right, false, len + 1);
}
if(root.left != null){
dfs(root.left, true, 1);
//重置,root.left应向右
}
}
}
}