LeetCode 話題の HOT 100
105. Preorder および Inorder トラバーサル シーケンスからのバイナリ ツリーの構築
質問: 2 つの整数配列 preorder と inorder が与えられた場合、preorder は二分木の前順走査であり、inorder は同じ木の順走査であり、
二分木を構築してそのルート ノードを返します。
例 1:
入力: preorder = [3,9,20,15,7]、inorder = [9,3,15,20,7]
出力: [3,9,20,null,null,15,7]
package ricky.com.Hot100;
import java.util.HashMap;
/**
* @Author xdg
*/
public class buildTree {
/*105. 从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,
请构造二叉树并返回其根节点。*/
// 定义二叉树节点的结构
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 {
// 声明一个 HashMap,用于存储中序遍历数组中每个元素的索引
HashMap<Integer, Integer> map = new HashMap<>();
// 构建二叉树的函数,参数为先序遍历数组和中序遍历数组
public TreeNode buildTree(int[] preorder, int[] inorder) {
// 将中序遍历数组中每个元素的值和索引存储到 HashMap 中
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
// 调用递归函数构建二叉树,返回根节点
return f(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}
// 递归函数,参数为先序遍历数组、中序遍历数组、以及它们在当前递归层次下的边界
private TreeNode f(int[] preorder, int l1, int r1, int[] inorder, int l2, int r2) {
// 如果左边界大于右边界,说明当前子树为空,返回 null
if (l1 > r1) {
return null;
}
// 构建当前子树的根节点
TreeNode root = new TreeNode(preorder[l1]);
// 在中序遍历数组中找到根节点的位置
int i = map.get(preorder[l1]);
// 递归构建左子树,左子树的元素范围为 preorder[l1+1, l1+i-l2] 和 inorder[l2, i-1]
root.left = f(preorder, l1 + 1, l1 + i - l2, inorder, l2, i - 1);
// 递归构建右子树,右子树的元素范围为 preorder[l1+i-l2+1, r1] 和 inorder[i+1, r2]
root.right = f(preorder, l1 + i - l2 + 1, r1, inorder, i + 1, r2);
// 返回当前子树的根节点
return root;
}
}
}
114. 二分木を連結リストに展開する
トピック: バイナリ ツリーのルート ノード ルートが与えられたら、単一リンク リストに展開してください:
展開された単一リンク リストも TreeNode を使用する必要があります。ここで、右のサブポインタはリンク リストの次のノードを指し、左のサブポインタはサブポインターは常に null です。
展開された単一リンク リストは、バイナリ ツリーの事前順序走査と同じ順序である必要があります。
**例 1:
入力: root = [1,2,5,3,4,null,6]
出力: [1,null,2,null,3,null,4,null,5,null,6]
アイデア分析:まず、二分木に対して事前順序探索を実行し、探索結果を List に格納します。次に、リスト内のノードをトラバースして、リンクされたリストを作成します。具体的には、List の最初のノードを新しいルート ノードとして取得し、その左ポインタを null に設定します。次に、ポインター cur を定義します。最初は新しいルート ノードを指し、List 内の残りのノードをトラバースし、現在のノードの右ポインターを次のノードに指し、左ポインターを null に設定し、ポインター cur を次のノードに指します。すべてのノードがトラバースされるまで、上記のプロセスを繰り返します。最後に戻るだけです。
class Solution {
List<TreeNode> list = new ArrayList<>(); // 声明一个 List,用于存储先序遍历的结果
// 将二叉树拉平为链表的函数,参数为二叉树的根节点
public void flatten(TreeNode root) {
if (root == null) {
// 如果根节点为空,直接返回
return;
}
preOrder(root); // 对二叉树进行先序遍历,将结果存储到 List 中
TreeNode newRoot = list.get(0); // 获取二叉树拉平后的新根节点
newRoot.left = null; // 将新根节点的左指针置为 null
TreeNode cur = newRoot; // 定义一个指针,指向当前处理的节点
for (int i = 1; i < list.size(); i++) {
// 遍历 List 中的节点,构建链表
cur.right = list.get(i); // 当前节点的右指针指向下一个节点
cur.left = null; // 当前节点的左指针置为 null
cur = cur.right; // 将指针指向下一个节点
}
return;
}
// 递归函数,对二叉树进行先序遍历,并将结果存储到 List 中
private void preOrder(TreeNode root) {
if (root == null) {
// 如果当前节点为空,直接返回
return;
}
list.add(root); // 将当前节点加入到 List 中
preOrder(root.left); // 递归遍历左子树
preOrder(root.right); // 递归遍历右子树
}
}
124. 二分木の最大パス合計
タイトル: パスは、ツリー内の任意のノードから始まり、親子接続をたどって任意のノードに到達するシーケンスとして定義されます。同じノードは、
パス シーケンス内で最大 1 回出現します。パスには少なくとも 1 つのノードが含まれており、必ずしもルート ノードを通過する必要はありません。
パスの合計は、パス内の各ノードの値の合計です。
バイナリ ツリーのルート ノード ルートを指定して、その最大パス合計を返します。.
**例 1:
入力: root = [-10,9,20,null,null,15,7]
出力: 42
説明: 最適なパスは 15 -> 20 -> 7 で、パスの合計は 15 + 20 + 7 = 42 です。
アイデア分析:ポストオーダー トラバーサルを使用してバイナリ ツリーをトラバースし、各ノードをパスの開始点として最大パス合計を計算します。各ノードについて、最初にその左右のサブツリーを再帰的にトラバースし、左右のサブツリーの最大パス合計を計算します。次に、現在のノードをパスの始点として、現在のノードの最大パス合計を計算します。つまり、現在のノードの値に、左部分木の最大パス合計と最大パスの合計を加えた値を計算します。右のサブツリーの合計、および現在のノードと左と右の値 最大パスとサブツリーの合計の合計の最大値。最後に、グローバル最大パス合計を現在のパスの最大値、つまり Math.max(res, Math.max(temp, root.val + left + right)) に更新します。最後に、グローバル最大パスと res を返します。
class Solution {
int res = Integer.MIN_VALUE; // 定义全局变量,用于保存最大路径和
public int maxPathSum(TreeNode root) {
if (root == null) {
// 如果根节点为空,返回0
return 0;
}
postOrder(root); // 对树进行后序遍历,计算最大路径和
return res; // 返回最大路径和
}
// 后序遍历二叉树,并计算以当前节点为起点的最大路径和
private int postOrder(TreeNode root) {
if (root == null) {
// 如果当前节点为空,返回0
return 0;
}
// 分别对左子树和右子树进行后序遍历,并计算左子树和右子树的最大路径和
int left = postOrder(root.left);
int right = postOrder(root.right);
// 计算以当前节点为起点的最大路径和,并更新全局最大路径和
int temp = Math.max(root.val, root.val + Math.max(left, right)); // 计算以当前节点为起点的路径
res = Math.max(res, Math.max(temp, root.val + left + right)); // 更新全局最大路径和
// 返回以当前节点为起点的最大路径和
return temp;
}
}