二叉树
二叉树 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
二叉树的前序遍历
解法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 List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
preOrder(result, root);
return result;
}
public void preOrder(List<Integer> result, TreeNode node) {
if (node == null) {
return;
}
result.add(node.val);
preOrder(result, node.left);
preOrder(result, node.right);
}
}
二叉树的中序遍历
解法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 List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
inOrder(result, root);
return result;
}
public void inOrder(List<Integer> result, TreeNode node) {
if (node == null) {
return;
}
inOrder(result, node.left);
result.add(node.val);
inOrder(result, node.right);
}
}
二叉树的后序遍历
解法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 List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
postOrder(result, root);
return result;
}
public void postOrder(List<Integer> result, TreeNode node) {
if (node == null) {
return;
}
postOrder(result, node.left);
postOrder(result, node.right);
result.add(node.val);
}
}
二叉树的层序遍历
解法1
- 递归
- 每层遍历都有一个level
- 如果当前level没有对应的list则往list中add一个ArrayList
- 每层从左至右,依次add进入当前level对应的list
/**
* 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 List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
levelO(result, root, 0);
return result;
}
public void levelO(List<List<Integer>> result, TreeNode node, int level) {
if (node == null) {
return;
}
if (level >= result.size()) {
result.add(new ArrayList<>());
}
result.get(level).add(node.val);
levelO(result, node.left, level + 1);
levelO(result, node.right, level + 1);
}
}
二叉树的最大深度
解法1
- 复用二叉树的层序遍历,里面有现成的level
- 定义一个le,当level大于le的时候给le赋值
- 返回层数
/**
* 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 le = 0;
public int maxDepth(TreeNode root) {
if (root == null) {
return le;
}
levelOrder(root);
return le + 1;
}
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
levelO(result, root, 0);
return result;
}
public void levelO(List<List<Integer>> result, TreeNode node, int level) {
if (node == null) {
return;
}
if (level > le) {
le = level;
}
if (level >= result.size()) {
result.add(new ArrayList<>());
}
result.get(level).add(node.val);
levelO(result, node.left, level + 1);
levelO(result, node.right, level + 1);
}
}
简单优化一下,去掉List输出和一些不必要的东西
/**
* 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 le = 0;
public int maxDepth(TreeNode root) {
if (root == null) {
return le;
}
levelO(root, 0);
return le + 1;
}
public void levelO(TreeNode node, int level) {
if (node == null) {
return;
}
if (level > le) {
le = level;
}
levelO(node.left, level + 1);
levelO(node.right, level + 1);
}
}
对称二叉树
解法1
- 递归
- 取两个根节点(一个root两遍)进行遍历
- 一个树的左节点是否和右节点相等,酱紫判断,
- 如果node1的左不等于node2的右就返回false
- return结果
/**
* 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 isSymmetric(TreeNode root) {
return isT(root, root);
}
public boolean isT(TreeNode node1, TreeNode node2) {
if (node1 == null) {
if (node2 == null) {
return true;
}
return false;
}
if (node2 == null) {
return false;
}
return (node1.val == node2.val) && isT(node1.left, node2.right) && isT(node1.right, node2.left);
}
}
路径总和
解法1
- 先序遍历二叉树,记录到每个结点的和
- 如果某个节点的左右节点都为null,再进行判断是否相等
- 返回左节点的先序遍历||右节点的先序遍历
/**
* 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 preOrder(root, 0, targetSum);
}
public boolean preOrder(TreeNode node, int sum, int targetSum) {
if (node == null) {
return false;
}
if (node.left == null && node.right == null) {
return sum + node.val == targetSum;
}
sum += node.val;
return preOrder(node.left, sum, targetSum) || preOrder(node.right, sum, targetSum);
}
}
从中序与后序遍历序列构造二叉树
解法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 {
private int postRootIndex = 0;
private int[] gInOrder;
private int[] gPostOrder;
private HashMap<Integer, Integer> map = new HashMap<>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
gInOrder = inorder;
gPostOrder = postorder;
int length = gPostOrder.length;
postRootIndex = length - 1;
for (int i = 0; i < length; i++) {
map.put(gInOrder[i], i);
}
return createNode(0, postRootIndex);
}
public TreeNode createNode(int inLeft, int inRight) {
if (inLeft > inRight) {
return null;
}
int rootValue = gPostOrder[postRootIndex];
postRootIndex--;
TreeNode node = new TreeNode(rootValue);
int inRootIndex = map.get(rootValue);
node.right = createNode(inRootIndex + 1, inRight);
node.left = createNode(inLeft, inRootIndex - 1);
return node;
}
}
从前序与中序遍历序列构造二叉树
解法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 {
private int preRootIndex = 0;
private int[] gPreOrder;
private int[] gInOrder;
private Map<Integer, Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
gPreOrder = preorder;
gInOrder = inorder;
int length = gPreOrder.length;
preRootIndex = 0;
for (int i = 0; i < length; i++) {
map.put(gInOrder[i], i);
}
return createNode(0, length - 1);
}
private TreeNode createNode(int inLeft, int inRight) {
if (inLeft > inRight) {
return null;
}
int rootValue = gPreOrder[preRootIndex];
preRootIndex++;
TreeNode node = new TreeNode(rootValue);
int inRootIndex = map.get(rootValue);
node.left = createNode(inLeft, inRootIndex - 1);
node.right = createNode(inRootIndex + 1, inRight);
return node;
}
}
填充每个结点的下一个右侧结点指针
解法1
- 递归
- 每个结点的左右节点进行递归
- 左的left连左的right
- 左的right连右的left
- 右的left连右的right
/*
// 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) {
if (root != null) {
dododo(root.left, root.right);
}
return root;
}
public void dododo (Node left, Node right) {
if (left == null || left.next == right) {
return;
}
left.next = right;
dododo(left.left, left.right);
dododo(left.right, right.left);
dododo(right.left, right.right);
}
}
填充每个结点的下一个右侧结点指针Ⅱ
思路X
一个思路,复用上一题,进行冗余连接,从外往里连,先连两头,然后逐渐缩小范围,but,有个例子过不了,留坑,待填
解法1
参考大佬思路
- 从右侧开始递归,确保当前节点next是连好的
- getNext传入父节点,可以get左右的left和right
/*
// 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) {
if (root == null) {
return root;
}
if (root.left != null) {
root.left.next = root.right != null ? root.right : getNext(root.next);
}
if (root.right != null) {
root.right.next = getNext(root.next);
}
connect(root.right);
connect(root.left);
return root;
}
public Node getNext (Node node) {
if (node == null) {
return null;
}
if (node.left != null) {
return node.left;
}
if (node.right != null) {
return node.right;
}
return getNext(node.next);
}
}
二叉树的最近公共祖先
解法1
- 递归
- 递归自己,如果碰到要找的节点,就返回
- 判断左为空就都在右边
- 判断右为空就都在左边
- 否则就一边一个,返回当前节点
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left == null) {
return right;
}
if (right == null) {
return left;
}
return root;
}
}
二叉树的序列化与反序列化
中序、后序、先序和层次遍历解法 - 二叉树的序列化与反序列化 - 力扣(LeetCode)
解法1
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) {
return "null";
}
return root.val + "," + serialize(root.left) + "," + serialize(root.right);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
List<String> list = new ArrayList<String>(Arrays.asList(data.split(",")));
return createTree(list);
}
public TreeNode createTree(List<String> list) {
if ("null".equals(list.get(0))) {
list.remove(0);
return null;
}
TreeNode node = new TreeNode(Integer.valueOf(list.get(0)));
list.remove(0);
node.left = createTree(list);
node.right = createTree(list);
return node;
}
}
// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// TreeNode ans = deser.deserialize(ser.serialize(root));