2014-05-08 08:26
原题:
Given a preorder traversal, create a binary search tree in optimized time
题目:给定一个二叉搜索树的前序遍历,请重建这棵树。要求最优化算法。
解法1:这人每次出题都要求“最优算法”,自己写的代码却实在让人汗颜,让人觉得这家伙就是懒得思考,想从别人那儿问答案。前序遍历的顺序是“根左右”,那么根节点之后所有小于根的部分就是左子树,后面就是右子树了。怎么找这条分界线呢?可以顺着找。那么算法的复杂度就是O(n * log(n))了。复杂度的证明参考归并排序即可。这个算法可行,但不是最优。
代码:
1 // http://www.careercup.com/question?id=5162732873580544 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 struct TreeNode { 7 int val; 8 TreeNode *left; 9 TreeNode *right; 10 TreeNode(int _val = 0): val(_val), left(nullptr), right(nullptr) {}; 11 }; 12 13 void constructBSTFromPreorderTraversal(vector<int> &v, int ll, int rr, TreeNode *&root) 14 { 15 root = new TreeNode(v[ll]); 16 17 int i = ll + 1; 18 while (i <= rr && v[i] < v[ll]) { 19 ++i; 20 } 21 if (ll + 1 <= i - 1) { 22 constructBSTFromPreorderTraversal(v, ll + 1, i - 1, root->left); 23 } 24 if (i <= rr) { 25 constructBSTFromPreorderTraversal(v, i, rr, root->right); 26 } 27 } 28 29 void inorderTraversal(TreeNode *root) 30 { 31 if (nullptr == root) { 32 return; 33 } 34 inorderTraversal(root->left); 35 cout << root->val << ' '; 36 inorderTraversal(root->right); 37 } 38 39 void clearTree(TreeNode *&root) 40 { 41 if (nullptr == root) { 42 return; 43 } 44 clearTree(root->left); 45 clearTree(root->right); 46 delete root; 47 root = nullptr; 48 } 49 50 int main() 51 { 52 vector<int> v; 53 int n; 54 int i; 55 TreeNode *root; 56 57 while (cin >> n && n > 0) { 58 v.resize(n); 59 for (i = 0; i < n; ++i) { 60 cin >> v[i]; 61 } 62 root = nullptr; 63 constructBSTFromPreorderTraversal(v, 0, n - 1, root); 64 inorderTraversal(root); 65 cout << endl; 66 67 clearTree(root); 68 v.clear(); 69 } 70 71 return 0; 72 }
解法2:既然遍历是O(n)时间完成的,重建应该也可以做到O(n)。我的思路,是比较三个节点的值:父节点,当前节点,新节点。根据它们之间的大小关系可以判断新的节点应该插入在哪儿。代码中的关键部分很短,所以不需要多余解释了。其中用到了一个节点栈,用于回溯。所以这个算法用递归来写也是同样直观的。
1 // http://www.careercup.com/question?id=5162732873580544 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 struct TreeNode { 7 int val; 8 TreeNode *left; 9 TreeNode *right; 10 TreeNode(int _val = 0): val(_val), left(nullptr), right(nullptr) {}; 11 }; 12 13 void inorderTraversal(TreeNode *root) 14 { 15 if (nullptr == root) { 16 return; 17 } 18 inorderTraversal(root->left); 19 cout << root->val << ' '; 20 inorderTraversal(root->right); 21 } 22 23 void clearTree(TreeNode *&root) 24 { 25 if (nullptr == root) { 26 return; 27 } 28 clearTree(root->left); 29 clearTree(root->right); 30 delete root; 31 root = nullptr; 32 } 33 34 int main() 35 { 36 vector<int> v; 37 int n; 38 int i; 39 TreeNode *root; 40 TreeNode *tmp; 41 vector<TreeNode *> st; 42 43 while (cin >> n && n > 0) { 44 v.resize(n); 45 for (i = 0; i < n; ++i) { 46 cin >> v[i]; 47 } 48 49 root = new TreeNode(v[0]); 50 st.push_back(root); 51 for (i = 1; i < n; ++i) { 52 if (v[i] < st[st.size() - 1]->val) { 53 tmp = new TreeNode(v[i]); 54 st[st.size() - 1]->left = tmp; 55 st.push_back(tmp); 56 } else if (st.size() == 1 || v[i] < st[st.size() - 2]->val) { 57 tmp = new TreeNode(v[i]); 58 st[st.size() - 1]->right = tmp; 59 st.push_back(tmp); 60 } else { 61 st.pop_back(); 62 --i; 63 } 64 } 65 66 inorderTraversal(root); 67 cout << endl; 68 69 v.clear(); 70 st.clear(); 71 clearTree(root); 72 } 73 74 return 0; 75 }