image.png
image.png

堆结构

image.png
小根堆

前缀树

image.png

算法稳定性的坑

image.png

二叉树

  1. public static class Node {
  2. public int value;
  3. public Node left;
  4. public Node right;
  5. public Node(int v) {
  6. value = v;
  7. }
  8. }

遍历

递归遍历

  1. public static void f(Node head) {
  2. if (head == null) {
  3. return;
  4. }
  5. // 先序
  6. f(head.left);
  7. // 中序
  8. f(head.right);
  9. // 后序
  10. }

非递归遍历

思路:使用栈
先序遍历,顺序为:头左右,则先压入头,弹出头后,有右压右,有左压左

  1. public static void pre(Node head) {
  2. System.out.print("pre-order: ");
  3. if (head != null) {
  4. Stack<Node> stack = new Stack<Node>();
  5. stack.add(head);
  6. while (!stack.isEmpty()) {
  7. head = stack.pop();
  8. System.out.print(head.value + " ");
  9. if (head.right != null) {
  10. stack.push(head.right);
  11. }
  12. if (head.left != null) {
  13. stack.push(head.left);
  14. }
  15. }
  16. }
  17. System.out.println();
  18. }

后序顺序为:左右头(逆序为头右左),则先压入头,弹出头后,有左压左,有右压右,此时顺序为 头右左 ,是后序遍历的逆序,再准备个栈即可

  1. public static void pos1(Node head) {
  2. System.out.print("pos-order: ");
  3. if (head != null) {
  4. Stack<Node> s1 = new Stack<Node>();
  5. Stack<Node> s2 = new Stack<Node>();
  6. s1.push(head);
  7. while (!s1.isEmpty()) {
  8. head = s1.pop(); // 头 右 左
  9. s2.push(head);
  10. if (head.left != null) {
  11. s1.push(head.left);
  12. }
  13. if (head.right != null) {
  14. s1.push(head.right);
  15. }
  16. }
  17. // 左 右 头
  18. while (!s2.isEmpty()) {
  19. System.out.print(s2.pop().value + " ");
  20. }
  21. }
  22. System.out.println();
  23. }

中序遍历,顺序为:左右头

  1. public static void in(Node cur) {
  2. System.out.print("in-order: ");
  3. if (cur != null) {
  4. Stack<Node> stack = new Stack<Node>();
  5. while (!stack.isEmpty() || cur != null) {
  6. if (cur != null) {
  7. stack.push(cur);
  8. cur = cur.left;
  9. } else {
  10. cur = stack.pop();
  11. System.out.print(cur.value + " ");
  12. cur = cur.right;
  13. }
  14. }
  15. }
  16. System.out.println();
  17. }

宽度优先遍历

关键点在于如何知道节点所在层

使用map记录节点所在层

在弹出队列时才做操作

  1. public static int maxWidthUseMap(Node head) {
  2. if (head == null) {
  3. return 0;
  4. }
  5. Queue<Node> queue = new LinkedList<>();
  6. queue.add(head);
  7. // key 在 哪一层,value
  8. HashMap<Node, Integer> levelMap = new HashMap<>();
  9. levelMap.put(head, 1);
  10. int curLevel = 1; // 当前你正在统计哪一层的宽度
  11. int curLevelNodes = 0; // 当前层curLevel层,宽度目前是多少
  12. int max = 0;
  13. while (!queue.isEmpty()) {
  14. // 在弹出队列时才做操作
  15. Node cur = queue.poll();
  16. int curNodeLevel = levelMap.get(cur);
  17. if (cur.left != null) {
  18. levelMap.put(cur.left, curNodeLevel + 1);
  19. queue.add(cur.left);
  20. }
  21. if (cur.right != null) {
  22. levelMap.put(cur.right, curNodeLevel + 1);
  23. queue.add(cur.right);
  24. }
  25. if (curNodeLevel == curLevel) {
  26. curLevelNodes++;
  27. } else {
  28. max = Math.max(max, curLevelNodes);
  29. curLevel++;
  30. curLevelNodes = 1;
  31. }
  32. }
  33. max = Math.max(max, curLevelNodes);
  34. return max;
  35. }

记录当前层和下一层的最右节点,就可以知道一层是否已结束

在弹出队列时才做操作

  1. public static int maxWidthNoMap(Node head) {
  2. if (head == null) {
  3. return 0;
  4. }
  5. Queue<Node> queue = new LinkedList<>();
  6. queue.add(head);
  7. Node curEnd = head; // 当前层,最右节点是谁
  8. Node nextEnd = null; // 下一层,最右节点是谁
  9. int max = 0;
  10. int curLevelNodes = 0; // 当前层的节点数
  11. while (!queue.isEmpty()) {
  12. // 在弹出队列时才做操作
  13. Node cur = queue.poll();
  14. if (cur.left != null) {
  15. queue.add(cur.left);
  16. nextEnd = cur.left;
  17. }
  18. if (cur.right != null) {
  19. queue.add(cur.right);
  20. nextEnd = cur.right;
  21. }
  22. curLevelNodes++;
  23. if (cur == curEnd) {
  24. max = Math.max(max, curLevelNodes);
  25. curLevelNodes = 0;
  26. curEnd = nextEnd;
  27. }
  28. }
  29. return max;
  30. }

二叉树序列化和反序列化

  1. 可以用先序、中序、后序序列化或按层遍历,来实现二叉树的变化
  2. 用什么方式序列化,就用什么方式反序列化

ps:空的节点也要序列化

递归序列化

  1. // 序列化
  2. public static Queue<String> preSerial(Node head) {
  3. Queue<String> ans = new LinkedList<>();
  4. pres(head, ans);
  5. return ans;
  6. }
  7. public static void pres(Node head, Queue<String> ans) {
  8. if (head == null) {
  9. ans.add(null);
  10. } else {
  11. // 先序
  12. ans.add(String.valueOf(head.value));
  13. pres(head.left, ans);
  14. // 中序
  15. pres(head.right, ans);
  16. // 后序
  17. }
  18. }
  19. // 反序列化
  20. public static Node buildByPreQueue(Queue<String> prelist) {
  21. if (prelist == null || prelist.size() == 0) {
  22. return null;
  23. }
  24. return preb(prelist);
  25. }
  26. public static Node preb(Queue<String> prelist) {
  27. String value = prelist.poll();
  28. if (value == null) {
  29. return null;
  30. }
  31. // 先序
  32. Node head = new Node(Integer.valueOf(value));
  33. head.left = preb(prelist);
  34. // 中序
  35. head.right = preb(prelist);
  36. // 后序
  37. return head;
  38. }

按层序列化

  1. public static Queue<String> levelSerial(Node head) {
  2. Queue<String> ans = new LinkedList<>();
  3. if (head == null) {
  4. ans.add(null);
  5. } else {
  6. ans.add(String.valueOf(head.value));
  7. Queue<Node> queue = new LinkedList<Node>();
  8. queue.add(head);
  9. while (!queue.isEmpty()) {
  10. head = queue.poll(); // head 父 子
  11. if (head.left != null) {
  12. ans.add(String.valueOf(head.left.value));
  13. queue.add(head.left);
  14. } else {
  15. ans.add(null);
  16. }
  17. if (head.right != null) {
  18. ans.add(String.valueOf(head.right.value));
  19. queue.add(head.right);
  20. } else {
  21. ans.add(null);
  22. }
  23. }
  24. }
  25. return ans;
  26. }
  27. public static Node buildByLevelQueue(Queue<String> levelList) {
  28. if (levelList == null || levelList.size() == 0) {
  29. return null;
  30. }
  31. Node head = generateNode(levelList.poll());
  32. Queue<Node> queue = new LinkedList<Node>();
  33. if (head != null) {
  34. queue.add(head);
  35. }
  36. Node node = null;
  37. while (!queue.isEmpty()) {
  38. node = queue.poll();
  39. node.left = generateNode(levelList.poll());
  40. node.right = generateNode(levelList.poll());
  41. if (node.left != null) {
  42. queue.add(node.left);
  43. }
  44. if (node.right != null) {
  45. queue.add(node.right);
  46. }
  47. }
  48. return head;
  49. }
  50. public static Node generateNode(String val) {
  51. if (val == null) {
  52. return null;
  53. }
  54. return new Node(Integer.valueOf(val));
  55. }