代码随想录Day17&Day18

Day17

今日任务

  • 110.平衡二叉树
    1. 二叉树的所有路径
  • 404.左叶子之和

代码实现

110.平衡二叉树
这里的巧妙之处在于发现不是一颗平衡二叉树的时候返回了-1,这样把计算高度和判断是否是平衡二叉树可以组合起来,这里我昨天想了半天,想不出,然后看题解,感觉会了,第二天再写,还是写不出,巧妙

    public boolean isBalanced(TreeNode root) {
        return getHeight(root) > 0;
    }

    int getHeight(TreeNode cur) {
        //左 右 中 后序遍历
        if (cur == null) return 0;
        int leftHeight = getHeight(cur.left);
        if (leftHeight == -1) {
            return -1;
        }
        int rightHeight = getHeight(cur.right);
        if (rightHeight == -1) {
            return -1;
        }
        return Math.abs(leftHeight - rightHeight) > 1 ? -1 : 1 + Math.max(leftHeight, rightHeight);
    }
  1. 二叉树的所有路径
    这里主要是需要记录路径,说实话,第一次写一点思路也没,现在都不会思考了
    public List<String> binaryTreePaths(TreeNode root) {
        if (root == null) return new ArrayList<>();
        List<String> result = new ArrayList<>();
        List<Integer> values = new ArrayList<>();
        getBinaryPath(root, values, result);
        return result;
    }

    void getBinaryPath(TreeNode cur, List<Integer> values, List<String> paths) {
        //这里这样写我认为是为了 当cur.left 和 cur.right 都为null的时候,下边会进入两次递归调用
        //中 左 右 先序遍历
        values.add(cur.val);
        if (cur.left == null && cur.right == null) {
            paths.add(getPath(values));
            return;
        }
        if (cur.left != null) {
            getBinaryPath(cur.left, values, paths);
            //每次处理完成后要移除掉最后一个元素也就是cur.left,这是因为在递归中已经获取到cur.left下面所有叶子节点的路径了,现在要往上返回
            values.remove(values.size() - 1);
        }
        if (cur.right != null) {
            getBinaryPath(cur.right, values, paths);
            values.remove(values.size() - 1);
        }
    }

    String getPath(List<Integer> values) {
        return values.stream().map(Object::toString).collect(Collectors.joining("->"));
    }

404.左叶子之和
这道题用递归的话其实比较简单,关键在于如何定义左叶子,要敢于用上一层的节点去判断,不局限于递归的current节点中

    public int sumOfLeftLeaves(TreeNode root) {
        //
        if (root == null) return 0;
        if (root.left != null && root.left.left == null && root.left.right == null) {
            return root.left.val + sumOfLeftLeaves(root.right);
        }
        return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right);

    }

Day18

今日任务

  • 513.找树左下角的值
    1. 路径总和 113.路径总和ii
  • 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树

代码实现

513.找树左下角的值
这里用层序遍历的话比较简单,用递归的话需要你定义两个全局变量,这个不太好想

//层序遍历
      public int findBottomLeftValue(TreeNode root) {
        int result = root.val;
        Queue<TreeNode> queue = new ArrayDeque<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode poll = queue.poll();
                if (i == 0) {
                    result = poll.val;
                }
                if (poll.left != null) queue.add(poll.left);
                if (poll.right != null) queue.add(poll.right);
            }
        }
        return result;
    }
//递归,只给出递归体,没写调用
    int maxDepth = Integer.MIN_VALUE;   // 全局变量 记录最大深度
    int result;       // 全局变量 最大深度最左节点的数值

    public void findLeftMost(TreeNode cur, int depth) {
        if (cur == null) return;
        if (depth > maxDepth) {
            result = cur.val;
        }
        findLeftMost(cur.right, depth + 1);
        findLeftMost(cur.left, depth +1);
    }
  1. 路径总和 113.路径总和ii
    这两道题的思路是一样的,和昨天的二叉树的所有路径也是一样的,正好我是一天做的,所以感觉简单
//路径总和 
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) return false;
        return hasTargetSum(root, 0, targetSum);
    }

    public boolean hasTargetSum(TreeNode cur, int beforeSum, int targetSum) {
        if (cur == null) return false;
        beforeSum+=cur.val;
        if (cur.left == null && cur.right == null && targetSum == beforeSum) {
            return true;
        }
        return hasTargetSum(cur.left, beforeSum, targetSum) || hasTargetSum(cur.right, beforeSum, targetSum);
    }
//路径总和ii
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        if(root == null) return new ArrayList();
        List<List<Integer>> result = new ArrayList<>();
        hasTargetSum(root, 0, targetSum, result, new ArrayList<>());
        return result;
    }

    public void hasTargetSum(TreeNode cur, int beforeSum, int targetSum, List<List<Integer>> result, List<Integer> beforeValues) {
        beforeSum+=cur.val;
        beforeValues.add(cur.val);
        if (cur.left == null && cur.right == null && targetSum == beforeSum) {
            result.add(new ArrayList<>(beforeValues));
        }
        if (cur.left != null) {
            hasTargetSum(cur.left, beforeSum, targetSum, result, beforeValues);
            beforeValues.remove(beforeValues.size() - 1);
        }
        if (cur.right != null) {
            hasTargetSum(cur.right, beforeSum, targetSum, result, beforeValues);
            beforeValues.remove(beforeValues.size() - 1);
        }
    }

从中序与后序遍历序列构造二叉树(节点中没有重复值)
这道题如果理清思路的话还是非常好写,同理,从前序与中序遍历序列构造二叉树也差不多
注意:前序和后序不能唯一的确定一颗二叉树
思路:首先由后序遍历数组确定中间的值(即root),然后用root值可以对中序遍历数组进行切分,找到切分的位置,即左右元素个数就确定了,此时可以对后序遍历的数组进行切分,然后对切分后的进行递归,即可确认每一个子树

//TODO 这里可以优化的是,在递归时不需要每次都搞一个新数组,而是用原数组+index的方式查找元素,
//这样写效率比较高,但是更容易出错,由于时间原因和身体原因,我就没有写了
    public TreeNode buildTree(int[] inorder, int[] postorder) {

        if (postorder == null || postorder.length == 0) return null;
        if (postorder.length == 1) return new TreeNode(postorder[0]);
        int middle = postorder[postorder.length - 1];
        TreeNode root = new TreeNode(middle);
        int middleIndex = 0;
        for (int i = 0; i < inorder.length; i++) {
            if (inorder[i] == middle){
                middleIndex = i;
            }
        }

        int[] leftInorder = new int[middleIndex];
        int[] rightInorder = new int[inorder.length - middleIndex - 1];

        int[] leftPostorder = new int[middleIndex];
        int[] rightPostorder = new int[inorder.length - middleIndex - 1];
        for (int i = 0; i < inorder.length; i++) {
            if (i < middleIndex) {
                leftInorder[i] = inorder[i];
            } else if (i > middleIndex) {
                rightInorder[i - middleIndex - 1] = inorder[i];
            }
        }

        for (int i = 0; i < postorder.length - 1; i++) {
            if (i < middleIndex) {
                leftPostorder[i] = postorder[i];
            } else {
                rightPostorder[i - middleIndex] = postorder[i];
            }
        }


        root.left = buildTree(leftInorder, leftPostorder);
        root.right = buildTree(rightInorder, rightPostorder);

        return root;

    }

两日总结

1.很多题目虽然是简单,看过解法之后也确实是简单,但是由于没有做过,对于很多技巧不知道,比如保存前值啦,设置全局变量啦,导致根本想不到,所以我基本上都是看了题解之后才能做出来,那么这一遍只能算是学习基础,了解一遍各种解法,后续再刷的时候才有机会自己想到;
2.今日发烧了,本来就不聪明的大脑现在更是雪上加霜;
3.现在的A股吧,买又怕回调,不买的话又怕踏空,真是左右为难,又没时间一直盯盘(盯了也不敢操作),希望早日回本。

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值