找树左下角的值
题目链接: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;
}
}