【LeetCode-面试经典150题-day16】

目录

114.二叉树展开为链表

 112.路径总和

 129.求根节点到叶节点数字之和

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


114.二叉树展开为链表

题意:

给你二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。
  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。

【输入样例】

root=[1,2,5,3,4,6]

扫描二维码关注公众号,回复: 16974389 查看本文章

【输出样例】[1,null,2,null,3,null,4,null,5,null,6]

解题思路:

先序遍历的顺序是:根 左右,

使用链表先存储先序遍历的节点顺序,之后遍历链表,更新每个节点的左右指针。

class Solution {
    public void flatten(TreeNode root) {
        List<TreeNode> list = new ArrayList<TreeNode>();
        preOrder(root,list);
        //list中存储的所有节点信息,已知第一个是root
        int size = list.size();
        for(int i=1;i<size;++i){
            //从根之后开始修改就好了
            TreeNode prev = list.get(i-1);//取上一个节点
            TreeNode curr = list.get(i);//取当前节点,当前节点作为上一节点的右节点
            prev.left = null;
            prev.right = curr;
        }
    }
    public void preOrder(TreeNode root, List<TreeNode> list){
        if(root != null){
            //先遍历根节点
            list.add(root);
            //遍历左子树
            preOrder(root.left,list);
            preOrder(root.right,list);
        }
    }
}

时间: 击败了21.30%

内存: 击败了92.42%

解题思路2:

边遍历边展开,每一次都把右子树接到左子树的最右边节点,然后把当前节点的左子树插入到右子树上。

class Solution {
    public void flatten(TreeNode root) {
       while(root != null){
           if(root.left == null){
               //左子树为空则遍历右子树第一个节点
               root = root.right;
           }else{
               //找到左子树最右边的节点
               TreeNode prev = root.left;
               while(prev.right != null){
                   prev = prev.right;
               }
               //原来的右子树接驾到这里来
               prev.right = root.right;
               //左子树插入到右子树
               root.right = root.left;
               root.left = null;//左子树一定要修改为空
               //考虑下一个节点
               root = root.right;
           }
       }
    }
}

时间: 击败了100.00%

内存: 击败了62.48%

 112.路径总和

题意:

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

【输入样例】

root=[5,4,8,11,null,13,4,7,2,null,null,null,null,1],targetSum=22

【输出样例】true

解题思路:

使用深度遍历结合递归的方法

没遍历到一个节点,targetSum-=root.val;之后进行判断

1.如果targetSum=0,并且当前节点是叶子节点,返回true;

2.否则,继续遍历,遍历采用双路遍历,直接判断其继续往左子树或右子树遍历,能否找到正确的路径。

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

时间: 击败了100.00%

内存: 击败了45.57%

 129.求根节点到叶节点数字之和

题意:

给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。

每条从根节点到叶节点的路径都代表一个数字:

  • 例如,从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 123 。

计算从根节点到叶节点生成的 所有数字之和 。

叶节点 是指没有子节点的节点。

【输入样例】

root=[4,9,0,5,1]

【输出样例】1026

495+191+40=1026

解题思路:

1. 采用深度遍历的想法,首先要遍历出每一条路径,并且统计她们的数字各自是多少,之后进行相加就可以。

class Solution {
    public int sumNumbers(TreeNode root) {
        return depthOrder(root,0);
    }
    public int depthOrder(TreeNode root,int temp){
        if(root == null){
            return 0;
        }
        int sum = temp * 10 + root.val;//之前得到的和*10加上当前的数字,就是路径上的数字
        if(root.left == null && root.right == null){
            return sum;
        }
        //左子树右子树继续遍历
        return depthOrder(root.left,sum)+depthOrder(root.right,sum);
    }
}

时间: 击败了100.00%

内存: 击败了70.62%

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

题意:

二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 

【输入样例】

root=[-10,9,20,null,null,15,7]

【输出样例】42

15+20+7=42

解题思路:

实际上就是找到,在以该节点为根节点的子树中寻找以该节点为起点的一条路径,使得该路径上的节点值之和最大。

class Solution {
    int maxSum = Integer.MIN_VALUE;
    public int maxPathSum(TreeNode root) {
        maxGain(root);//计算
        return maxSum;
    }
    public int maxGain(TreeNode node){
        if(node == null){
            return 0;
        }
        //递归,计算该节点左节点的最大贡献值
        //跟0比是考虑,如果这个以左节点为根,其子树所有的路径加起来都是负数,就不选择,用0代替
        int leftGain = Math.max(maxGain(node.left),0);
        //递归,计算该节点右节点的最大贡献值
        int rightGain = Math.max(maxGain(node.right),0);

        int newPathSum = node.val + leftGain + rightGain;
        maxSum = Math.max(maxSum,newPathSum);
        //这个return是用来递归的时候使用的,所以主函数中返回的是maxSum
        return node.val + Math.max(leftGain,rightGain);
    }
}

时间: 击败了100.00%

内存: 击败了47.52%

猜你喜欢

转载自blog.csdn.net/qq_37998848/article/details/132545773