【LeetCode】刷题笔记

124. 二叉树中的最大路径和

链接:二叉树中的最大路径和
解题思路:
最大路径 = 该节点的值 + 左节点的最大贡献值 + 右节点的最大贡献值,即:
ans = Math.max(ans, left + right + root.val);
每个节点的最大贡献值 = 该节点的值 + max(左节点的最大贡献值, 右节点的最大贡献值),即:
root.val + Math.max(left, right);
最后才加上该节点的值,故采用后序遍历。
代码:

class Solution {
    int ans = Integer.MIN_VALUE;
    public int maxGain(TreeNode root) {
        if(root == null) {
            return 0;
        }else {
            int left = Math.max(0, maxGain(root.left));
            int right = Math.max(0, maxGain(root.right));
            ans = Math.max(ans, left + right + root.val);
            return root.val + Math.max(left, right);
        }
        
    }
    public int maxPathSum(TreeNode root) {
        maxGain(root);
        return ans;
    }
}

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

链接:从前序与中序遍历序列构造二叉树
解题思路:
根据前序遍历可以知道根节点,再根据根节点在中序遍历中的位置可以得到左子树与右子树。
前序遍历:[根节点,左子树,右子树],其中左右子树皆是前序遍历的结果
中序遍历:[左子树,根节点,右子树],其中左右子树皆是中序遍历的结果

如上,根据中序遍历中根节点的位置与左子树的边界,可以得到左子树数目的大小,再通过左子树数目的大小推出前序遍历中属于左子树的部分;中序遍历中右子树的部分所以可以采用递归不断构建左右子树。
最初时中序遍历中左子树边界为0,右子树边界为inorder.length-1;前序遍历中左子树边界为0,右子树边界为preorder.length-1。即build(preorder, inorder, 0, preorder.length-1, 0, inorder.length-1);

中序遍历中:
左子树节点数目size = 根节点位置index - 左子树边界preLeft
左子树:[左子树边界inLeft, 根节点位置index -1]
右子树:[根节点位置index +1, 右子树边界inRight]
前序遍历中:
原左边界preLeft即是根节点,+1则是左子树开始部分
左子树:[左子树边界preLeft+ 1, 左子树边界preLeft + 左子树节点数目size]
右子树:[左子树边界preLeft + 左子树节点数目size + 1, 右子树边界preRight]
即:
root.left = build(preorder, inorder, preleft+1, preleft+size, inleft, index-1);
root.right = build(preorder, inorder, preleft+size+1, preright, index+1, inright);

另外,采用hashmap可以快速获取中序遍历中节点在中序遍历中的位置

代码:

class Solution {
    private HashMap<Integer, Integer> map;
    public TreeNode build(int[] preorder, int[] inorder, int preleft, int preright, int inleft, int inright) {
        if (preleft > preright) {
            return null;
        }
        int index = map.get(preorder[preleft]);
        int size = index - inleft;

        TreeNode root = new TreeNode(preorder[preleft]);
        root.left = build(preorder, inorder, preleft+1, preleft+size, inleft, index-1);
        root.right = build(preorder, inorder, preleft+size+1, preright, index+1, inright);
        return root;
    }

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        map = new HashMap<Integer, Integer>();
        for(int i = 0; i < inorder.length; i++) {
            map.put(inorder[i], i);
        }
        return build(preorder, inorder, 0, preorder.length-1, 0, inorder.length-1);
    }
}

99. 恢复二叉搜索树

链接:恢复二叉搜索树
解题思路:
采用中序遍历,则得到的是一个递增的数列。
xy两个节点变量为null,每次root与前一个节点pre进行比较大小:倘若root.val > pre.root,则x = root,如果 y != null,y = pre(y值只需要记录一次)。
最后再将x的值与y的值进行交换
代码:

class Solution {
    TreeNode x = null;
    TreeNode y = null;
    TreeNode pre = new TreeNode(Integer.MIN_VALUE);

    public void recoverTree(TreeNode root) {
        recover(root);
        if(x != null && y != null) {
            int temp = x.val;
            x.val = y.val;
            y.val = temp;
        }
    }
    void recover(TreeNode root) {
        if(root == null) return;
        recover(root.left);
        if(root.val < pre.val) {
            x = root;
            if(y == null) {
                y = pre;
            }
        }
        pre = root;
        recover(root.right);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值