Leetcode:96.不同的二叉搜索树
给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?
示例:
输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
解题思路:
核心思想:卡特兰数列,动态规划(DP)。
f(n)=f(0)*f(n-1)+f(1)*f(n-2)+f(2)*f(n-3)+......+f(n-1)*f(0);
很显然,如果不用数组保存已经算过的值,就要重复计算多次相同的结果,当n非常大时,重复的量也非常多,难免超时。
class Solution { public: int numTrees(int n) { if (n == 0) return 1; if (n == 1) return 1; if (data[n] != 0) return data[n]; int sum = 0; for (int i = 1; i <= n; i++) { sum += numTrees(i - 1)*numTrees(n - i); } data[n] = sum; return sum; } private: vector<int> data = vector<int>(10000, 0); }; |
Leetcode:95.不同的二叉搜索树II
核心思想:卡特兰数列,递归,动态规划。先按照递归的思想生成n个结点所有形状的树,之后再将1-n按照中序遍历的顺序写入树中。
根据这题,本人编写了如下的关于二叉树的几个功能。
1. 树的复制。复制一个二叉树,形状与root相同,但是重新分配了内存。
TreeNode* copyTree(TreeNode* root);
2. 查找n个结点的树的形状。将他们的根结点储存起来,确保这些树没有共同的结点。
vector<TreeNode*> find(int n);
3. 按照中序遍历的顺序,将1-n写入一个二叉树中。
void In_order(TreeNode* root);
这个代码最快速度为16ms,多次出现,相比8ms,12ms的代码而言,我觉得主要的差距在于,我这个生成树的形状之后,将所有结点赋值为0,最后又要按照中序遍历顺序将1-n赋值到结点中,这里出现了多余的2倍操作,但是按照这个思路不太好一开始将应有的数值赋值,后续仍需改进。
#define hasLChild(x) (!(x->left==NULL)) #define hasRChild(x) (!(x->right==NULL)) class Solution { public: vector<TreeNode*> generateTrees(int n) { if (n <= 0) return{}; vector<TreeNode*> res = find(n); //将中序遍历所有二叉树,将1-n写入树中 for (int i = 1; i <= int(res.size()); i++) { num = 1; In_order(res[i - 1]); } return res; } void In_order(TreeNode* root) { if (hasLChild(root)) In_order(root->left); root->val = num; num++; if (hasRChild(root)) In_order(root->right); } vector<TreeNode*> find(int n) { if (n == 0) return{ NULL }; if (n == 1) return{ new TreeNode(0) }; if (int(dp[n].size()) > 0) return dp[n]; vector<TreeNode*> res; vector<TreeNode*> data1, data2; for (int i = 1; i <= n; i++) { data1 = find(i - 1); data2 = find(n - i); for (int j = 1; j <= int(data1.size()); j++) { for (int k = 1; k <= int(data2.size()); k++) { TreeNode* temp = new TreeNode(0); temp->right = copyTree(data1[j - 1]); temp->left = copyTree(data2[k - 1]); res.push_back(temp); } } } dp[n] = res; return res; } TreeNode* copyTree(TreeNode* root) {//将root复制到copy中 TreeNode* copy; if (root == NULL) { copy = NULL; return copy; } copy = new TreeNode(0); queue<TreeNode*> Qr, Qc; TreeNode* tempr,*tempc; Qr.push(root); Qc.push(copy); while (!Qr.empty()) { tempr = Qr.front(); tempc = Qc.front(); Qr.pop(); Qc.pop(); if (hasLChild(tempr)) { tempc->left = new TreeNode(0); Qr.push(tempr->left); Qc.push(tempc->left); } if (hasRChild(tempr)) { tempc->right = new TreeNode(0); Qr.push(tempr->right); Qc.push(tempc->right); } } return copy; } private: int num = 0; vector<TreeNode*> dp[1000]; }; |
参考的别人的更优秀的代码,学到了很多,平均用时12ms,如下。
class Solution { if(b>e){ |