代码随想录第十九天LeetCode|513.找树左下角的值、112. 路径总和、113.路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树

 找树左下角的值  

        题目链接:513. 找树左下角的值 - 力扣(LeetCode)

        代码随想录题目解析:代码随想录 (programmercarl.com)

具体代码实现:

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

//给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

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 Solution1 {
    private int Deep = -1;
    private int value = 0;
    public int findBottomLeftValue(TreeNode root) {
        value = root.val;
        findLeftValue(root,0);
        return value;
    }

    private void findLeftValue (TreeNode root,int deep) {
        if (root == null) return;
        if (root.left == null && root.right == null) {
            if (deep > Deep) {
                value = root.val;
                Deep = deep;
            }
        }
        if (root.left != null) findLeftValue(root.left,deep + 1);
        if (root.right != null) findLeftValue(root.right,deep + 1);
    }
}

//迭代法
class Solution2 {

    public int findBottomLeftValue(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        int res = 0;
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode poll = queue.poll();
                if (i == 0) {
                    res = poll.val;
                }
                if (poll.left != null) {
                    queue.offer(poll.left);
                }
                if (poll.right != null) {
                    queue.offer(poll.right);
                }
            }
        }
        return res;
    }
}
public class Solution_text {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个完全二叉树的节点值(按层序遍历顺序输入,空节点用null表示):");
        String[] values = scanner.nextLine().trim().split(" ");
        int index = 0;
        TreeNode root = buildTree(values, index);

        Solution1 solution1 = new Solution1();
        int res = solution1.findBottomLeftValue(root);
        System.out.println("该二叉树的 最底层 最左边 节点的值:" + res);
        
        Solution2 solution2 = new Solution2();
        System.out.println("该二叉树的 最底层 最左边 节点的值:" + solution2.findBottomLeftValue(root));

        scanner.close();

    }

    private static TreeNode buildTree(String[] values, int index) {
        if (index >= values.length || values[index].equals("null")) {
            return null;
        }

        int val = Integer.parseInt(values[index]);
        TreeNode node = new TreeNode(val , buildTree(values, 2 * index + 1) , buildTree(values, 2 * index + 2));

        return node;
    }

}

 路径总和 ,路径总和||

        题目链接:112. 路径总和 - 力扣(LeetCode)113. 路径总和 II - 力扣(LeetCode)

        代码随想录题目解析:代码随想录 (programmercarl.com)

具体代码实现:


import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;


//112 判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 
//113 输出所有 从根节点到叶子节点 路径总和等于给定目标和的路径

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 Solution112 {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }
        targetSum -= root.val;
        // 叶子结点
        if (root.left == null && root.right == null) {
            return targetSum == 0;
        }
        if (root.left != null) {
            if (hasPathSum(root.left, targetSum)) {      // 已经找到
// 不用回溯,因为targetSum是定义在递归内的变量,在递归中传递他的副本,在本递归中保持不变,下层递归不影响它的值,只改变他的副本
                return true;							 
            }
        }
        if (root.right != null) {
            if (hasPathSum(root.right, targetSum)) {     // 已经找到
// 不用回溯,因为targetSum是定义在递归内的变量,在递归中传递他的副本,在本递归中保持不变,下层递归不影响它的值,只改变他的副本
                return true;
            }
        }
        return false;
    }
}

class Solution113 {
    public ArrayList<ArrayList<Integer>> pathSum(TreeNode root, int targetSum) {
    	ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
        if (root == null) return res; // 非空判断

        LinkedList<Integer> path = new LinkedList<Integer>();
        preorderdfs(root, targetSum, res, path);
        return res;
    }

    public void preorderdfs(TreeNode root, int targetSum, ArrayList<ArrayList<Integer>> res, LinkedList<Integer> path) {
        path.add(root.val);
        // 遇到了叶子节点
        if (root.left == null && root.right == null) {
            // 找到了和为 targetSum 的路径
            if (targetSum - root.val == 0) {
                res.add(new ArrayList<Integer>(path));
            }
            return; // 如果和不为 targetSum,返回
        }

        if (root.left != null) {
            preorderdfs(root.left, targetSum - root.val, res, path);
            path.remove(path.size() - 1); // 回溯,因为path是定义在递归外的变量,在递归中要手动回溯
        }
        if (root.right != null) {
            preorderdfs(root.right, targetSum - root.val, res, path);
            path.remove(path.size() - 1); // 回溯,因为path是定义在递归外的变量,在递归中要手动回溯
        }
    }
}

public class Solution_text {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个完全二叉树的节点值(按层序遍历顺序输入,用“,”分割,空节点用null表示):");
        String[] values = scanner.nextLine().trim().split(",");
        int index = 0;
        TreeNode root = buildTree(values, index);
        
        System.out.println("请输入目标和:");
        int targetSum = scanner.nextInt();

        Solution112 solution112 = new Solution112();
        if(solution112.hasPathSum(root, targetSum))
        	System.out.println("该树中存在根节点到叶子节点点值相加等于目标和的路径 ");
        else
        	System.out.println("该树中不存在根节点到叶子节点点值相加等于目标和的路径 ");
        
        Solution113 solution113 = new Solution113();
        
        for(ArrayList<Integer> i :solution113.pathSum(root,targetSum))
        	System.out.println(i);

        scanner.close();

    }

    private static TreeNode buildTree(String[] values, int index) {
        if (index >= values.length || values[index].equals("null")) {
            return null;
        }

        int val = Integer.parseInt(values[index]);
        TreeNode node = new TreeNode(val , buildTree(values, 2 * index + 1) , buildTree(values, 2 * index + 2));

        return node;
    }

}

 从中序与后序遍历序列构造二叉树 &&从前序与中序遍历序列构造二叉树

        代码随想录题目解析: 代码随想录 (programmercarl.com)
 具体代码实现:
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Scanner;


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;
	}
}

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

class Solution106 {
    Map<Integer, Integer> map;  // 方便根据数值查找位置
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        map = new HashMap<Integer, Integer>();
        for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
            map.put(inorder[i], i);
        }

        return findNode(inorder,  0, inorder.length, postorder,0, postorder.length);  // 前闭后开
    }

    public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
        // 参数里的范围都是前闭后开
        if (inBegin >= inEnd || postBegin >= postEnd) {  // 不满足左闭右开,说明没有元素,返回空树
            return null;
        }
        int rootIndex = map.get(postorder[postEnd - 1]);  // 找到后序遍历的最后一个元素在中序遍历中的位置
        TreeNode root = new TreeNode(inorder[rootIndex]);  // 构造结点
        int lenOfLeft = rootIndex - inBegin;  // 保存中序左子树个数,用来确定后序数列的个数
        
        //中序被分为[左中序,右中序],即[[inBegin,rootIndex),[rootIndex+1,inEnd)]   
        //注意左闭右开,相当于数学符号中的[inBegin,rootIndex-1]和[rootIndex+1,inorder.length-1],去除了rootIndex也就是根
        
        //后序被分为[左后序,右后序],即[[postBegin,postBegin+lenOfLeft),[postBegin+lenOfLeft,inEnd-1)]   
        //注意左闭右开,相当于数学符号中的[postBegin,postBegin+lenOfLeft-1]和[postBegin+lenOfLeft,inEnd-2],去除了inEnd-1,也就是根
        root.left = findNode(inorder, inBegin, rootIndex,                       //左中序
                            postorder, postBegin, postBegin + lenOfLeft);       //左后序
        root.right = findNode(inorder, rootIndex + 1, inEnd,					//右中序
                            postorder, postBegin + lenOfLeft, postEnd - 1);		//右后序

        return root;
    }
}

class Solution105 {
    Map<Integer, Integer> map;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        map = new HashMap<Integer, Integer>();
        for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
            map.put(inorder[i], i);
        }

        return findNode(preorder, 0, preorder.length, inorder,  0, inorder.length);  // 前闭后开
    }

    public TreeNode findNode(int[] preorder, int preBegin, int preEnd, int[] inorder, int inBegin, int inEnd) {
        // 参数里的范围都是前闭后开
        if (preBegin >= preEnd || inBegin >= inEnd) {  // 不满足左闭右开,说明没有元素,返回空树
            return null;
        }
        int rootIndex = map.get(preorder[preBegin]);  // 找到前序遍历的第一个元素在中序遍历中的位置
        TreeNode root = new TreeNode(inorder[rootIndex]);  // 构造结点
        int lenOfLeft = rootIndex - inBegin;  // 保存中序左子树个数,用来确定前序数列的个数
        
        //前序被分为[左前序,右前序],即[[preBegin + 1, preBegin + lenOfLeft + 1),[preBegin + lenOfLeft + 1, preEnd)]
        //注意左闭右开,相当于数学符号中的 [preBegin + 1, preBegin + lenOfLeft],[preBegin + lenOfLeft + 1, preEnd-1],去除了preBegin,也就是根
        
        //中序被分为[左中序,右中序],即[[inBegin,rootIndex),[rootIndex+1,inEnd)]   
        //注意左闭右开,相当于数学符号中的[inBegin,rootIndex-1]和[rootIndex+1,inorder.length-1],去除了rootIndex也就是根
        
        root.left = findNode(preorder, preBegin + 1, preBegin + lenOfLeft + 1,    //左前序
                            inorder, inBegin, rootIndex);						  //左中序
        root.right = findNode(preorder, preBegin + lenOfLeft + 1, preEnd,	      //右前序
                            inorder, rootIndex + 1, inEnd);						  //右中序

        return root;
    }
}
public class Solution_text {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入二叉树的前序遍历数组(数之间用,隔开):");
        String[] pre = scanner.nextLine().trim().split(",");
        int[] preorder = convertToIntArray(pre);
        
        System.out.println("请输入二叉树的中序遍历数组(数之间用,隔开):");
        String[] in = scanner.nextLine().trim().split(",");
        int[] inorder = convertToIntArray(in);
        
        System.out.println("请输入二叉树的后序遍历数组(数之间用,隔开):");
        String[] pos = scanner.nextLine().trim().split(",");
        int[] posorder = convertToIntArray(pos);
        
        System.out.println("106,按照中序和后续层序遍历输出节点值:");
        Solution106 solution106 = new Solution106();
        levelOrderTraversal(solution106.buildTree(inorder, posorder));
        
        System.out.println("105,按照中序和前续层序遍历输出节点值:");
        Solution105 solution105 = new Solution105();
        levelOrderTraversal(solution105.buildTree(preorder, inorder));
        
        scanner.close();

    }

    public static void levelOrderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }

        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);

        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();

            if (node == null) {
                System.out.print("null ");
                continue; // 跳过后续处理,直接进入下一次循环
            }

            System.out.print(node.val + " ");

            queue.offer(node.left);
            queue.offer(node.right);
        }
        System.out.print("\n");
    }

	public static int[] convertToIntArray(String[] stringArray) {
        int[] intArray = new int[stringArray.length];
        for (int i = 0; i < stringArray.length; i++) {
            intArray[i] = Integer.parseInt(stringArray[i]);
        }
        return intArray;
    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值