给定一个二叉树,返回它的 后序 遍历。

    示例:
    **
    输入: [1,null,2,3]
    1
    \
    2
    /
    3
    输出: [3,2,1]

    进阶: 递归算法很简单,你可以通过迭代算法完成吗?

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/binary-tree-postorder-traversal
    思路:

    • 递归

    后续遍历顺序:左子树——右子树——根节点,而在访问左子树或者右子树的时候我们按照同样的方式遍历,直到遍历完整棵树。因此整个遍历过程天然具有递归的性质。
    时间复杂度O(n)
    空间复杂度O(n)

    • 迭代

    前序遍历: 中左右 —> 调整代码左右顺序 —> 中右左 —> 反转数组 —> 左右中 —> 后序遍历
    时间复杂度O(n)
    空间复杂度O(n)

    • Mirrors遍历

      Mirrors遍历原理 cur:当前遍历的指针
      rightMost:cur节点的左子树的最右节点

      1. 如果cur左子树为空:cur=cur.right;
      2. 如果cur左子树不为空: 找到rightMost
        ——1)如果rightMost.right=null, 那么令rightMost=cur, cur=cur.left;
        ——2)否则,不为空则说明rightMost.right曾经被修改过,我们这是第二次来到这个点,修改rightMost.right=null,cur=cur.right;

      解释一下上面的步骤:

      1. 首先整体向左走,如果没有左子树向右走。
      2. 如果左子树不为空,那么就找到左子树上最右的节点这个节点的右子树一定是空的。把这个空指针指向当前节点,即保存了一个指向父节点的指针。此时,左子树还有值没有访问,cur向左走
      3. 3 中的结果是rightMost遍历到这个节点的,cur指针也会遍历到这个节点,这就是第二次访问到了,那么此时该节点作为rightMost时,是被修改过的,所以我们要重新修改其为null。
      4. 当出现3的情况时,说明该节点的左子树全部访问完毕,所以此时cur向右走
      5. cur是真正有效的移动指针,它会走过所有的节点,rightMost是为了修改指针而存在的。

    前序遍历: 中左右 —> 调整代码左右顺序 —> 中右左 —> 反转数组 —> 左右中 —> 后序遍历
    魔改mirror:pre改为找cur节点的右子树的最左节点,
    假设当前遍历到的节点为 x):

    1. 如果 x 无右孩子,先将 x 的值加入答案数组,再访问 x 的左孩子,即 x=x.left
    2. 如果 x 有右孩子,则找到 x 右子树上最左的节点(即右子树中序遍历的最后一个节点,x 在中序遍历中的前驱节点),我们记为 predecessor。根据 predecessor 的左孩子是否为空,进行如下操作。
    3. 如果 predecessor 的左孩子为空,说明还未遍历过x的右子树,将x的值加入答案。则将其左孩子指向x,然后访问 x 的右孩子,即 x=x.right
    4. 如果 predecessor 的左孩子不为空,说明我们已经遍历完 x 的右子树,我们将 predecessor 的左孩子置空,然后访问 x 的左孩子,即x=x.left
    5. 重复上述操作,直至访问完整棵树。

    左—>右是,先序遍历到后序遍历的变化:**left ->right** ,**left-> right**, **ans ->ans.reverse()**
    时间复杂度O(n) 实际表现为O(2*n),因为每个节点需要访问两次,会比前两种方法稍慢。
    空间复杂度O(1)

    1. //递归版
    2. var postorderTraversal = function (root) {
    3. let ans = [];
    4. const dfs = (root) => {
    5. if (root === null) return;
    6. dfs(root.left);
    7. dfs(root.right);
    8. ans.push(root.val);
    9. };
    10. dfs(root);
    11. return ans;
    12. };
    13. //迭代版
    14. var postorderTraversal = function (root) {
    15. let ans = [];
    16. if (root === null) return [];
    17. let stack = [root];
    18. while (stack.length) {
    19. let root = stack.pop();
    20. ans.push(root.val);
    21. if (root.left !== null) {
    22. stack.push(root.left);
    23. }
    24. if (root.right !== null) {
    25. stack.push(root.right);
    26. }
    27. }
    28. return ans.reverse();
    29. };
    30. //官方题解的mirrors遍历
    31. var postorderTraversal = function (root) {
    32. let ans = [];
    33. if (root === null) return ans;
    34. const addPath = (ans, node) => {
    35. let count = 0;
    36. while (node !== null) {
    37. ans.push(node.val);
    38. node = node.right;
    39. count++;
    40. }
    41. let left = ans.length - count;
    42. let right = ans.length - 1;
    43. while (left < right) {
    44. let temp = ans[left];
    45. ans[left] = ans[right];
    46. ans[right] = temp;
    47. left++;
    48. right--;
    49. }
    50. };
    51. let cur = root;
    52. while (cur) {
    53. if (cur.left !== null) {
    54. let pre = cur.left;
    55. while (pre.right !== null && pre.right !== cur) {
    56. pre = pre.right;
    57. }
    58. if (pre.right !== null) {
    59. pre.right = null;
    60. addPath(ans, cur.left);
    61. cur = cur.right;
    62. } else {
    63. pre.right = cur;
    64. cur = cur.left;
    65. }
    66. } else {
    67. cur = cur.right;
    68. }
    69. }
    70. addPath(ans, root);
    71. return ans;
    72. };
    73. //另一种形式的mirriors 遍历
    74. var postorderTraversal = function (root) {
    75. let ans = [];
    76. while (root) {
    77. if (root.right !== null) {
    78. let pre = root.right;
    79. while (pre.left !== null && pre.left !== root) {
    80. pre = pre.left;
    81. }
    82. if (pre.left !== null) {
    83. pre.left = null;
    84. root = root.left;
    85. } else {
    86. ans.push(root.val);
    87. pre.left = root;
    88. root = root.right;
    89. }
    90. } else {
    91. ans.push(root.val);
    92. root = root.left;
    93. }
    94. }
    95. return ans.reverse();
    96. };