查看原文
其他

612,BFS和DFS解奇偶树

博哥 数据结构和算法 2022-05-01

问题描述



来源:LeetCode第1609题

难度:中等


如果一棵二叉树满足下述几个条件,则可以称为奇偶树

  • 二叉树根节点所在层下标为0,根的子节点所在层下标为1,根的孙节点所在层下标为2,依此类推。

  • 偶数下标层上的所有节点的值都是整数,从左到右按顺序严格递增

  • 奇数下标层上的所有节点的值都是整数,从左到右按顺序严格递减


给你二叉树的根节点,如果二叉树为奇偶树,则返回true,否则返回false。


示例 1:

输入:root = [1,10,4,3,null,7,9,12,8,6,null,null,2]

输出:true

解释:每一层的节点值分别是:

0 层:[1]

1 层:[10,4]

2 层:[3,7,9]

3 层:[12,8,6,2]

由于 0 层和 2 层上的节点值都是奇数且严格递增,而 1 层和 3 层上的节点值都是偶数且严格递减,因此这是一棵奇偶树。

示例 2:

输入:root = [5,4,2,3,3,7]

输出:false

解释:每一层的节点值分别是:

0 层:[5]

1 层:[4,2]

2 层:[3,3,7]

2 层上的节点值不满足严格递增的条件,所以这不是一棵奇偶树。

示例 3:

输入:root = [5,9,1,3,5,7]

输出:false

解释:1 层上的节点值应为偶数。

示例 4:

输入:root = [1]

输出:true

示例 5:

输入:root = [11,8,6,1,3,9,11,30,20,18,16,12,10,4,2,17]

输出:true


BFS解决



看到这道题的条件我们最容易想到的就是BFS解决,也就是一层一层的遍历。遍历每一层的时候我们只需要满足以下两个条件即可:

  • 偶数层的节点值都是奇数并且从左到右递增

  • 奇数层的节点值都是偶数并且从左到右递减


只要有一个不满足,就返回false。对于二叉树的BFS遍历我们前面已经介绍过很多次了,如下图所示

他的代码我们再来看下

public void BFS(TreeNode node) {
    //使用一个队列
    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(node);
    while (!queue.isEmpty()) {
        //出队
        TreeNode curNode = queue.poll();
        //访问当前节点
        System.out.println(curNode.val);
        //左右子节点只要有一个不为空就把他加入到队列中
        if (curNode.left != null)
            queue.add(curNode.left);
        if (curNode.right != null)
            queue.add(curNode.right);
    }
}

我们只需要参照上面的代码修改一下就是这题的答案。

public boolean isEvenOddTree(TreeNode root) {
    Queue<TreeNode> queue = new LinkedList();
    //把根节点加入到队列中
    queue.add(root);
    boolean even = true;//默认根节点是偶数层
    while (!queue.isEmpty()) {
        //每一层节点的个数
        int levelCount = queue.size();
        //每层节点的前一个节点值
        int prevVal = even ? Integer.MIN_VALUE : Integer.MAX_VALUE;
        //遍历当前层的所有节点
        while (levelCount-- > 0) {
            TreeNode curNode = queue.poll();
            //偶数层上的节点都是奇数,并且是递增的,如果不满足条件直接返回false
            if (even && (curNode.val % 2 == 0 || curNode.val <= prevVal))
                return false;
            //奇数层上的节点都是偶数,并且是递减的
            if (!even && (curNode.val % 2 == 1 || curNode.val >= prevVal))
                return false;
            //更新前一个节点
            prevVal = curNode.val;
            //如果左右子节点不为空,就把他加入到队列中
            if (curNode.left != null)
                queue.add(curNode.left);
            if (curNode.right != null)
                queue.add(curNode.right);
        }
        //奇偶交换
        even = !even;
    }
    return true;
}


DFS解决



这题除了BFS我们还可以使用DFS来解决,这里使用的DFS就是二叉树的前序遍历。我们可以参照609,从先序遍历还原二叉树的最后一种解法。使用一个list集合存储每层的节点,注意,每层只存储一个节点。


当前节点所在的层数如果是第一次访问,我们就把他加入到集合list中。否则就需要和他前面的值进行比较。究竟是递增还是递减,这个需要根据所在是层数来决定的码如下

public boolean isEvenOddTree(TreeNode root) {
    //list集合,每层只存储一个节点
    List<Integer> mList = new ArrayList<>();
    return dfs(root, mList, 0);
}

//level表示访问的当前节点是在第几层
private boolean dfs(TreeNode root, List<Integer> mList, int level) {
    if (root == null)
        return true;
    //偶数层的值都是奇数,奇数层的值都是偶数,如果不满足直接返回false
    if (root.val % 2 == level % 2)
        return false;
    //这里是判断当前层是不是第一次遍历,也可以这样理解,就是当前节点
    //是不是这一层的第一个节点,如果不是第一个节点,我们需要和前面的
    //比较,如果是第一个节点,就没法和前面一个节点比较,直接存储到
    //集合list中。
    if (mList.size() > level) {
        //根据当前节点是奇数层还是偶数层,来判断是递增还是递减
        if ((level % 2 == 1 && mList.get(level) <= root.val) ||
                ((level % 2 == 0) && mList.get(level) >= root.val))
            return false;
        mList.set(level, root.val);
    } else {
        mList.add(root.val);
    }
    //继续访问他的左右两个子节点
    return dfs(root.left, mList, level + 1)
            && dfs(root.right, mList, level + 1);
}


609,从先序遍历还原二叉树

582,DFS解二叉树剪枝

580,BFS和DFS解二叉树的堂兄弟节点

564,二叉树最大宽度


截止到目前我已经写了600多道算法题了,为了方便大家阅读,我把部分算法题整理成了pdf文档,目前有1000多页,大家可以在下面公众号“数据结构和算法”中回复关键字“pdf”即可获取下载链接。

你点的每个赞,我都认真当成了喜欢

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存