数据结构之树(其二)

//搜索一条边
if (函数(root.left)) return...;
if (函数(root.right)) return...;

//搜索整棵树
left = 函数(root.left);
right = 函数(root.right);
left与right逻辑处理

 

对称二叉树 题目 解析

迭代用队列,栈也可以。戳这里

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

    public boolean mirror(TreeNode Nodeleft, TreeNode Noderight) {
        if (Nodeleft == null && Noderight == null) return true;
        if (Nodeleft == null && Noderight != null) return false;
        if (Nodeleft != null && Noderight == null) return false;
        if (Nodeleft.val != Noderight.val) return false;
        return mirror(Nodeleft.right, Noderight.left) && mirror(Nodeleft.left, Noderight.right);  
    }
}
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null) return true;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root.left);
        queue.offer(root.right);
        while (!queue.isEmpty()) {
            TreeNode Nodeleft = queue.poll();
            TreeNode Noderight = queue.poll();
            if (Nodeleft == null && Noderight == null) continue;
            if (Nodeleft == null || Noderight == null) return false;
            if (Nodeleft.val != Noderight.val) return false;
            queue.offer(Nodeleft.left);
            queue.offer(Noderight.right);
            queue.offer(Nodeleft.right);
            queue.offer(Noderight.left); 
        }
        return true;
    }
}

 

二叉树的最大深度 题目 解析

递归就想成每一个节点都是1,从上一顺加下来。迭代就是层序遍历取层数。

class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) return 0;
        return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
    }
}

 

二叉树的最小深度 题目 解析

只有左右子节点都为空才行,只用一边为空的话还要从另一边继续向下。

class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) return 0;
        if (root.left == null && root.right != null) return 1 + minDepth(root.right);
        if (root.right == null && root.left != null) return 1 + minDepth(root.left);
        return 1 + Math.min(minDepth(root.right), minDepth(root.left));
    }
}
class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) return 0;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int deep = 0;
        while (!queue.isEmpty()) {
            int len = queue.size();
            deep++;
            for (int i = 0; i < len; i++) {
                TreeNode temp = queue.poll();
                if (temp.right == null && temp.left == null) return deep;
                if (temp.right != null) queue.offer(temp.right);
                if (temp.left != null) queue.offer(temp.left);
            }
        }
        return deep;
    }
}

 

二叉树节点个数 题目 解析

迭代依然是用层序遍历

class Solution {
    public int countNodes(TreeNode root) {
        if (root == null) return 0;
        return 1 + countNodes(root.left) + countNodes(root.right);
    }
}

 

平衡二叉树 题目 解析

递归真的很像树。

class Solution {
    public boolean isBalanced(TreeNode root) {
        return getDepth(root) == -1 ? false : true;
    }
    public int getDepth(TreeNode root) {
        if (root == null) return 0;
        int leftDepth = getDepth(root.left);
        if (leftDepth == -1) return -1;
        int rightDepth = getDepth(root.right);
        if (rightDepth == -1) return -1;
        return Math.abs(leftDepth - rightDepth) <= 1 ? 1 + Math.max(leftDepth, rightDepth) : -1;
    }
}

 

左子叶之和 题目 解析

这就是套路啊,就是一个前序遍历。

class Solution {
    private int ans;
    public int sumOfLeftLeaves(TreeNode root) {
        sumLeft(root);
        return ans;
    }
    public void sumLeft(TreeNode root) {
        if (root == null) return;
        if (root.left != null && root.left.left == null && root.left.right == null) {
            ans += root.left.val;
        }
        sumLeft(root.left);
        sumLeft(root.right);
    }
}

 

找树左下角的值 题目 解析

先右后左,这样最后一个出列的就是左下角了。也可以用层序遍历一层一层地找。

class Solution {
    public int findBottomLeftValue(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            root = queue.poll();
            if (root.right != null) queue.offer(root.right);
            if (root.left != null) queue.offer(root.left);
        }
        return root.val;
    }
}

 

路径总和 题目 解析

class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
        if (root == null) return false;
        if (root.right == null && root.left == null && sum == root.val) return true;
        return hasPathSum(root.left, sum-root.val) || hasPathSum(root.right, sum-root.val);
    }
}

 

从中序与后序遍历序列构造二叉树 题目 解析

试了一下,这里用哈希表索引比循环遍历快了3倍。难点是后序和中序的左右子树的头和尾指针的变换。

class Solution {
    private Map<Integer, Integer> hashmap = new HashMap<>();
    private int[] pos;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        for (int i = 0; i < inorder.length; i++) {
            hashmap.put(inorder[i], i);
        }
        pos = postorder;
        return build(0, inorder.length-1, 0, inorder.length-1);
    }
    public TreeNode build(int is, int ie, int ps, int pe) {
        if (is > ie || ps > pe) return null;
        int mid = hashmap.get(pos[pe]);
        TreeNode node = new TreeNode(pos[pe]);
        node.left = build(is, mid-1, ps, mid-1-is+ps);
        node.right = build(mid+1, pe+is-ps, mid-is+ps, pe-1);
        return node;
    }
}

前序与中序遍历序列构造二叉树

class Solution {
    private int[] pre;
    private Map<Integer, Integer> hashmap = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        for (int i = 0; i < inorder.length; i++) {
            hashmap.put(inorder[i],i);
        }
        pre = preorder;
        return build(0, preorder.length-1, 0, inorder.length-1);
    }
    public TreeNode build(int ps, int pe, int is, int ie) {
        if (ps > pe || is > ie) return null;
        int mid = hashmap.get(pre[ps]);
        TreeNode node = new TreeNode(pre[ps]);
        node.left = build(ps+1,ps+mid-is,is,mid-1);
        node.right = build(ps+mid-is+1,pe,mid+1,ie);
        return node;
    }
}

 

最大二叉树 题目 解析

和上面一个思路,相当于切割左右子树

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return build(nums, 0, nums.length-1);
    }
    public TreeNode build(int[] nums, int l, int r) {
        if (l > r) return null;
        int index = l;
        int max = nums[index];
        for (int i = l; i <= r; i++) {
            if (max < nums[i]) {
                index = i;
                max = nums[i];
            }
        }
        TreeNode node = new TreeNode(nums[index]);
        node.left = build(nums, l, index-1);
        node.right = build(nums, index+1, r);
        return node;
    }
}

 

合并二叉树 题目 解析

又是前序遍历,t1为空时连接t2,t2为空是连接t1,体会一下。

class Solution {
    public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
        if (t1 == null) return t2;
        if (t2 == null) return t1;
        TreeNode node = new TreeNode(t1.val + t2.val);
        node.left = mergeTrees(t1.left, t2.left);
        node.right = mergeTrees(t1.right, t2.right);
        return node;
    }
}

 

posted @ 2020-11-07 22:32  CPJ31415  阅读(114)  评论(0)    收藏  举报