leetcode99。バイナリ検索ツリー/順序通りのトラバーサルを復元する

問題:バイナリ検索ツリーの2つのノードが誤って入れ替わっています。

構造を変更せずにこのツリーを復元してください。

例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
著作権はLeetCode が所有しています商用転載については、正式な許可書にご連絡ください。非商用転載については、出典を明記してください。

基本的な考え方1:順序トラバーサル

二分探索木のインオーダートラバーサルの結果は昇順のシーケンスである必要があるため、この質問のミドルオーダートラバーサルのシーケンスは、2つの要素を交換すると昇順のシーケンスになります。

  • まず、二分木の順序通りの探索を実行し、順序通りの探索の結果シーケンスを保存します。
  • 結果シーケンスの最初の反転要素の前にある要素preを検索します
  • 要素preから後ろに向かって検索します。要素よりも大きい要素tempが見つかった場合、tempの前の要素postは、交換する必要のある要素です。
  • 事前と事後の2つの要素を交換する

空間の複雑度はO(n)です。
配列を定義して、順序どおりの走査の順序を保存します

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    
    
public:
    vector<TreeNode*> vec;
    void recoverTree(TreeNode* root) {
    
    
        inorder(root);
        int pre = 0, i;
        for(i = 1; i < vec.size(); ++i){
    
    
            if(vec[i]->val > vec[pre]->val)
                ++pre;
            else
                break;
        }
        
        for(; i < vec.size(); ++i){
    
    
            if(vec[i]->val > vec[pre]-> val)
                break;
        }
        --i;
        int t = vec[i]->val;
        vec[i]->val = vec[pre]->val;
        vec[pre]->val = t;
        
    }
    void inorder(TreeNode* root){
    
    
        if(root == NULL)
            return;
        inorder(root->left);
        vec.push_back(root);
        inorder(root->right);
    }
};

スペースの複雑さはO(1)です
。2つの変数を定義して、2つのノードを逆の順序で保存します。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    
    
public:
    
    void recoverTree(TreeNode* root) {
    
    
        TreeNode* pre1 = NULL, *pre2 = NULL;
        inorder(root, pre1, pre2);
        int t = pre1->val;
        pre1->val = pre2->val;
        pre2->val = t;
    }
    void inorder(TreeNode* root, TreeNode* &pre1, TreeNode* &pre2){
    
    
        if(root == NULL)
            return;
        inorder(root->left, pre1, pre2);
        if(pre1 == NULL){
    
    //root是根节点的情况
            pre1 = root;
        }
        else{
    
    
            if(root->val > pre1->val && (!pre2 || root->val < pre2->val)){
    
    
                pre1 = root;
            }
            else if(pre2 == NULL){
    
    //此时找到了第一个需要交换的节点,保存在pre2中
                pre2 = pre1;
                pre1 = root;
            }
            if((root->val < pre1->val) && (pre2) && (pre2->val > root->val)){
    
    //此时找到了第二个需要交换的节点保存在pre1中
                pre1 = root;
            }
        }
        inorder(root->right, pre1, pre2);
    }
};

おすすめ

転載: blog.csdn.net/qq_31672701/article/details/107880419