LeetBook-二叉树

105 阅读7分钟

二叉树

二叉树 - 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

  1. 递归
  2. 每层遍历都有一个level
  3. 如果当前level没有对应的list则往list中add一个ArrayList
  4. 每层从左至右,依次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

  1. 复用二叉树的层序遍历,里面有现成的level
  2. 定义一个le,当level大于le的时候给le赋值
  3. 返回层数
/**
 * 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

  1. 递归
  2. 取两个根节点(一个root两遍)进行遍历
  3. 一个树的左节点是否和右节点相等,酱紫判断,
  4. 如果node1的左不等于node2的右就返回false
  5. 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

  1. 先序遍历二叉树,记录到每个结点的和
  2. 如果某个节点的左右节点都为null,再进行判断是否相等
  3. 返回左节点的先序遍历||右节点的先序遍历
/**
 * 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

  1. 递归
  2. 每个结点的左右节点进行递归
    • 左的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

参考大佬思路

  1. 从右侧开始递归,确保当前节点next是连好的
  2. 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

  1. 递归
  2. 递归自己,如果碰到要找的节点,就返回
  3. 判断左为空就都在右边
  4. 判断右为空就都在左边
  5. 否则就一边一个,返回当前节点
/**
 * 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));