資料結構----Recover Binary Search Tree 復原二叉搜尋樹
阿新 • • 發佈:2019-02-07
題目描述:
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?
思路:
二叉搜尋樹的概念:二叉查詢樹(Binary Search Tree),(又:二叉搜尋樹,二叉排序樹)它或者是一棵空樹,或者是具有下列性質的 二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; 它的左、右子樹也分別為二叉排序樹。現在我們來用下面的樹分析:
4
/ \
2 6
/ \ / \
1 5 3 7
正確的中序遍歷為:左根右的原則:[1234567]
現在的中序遍歷為:[1254367]
很明顯3和5顛倒了。那麼在中序遍歷時:當碰到第一個逆序時:為5->4,那麼將first指向5,second指向4,注意,此時first已經確定下來了。然後pre和root一直向後遍歷,直到碰到第二個逆序時:4->3,此時將second指向3,那麼first和second都已經確定,只需要交換節點的值即可。prev指標用來比較中序遍歷中相鄰兩個值的大小關係,很巧妙。
/** * Definition for binary tree * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; *//* 4 / \ 2 6 / \ / \ 1 5 3 7 正確的中序遍歷為:左根右的原則:[1234567] 現在的中序遍歷為:[1254367] 很明顯3和5顛倒了。那麼在中序遍歷時:當碰到第一個逆序時:為5->4,那麼將first指向5,second指向4, 注意,此時first已經確定下來了。然後parent和root一直向後遍歷,直到碰到第二個逆序時:4->3,此時將second指向3, 那麼first和second都已經確定,只需要交換節點的值即可。pre指標用來比較中序遍歷中相鄰兩個值的大小關係*/ class Solution { public: //非遞迴 /*void recoverTree(TreeNode *root) { TreeNode *first = NULL, *second = NULL, *parent = NULL; TreeNode *cur, *pre; cur = root; while (cur) { if (cur->left==NULL) { if (parent && parent->val > cur->val) { if (!first) first = parent; second = cur; } parent = cur; cur = cur->right; } else { pre = cur->left; while (pre->right && pre->right != cur) pre = pre->right; if (!pre->right) { pre->right = cur; cur = cur->left; } else { pre->right = NULL; if (parent->val > cur->val) { if (!first) first = parent; second = cur; } parent = cur; cur = cur->right; } } } if (first && second) swap(first->val, second->val);*/ //遞迴 //定義三個指標,*pre用來比較大小,*first用來存放第一個錯位的數,*second用來存放第二個錯位的數 TreeNode *pre; TreeNode *first; TreeNode *second; void recoverTree(TreeNode *root) { pre = NULL; first = NULL; second = NULL; inorder(root); if (first !=NULL&& second!=NULL) //交換兩個錯位的值 swap(first->val, second->val); } void inorder(TreeNode *root) { if (root==NULL) return; inorder(root->left);//遞迴遍歷左子樹 if (pre==NULL) pre = root; else { if (pre->val > root->val) { if (first==NULL) first = pre; second = root; } pre = root; } inorder(root->right);//遞迴遍歷右子樹 } };