leetcode Recover Binary Search Tree

本文讨论了如何在不改变二叉搜索树结构的情况下修复因错误交换两个元素导致的问题,并提供了常数空间解决方案的实现。通过深入分析二叉树的中序遍历,找出并修复错误交换的节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Two elements of a binary search tree (BST) are swapped by mistake.

Recover the tree without changing its structure.

Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.

 

Give an inorder traversal for the binary tree. 

 

Find the first node res1, which is larger than its successor. 

Find the first node p, which is larger than res1->val. So the predecessor of p is the second index we wanna find. 

However, in the recursive program, there are some mistake, here is wrong code: 

 

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
 public:
 
  TreeNode *last = NULL, *res1 = NULL, *res2 = NULL;
  void inorder(TreeNode* root) {
    if (root == NULL)
      return;
    if (res1 && res2)
      return;
    inorder(root->left);
    
    if (last != NULL && res1 == NULL && last->val > root->val) 
      res1 = last;
    else if (last != NULL && res1 != NULL && root->val > res1->val) {
      res2 = last;
      swap(res1->val, last->val);
      return;  
    }
    last = root;
    
    inorder(root->right);
  }
  
  void recoverTree(TreeNode *root) {
    // Note: The Solution object is instantiated only once and is reused by each test case.
    last = res1 = res2 = NULL;
    inorder(root);
    if (res2 == NULL)
      swap(res1->val, last->val);
    //if (res1 && res2)
    //  swap(res1->val, res2->val);
    
  }
};


The wrong case is :

 

 

Input:{10,5,15,0,8,13,20,2,-5,6,9,12,14,18,25}
Output:{10,5,15,0,8,13,20,2,-5,6,9,12,14,18,25}
Expected:{10,5,15,0,8,13,20,-5,2,6,9,12,14,18,25}

 

The reason is that the branch else if is executed more than once although returning. Take the WA case for example, after visiting 5, 8 is returned. But 10 is visited afterwards: TreeNode* last hasn't been updated, so swap the second time. The right code is: 

 

 

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
 public:
 
  TreeNode *last = NULL, *res1 = NULL, *res2 = NULL;
  void inorder(TreeNode* root) {
    if (root == NULL)
      return;
    if (res1 && res2)
      return;
    inorder(root->left);
    
    if (last != NULL && res1 == NULL && last->val > root->val) 
      res1 = last;
    else if (last != NULL && res1 != NULL && res2 ==NULL && root->val > res1->val) {
      res2 = last;
      swap(res1->val, last->val);
      return;  
    }
    last = root;
    
    inorder(root->right);
  }
  
  void recoverTree(TreeNode *root) {
    // Note: The Solution object is instantiated only once and is reused by each test case.
    last = res1 = res2 = NULL;
    inorder(root);
    if (res2 == NULL)
      swap(res1->val, last->val);
    //if (res1 && res2)
    //  swap(res1->val, res2->val);
    
  }
};

Python Version:

class Solution:
    def recoverTree(self, root):
        prev,cur,last = None,root,None
        stack,wrongPairs = [],[]
        while (cur != None or stack):
            while (cur != None):
                stack.append(cur)
                cur = cur.left
            if (stack):
                cur = stack.pop()
                if (prev != None and prev.val > cur.val):
                    wrongPairs.append([prev,cur])
                last,prev = cur,cur
                cur = cur.right
        if (len(wrongPairs) > 1):
            wrongPairs[0][0].val,wrongPairs[1][1].val=wrongPairs[1][1].val,wrongPairs[0][0].val
        elif (len(wrongPairs) == 1):
            wrongPairs[0][0].val,wrongPairs[0][1].val=wrongPairs[0][1].val,wrongPairs[0][0].val

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值