代码随想录算法训练营第18天 | 513. 找树左下角的值,112. 路径总和,106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树

代码随想录算法训练营第18天 | 513. 找树左下角的值,112. 路径总和,106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树

513. 找树左下角的值

  1. 用层序遍历的话 每一层都把最左边节点的值给到一个变量 那么他每次都会更新 最后输出为最后一层的值

层序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int findBottomLeftValue(TreeNode root) {
        //层序遍历 最后一层第一个为结果  
        Deque<TreeNode> que = new LinkedList<>();
        int leftval = 0;

        if(root!=null) que.addLast(root);

        while(!que.isEmpty()){
            int size = que.size();
            int size2 = size;
            while(size!=0){
                TreeNode node = que.pollFirst();
                if(size==size2){
                    leftval = node.val;
                }

                if(node.left!=null) que.addLast(node.left);
                if(node.right!=null) que.addLast(node.right);
                size--;

                
            }
        }
        return leftval;
        

    }
}

递归法

  1. 要求最后一行最靠左节点的值 只需要先向左遍历到最后一行即为结果
  2. 此题也没有中的操作 所以只需要先向左遍历再向右遍历
  3. 如何判断当前深度为最后一行 即每次遇到叶节点就判断 是否大于当前记录的最大深度 若不是就更新最大深度
  4. 回溯 就是当左边遍历到底了 想回去继续遍历右边 就需要每次递归完一次就往回退一格 往上回去
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int maxdepth = -1;
    int res = 0;
    public int findBottomLeftValue(TreeNode root) {
        traversal(root,0);
        return res;


    }

    public void traversal(TreeNode node,int depth){
        //终止条件
        if(node.left==null && node.right==null){
            if(depth>maxdepth){
                res = node.val;
                maxdepth = depth;
                //return res;
            }
        }

        //先向左遍历
        if(node.left!=null){
            depth++;
            traversal(node.left,depth);
            depth--;
        }

        //再向右遍历
        if(node.right!=null){
            depth++;
            traversal(node.right,depth);
            depth--;
        }
    }
}

112. 路径总和

  1. 终止条件为当 count减到0就 return ture 否则return false
  2. 需要首先减掉一次VAL 有可能root只有一个节点
  3. 接下来向左右遍历 如果下面的结果返回为ture 那么继续往上返回ture 往上面传递
  4. 然后回溯 即把count值加回来
  5. 注意传入 递归函数的参数很重要 假如传入的是 targetsum 那么就需要另一个变量来计数 然后就需要回溯 因为这个变量下去之后他的值变了
  6. 但是假如传入参数 就为count 那么就不需要回溯 因为每次递归 的count都是没变的 返回来上层的count

回溯隐藏

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root==null) return false;
        return pathsum(root,targetSum);

    }


    public boolean pathsum(TreeNode node, int count){
        //终止条件
        count-=node.val;
        if(node.left==null && node.right==null && count==0){
            return true;
        }
        if(node.left==null && node.right==null && count!=0){
            return false;
        }
        //向左右递归
        if(node.left!=null){
            //count-=node.left.val;
            if(pathsum(node.left,count)){
                return true;
            }
            //count+=node.left.val;
        }        

        if(node.right!=null){
            //count-=node.right.val;
            if(pathsum(node.right,count)==true){
                return true;
            }
            //count+=node.right.val;
        }      
        return false;      
    }
}

回溯不隐藏

  1. 设置全局变量
class Solution {
    boolean flag = false;
    int count = 0;
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if(root==null) return false;
        pathsum(root,targetSum);
        return flag;

    }


    public void pathsum(TreeNode node, int targetSum){
        //终止条件
        count+=node.val;
        if(node.left==null && node.right==null && count==targetSum){
            flag = true;
            return;
        }
        
        //向左右递归
        if(node.left!=null){
            //count-=node.left.val;
            pathsum(node.left,targetSum);
            //count+=node.left.val;
        }        

        if(node.right!=null){
            //count-=node.right.val;
            pathsum(node.right,targetSum);
            //count+=node.right.val;
        }        

        count-=node.val;
            
    }
}

113. 路径总和 II

  1. 路径总和ii要遍历整个树,找到所有路径,所以递归函数不要返回值
  2. 每次判断 targetSum-node.val是否为0 若不是 就继续向下面递归
  3. 向下递归时 传入的参数可以为 targetSum-node.val 这样递归完返回出来接下去的时候 targetSum不会改变
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> arr = new ArrayList<>();
    


    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        if(root==null) return res;
        getpath(root,targetSum);
        return res;
    }


    public void getpath(TreeNode node, int targetSum){
        //终止条件
        
        arr.add(node.val);
        //遍历到叶节点 
        if(node.left==null && node.right==null){
            if(targetSum-node.val==0){
                res.add(new ArrayList<>(arr));

            }
            

            return;
            
        }
        

        //向左右遍历
        if(node.left!=null){
            //回溯隐藏 进去 因为每一次都是减去当前的Node.val 接下去的时候targetsum不会变
            getpath(node.left,targetSum-node.val);
            //数组arr回溯
            arr.remove(arr.size()-1);
        }

        if(node.right!=null){
            
            getpath(node.right,targetSum-node.val);
            arr.remove(arr.size()-1);
        }        
        
    }
}

106.从中序与后序遍历序列构造二叉树

  1. 后序最后一个元素是根节点的值 找到根节点后 在中序中就可以知道左子树的长度 从而也知道右子树
  2. 然后对两个数组都进行切割 向左右递归

用map存inorder索引做法

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //map用来存中序数组的索引
    Map<Integer,Integer> map = new HashMap<>();
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        for(int i=0;i<inorder.length;i++){
            map.put(inorder[i],i);
        }

        return createTree(inorder,0,inorder.length,postorder,0,postorder.length);
    }

    //左闭右开区间
    public TreeNode createTree(int[] inorder,int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd){
        //终止条件
        if(inBegin>=inEnd || postBegin>=postEnd){
            return null;
        }

        //root为后序中最后一个
        TreeNode root = new TreeNode(postorder[postEnd-1]);
        
        //找中序数组的中root
        int rootIndex = map.get(root.val);

        //从中序数组中获取左子树的长度
        int leftLen = rootIndex-inBegin;

        //向左右递归
        root.left = createTree(inorder,inBegin,rootIndex,postorder,postBegin,postBegin+leftLen);
        root.right = createTree(inorder,rootIndex+1,inEnd,postorder,postBegin+leftLen,postEnd-1);

        return root;
        

    }
}

直接用循环遍历来找rootIndex

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    
    
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        

        return createTree(inorder,0,inorder.length,postorder,0,postorder.length);
    }

    //左闭右开区间
    public TreeNode createTree(int[] inorder,int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd){
        //终止条件
        if(inBegin>=inEnd || postBegin>=postEnd){
            return null;
        }

        //root为后序中最后一个
        TreeNode root = new TreeNode(postorder[postEnd-1]);
        
        //找中序数组的中root的索引
        int rootIndex=inBegin;
        for(;rootIndex<inEnd;rootIndex++){
            if(inorder[rootIndex]==root.val){
                break;
            }
        }

        //从中序数组中获取左子树的长度
        int leftLen = rootIndex-inBegin;

        //向左右递归
        root.left = createTree(inorder,inBegin,rootIndex,postorder,postBegin,postBegin+leftLen);
        root.right = createTree(inorder,rootIndex+1,inEnd,postorder,postBegin+leftLen,postEnd-1);

        return root;
        

    }
}

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

  1. 原理同上一题一样 即利用前序数组找到root 然后利用中序数组找到左右子树 递归下去
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    Map<Integer,Integer> map = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        for(int i = 0;i<inorder.length;i++){
            map.put(inorder[i],i);
        }
        return createTree(preorder,0,preorder.length,inorder,0,inorder.length);
    }
    
    //左闭右开区间
    public TreeNode createTree(int[] preorder,int preBegin,int preEnd,int[] inorder,int inBegin, int inEnd){
        //若root为空
        if(preBegin>=preEnd || inBegin>=inEnd){
            return null;
        }

        //从前序数组中获取中节点 root
        TreeNode root = new TreeNode(preorder[preBegin]);

        //获取中序数组中获取root的Index
        int rootIndex = map.get(root.val);

        //获取左子树的长度
        int leftlen = rootIndex - inBegin;

        //向左右节点递归
        root.left = createTree(preorder,preBegin+1,preBegin+leftlen+1,inorder,inBegin,rootIndex);
        root.right = createTree(preorder,preBegin+leftlen+1,preEnd,inorder,rootIndex+1,inEnd);

        return root;





    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值