image.png

二叉树遍历

144. 二叉树的前序遍历

94. 二叉树的中序遍历

145. 二叉树的后序遍历

102. 二叉树的层序遍历

image.png

递归

image.png

前序遍历

image.png

中序遍历

image.png

后序遍历

image.png

迭代

前序遍历 二叉树前序遍历 迭代法(显示递归栈) 结果放到数组中,不停的往后放

image.png
image.png

中序遍历

image.png
image.png

后续遍历

二叉树后序遍历 迭代法(显示递归栈) 前序遍历结果放到ArrayList数组中,不停的往后放, 后序遍历结果放到LinkedList(双端队列,可以往前放)中,结果不停的往前放。与前序历不同之处:

  1. 把左右节点的入栈顺序调换
  2. 完成整个数组的反转(通过linkedList双端队列完成) 如果不用LinkedList把结果放在前面则可以用Collections把结果反转

image.png
image.png

统一迭代

前序遍历

image.png

中序遍历

image.png

后序遍历

image.png

层序遍历

层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。 需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑, 而是用栈先进后出适合模拟 深度优先遍历也就是递归的逻辑。

image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode() {}
  8. * TreeNode(int val) { this.val = val; }
  9. * TreeNode(int val, TreeNode left, TreeNode right) {
  10. * this.val = val;
  11. * this.left = left;
  12. * this.right = right;
  13. * }
  14. * }
  15. */
  16. class Solution {
  17. public List<List<Integer>> levelOrder(TreeNode root) {
  18. List<List<Integer>> res = new ArrayList<>();
  19. Queue<TreeNode> queue = new LinkedList<>();
  20. if(root != null) queue.add(root);
  21. while(!queue.isEmpty()){
  22. int size = queue.size(); //固定大小的size
  23. List<Integer> list = new ArrayList<>();
  24. for(int i = 0;i < size; i++){
  25. TreeNode node = queue.peek(); //获取队列第一个元素
  26. queue.poll(); //删除队列的第一个元素
  27. list.add(node.val);
  28. if(node.left != null) queue.add(node.left);
  29. if(node.right != null) queue.add(node.right);
  30. }
  31. res.add(list);
  32. }
  33. return res;
  34. }
  35. }

剑指 Offer 07. 重建二叉树

image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. class Solution {
  11. public TreeNode buildTree(int[] preorder, int[] inorder) {
  12. if(preorder == null || preorder.length == 0) return null;
  13. HashMap<Integer, Integer> hashMap = new HashMap<>();
  14. for(int i = 0; i < inorder.length; i++){
  15. hashMap.put(inorder[i], i);
  16. }
  17. return dfs(preorder, 0 , inorder.length - 1, 0 ,hashMap);
  18. }
  19. public TreeNode dfs(int[] preorder, int pl, int pr, int il, HashMap<Integer, Integer> hashMap){
  20. if(pl > pr) return null;
  21. TreeNode curRoot = new TreeNode(preorder[pl]);
  22. int k = hashMap.get(curRoot.val);
  23. curRoot.left = dfs(preorder, pl + 1, pl + (k - il), il, hashMap);
  24. curRoot.right = dfs(preorder, pl + (k - il) + 1, pr, k + 1, hashMap);
  25. return curRoot;
  26. }
  27. }

剑指 Offer 26. 树的子结构

image.png

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构) B是A的子结构, 即 A中有出现和B相同的结构和节点值

image.png

剑指 Offer 27. 二叉树的镜像

image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. class Solution {
  11. public TreeNode mirrorTree(TreeNode root) {
  12. if(root == null){
  13. return null;
  14. }
  15. swap(root);
  16. mirrorTree(root.left);
  17. mirrorTree(root.right);
  18. return root;
  19. }
  20. private void swap(TreeNode root){
  21. TreeNode temp = root.left;
  22. root.left = root.right;
  23. root.right = temp;
  24. }
  25. }

剑指 Offer 28. 对称的二叉树

image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. class Solution {
  11. public boolean isSymmetric(TreeNode root) {
  12. if(root == null) return true;
  13. return dfs(root, root);
  14. }
  15. public boolean dfs(TreeNode p, TreeNode q){
  16. if(p == null && q == null) return true;
  17. if(p == null || q == null) return false;
  18. if(p.val != q.val) return false;
  19. return dfs(p.left, q.right) && dfs(p.right, q.left);
  20. }
  21. }

剑指 Offer 32 - I. 从上到下打印二叉树

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。

image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. class Solution {
  11. public int[] levelOrder(TreeNode root) {
  12. if(root == null){
  13. return new int[0];
  14. }
  15. Queue<TreeNode> queue = new LinkedList<>();
  16. ArrayList<Integer> arr = new ArrayList<>();
  17. queue.add(root);
  18. while(!queue.isEmpty()){
  19. TreeNode node = queue.poll();
  20. arr.add(node.val);
  21. if(node.left != null){
  22. queue.add(node.left);
  23. }
  24. if(node.right != null){
  25. queue.add(node.right);
  26. }
  27. }
  28. int[] res = new int[arr.size()];
  29. for(int i = 0; i < res.length; i++){
  30. res[i] = arr.get(i);
  31. }
  32. return res;
  33. }
  34. }

剑指 Offer 32 - II. 从上到下打印二叉树 II

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. class Solution {
  11. public List<List<Integer>> levelOrder(TreeNode root) {
  12. Queue<TreeNode> queue = new LinkedList<>();
  13. List<List<Integer>> res = new ArrayList<>();
  14. if(root != null){
  15. queue.add(root);
  16. }
  17. while(!queue.isEmpty()){
  18. int size = queue.size();
  19. ArrayList<Integer> list = new ArrayList<>();
  20. for(int i = 0; i < size; i++){
  21. TreeNode node = queue.peek();
  22. queue.poll();
  23. list.add(node.val);
  24. if(node.left != null) queue.add(node.left);
  25. if(node.right != null) queue.add(node.right);
  26. }
  27. res.add(list);
  28. }
  29. return res;
  30. }
  31. }

剑指 Offer 32 - III. 从上到下打印二叉树 III

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. class Solution {
  11. public List<List<Integer>> levelOrder(TreeNode root) {
  12. List<List<Integer>> res = new ArrayList<>();
  13. Queue<TreeNode> queue = new LinkedList<>();
  14. if(root != null){
  15. queue.add(root);
  16. }
  17. while(!queue.isEmpty()){
  18. int size = queue.size();
  19. LinkedList<Integer> list = new LinkedList<>();
  20. for(int i = 0; i < size; i++){
  21. TreeNode node = queue.poll();
  22. if(res.size() % 2 == 0){
  23. list.addLast(node.val);
  24. }else{
  25. list.addFirst(node.val);
  26. }
  27. if(node.left != null) queue.add(node.left);
  28. if(node.right != null) queue.add(node.right);
  29. }
  30. res.add(list);
  31. }
  32. return res;
  33. }
  34. }

剑指 Offer 33. 二叉搜索树的后序遍历序列

image.png
image.png

  1. class Solution {
  2. public boolean verifyPostorder(int[] postorder) {
  3. return res(postorder, 0 , postorder.length - 1);
  4. }
  5. private boolean res(int[] postorder, int i, int j){
  6. if(i >= j){
  7. return true;
  8. }
  9. int p = i;
  10. while(postorder[p] < postorder[j]) p++;
  11. int m = p;
  12. while(postorder[p] > postorder[j]) p++;
  13. return p==j&&res(postorder, i , m-1)&&res(postorder, m ,j-1);
  14. }
  15. }

剑指 Offer 34. 二叉树中和为某一值的路径

image.png
image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode() {}
  8. * TreeNode(int val) { this.val = val; }
  9. * TreeNode(int val, TreeNode left, TreeNode right) {
  10. * this.val = val;
  11. * this.left = left;
  12. * this.right = right;
  13. * }
  14. * }
  15. */
  16. class Solution {
  17. LinkedList<List<Integer>> res = new LinkedList<>();
  18. LinkedList<Integer> path = new LinkedList<>();
  19. public List<List<Integer>> pathSum(TreeNode root, int target) {
  20. res(root, target);
  21. return res;
  22. }
  23. public void res(TreeNode root, int target){
  24. if(root == null){
  25. return;
  26. }
  27. path.add(root.val);
  28. target = target - root.val;
  29. if(target == 0 && root.left== null && root.right==null){
  30. res.add(new LinkedList(path));
  31. }
  32. res(root.left, target);
  33. res(root.right, target);
  34. path.removeLast();
  35. }
  36. }

剑指 Offer 36. 二叉搜索树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向

image.png
image.png

  1. /*
  2. // Definition for a Node.
  3. class Node {
  4. public int val;
  5. public Node left;
  6. public Node right;
  7. public Node() {}
  8. public Node(int _val) {
  9. val = _val;
  10. }
  11. public Node(int _val,Node _left,Node _right) {
  12. val = _val;
  13. left = _left;
  14. right = _right;
  15. }
  16. };
  17. */
  18. class Solution {
  19. Node head, pre;
  20. public Node treeToDoublyList(Node root) {
  21. if(root==null) return null;
  22. dfs(root);
  23. pre.right = head;
  24. head.left =pre;//进行头节点和尾节点的相互指向,这两句的顺序也是可以颠倒的
  25. return head;
  26. }
  27. public void dfs(Node cur){
  28. if(cur==null) return;
  29. dfs(cur.left);
  30. //pre用于记录双向链表中位于cur左侧的节点,即上一次迭代中的cur,
  31. //当pre==null时,cur左侧没有节点,即此时cur为双向链表中的头节点
  32. if(pre==null) head = cur;
  33. //反之,pre!=null时,cur左侧存在节点pre,需要进行pre.right=cur的操作。
  34. else pre.right = cur;
  35. cur.left = pre;//pre是否为null对这句没有影响,且这句放在上面两句if else之前也是可以的。
  36. pre = cur;//pre指向当前的cur
  37. dfs(cur.right);//全部迭代完成后,pre指向双向链表中的尾节点
  38. }
  39. }

剑指 Offer 37. 序列化二叉树

请实现两个函数,分别用来序列化和反序列化二叉树

image.png
image.png
image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. public class Codec {
  11. // Encodes a tree to a single string.
  12. public String serialize(TreeNode root) {
  13. if(root == null) return "[]";
  14. StringBuilder res = new StringBuilder("[");
  15. Queue<TreeNode> q = new LinkedList<>();
  16. q.add(root);
  17. while(!q.isEmpty()){
  18. TreeNode t = q.poll();
  19. if(t != null){
  20. res.append(t.val + ",");
  21. q.add(t.left);
  22. q.add(t.right);
  23. }else{
  24. res.append("null,");
  25. }
  26. }
  27. res.append("]");
  28. return res.toString();
  29. }
  30. // Decodes your encoded data to tree.
  31. public TreeNode deserialize(String data) {
  32. if(data.equals("[]")) return null;
  33. String[] vals = data.substring(1, data.length() - 1).split(",");
  34. TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
  35. Queue<TreeNode> q = new LinkedList<>();
  36. q.add(root);
  37. int i = 1;
  38. while(!q.isEmpty()){
  39. TreeNode node = q.poll();
  40. if(!vals[i].equals("null")){
  41. node.left = new TreeNode(Integer.parseInt(vals[i]));
  42. q.add(node.left);
  43. }
  44. i++;
  45. if(!vals[i].equals("null")){
  46. node.right = new TreeNode(Integer.parseInt(vals[i]));
  47. q.add(node.right);
  48. }
  49. i++;
  50. }
  51. return root;
  52. }
  53. }
  54. // Your Codec object will be instantiated and called as such:
  55. // Codec codec = new Codec();
  56. // codec.deserialize(codec.serialize(root));

剑指 Offer 54. 二叉搜索树的第k大节点

给定一棵二叉搜索树,请找出其中第k大的节点。

image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. class Solution {
  11. int k1, res;
  12. public int kthLargest(TreeNode root, int k) {
  13. k1 = k;
  14. dfs(root);
  15. return res;
  16. }
  17. private void dfs(TreeNode root){
  18. if(root == null || k1 == 0){
  19. return;
  20. }
  21. dfs(root.right); //右子树
  22. if(--k1 == 0) res = root.val; //根节点
  23. dfs(root.left); //左子树
  24. }
  25. }

剑指 Offer 55 - I. 二叉树的深度

输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。

image.png
image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. //左右子树的最大深度,再加上根节点的深度1,一起构成树的深度
  11. class Solution {
  12. public int maxDepth(TreeNode root) {
  13. if(root == null){
  14. return 0;
  15. }
  16. int left = maxDepth(root.left);
  17. int right = maxDepth(root.right);
  18. return left > right ? left + 1 : right + 1;
  19. }
  20. }

剑指 Offer 55 - II. 平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树

image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. class Solution {
  11. public boolean isBalanced(TreeNode root) {
  12. if(root == null){
  13. return true;
  14. }
  15. int left = treeDepth(root.left);
  16. int right = treeDepth(root.right); //任意节点都满足
  17. return Math.abs(left - right) > 1 ? false : true && isBalanced(root.left) &&
  18. isBalanced(root.right);
  19. }
  20. //树的深度
  21. public int treeDepth(TreeNode root){
  22. if(root == null){
  23. return 0;
  24. }
  25. int a = treeDepth(root.left);
  26. int b = treeDepth(root.right);
  27. return a > b ? a + 1:b + 1;
  28. }
  29. }

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)

image.png
image.png

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode(int x) { val = x; }
  8. * }
  9. */
  10. class Solution {
  11. public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
  12. if(p.val > q.val){
  13. TreeNode temp = p;
  14. p = q;
  15. q = temp;
  16. }
  17. while(root != null){
  18. if(root.val < p.val){
  19. root = root.right;
  20. }else if(root.val > q.val){
  21. root = root.left;
  22. }else{
  23. break;
  24. }
  25. }
  26. return root;
  27. }
  28. }
  29. class Solution{
  30. public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q){
  31. if(root.val < p.val && root.val < q.val){
  32. return lowestCommonAncestor(root.right, p, q);
  33. }
  34. if(root.val > p.val && root.val > q.val){
  35. return lowestCommonAncestor(root.left, p, q);
  36. }
  37. return root;
  38. }
  39. }

剑指 Offer 68 - II. 二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先

image.png