代码随想录day13|层序遍历,对称二叉树,翻转二叉树

文章:代码随想录

层序遍历:

思路:

BFS(Leecode有相关十道题都可以用层序遍历的思路,随想录可以看 已都做完)

通过队列来实现,对于每个节点依次在队列后面加入它的左节点和右子节点.那么怎么知道当前层有多少个节点呢?(需要pop多少次呢?)

那这个次数就由未开始for循环的队列的size来记录 因为for循环开始后,会加入节点的下一层的左右孩子,队列的size会不断改变,所以要先先记录队列的size来保证循环次数正确。 然后依次pop正确次数后,pop出来的就是当前层的节点.

public static List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> level=new LinkedList<>();
        List<List<Integer>> result=new ArrayList<>();
        if(root==null){return result;}
        level.offer(root);
        while (!level.isEmpty()){
            ArrayList<Integer> eachLevel = new ArrayList<>();
            //因为for循环中level.size会改变,会加入下一层的节点.所以这里要先记录它的size。
            //这时候它的size还是当前层的节点个数
            int size=level.size();
            for (int i = 0; i < size; i++) {
                TreeNode top= level.poll();
                eachLevel.add(top.val);
                //加入下一层节点,空节点不入队列
                if(top.left!=null){level.offer(top.left);}
                if(top.right!=null){level.offer(top.right); }

            }
            result.add(eachLevel);
        }
        return result;
    }

DFS:

思路:

--递归方式

是通过depth深度来标识是树的第几层,同时这也代表着结果集里的索引位置,比如第0层的元素要加入Lsit[0]位置的list中。

代码:

 public List<List<Integer>> resList = new ArrayList<List<Integer>>();

    public List<List<Integer>> levelOrderDFS(TreeNode root) {
        checkFun01(root,0);

        return resList;
    }


    public void checkFun01(TreeNode node, Integer deep) {
        if (node == null) return;
        //第一次遍历到这个深度时,需要给结果集先加入一个空的集合,不然后面会报空指针
        if (resList.size() <= deep) {
            //当层级增加时,list的Item也增加,利用list的索引值进行层级界定
            List<Integer> item = new ArrayList<Integer>();
            resList.add(item);
        }
        resList.get(deep ).add(node.val);
        deep++;
        checkFun01(node.left, deep);
        checkFun01(node.right, deep);
    }

翻转二叉树:

思路:

递归法(前后序遍历) 但是这种写法,中序不行,为什么呢? 

中序是左中右,试想一下,我们先把左子树的所有孩子交换后,我们这时候把根节点的左右孩子交换再去遍历右子树,  那这时候根节点的右子树就变成了之前的左子树,那右子树的孩子就没交换还是处理的左子树,之前处理的左子树的孩子也会交换回来。

代码:

  public TreeNode invertTreePre(TreeNode root) {
        if (root==null){return root;}
        TreeNode temp=root.left;
        root.left=root.right;
        root.right=temp;
        invertTreePre(root.left);
        invertTreePre(root.right);
        return root;
    }

    public TreeNode invertTreePost(TreeNode root) {
        if (root==null){return root;}

        invertTreePost(root.left);
        invertTreePost(root.right);
        TreeNode temp=root.left;
        root.left=root.right;
        root.right=temp;
        return root;
    }

重温前一天的迭代方式来做前序遍历:

//非递归 栈 前序
    public TreeNode invertTreeStPre(TreeNode root) {
//        if(root==null){return root;}
        Stack<TreeNode> record=new Stack<>();

        //因为如果为null就push,下面的while会报空指针异常,或者前面直接判断为空return也可以.
        if(root!=null){record.push(root);}
        while (!record.empty()){
            TreeNode node=record.pop();
            if(node!=null){
                if(node.right!=null){record.push(node.right);}
                if(node.left!=null){record.push(node.left);}
                record.push(node);
                record.push(null);

            }else {
                TreeNode top= record.pop();
                TreeNode temp=top.left;
                top.left=top.right;
                top.right=temp;
            }
        }
        return root;
    }

层序:

同时也可以用今天学的层序遍历来做:

//层序遍历方式
    public TreeNode invertTreeLevelOrder(TreeNode root) {
        if (root==null){return root;}
        Queue<TreeNode> levelRecord=new LinkedList<>();
        levelRecord.offer(root);

        while (!levelRecord.isEmpty()){
            int size= levelRecord.size();
            for (int i = 0; i < size; i++) {
                TreeNode top = levelRecord.poll();
                TreeNode temp=top.left;
                top.left=top.right;
                top.right=temp;
                if(top.left!=null){levelRecord.offer(top.left);}
                if(top.right!=null){levelRecord.offer(top.right);}
            }
        }
        return root;
    }

对称二叉树:

思路:

这道题要对比每一层的外侧和内侧是否都相同。

递归法:

这道题只能用后序遍历,因为要对比完左右孩子才能返回中节点,如果先处理了中节点,那么就会缺少左孩子或者右孩子的信息,那么这时候返回中节点就没意义 //所以只能用后序遍历.

public boolean isSymmetric(TreeNode root) {
        if (root == null) {
            return true;
        }
        return compare(root.left, root.right);
    }

    private boolean compare(TreeNode left, TreeNode right) {
        if (left != null && right == null) {
            return false;
        }
        if (left == null && right != null) {
            return false;
        }
        if (left == null && right == null) {
            return true;
        }
        //null要在前面就判断不然会报空指针.
        if (left.val != right.val) {
            return false;
        }

        //比较外侧
        boolean outside = compare(left.left, right.right);
        //比较内侧
        boolean inside = compare(left.right, right.left);
        //这也是为什么只能用后序,试想把result这个中序放到左(outside)/右(inside)之前,结果都会变得无意义。
        boolean result=outside && inside;
        //两者都为true时才为true
        return result;

    }

非递归法,迭代:

--队列

思路:其实用层序遍历的思路转变一下,可以定义两个指针来改变压入队列的元素的顺序,然后两两抛出看看匹不匹配.

代码:

public boolean isSymmetricQueue(TreeNode root) {
        if (root == null) {
            return true;
        }
        Queue<TreeNode> levelRecord = new LinkedList<>();
        levelRecord.offer(root.left);
        levelRecord.offer(root.right);
        while (!levelRecord.isEmpty()) {

            //这里并不需要层序输出,或者对每一层的结果进行处理,只需要两两对比
            // 所以不需要用for循环记录size,一直到队列内没有元素就可以
            TreeNode leftNode = levelRecord.poll();
            TreeNode rightNode = levelRecord.poll();
            //判断条件
            //如果都为空,则开始下一个循环,要遍历完全部元素判断才知道最终结果.
            if (leftNode==null && rightNode==null) {
                continue;
            }
//            if(leftNode!=null && rightNode==null){return false;}
//            if(leftNode==null && rightNode!=null){return false;}
//            if(leftNode.val!=rightNode.val){return false;}
            //这里可以将上述三个条件合并,因为一开始已经判断了两者都为空的情况.
            if(leftNode==null|| rightNode==null || leftNode.val!=rightNode.val){return false;}

            //注意压入顺序
            //外侧
            levelRecord.offer(leftNode.left);
            levelRecord.offer(rightNode.right);
            //内测
            levelRecord.offer(leftNode.right);
            levelRecord.offer(rightNode.left);
        }
        return true;
    }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值