leecode 解题总结:95. Unique Binary Search Trees II
2017-02-14 12:31
405 查看
#include <iostream> #include <stdio.h> #include <vector> using namespace std; /* 问题: Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1...n. For example, Given n = 3, your program should return all 5 unique BST's shown below. 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3 分析:这道题目实际上就是构建二叉查找树。二叉查找树由于不能调整位置,因此输入的 数据顺序会对树的形状产生影响。可以每次尝试不同的输入顺序: 比如1,2,3或者1,3,2;或者2,1,3;或者3,1,2或者3,2,1 但是即使用不同的顺序,可能会产生重复,比如:2,1,3和2,3,1产生的树的形状是一样的。 根本原因在于选用的根节点恰好是中间的数据。 简单的方式就是:每次产生一棵树,就和之前产生的所有树比较,看是否重复,如果重复 就过滤。 判断两棵树是否相同,可以递归得判定。 先判定两棵树当前结点值是否相同,如果不相同,直接返回两棵树不同; 否则,递归判定当前结点的左右子树是否相同即可 对于不同的输入:这个需要通过排列生成 输入: 3 输出: 1 3 2,3 2 1,3 1 2,2 1 3,1 2 3 关键: 1 采用排列+构建二叉查找树+去重做 2 leecode解法:https://leetcode.com/problems/unique-binary-search-trees-ii/?tab=Solutions 由于二叉查找树是中序,因此,可以选定[1...n]中任意数i为根节点, 那么左子树为[1...i-1],右子树为[i+1...len] 如果发现左边=右边,说明当前要生成的就是一个结点,就把结点当做根节点压入【参见n为1的情况】 如果左边>右边,不可能,返回空插入 本质是不断从给定的序列中选定一个成为根节点,令左半段成为左子树,令右半段成为右子树。 牛逼,以后看到树的问题多从递归入手 //注意每颗子树中也会产生不同的根节点,因此返回的左子树也是一个数组,右子树也是一个数组,然后做笛卡尔积 vector<TreeNode*> buildTree(int start , int end ) */ struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; class Solution { public: //注意每颗子树中也会产生不同的根节点,因此返回的左子树也是一个数组,右子树也是一个数组,然后做笛卡尔积 vector<TreeNode*> buildTree(int start , int end ) //TreeNode* buildTree(int start , int end, vector<TreeNode*>& result) { vector<TreeNode*> result; //递归出口,返回的NULL,实际上可能是 if(start > end) { result.push_back(NULL); return result; } //只提供一个结点,则直接是根节点,后续会遍历到这里 if(start == end) { TreeNode* node = new TreeNode(start); result.push_back(node); return result; } vector<TreeNode*> lefts; vector<TreeNode*> rights; int leftSize; int rightSize; for(int i = start ; i <= end ; i++) { lefts = buildTree(start , i - 1); rights = buildTree(i + 1 , end); leftSize = lefts.size(); rightSize = rights.size(); for(int j = 0 ; j < leftSize; j++) { for(int k = 0 ; k < rightSize ; k++) { TreeNode* root = new TreeNode(i); root->left = lefts.at(j); root->right = rights.at(k); result.push_back(root); } } } return result; } vector<TreeNode*> generateTrees(int n) { vector<TreeNode*> nodes; if(n <= 0) { return nodes; } nodes = buildTree(1 , n); return nodes; } }; class Solution2 { public: void permutate(int n,int pos , vector<int>& result, vector< vector<int> >& results) { if(pos == n) { results.push_back(result); return; } bool isOk; for(int i = 1 ; i <= n ; i++) { isOk = true; for(int j = 0 ; j < pos ; j++) { if(i == result.at(j)) { isOk = false; break; } } if(isOk) { result.push_back(i); permutate(n , pos + 1 , result , results); result.pop_back(); } } } TreeNode* insertNode(TreeNode* root , int value) { if(!root) { return NULL; } //如果给定值> 根节点值,如果右孩子为空,作为右孩子,否则以右孩子作为根节点,递归 if(value >= root->val) { if(NULL == root->right) { TreeNode* node = new TreeNode(value); root->right = node; } else { insertNode(root->right , value); } } else { if(NULL == root->left) { TreeNode* node = new TreeNode(value); root->left = node; } else { insertNode(root->left , value); } } return root; } bool isSameTree(TreeNode* root1 , TreeNode* root2) { //如果两个当前结点都为空,则相同 if(NULL == root1 && NULL == root2) { return true; } else if(NULL == root1) { return false; } else if(NULL == root2) { return false; } if(root1->val != root2->val) { return false; } return isSameTree(root1->left , root2->left) && isSameTree(root1->right ,root2->right); } //判断当前二叉查找树是否和集合中的二叉查找树重复 bool isRepeated(vector<TreeNode*>& nodes , TreeNode* root) { if(nodes.empty()) { return false; } int size = nodes.size(); for(int i = 0 ; i < size ; i++) { if(isSameTree(nodes.at(i) , root)) { return true; } } return false; } vector<TreeNode*> generateTrees2(int n) { vector<TreeNode*> nodes; if(n <= 0) { return nodes; } vector< vector<int> > results; vector<int> result; permutate(n , 0 , result , results); int size = results.size(); //尝试不同的数据输入,来构建二叉树 int len; for(int i = 0 ; i < size ; i++) { len = results.at(i).size(); TreeNode* root = NULL; for(int j = 0 ; j < len ; j++ ) { if(j) { root = insertNode(root , results.at(i).at(j) ); } //输入根节点 else { root = new TreeNode( results.at(i).at(j) ); } } //构建完了二叉查找树,下面判断是否重复 if(nodes.empty()) { nodes.push_back(root); } //如果 else { //如果不重复 if(!isRepeated(nodes , root)) { nodes.push_back(root); } } } return nodes; } }; //根左右 void preOrderVisit(TreeNode* root , vector<int>& result) { if(NULL == root) { return; } if(root) { result.push_back(root->val); } preOrderVisit(root->left, result); preOrderVisit(root->right , result); } //打印每颗二叉查找树,用前序方式 void print(vector<TreeNode*>& result) { if(result.empty()) { cout << "no result" << endl; return; } int size = result.size(); int len; for(int i = 0 ; i < size ; i++) { vector<int> datas; preOrderVisit(result.at(i) , datas); len = datas.size(); for(int j = 0 ; j < len ; j++) { cout << datas.at(j) << " "; } cout << ","; } cout << endl; } //如果删除一棵树,只能先递归删除其左右子树,如果遇到一个结点没有左右孩子,就删除 void deleteTree(TreeNode* node) { //如果当前结点为空,无需删除,直接返回 if(!node) { return; } else if(NULL == node->left && NULL == node->right) { delete node; node = NULL; } if(node) { deleteTree(node->left); deleteTree(node->right); } } void deleteTrees(vector<TreeNode*>& nodes) { if(nodes.empty()) { return; } int size = nodes.size(); for(int i = 0 ; i < size ; i++) { deleteTree(nodes.at(i)); } } void process() { vector<int> nums; int value; int num; Solution solution; vector<TreeNode*> result; while(cin >> num ) { result = solution.generateTrees(num); print(result); deleteTrees(result); } } int main(int argc , char* argv[]) { process(); getchar(); return 0; }
相关文章推荐
- Leetcode 95. Unique Binary Search Trees II及二叉树最大最小深度镜像树总结
- [Leetcode] 95. Unique Binary Search Trees II 解题报告
- leetCode 95.Unique Binary Search Trees II (唯一二叉搜索树) 解题思路和方法
- Leetcode 95. Unique Binary Search Trees II 二叉搜索树2 解题报告
- [leetcode] 95. Unique Binary Search Trees II 解题报告
- leetCode 95.Unique Binary Search Trees II (唯一二叉搜索树) 解题思路和方法
- 【LeetCode】95.Unique Binary Search Trees II(Medium)解题报告
- 95. Unique Binary Search Trees II
- 【LeetCode】95. Unique Binary Search Trees II
- LeetCode OJ 95. Unique Binary Search Trees II
- LeetCode --- 95. Unique Binary Search Trees II
- Middle-题目64:95. Unique Binary Search Trees II
- [Leetcode] 95. Unique Binary Search Trees II
- Leetcode 95. Unique Binary Search Trees II
- Unique Binary Search Trees II [Leetcode 解题报告]
- 95. Unique Binary Search Trees II
- leetcode 95. Unique Binary Search Trees II-分治算法|动态规划|卡特兰数
- LeetCode *** 95. Unique Binary Search Trees II
- [leetcode] 95. Unique Binary Search Trees II
- leetcode 95. Unique Binary Search Trees II