二叉树系列

对于二叉树的题目来说,无非就是递归左右子树,需要注意的是自顶向下还是自下而上!

1、中序遍历二叉树

在这里插入图片描述

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        // 递归
        List<Integer> list = new LinkedList<>();
        dfs(root, list);
        return list;
        void dfs(TreeNode cur, List<Integer> list) {
            if (cur == null) return;
            dfs(cur.left, list);
            list.add(cur.val);
            dfs(cur.right, list);
       	}
		// 非递归
        List<Integer> list = new ArrayList<>();
        if (root == null){
            return list;
        }
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.isEmpty()) {
            if (cur != null) {
                stack.push(cur);
                cur = cur.left;
            } else {
                cur = stack.pop();
                list.add(cur.val);
                cur = cur.right;
            }
        }
        return list;
    }
}

2、相同的树

在这里插入图片描述

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

3、对称二叉树

在这里插入图片描述

class Solution {
    public boolean isSymmetric(TreeNode root) {
        return traverse(root.left, root.right);
    }

    boolean traverse(TreeNode a, TreeNode b) {
        if (a == null && b == null) {
            return true;
        } else if (a != null && b == null) {
            return false;
        } else if (a == null && b != null) {
            return false;
        }
        if (a.val == b.val && traverse(a.left, b.right) && traverse(a.right, b.left)) {
            return true;
        }
        return false;
    }
}

4、二叉树的最大深度

在这里插入图片描述

class Solution {
    int max = 0;
    public int maxDepth(TreeNode root) {
        traverse(root, 0);
        return max;
    }

    int traverse(TreeNode root, int depth) {
        if (root == null) return depth;
        depth++;
        if (depth > max) {
            max = depth;
        }
        traverse(root.left, depth);
        traverse(root.right, depth);
        return depth;
    }
}

5、将有序数组转换为二叉搜索树

在这里插入图片描述

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return traverse(nums, 0, nums.length-1);
    }

    TreeNode traverse(int[] nums, int left, int right) {
        if (left > right) return null;
        int mid = (left + right) / 2;
        TreeNode root = new TreeNode(nums[mid]);
        root.left = traverse(nums, left, mid-1);
        root.right = traverse(nums, mid+1, right);
        return root;
    }
}

6、平衡二叉树

在这里插入图片描述

class Solution {
    boolean flag = true;
    public boolean isBalanced(TreeNode root) {
        int res = traverse(root);
        if (res > -1) {
            return true;
        }
        return false;
    }

    int traverse(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int l = traverse(root.left);
        int r = traverse(root.right);
        if (l == -1 || r == -1 || Math.abs(l-r) > 1) {
            return -1;
        } else {
            return Math.max(l, r) + 1;
        }
    }
}

7、二叉树的最小深度

在这里插入图片描述

class Solution {
    public int minDepth(TreeNode root) {
        return minL(root);
    }

    int minL(TreeNode root) {
        if (root == null) return 0;
        int l = minL(root.left);
        int r = minL(root.right);
        if (l == 0) {
            return r + 1;
        } else if (r == 0) {
            return l + 1;
        }
        return Math.min(l, r) + 1;
    }
}

8、路径总和

在这里插入图片描述

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

9、二叉树的前序遍历

在这里插入图片描述

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        return list;
    }
    void dfs (TreeNode cur, List<Integer> list) {
        if (cur == null) return;
        list.add(cur.val);
        dfs(cur.left, list);
        dfs(cur.right, list);
    }
}

10、二叉树的后序遍历

在这里插入图片描述

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        dfs(root, list);
        return list;
    }
    void dfs(TreeNode node, List<Integer> list) {
        if (node == null) return;
        dfs(node.left, list);
        dfs(node.right, list);
        list.add(node.val);
    }
}

11、翻转二叉树

在这里插入图片描述

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return null;
        TreeNode left = invertTree(root.left);
        TreeNode right = invertTree(root.right);
        root.left = right;
        root.right = left;
        return root;
    }
}

12、二叉搜索树的最近公共祖先

在这里插入图片描述

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) return null;
        if (root == p || root == q) return root;
        
        TreeNode left = null;
        TreeNode right = null;
        if (p.val > root.val && q.val > root.val) {
            right = lowestCommonAncestor(root.right, p, q);
        } else if (p.val < root.val && q.val > root.val) {
            left = lowestCommonAncestor(root.left, p, q);
            right = lowestCommonAncestor(root.right, p, q);
        } else if (q.val < root.val && p.val > root.val) {
            left = lowestCommonAncestor(root.left, p, q);
            right = lowestCommonAncestor(root.right, p, q);
        } else if (p.val < root.val && q.val < root.val) {
            left = lowestCommonAncestor(root.left, p, q);
        }
        
        if (left != null && right != null) return root;
        if (left != null && right == null) return left;
        if (left == null && right != null) return right;
        if (left == null && right == null) return null;
        return null;
    }
}

13、二叉树的所有路径

在这里插入图片描述

class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> res = new ArrayList<>();
        getPath(root, "", res);
        return res;
    }

    void getPath(TreeNode root, String path, List<String> paths) {
        if (root != null) {
            path += root.val;
            if (root.left == null && root.right == null) {
                paths.add(path);
            } else if (root.left != null || root.right != null) {
                path += "->";
                getPath(root.left, path, paths);
                getPath(root.right, path, paths);
            }
        } 
    }
}

14、左叶子之和

在这里插入图片描述

// 需要注意的是,这里是左叶子之和不是左节点!!
class Solution {
    private int sum;
    public int sumOfLeftLeaves(TreeNode root) {
        sum = 0;
        traverse(root);
        return sum;
    }

    void traverse(TreeNode root) {
        if (root == null) return;

        if (root.left != null && root.left.left == null && root.left.right == null) {
            sum += root.left.val;
        }
        traverse(root.left);
        traverse(root.right);
    }
}

15、二叉树的坡度

需要注意审题,这里是左右子树之和的差
在这里插入图片描述

class Solution {
    int sum = 0;
    public int findTilt(TreeNode root) {
        traverse(root);
        return sum;
    }

    int traverse(TreeNode root) {
        if (root == null) return 0;

        int left = traverse(root.left);
        int right = traverse(root.right);
        sum += Math.abs(left - right);
        return root.val + left + right;
    }
}

16、二叉搜索树中的众数

在这里插入图片描述

class Solution {
    List<Integer> res = new LinkedList<>();
    int max = 0;
    int tempMax  = 0;
    TreeNode pre = null;
    public int[] findMode(TreeNode root) {
        traverse(root);
        int[] arr = res.stream().mapToInt(Integer::intValue).toArray();
        return arr;
    }

    void traverse(TreeNode root) {
        if (root == null) return;
        
        traverse(root.left);
        if (pre != null && root.val == pre.val) {
            tempMax++;
        } else {
            tempMax = 1;
        }
        if (tempMax == max){
            res.add(root.val);
        } else if (tempMax > max) {
            res.clear();
            max = tempMax;
            res.add(root.val);
        }
        pre = root;
        traverse(root.right);
    }
}

17、二叉搜索树的最小绝对差

在这里插入图片描述

class Solution {
    private TreeNode pre = null;
    int min = 0;
    boolean flag = false;  // 判断是否初始化了min
    public int getMinimumDifference(TreeNode root) {
        traverse(root);
        return min;
    }

    void traverse(TreeNode cur) {
        if (cur == null) return;

        traverse(cur.left);
        if (pre == null) {
            pre = cur;
        } else if (!flag) {
            flag = true;
            min = Math.abs(cur.val - pre.val);
        } else if (flag && Math.abs(cur.val-pre.val) < min) {
            min = Math.abs(cur.val - pre.val);
        }
        pre = cur;
        traverse(cur.right);
    }
}

18、二叉树的直径

在这里插入图片描述

class Solution {
    int ans;
    public int diameterOfBinaryTree(TreeNode root) {
        ans = 1;
        depth(root);
        return ans - 1;
    }
    public int depth(TreeNode node) {
        if (node == null) {
            return 0; // 访问到空节点了,返回0
        }
        int L = depth(node.left); // 左儿子为根的子树的深度
        int R = depth(node.right); // 右儿子为根的子树的深度
        ans = Math.max(ans, L+R+1); // 计算d_node即L+R+1 并更新ans
        return Math.max(L, R) + 1; // 返回该节点为根的子树的深度
    }
}

19、另一颗树的子树(此题有哈希解法)

在这里插入图片描述

class Solution {
    public boolean isSubtree(TreeNode s, TreeNode t) {
        return dfs(s, t);
    }

    public boolean dfs(TreeNode s, TreeNode t) {
        if (s == null) {
            return false;
        }
        return check(s, t) || dfs(s.left, t) || dfs(s.right, t);
    }

    public boolean check(TreeNode s, TreeNode t) {
        if (s == null && t == null) {
            return true;
        }
        if (s == null || t == null || s.val != t.val) {
            return false;
        }
        return check(s.left, t.left) && check(s.right, t.right);
    }
}

哈希

class Solution {
    static final int MAX_N = 1005;
    static final int MOD = 1000000007;
    boolean[] vis = new boolean[MAX_N];
    int[] p = new int[MAX_N];
    int tot;
    Map<TreeNode, int[]> hS = new HashMap<TreeNode, int[]>();
    Map<TreeNode, int[]> hT = new HashMap<TreeNode, int[]>();

    public boolean isSubtree(TreeNode s, TreeNode t) {
        getPrime();
        dfs(s, hS);
        dfs(t, hT);

        int tHash = hT.get(t)[0];
        for (Map.Entry<TreeNode, int[]> entry : hS.entrySet()) {
            if (entry.getValue()[0] == tHash) {
                return true;
            }
        }

        return false;
    }

    public void getPrime() {
        vis[0] = vis[1] = true;
        tot = 0;
        for (int i = 2; i < MAX_N; ++i) {
            if (!vis[i]) {
                p[++tot] = i;
            }
            for (int j = 1; j <= tot && i * p[j] < MAX_N; ++j) {
                vis[i * p[j]] = true;
                if (i % p[j] == 0) {
                    break;
                }
            }
        }
    }

    public void dfs(TreeNode o, Map<TreeNode, int[]> h) {
        h.put(o, new int[]{o.val, 1});
        if (o.left == null && o.right == null) {
            return;
        }
        if (o.left != null) {
            dfs(o.left, h);
            int[] val = h.get(o);
            val[1] += h.get(o.left)[1];
            val[0] = (int) ((val[0] + (31L * h.get(o.left)[0] * p[h.get(o.left)[1]]) % MOD) % MOD);
        }
        if (o.right != null) {
            dfs(o.right, h);
            int[] val = h.get(o);
            val[1] += h.get(o.right)[1];
            val[0] = (int) ((val[0] + (179L * h.get(o.right)[0] * p[h.get(o.right)[1]]) % MOD) % MOD);
        }
    }
}

20、根据二叉树创建字符串

这题主要是吓唬人,看清题意就行。
在这里插入图片描述

class Solution {
    public String tree2str(TreeNode root) {
        return dfs(root);
    }

    String dfs(TreeNode root) {
        if (root == null) return "-";
        String left = dfs(root.left);
        String right = dfs(root.right);

        if (left.equals("-") && right.equals("-")) {
            return root.val + "";
        } else if (!left.equals("-") && right.equals("-")) {
            return root.val + "(" + left + ")";
        } else if (left.equals("-") && !right.equals("-")) {
            return root.val + "()"  + "(" + right+ ")";
        } else if (!left.equals("-") && !right.equals("-")) {
            return root.val + "(" + left + ")" + "(" + right +")";
        }
        return "-"; 
    }
}

21、合并二叉树

在这里插入图片描述

class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if (root1 == null) {
            return root2;
        }
        if (root2 == null) {
            return root1;
        }
        TreeNode merged = new TreeNode(root1.val + root2.val);
        merged.left = mergeTrees(root1.left, root2.left);
        merged.right = mergeTrees(root1.right, root2.right);
        return merged;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值