[力扣]二叉树3—属性操作

  • 好好体会递归思想

代码随想录[原文指路]

判断

1.对称二叉树[101]

  • 递归
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null) return true;
        return compare(root.left,root.right);
    }
    public static boolean compare(TreeNode left,TreeNode right){
        if(left==null&&right==null) return true;
        if(left==null&&right!=null || left!=null&&right==null || left.val!=right.val) return false;
        //比较外侧
        boolean res1 = compare(left.left,right.right);
        //比较内侧
        boolean res2 = compare(left.right,right.left);
        //若内外侧都相等返回true
        return res1&&res2;
    }
}
  • 双端队列
class Solution {
    public boolean isSymmetric(TreeNode root){
        Deque<TreeNode> deque = new LinkedList<>();
        deque.offerFirst(root.left);
        deque.offerLast(root.right);
        while(!deque.isEmpty()){
            TreeNode leftNode = deque.pollFirst();
            TreeNode rightNode = deque.pollLast();
            if(leftNode==null && rightNode==null) {
                continue;
            }
            if(leftNode==null || rightNode==null || leftNode.val!=rightNode.val) {
                return false;
            }
            deque.offerFirst(leftNode.left);
            deque.offerFirst(leftNode.right);
            deque.offerLast(rightNode.right);
            deque.offerLast(rightNode.left);
        }
        return true;
    }
}
  • 普通队列
class Solution {
    public boolean isSymmetric(TreeNode root){
        Deque<TreeNode> deque = new LinkedList<>();
        deque.offer(root.left);
        deque.offer(root.right);
        while(!deque.isEmpty()){
            TreeNode leftNode = deque.poll();
            TreeNode rightNode = deque.poll();
            if(leftNode==null && rightNode==null) {
                continue;
            }
            if(leftNode==null || rightNode==null || leftNode.val!=rightNode.val) {
                return false;
            }
            deque.offer(leftNode.left);
            deque.offer(rightNode.right);
            deque.offer(leftNode.right);
            deque.offer(rightNode.left);
        }
        return true;
    }
}

2.相同的树[100]

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p==null && q==null) return true;
        if(p==null || q==null || p.val!=q.val) return false;
        
        boolean bool1 = isSameTree(p.left,q.left);
        boolean bool2 = isSameTree(p.right,q.right);
        return bool1&&bool2;
    }
}

3.另一棵树的子树[572]

class Solution {
    //遍历root的每一个子节点作为开始节点与subRoot结构比较
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root==null) return false;
		return isSameTree(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
    }
    //比较pq是否相同
    public static boolean isSameTree(TreeNode p, TreeNode q) {
    	if(p==null && q==null) return true;
        if(p==null || q==null || p.val!=q.val) return false;
        
        boolean bool1 = isSameTree(p.left,q.left);
        boolean bool2 = isSameTree(p.right,q.right);
        return bool1&&bool2;
    }
}

深度

1.二叉树的最大深度[104]

  • 递归
class Solution {
    public int maxDepth(TreeNode root) {
        if(root==null) return 0;

        int len1 = maxDepth(root.left);
        int len2 = maxDepth(root.right);
        return Math.max(len1,len2)+1;
    }
}
  • 迭代(层序)
class Solution {
    public int maxDepth(TreeNode root) {
        int res = 0;
        if(root==null) return res;

        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            for(int i=0;i<size;i++){
                TreeNode node = queue.poll();
                if(node.left!=null) queue.offer(node.left);
                if(node.right!=null) queue.offer(node.right);
            }
            res++;
        }
        return res;
    }
}

2.N 叉树的最大深度[559]

  • 递归
class Solution {
    public int maxDepth(Node root) {
        int res = 0;
        if(root==null) return res;

        for(Node node:root.children){
            int len = maxDepth(node);
            res = Math.max(len,res);
        }
        return res+1;
    }
}
  • 迭代(层序)
class Solution {
    public int maxDepth(Node root) {
        int res = 0;
        if(root==null) return res;

        Queue<Node> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            for(int i=0;i<size;i++){
                Node node = queue.poll();
                for(Node node1:node.children){
                    queue.offer(node1);
                }
            }
            res++;
        }
        return res;
    }
}

3.二叉树的最小深度[111]

  • 递归
class Solution {
    public int minDepth(TreeNode root) {
        if(root==null) return 0;

        int len1 = minDepth(root.left);
        int len2 = minDepth(root.right);
        
        if(root.left==null) return len2+1;
        if(root.right==null) return len1+1;
        return Math.min(len1,len2)+1;
    }
}
  • 迭代(层序)
class Solution {
    public int minDepth(TreeNode root) {
        int res = 0;
        if(root==null) return res;

        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            res++;
            for(int i=0;i<size;i++){
                TreeNode node = queue.poll();
                if(node.left!=null) queue.offer(node.left);
                if(node.right!=null) queue.offer(node.right);
                if(node.left==null&&node.right==null){
                    return res;
                }
            }
        }
        return res;
    }
}

平衡二叉树[110]

  • 递归:涉及判断与深度
class Solution {
    public boolean isBalanced(TreeNode root) {
        return getHeight(root)!=-1;
    }

    public static int getHeight(TreeNode root){
        if(root==null) return 0;

        int count1 = getHeight(root.left);
        if(count1==-1) return -1;
        int count2 = getHeight(root.right);
        if(count2==-1) return -1;
        int height = Math.max(count1,count2);
        return Math.abs(count1-count2)>1?-1:height+1;
    }
}

路径

1.二叉树的所有路径[257]

  • 递归+回溯
class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> ress = new ArrayList();
        if(root == null) return ress;
        preOrder(root,ress,"");
        return ress;
    }

    public static void preOrder(TreeNode root,List<String> ress,String res){
        if(res!=null && !res.equals("")) res+="->";
        res+=root.val;

        if(root.left!=null) preOrder(root.left,ress,res);
        if(root.right!=null) preOrder(root.right,ress,res);
        //此处到达叶子节点
        if(root.left==null && root.right==null){
            ress.add(res);
        }
    }
}

2.路径总和[112]

  • 递归使用
1.如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值
2.如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值
3.如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回
  • 递归
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root==null) return false;
        //使用累加较麻烦,此处使用累减,每次让targetSum-root.val,若到叶子节点且targetSum=0则找到
        //此题只需要找到一条满足条件的路径就返回,所以此处返回值为Boolean型标记有没有找到满足条件的路径
        targetSum -= root.val;
        if(targetSum==0&&root.left==null&&root.right==null) return true;

        boolean bool1 = hasPathSum(root.left,targetSum);
        boolean bool2 = hasPathSum(root.right,targetSum);

        return bool1||bool2;
    }
}
  • 栈迭代
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root==null) return false;
        //栈里一个元素不仅要记录该节点指针,还要记录从头结点到该节点的路径数值总和
        Stack<TreeNode> stack1 = new Stack();
        Stack<Integer> stack2 = new Stack();
        stack1.push(root);
        stack2.push(root.val);
        while(!stack1.isEmpty()){
            int size = stack1.size();
            while(size-->0){
                TreeNode node = stack1.pop();
                int sum=stack2.pop();
                //如果该节点是叶子节点,同时该节点的路径数值等于sum,那么就返回true
                if(node.left==null && node.right==null && sum==targetSum)return true;
                //左节点,压进去一个节点的时候,将该节点的路径数值也记录下来
                if(node.left!=null){
                    stack1.push(node.left);
                    stack2.push(sum+node.left.val);
                }
                //右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
                if(node.right!=null){
                    stack1.push(node.right);
                    stack2.push(sum+node.right.val);
                }
            }
        }
        return false;
    }
}

3.路径总和 II[113]

  • 递归
class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> ress = new ArrayList();
        if(root==null) return ress;
        List<Integer> res = new ArrayList();
        getpathSum(root,targetSum,res,ress);
        return ress;
    }

    public void getpathSum(TreeNode root, int targetSum,List<Integer> res,List<List<Integer>> ress) {
        //使用累加较麻烦,此处使用累减,每次让targetSum-root.val,若到叶子节点且targetSum=0则找到
        //此题需要找到所有满足条件的路径就返回,此处不用返回值  
        res.add(root.val);
        targetSum -= root.val;
        if(root.left==null && root.right==null){
        	//注意此处res的改变直接影响ress,所以此处new
            if(targetSum==0) ress.add(new ArrayList<>(res));
            return ;
        }
        if(root.left!=null){
            getpathSum(root.left,targetSum,res,ress);
            res.remove(res.size()-1);//回溯
        }
        if(root.right!=null){
            getpathSum(root.right,targetSum,res,ress);
            res.remove(res.size()-1);//回溯
        }
    }
}

结果和

1.完全二叉树的节点个数[222]

  • 递归
class Solution {
    public int countNodes(TreeNode root) {
        if(root==null) return 0;

        int count1 = countNodes(root.left);
        int count2 = countNodes(root.right);
        return count1+count2+1;
    }
}
  • 迭代
class Solution {
    public int countNodes(TreeNode root) {
        int count = 0;
        if(root==null) return count;

        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            count +=size;
            for(int i=0;i<size;i++){
                TreeNode node = queue.poll();
                if(node.left!=null) queue.offer(node.left);
                if(node.right!=null) queue.offer(node.right);
            }
        }
        return count;
    }
}
  • 利用完全二叉树特性递归
完全二叉树只有两种情况
	1.满二叉树:2^数深度-1
	2.最后一层叶子节点没有满:分别递归左右孩子,直到左右孩子为满二叉树,依然按情况1处理
class Solution {
    public int countNodes(TreeNode root) {
        if(root==null) return 0;
        int leftHeight = 0,rightHeight = 0;
        TreeNode left = root.left;
        TreeNode right = root.right;
        //求左子树最左节点深度
        while(left!=null){
            left = left.left;
            leftHeight++;
        }
        //求右子树最右节点深度
        while(right!=null){
            right = right.right;
            rightHeight++;
        }
        if(leftHeight == rightHeight){//这是一颗满二叉树
            return (2<<leftHeight)-1;
        }
        return countNodes(root.left)+countNodes(root.right)+1;
    }
}

2.左叶子之和[404]

  • 递归
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        //直接通过当前节点是无法判断是否是叶子节点的
        //如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子
        if(root==null) return 0;
        int sum=0;
        if(root.left!=null&&root.left.left==null&&root.left.right==null) {
            sum += root.left.val;
        }
        
        int leftsum = sumOfLeftLeaves(root.left);
        int rightsum = sumOfLeftLeaves(root.right);
        return leftsum+rightsum+sum;
    }
}
  • 栈迭代
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        //直接通过当前节点是无法判断是否是叶子节点的
        //如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子
        if(root==null) return 0;
        int sum=0;
        Stack<TreeNode> stack = new Stack();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node = stack.pop();
            if(node.left!=null && node.left.left==null && node.left.right==null){
                sum += node.left.val;
            }
            if(node.left!=null) stack.push(node.left);
            if(node.right!=null) stack.push(node.right);
        }
        return sum;
    }
}
  • 队列迭代(层序)
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        //直接通过当前节点是无法判断是否是叶子节点的
        //如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子
        if(root==null) return 0;
        int sum=0;
        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            while(size-->0){
                TreeNode node = queue.poll();
                if(node.left!=null){
                    if(node.left.left==null&&node.left.right==null){
                        sum += node.left.val;
                    }else{
                        queue.offer(node.left);
                    }
                }
                if(node.right!=null) queue.offer(node.right);
            }
        }
        return sum;
    }
}

找树左下角的值[513]

  • 递归
class Solution {
    //最大深度
    private int maxheight = -1;
    //最左节点的值
    private int value = 0;

    public int findBottomLeftValue(TreeNode root) {
        if(root==null) return 0;
        //本题要求求最深的叶子节点,所以不采取从下向上递归(返回值),而采取从上往下递归(传参)
        findLeftValue(root,0);
        return value;
    }

    private void findLeftValue(TreeNode root,int deep){
        //deep当前深度
        if(root.left==null && root.right==null) {
            if(deep>maxheight){
                value=root.val;
                maxheight=deep;
            }
        }
        if(root.left!=null) findLeftValue(root.left,deep+1);
        if(root.right!=null) findLeftValue(root.right,deep+1);
    }
}
  • 队列迭代(层序)
class Solution {
    public int findBottomLeftValue(TreeNode root) {
        if(root==null) return 0;

        int leftOrder = 0;
        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        while(!queue.isEmpty()){
            int size = queue.size();
            leftOrder = queue.peek().val;
            while(size-->0){
                TreeNode node = queue.poll();
                if(node.left!=null) queue.offer(node.left);
                if(node.right!=null) queue.offer(node.right);
            }
        }
        return leftOrder;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值