二叉树的一些递归和迭代的解题思路

目录

一.递归

(1).前中后序遍历

(2).经典递归求解

(1)如判断一棵树是不是平衡二叉树

(2)将两个二叉树合并成一个二叉树

二.迭代(层序遍历)

(1).正常的层序遍历

(2).分层的层序遍历

(3).带深度(depth)和序号的(pos)的层序遍历


一.递归

(1).前中后序遍历

实质其实都一样,主要是在对当前遍历的结点进行处理的时候的方式不同。

前中后序遍历的方法可以参考本人另一博客

https://blog.csdn.net/qq_24016309/article/details/122382593


(2).经典递归求解

(1)如判断一棵树是不是平衡二叉树

给定一棵二叉树,判断该二叉树是否为平衡二叉树。对标LeetCode第110题

思路:要一棵树是不是平衡二叉树,

  1. 首先判断这棵树的左子树是不是平衡二叉树
  2. 再判断这棵树的右子树是不是平衡二叉树
  3. 判断当前左右子树的高度差是否 > 1

直接写递归的话求树的高度的时候会有很多重复的操作。

ps:最优解:从求树高的函数入手,如果左右子树有一个-1就返回-1,高度差>1也返回-1。然后最后直接求树高,如果树高不是-1,那就是平衡二叉树。这种找到有重复操作的函数,并且针对性的对这个函数进行优化的方式值得注意。

(2)将两个二叉树合并成一个二叉树

合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。对标LeetCode第617题

思路:要合并两颗二叉树,

  1. 首先如果当前传入的两棵树有一棵是空,那么直接返回另一棵树就行
  2. 如果两棵树都不空,那就new一个新的根结点,值等于两棵树的根节点的值相加
  3. 然后node.left=merge(第一棵树的left,第二棵树的left);node.right = merge(第一棵树的right,第二棵树的right)

二.迭代(层序遍历)

(1).正常的层序遍历

使用队列,进行层序遍历

Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()){
    TreeNode node = queue.remove();
    System.out.println(node);
    if (node.left != null){
        queue.add(node.left);
    }
    if (node.right != null){
        queue.add(node.right);
    }
}

(2).分层的层序遍历

如果说要一层一层进行层序遍历,那就可以借助队列的size函数,每轮循环开始之前,先获取当前队列的长度,也就是当前层的结点数量,然后进入另一个while循环,循环size轮即可。对标LeetCode第102题(要求将每一层的元素都放到不同的list集合中)。

while (!queue.isEmpty()){
    int size = queue.size();
    List<Integer> listEle = new ArrayList<>();
    while (size > 0){
        TreeNode node = queue.remove();
        if (node.left != null){
            queue.add(node.left);
        }
        if (node.right != null){
            queue.add(node.right);
        }
        listEle.add(node.val);
        size--;
    }
    list.add(listEle);
}

(3).带深度(depth)和序号的(pos)的层序遍历

自己定义一个MyNode,里面存储一个深度(depth)和序号(pos),用来表示当前结点的序号,这里注意一下根节点的序号是0还是1,这个对求左右孩子的pos是有影响的。

如LeetCode第662题,要你求二叉树的宽度,主要它中间可能一大片没有结点,不好用正常的层序遍历。

思路:层序遍历+利用队列的取头取尾的性质

每一次循环前,取出当前队列中的最前和最后的元素,根据他们两个的pos之差,维护一下ans,也就是最大的宽度。

class MyNode{
    TreeNode node;
    int depth;
    int pos;

    public MyNode(TreeNode node, int depth, int pos) {
        this.node = node;
        this.depth = depth;
        this.pos = pos;
    }
}
class Solution {
    public int widthOfBinaryTree(TreeNode root) {
        Deque<MyNode> queue = new LinkedList<>();
        int ans = 0;
        queue.add(new MyNode(root,0,0));
        while (!queue.isEmpty()){
            int size = queue.size();
            ans = Math.max(queue.getLast().pos-queue.getFirst().pos+1,ans);
            while (size > 0){
                MyNode myNode = queue.remove();
                if (myNode.node.left != null){
                    queue.add(new MyNode(myNode.node.left,myNode.depth+1,myNode.pos*2+1));
                }
                if (myNode.node.right != null){
                    queue.add(new MyNode(myNode.node.right,myNode.depth+1,myNode.pos*2+2));
                }
                size--;
            }
        }
        return ans;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值