- 二叉树
- 题型1:二叉树前中后序遍历
- 144. 二叉树的前序遍历(简单)">144. 二叉树的前序遍历(简单)
- 94. 二叉树的中序遍历 (简单)">94. 二叉树的中序遍历 (简单)
- 145. 二叉树的后序遍历(简单)">145. 二叉树的后序遍历(简单)
- 589. N 叉树的前序遍历(简单)例题">589. N 叉树的前序遍历(简单)例题
- 590. N 叉树的后序遍历(简单)">590. N 叉树的后序遍历(简单)
- 题型2:二叉树按层遍历
- 题型3:二叉树上的递归
- 104. 二叉树的最大深度(简单)例题">104. 二叉树的最大深度(简单)例题
- 559. N 叉树的最大深度(简单)">559. N 叉树的最大深度(简单)
- 剑指 Offer 55 - II. 平衡二叉树(中等)例题">剑指 Offer 55 - II. 平衡二叉树(中等)例题
- 617. 合并二叉树(简单)">617. 合并二叉树(简单)
- 226. 翻转二叉树 (简单)">226. 翻转二叉树 (简单)
- 101. 对称二叉树(中等)">101. 对称二叉树(中等)
- 98. 验证二叉搜索树(中等)">98. 验证二叉搜索树(中等)
- 题型4:二叉查找树
- 题型1:二叉树前中后序遍历
二叉树
题型1:二叉树前中后序遍历
144. 二叉树的前序遍历(简单)
递归
class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();doPreOrderTraversal(root, result);return result;}private void doPreOrderTraversal(TreeNode root, List<Integer> list) {if(root == null) {return;}list.add(root.val);doPreOrderTraversal(root.left, list);doPreOrderTraversal(root.right, list);}}
迭代
解题思路:
class Solution {class StackFrame {private int status;private TreeNode node;public StackFrame(int status, TreeNode node) {this.status = status;this.node = node;}}public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();Stack<StackFrame> stack = new Stack<>();TreeNode p = root;while(true) {// 一路向左while(p != null) {stack.push(new StackFrame(1, p));result.add(p.val);p = p.left;}while(!stack.isEmpty() && stack.peek().status == 2) {p = stack.pop().node;}if(stack.isEmpty()) {break;}stack.peek().status = 2;p = stack.peek().node.right;}return result;}}
94. 二叉树的中序遍历 (简单)
递归
class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();doInorderTraversal(root, result);return result;}private void doInorderTraversal(TreeNode root, List<Integer> list) {if(root == null) {return;}doInorderTraversal(root.left, list);list.add(root.val);doInorderTraversal(root.right, list);}}
迭代
class Solution {class SFrame {private int status;private TreeNode node;public SFrame(int status, TreeNode node) {this.status = status;this.node = node;}}public List<Integer> inorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();Stack<SFrame> stack = new Stack<>();while(true) {// 一路向左while(root != null) {stack.push(new SFrame(1, root));root = root.left;}while(!stack.isEmpty() && stack.peek().status == 2) {stack.pop();}// 栈空证明迭代完成,结束死循环if(stack.isEmpty()) {break;}stack.peek().status = 2;// 中序遍历result.add(stack.peek().node.val);root = stack.peek().node.right;}return result;}}
145. 二叉树的后序遍历(简单)
递归
class Solution {public List<Integer> postorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();doPostOrderTraversal(root, result);return result;}private void doPostOrderTraversal(TreeNode root, List<Integer> list) {if(root == null) {return;}doPostOrderTraversal(root.left, list);doPostOrderTraversal(root.right, list);list.add(root.val);}}
迭代
class Solution {class SFrame {private int status;private TreeNode node;public SFrame(int status, TreeNode node) {this.status = status;this.node = node;}}public List<Integer> postorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>();Stack<SFrame> stack = new Stack<>();while(true) {// 一路向左while(root != null) {stack.push(new SFrame(1, root));root = root.left;}while(!stack.isEmpty() && stack.peek().status == 2) {result.add(stack.pop().node.val);}// 栈空证明迭代完成,结束死循环if(stack.isEmpty()) {break;}stack.peek().status = 2;// 中序遍历root = stack.peek().node.right;}return result;}}
589. N 叉树的前序遍历(简单)例题
递归
class Solution {public List<Integer> preorder(Node root) {List<Integer> res = new ArrayList<>();doPreOrder(root, res);return res;}private void doPreOrder(Node root, List<Integer> list) {if(root == null) {return;}list.add(root.val);for(Node child : root.children) {doPreOrder(child, list);}}}
迭代
class Solution {public List<Integer> preorder(Node root) {List<Integer> result = new ArrayList<>();if(root == null) {return result;}LinkedList<Node> stack = new LinkedList<>();stack.add(root);while(!stack.isEmpty()) {Node cur = stack.pollLast();result.add(cur.val);Collections.reverse(cur.children);stack.addAll(cur.children);}return result;}}
590. N 叉树的后序遍历(简单)
递归
class Solution {public List<Integer> postorder(Node root) {List<Integer> result = new ArrayList<>();if(root == null) {return result;}doPostOrder(root, result);result.add(root.val);return result;}private void doPostOrder(Node root, List<Integer> list) {if(root == null) {return;}for(Node child : root.children) {doPostOrder(child, list);list.add(child.val);}}}
迭代
解题思路:
class Solution {class SFrame {private Node node;private int status;public SFrame(int status, Node node) {this.status = status;this.node = node;}}public List<Integer> postorder(Node root) {List<Integer> result = new ArrayList<>();if(root == null) {return result;}LinkedList<SFrame> stack = new LinkedList<>();stack.add(new SFrame(1, root));while(!stack.isEmpty()) {Node node = stack.peekLast().node;stack.peekLast().status = 2;Collections.reverse(node.children);for(Node n : node.children) {stack.add(new SFrame(1, n));}while(!stack.isEmpty() && stack.peekLast().status == 2) {result.add(stack.pollLast().node.val);}}return result;}}
题型2:二叉树按层遍历
剑指 Offer 32 - I. 从上到下打印二叉树(中等)例题
队列
class Solution {public int[] levelOrder(TreeNode root) {if(root == null) {return new int[0];}Queue<TreeNode> queue = new LinkedList<>();List<Integer> list = new ArrayList<>();queue.add(root);while(!queue.isEmpty()) {TreeNode node = queue.poll();list.add(node.val);if(node.left != null) {queue.offer(node.left);}if(node.right != null) {queue.offer(node.right);}}int[] res = new int[list.size()];for(int i = 0; i< list.size(); i++) {res[i] = list.get(i);}return res;}}
102. 二叉树的层序遍历(中等)
利用队列实现层析遍历
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> resList = new ArrayList<>();if(root == null) {return resList;}LinkedList<TreeNode> queue = new LinkedList<>();queue.offer(root);while(!queue.isEmpty()) {int size = queue.size();List<Integer> list = new ArrayList<>();for(int i = 0; i < size; i++) {TreeNode node = queue.poll();list.add(node.val);if(node.left != null) {queue.offer(node.left);}if(node.right != null) {queue.offer(node.right);}}resList.add(list);}return resList;}}
递归-二叉树后序遍历
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> resList = new ArrayList<>();if(root == null) {return resList;}recursion(root, resList, 0);return resList;}private void recursion(TreeNode root, List<List<Integer>> resList, int level) {if(root == null) {return;}// 预先创建listif(resList.size() <= level) {resList.add(new ArrayList<>());}// 后序遍历recursion(root.left, resList, level + 1);recursion(root.right, resList, level + 1);// 利用下标来实现层次添加resList.get(level).add(root.val);}}
剑指 Offer 32 - III. 从上到下打印二叉树 III (中等)
队列
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> resList = new ArrayList<>();if(root == null) {return resList;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);int flag = 0;while(!queue.isEmpty()) {LinkedList<Integer> list = new LinkedList<>();int size = queue.size();for(int i = 0; i < size; i++) {TreeNode node = null;node = queue.poll();if((flag & 1) == 1) {list.offerFirst(node.val);} else {list.offerLast(node.val);}if(node.left != null) {queue.offer(node.left);}if(node.right != null) {queue.offer(node.right);}}resList.add(list);flag++;}return resList;}}
429. N 叉树的层序遍历(中等)
队列
class Solution {public List<List<Integer>> levelOrder(Node root) {List<List<Integer>> resList = new ArrayList<>();if(root == null) {return resList;}Queue<Node> queue = new LinkedList<>();queue.offer(root);while(!queue.isEmpty()) {List<Integer> list = new ArrayList<>();int size = queue.size();for(int i = 0; i < size; i++) {Node node = queue.poll();for(Node child : node.children) {queue.offer(child);}list.add(node.val);}resList.add(list);}return resList;}}
递归
class Solution {public List<List<Integer>> levelOrder(Node root) {List<List<Integer>> res = new ArrayList<>();doLevelOrder(root, res, 0);return res;}private void doLevelOrder(Node root, List<List<Integer>> list, int level) {if(root == null) {return;}if(list.size() <= level) {list.add(new ArrayList<Integer>());}list.get(level).add(root.val);for(Node child : root.children) {doLevelOrder(child, list, level + 1);}}}
513. 找树左下角的值(中等)
DFS-深度优先遍历
class Solution {private int depth = Integer.MIN_VALUE;private int res = 0;public int findBottomLeftValue(TreeNode root) {dfs(root, 0);return res;}private void dfs(TreeNode root, int d) {if(root != null) {if(root.left == null && root.right == null) {if(depth < d) {depth = d;res = root.val;}}dfs(root.left, d + 1);dfs(root.right, d + 1);}}}
递归
class Solution {public int findBottomLeftValue(TreeNode root) {List<List<Integer>> list = new ArrayList<>();postOrder(root, list, 0);return list.get(list.size() - 1).get(0);}private void postOrder(TreeNode root, List<List<Integer>> list, int level) {if(root == null) {return;}if(list.size() <= level) {list.add(new ArrayList<>());}postOrder(root.left, list, level + 1);postOrder(root.right, list, level + 1);list.get(level).add(root.val);}}
题型3:二叉树上的递归
104. 二叉树的最大深度(简单)例题
class Solution {public int maxDepth(TreeNode root) {if(root == null) {return 0;}int ld = maxDepth(root.left);int rd = maxDepth(root.right);return Math.max(ld, rd) + 1;}}
559. N 叉树的最大深度(简单)
class Solution {public int maxDepth(Node root) {if(root == null) {return 0;}if(root.children == null || root.children.isEmpty()){return 1;}int res = 0;for(Node child : root.children) {res = Math.max(res, maxDepth(child));}return res + 1;}}
剑指 Offer 55 - II. 平衡二叉树(中等)例题
解题思路:
class Solution {private boolean flag = true;public boolean isBalanced(TreeNode root) {maxDepth(root);if(!flag) {return false;}return true;}private int maxDepth(TreeNode root) {if(root == null) {return 0;}int ld = maxDepth(root.left);if(!flag) {return 0;}int rd = maxDepth(root.right);if(!flag) {return 0;}if(Math.abs(ld - rd) > 1) {flag = false;}return Math.max(ld, rd) + 1;}}
617. 合并二叉树(简单)
class Solution {public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {if(root1 == null && root2 == null) {return null;}if(root1 == null) {return root2;}if(root2 == null) {return root1;}TreeNode root = new TreeNode(root1.val + root2.val);root.left = mergeTrees(root1.left, root2.left);root.right = mergeTrees(root1.right, root2.right);return root;}}
226. 翻转二叉树 (简单)
解题思路:
递归公式:
- 原问题:交换根节点的左右子树的根节点
- 分解成子问题:
- 交换左子树的左右子树的根节点
- 交换右子树的左右子树的根节点
class Solution {public TreeNode invertTree(TreeNode root) {if(root == null) {return null;}TreeNode tmp = root.left;root.left = root.right;root.right = tmp;root.left = invertTree(root.left);root.right = invertTree(root.right);return root;}}
- 交换右子树的左右子树的根节点
101. 对称二叉树(中等)
递归
class Solution {private boolean flag = true;public boolean isSymmetric(TreeNode root) {if(root.left == null && root.right == null) {return flag;}dfs(root.left, root.right);return flag;}private void dfs(TreeNode lNode, TreeNode rNode) {if(lNode == null && rNode == null) {return;}if(lNode == null || rNode == null) {flag = false;return;}if(lNode.val != rNode.val) {flag = false;}dfs(lNode.left, rNode.right);dfs(lNode.right, rNode.left);}}
迭代
98. 验证二叉搜索树(中等)
中序遍历
解题思路:BST中序遍历,当前遍历的节点的值一定比上一个节点的值大。
/*** 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 long pre = Long.MIN_VALUE;public boolean isValidBST(TreeNode root) {if(root == null) {return true;}if(!isValidBST(root.left)) {return false;}long target = (long)root.val;if(pre >= target) {return false;}pre = target;return isValidBST(root.right);}}
递归
解题思路:
- BST 任意节点的值都比其左子树的节点值大,比其右子树节点的值小。
- 设置上界值upper、下界值lower,那么任意节点 node 的值都要满足 lower < node.val < upper。
对于左子树的上界值 upper = node.val,下界值为负无穷,右子树的下界值 lower = node.val,上界值为正无穷。
/*** 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 isValidBST(TreeNode root) {return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);}private boolean isValidBST(TreeNode node, long low, long upper) {if(node == null) {return true;}if(low < node.val && node.val < upper) {return isValidBST(node.left, low, node.val) && isValidBST(node.right, node.val, upper);}return false;}}
题型4:二叉查找树
剑指 Offer 54. 二叉搜索树的第k大节点(中等)
递归-中序遍历
class Solution {public int kthLargest(TreeNode root, int k) {List<Integer> list = new ArrayList<>();inOrder(root, list);int size = list.size();int idx = size - k;return list.get(idx);}private void inOrder(TreeNode root, List<Integer> list) {if(root == null) {return;}inOrder(root.left, list);list.add(root.val);inOrder(root.right, list);}}
时间复杂度:O(n)
空间复杂度:O(n)
中序遍历-剪枝优化
class Solution {private int count = 0;private int res = Integer.MIN_VALUE;public int kthLargest(TreeNode root, int k) {inOrder(root, k);return res;}private void inOrder(TreeNode root, int k) {if(root == null) {return;}inOrder(root.right, k);// 剪枝if(++count == k) {res = root.val;return;}inOrder(root.left, k);}}
时间复杂度:O(n)
空间复杂度:O(1)
538. 把二叉搜索树转换为累加树 (中等)
递归-中序遍历
class Solution {private int sum = 0;public TreeNode convertBST(TreeNode root) {if(root == null) {return null;}convertBST(root.right);sum += root.val;root.val = sum;convertBST(root.left);return root;}}
面试题 04.06. 后继者(中等)
递归-中序遍历
class Solution {private TreeNode res, pre, p;public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {this.p = p;dfs(root);return res;}private void dfs(TreeNode root) {if(root == null) {if(pre == p) {res = null;}return;}dfs(root.left);if(pre == p) {res = root;}pre = root;dfs(root.right);}}
