1. 程式人生 > 實用技巧 >Vagrant在虛擬機器Centos7上安裝Docker

Vagrant在虛擬機器Centos7上安裝Docker

題解

方法一:

對於二叉搜尋樹,如果進行中序遍歷,那麼得到的序列是有序的,如果有兩個節點交換了,那麼就是無序的,我們只需要找出這兩個節點所在的位置然後交換值就好了。

先來看看交換兩個值會發生什麼。對於遞增序列a=[1,2,3,4,5]

  • 如果交換不相鄰的數字,例如swap(a[1],a[3]),那麼a=[1,4,3,2,5],此時a[1]>a[2]&&a[2]>a[3],存在兩個非遞增序列。
  • 如果交換相鄰的數字,例如swap(a[1],a[2]),那麼a=[1,3,2,4,5],此時a[1]>a[2],只存在一個非遞增序列。

程式碼

首先講一下pair的用法

pair<T,U> p1;
p1.first=value1;
p1.second=value2;

pair<T,U> p2(value1,value2);

pair<int,int> p3=make_pair(value1,value2);

//pair作為函式返回值
pair<int,int> function(int x,int y){
	//注意是大括號
	return {x,y};
}

程式碼

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:

	//中序遍歷,把中序遍歷的序列存入nums陣列中
    void inorder(TreeNode* root,vector<int>& nums){
        if(root==nullptr)
            return;
        inorder(root->left,nums);
        nums.push_back(root->val);
        inorder(root->right,nums);
    }
    
	//返回中序遍歷陣列中應該交換的兩個值(x,y)
    pair<int,int>findTwoSwapped(vector<int>& nums){
        int n=nums.size();
        int x=-1,y=-1;
        for(int i=0;i<n-1;++i){
        	//如果存在逆序對
            if(nums[i]>nums[i+1]){
                y=nums[i+1];
                //如果x==-1,那麼x還沒有找到,否則若x!=-1,說明已經找到正確的x,此時(x,y)已經找到,退出就好
                if(x==-1)
                    x=nums[i];
                else
                    break;
            }
        }
        return {x,y};
        
    }

	//在樹中swap(x,y),其中count用來記錄修改的次數,應該修改兩次,即count=2
    void recover(TreeNode* root,int count,int x,int y){
        if(root){
            if(root->val==x||root->val==y){
            	//如果當前節點的值為x,那麼另它為y,否則若當前節點的值為y,那麼另它為x
                root->val=root->val==x?y:x;
                //如果count==0說明x和y已經修改完畢(修改了兩次)
                if(--count==0)
                    return;
            }
            recover(root->left,count,x,y);
            recover(root->right,count,x,y);
        }
    }

    void recoverTree(TreeNode* root) {
        vector<int> nums;
        inorder(root,nums);
        pair<int,int> swapped=findTwoSwapped(nums);
        recover(root,2,swapped.first,swapped.second);
    }
};

方法二:

通過非遞迴的中序遍歷找出(x,y),設定一個指標pred指向當前節點的root的前驅,如果pred->val>root->val,說明x=pred,x此時就找到了,繼續按相同的方法找y即可。

最後swap(x->val,y->val)

首先回顧一下中序遍歷的兩種非遞迴寫法:

第一種

void InOrder(TreeNode *root){
	//空樹
    if(!root)
    	return;
    TreeNode* p=root;
    stack<TreeNode> s;
    //當p為root時,s為空
    while(!s.empty()||p){
    	//一直遍歷到最左邊的節點
    	while(p){
        	s.push(p);
            p=p->left;
        }
        //此時p==nullptr,可以訪問p的父節點以及右孩子了
        if(!s.empty()){
        	p=s.top();
            s.pop();
            visit(p);
            p=p->right;
       	}
    }
}

第二種


void InOrder2(TreeNode* root){
	//空樹
	if (!root)
		return;
	//樹非空
	TreeNode* p = root;
	stack<TreeNode*> s;
	while (!s.empty() || p){
		if (p){
			s.push(p);
			p = p->left;
		}
		else{
			p = s.top();
			s.pop();
			visit(p);
			p = p->right;
		}
	}

程式碼

利用第一種中序遍歷非遞迴寫法

class Solution {
public:
    void recoverTree(TreeNode* root){
        stack<TreeNode*> s;
        TreeNode* x=nullptr;
        TreeNode* y=nullptr;
        TreeNode* pred=nullptr;
        TreeNode* p=root;
        while(!s.empty()||p){
            while(p){
                s.push(p);
                p=p->left;
            }
            if(!s.empty()){
                p=s.top();
                s.pop();
                if(pred&&p->val<pred->val){
                    y=p;
                    if(x==nullptr)
                        x=pred;
                    else break;
                }
                pred=p;
                p=p->right;
            }
        }
        swap(x->val,y->val);
    }
};

利用第二種非遞迴中序遍歷寫法

class Solution {
public:
    void recoverTree(TreeNode* root){
        stack<TreeNode*> s;
        TreeNode* x=nullptr;
        TreeNode* y=nullptr;
        TreeNode* pred=nullptr;
        TreeNode* p=root;
        while(!s.empty()||p){
            if(p){
                s.push(p);
                p=p->left;
            }
            else{
                p=s.top();
                s.pop();
                if(pred&&p->val<pred->val){
                    y=p;
                    if(x==nullptr)
                        x=pred;
                    else break;
                }
                pred=p;
                p=p->right;
            }
        }
        swap(x->val,y->val);
    }
};

題目連結(https://leetcode-cn.com/problems/recover-binary-search-tree/)