lc105. 从前序和中序遍历序列构造二叉树(MD)

给定两个整数数组 preorderinorder ,其中 preorder 是二叉树的先序遍历inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

img

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]

提示:

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorderinorder无重复 元素
  • inorder 均出现在 preorder
  • preorder 保证 为二叉树的前序遍历序列
  • inorder 保证 为二叉树的中序遍历序列

用一个栈和一个指针辅助构造。依次遍历前序序列的每一个节点,如果index和栈顶节点不同,就把当前节点作为栈顶节点的左儿子;如果index恰好指向栈顶节点,那么不断弹出栈顶节点并移动index

/**
* 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[] preorder, int[] inorder) {
if (preorder == null || preorder.length == 0) {
return null;
}
TreeNode root = new TreeNode(preorder[0]);
Deque<TreeNode> stk = new LinkedList<>();
stk.push(root);
int inorderIndex = 0;
for (int i = 1; i < preorder.length; i++) {
int preorderVal = preorder[i];
TreeNode node = stk.peek();
if (node.val != inorder[inorderIndex]) {
node.left = new TreeNode(preorderVal);
stk.push(node.left);
} else {
while (!stk.isEmpty() && stk.peek().val == inorder[inorderIndex]) {
node = stk.pop();
inorderIndex++;
}
node.right = new TreeNode(preorderVal);
stk.push(node.right);
}
}
return root;
}
}

lc106. 从中序和后序遍历序列构造二叉树(MD)

给定两个整数数组 inorderpostorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树

示例 1:

img

输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]

示例 2:

输入:inorder = [-1], postorder = [-1]
输出:[-1]

提示:

  • 1 <= inorder.length <= 3000
  • postorder.length == inorder.length
  • -3000 <= inorder[i], postorder[i] <= 3000
  • inorderpostorder 都由 不同 的值组成
  • postorder 中每一个值都在 inorder
  • inorder 保证是树的中序遍历
  • postorder 保证是树的后序遍历

和上一题思路一样

/**
* 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) {
if (postorder == null || postorder.length == 0) {
return null;
}
TreeNode root = new TreeNode(postorder[postorder.length - 1]);
Deque<TreeNode> stk = new LinkedList<>();
stk.push(root);
int inorderIndex = inorder.length - 1;
for (int i = postorder.length - 2; i >= 0; i--) {
int postorderVal = postorder[i];
TreeNode node = stk.peek();
if (node.val != inorder[inorderIndex]) {
node.right = new TreeNode(postorderVal);
stk.push(node.right);
} else {
while (!stk.isEmpty() && stk.peek().val == inorder[inorderIndex]) {
node = stk.pop();
inorderIndex--;
}
node.left = new TreeNode(postorderVal);
stk.push(node.left);
}
}
return root;
}
}

lc117. 填充每个节点的下一个右侧节点指针 II(MD)

给定一个二叉树:

struct Node {
int val;
Node *left;
Node *right;
Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL

初始状态下,所有 next 指针都被设置为 NULL

示例 1:

img

输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),'#' 表示每层的末尾。

示例 2:

输入:root = []
输出:[]

提示:

  • 树中的节点数在范围 [0, 6000]
  • -100 <= Node.val <= 100

进阶:

  • 你只能使用常量级额外空间。
  • 使用递归解题也符合要求,本题中递归程序的隐式栈空间不计入额外空间复杂度。

暂时不考虑进阶要求,其实是我写不出来

有点类似于二叉树层级遍历,思路上总体相似

/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node next;

public Node() {}

public Node(int _val) {
val = _val;
}

public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
};
*/

class Solution {
public Node connect(Node root) {
Queue<Node> que = new LinkedList<>();
if (root != null) {
que.offer(root);
}
while (!que.isEmpty()) {
int len = que.size();
Node node = null;
Node next = null;
for (int i = 0; i < len; i++) {
if (i == 0) {
next = que.poll();
node = next;
} else {
next = que.poll();
node.next = next;
node = next;
}
if (node.left != null) {
que.offer(next.left);
}
if (node.right != null) {
que.offer(next.right);
}
}
next.next = null;
}
return root;
}
}

lc114. 二叉树展开为链表(MD)

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

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

示例 1:

img

输入:root = [1,2,5,3,4,null,6]
输出:[1,null,2,null,3,null,4,null,5,null,6]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [0]
输出:[0]

提示:

  • 树中结点数在范围 [0, 2000]
  • -100 <= Node.val <= 100

**进阶:**你可以使用原地算法(O(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 void flatten(TreeNode root) {
while (root != null) {
if (root.left == null) {
root = root.right;
} else {
TreeNode pre = root.left;
while (pre.right != null) {
pre = pre.right;
}
pre.right = root.right;
root.right = root.left;
root.left = null;
root = root.right;
}
}
}
}