解法一

参考了评论区的思路。先解析字符串,提取每个结点的信息,然后按顺序建树,根据深度信息判断是否进一步建立子结点。
也可以一边遍历一边解析字符串,总体类似。

  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. // 结点深度队列
  12. private Queue<Integer> depthQueue;
  13. // 结点数值队列
  14. private Queue<Integer> numQueue;
  15. public TreeNode recoverFromPreorder(String S) {
  16. depthQueue = new LinkedList<>();
  17. numQueue = new LinkedList<>();
  18. // 当前结点的深度信息在S中的起始下标
  19. int depthHead = 0;
  20. for (int i = 0; i < S.length(); ) {
  21. // 解析深度
  22. while (S.charAt(i) == '-') {
  23. ++i;
  24. }
  25. depthQueue.offer(i - depthHead);
  26. // 解析数值
  27. int num = 0;
  28. while ((i < S.length()) && (S.charAt(i) != '-')) {
  29. num = num * 10 + S.charAt(i) - 48;
  30. ++i;
  31. }
  32. numQueue.offer(num);
  33. depthHead = i;
  34. }
  35. if (depthQueue.isEmpty()) {
  36. return null;
  37. }
  38. return build(0);
  39. }
  40. /**
  41. * 建树
  42. *
  43. * @param depth 当前深度
  44. * @return 该深度结点
  45. */
  46. private TreeNode build(int depth) {
  47. if ((depthQueue.isEmpty()) || (depthQueue.peek() != depth)) {
  48. return null;
  49. }
  50. depthQueue.poll();
  51. TreeNode root = new TreeNode(numQueue.poll());
  52. // 左子树优先于右子树
  53. // 根据题中字符串的性质, 没有左子树一定也没有右子树
  54. root.left = build(depth + 1);
  55. root.right = build(depth + 1);
  56. return root;
  57. }
  58. }