二叉搜索树中的两个节点被错误地交换。
    请在不改变其结构的情况下,恢复这棵树。

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

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

    进阶:

    • 使用 O(n) 空间复杂度的解法很容易实现。
    • 你能想出一个只使用常数空间的解决方案吗?

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/recover-binary-search-tree

    思路:
    正常思路是使用中序遍历
    解法一:中序遍历结果为一个升序数组,错误交换的节点必然有a解法二:增加一个辅助的pre指针,记录 上一个 节点的值。如果 当前节点的值,小于 上一个节点的值,这就找到了需要交换的节点:空间复杂度O(h) h是二叉搜索数高度
    解法三:常数空间的解决方案必然是mirrors遍历。
    复杂度分析:
    时间复杂度O(n) 实际因为需要对每个节点遍历两次为O(2n)
    空间复杂度O(1)

    1. var recoverTree = function (root) {
    2. const swap = (a, b) => {
    3. [a.val, b.val] = [b.val, a.val];
    4. };
    5. const mirrors = (root) => {
    6. let x = null, y = null, pre = null, pred = null;
    7. while (root) {
    8. if (root.left) {
    9. pre = root.left;
    10. while (pre.right && pre.right !== root) {
    11. pre = pre.right;
    12. }
    13. if (!pre.right) {
    14. pre.right = root;
    15. root = root.left;
    16. } else {
    17. if (pred !== null && pred.val > root.val) {
    18. y = root;
    19. if (x === null) {
    20. x = pred;
    21. }
    22. }
    23. pred = root;
    24. pre.right = null;
    25. root = root.right;
    26. }
    27. } else {
    28. if (pred !== null && pred.val > root.val) {
    29. y = root;
    30. if (x === null) {
    31. x = pred;
    32. }
    33. }
    34. pred = root;
    35. root = root.right;
    36. }
    37. }
    38. swap(x, y);
    39. };
    40. mirrors(root);
    41. return root;
    42. };