单链表转二叉树
题目描述
给定一个单链表,其中的元素按升序排序,请将它转化成平衡二叉搜索树(BST)
示例1
输入
复制
{-1,0,1,2}
返回值
复制
{1,0,2,-1}
说明:本题目包含复杂数据结构TreeNode、ListNode,点此查看相关信息
typedef TreeNode Node;
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类
* @return TreeNode类
*/
TreeNode* sortedListToBST(ListNode* head) {
// write code here
return build(head,NULL);
}
Node* build(ListNode* head,ListNode* tail) {
if(head==NULL|| head==tail) return NULL;
ListNode* first= head,*last=head;
while(first!=tail && first->next!=tail) first = first->next->next,last = last->next;
Node *root = new Node(last->val);
root->left = build(head,last);
root ->right = build(last->next,tail);
return root;
}
};
升序数组转二叉树
题目描述
给出一个升序排序的数组,将其转化为平衡二叉搜索树(BST).
示例1
输入
复制
[-1,0,1,2]
返回值
复制
{1,0,2,-1}
说明:本题目包含复杂数据结构TreeNode,点此查看相关信息
typedef TreeNode Node;
class Solution {
public:
/**
*
* @param num int整型vector
* @return TreeNode类
*/
TreeNode* sortedArrayToBST(vector<int>& num) {
if(num.size()<=0) return NULL;
return build(num,0 ,num.size()-1);
}
Node* build(vector<int>& a,int l,int r) {
if(l>r) return nullptr;
// if(l==r) return new Node(a[l]);
int mid = l+r+1>>1;
Node * root = new Node(a[mid]);
root ->left = build(a,l,mid-1);
root ->right = build(a,mid+1,r);
return root;
}
};
中序遍历 和后续遍历序列 生成的二叉树
题目描述
给出一棵树的中序遍历和后序遍历,请构造这颗二叉树
注意:
保证给出的树中不存在重复的节点
示例1
输入
复制
[2,1,3],[2,3,1]
返回值
复制
typedef TreeNode Node;
class Solution {
public:
/**
*
* @param inorder int整型vector
* @param postorder int整型vector
* @return TreeNode类
*/
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
// write code here
int n = inorder.size(),m = postorder.size();
if(n!=m) return NULL;
return build(inorder,postorder,0,n-1,0,n-1);
}
Node* build(vector<int>&in,vector<int> &post,int il,int ir,int pl,int pr) {
if(il>ir || pl>pr) return NULL;
//post order 左右 [根] root-> pr
//inorder 左根右 root-> il+ir/2
int target = post[pr],in_root_idx=il;
for(int i=il;i<=ir;++i) {
if(in[i]==target) {
in_root_idx = i;
break;
}
}
Node* root = new Node(target);
int r_to_i = ir - in_root_idx;
root->left = build(in,post,il,in_root_idx-1,pl,pr-r_to_i-1);
root->right = build(in,post,in_root_idx+1,ir,pr-r_to_i,pr-1);
return root;
}
};
题目描述
给出一棵树的前序遍历和中序遍历,请构造这颗二叉树
注意:
可以假设树中不存在重复的节点
示例1
输入
复制
[1,2],[1,2]
返回值
复制
typedef TreeNode Node;
typedef vector<int> Array;
class Solution {
public:
/**
*
* @param preorder int整型vector
* @param inorder int整型vector
* @return TreeNode类
*/
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
// write code here
int n = preorder.size(),m = inorder.size();
if(n!=m) return NULL;
return build(preorder,inorder,0,n-1,0,n-1);
}
Node* build(Array &pre,Array &in, int pl,int pr,int il,int ir) {
if(pl>pr || il>ir) return NULL;
int target = pre[pl];int root_idx=il;
for(int i=il;i<=ir;++i) {
if(in[i]==target){root_idx = i;break;}
}
Node* root = new Node(target);
int len = root_idx - il;
//先序,根左,右
root ->left = build(pre,in,pl+1,pl+len,il,root_idx-1);
root ->right = build(pre,in,pl+len+1,pr,root_idx+1,ir);
return root;
}
};
后序遍历生成BST
给定一个值n,请生成所有的存储值1...n.的二叉搜索树(BST)的结构
例如:
给定n=3,你的程序应该给出下面五种不同的二叉搜索树(BST)
typedef TreeNode Node;
class Solution {
public:
/**
*
* @param n int整型
* @return TreeNode类vector
*/
vector<TreeNode*> generateTrees(int n) {
// write code here
return build(1,n);
}
vector<Node*> build(int l,int r) {
if(l>r) return {NULL};
vector<Node*> res;
for(int k=l;k<=r;++k) {
vector<Node*> left = build(l,k-1);
vector<Node*> right = build(k+1,r);
for(int i=0;i<left.size();++i) {
for(int j=0;j<right.size();++j) {
Node* root = new Node(k);
root->left = left[i];
root->right = right[j];
res.push_back(root);
}
}
}
return res;
}
};
输入N 求二叉树生成的个数
给定一个值n,能构建出多少不同的值包含1...n的二叉搜索树(BST)?
例如
给定 n = 3, 有五种不同的二叉搜索树(BST)
分析:
f(1) = 1;
f(2) = f(1)+f(1);
f(3) = f(2)+f(1)f(1)+f(2);
f(4) = f(3)+f(1)f(2)+f(2)f(1)+f(3)
f(5) = f(4)+f(1)f(3)+f(2)f(2)f(3)*f(1)+f(4)
思路:
考虑根节点,设对于任意根节点k,有f(k)种树的可能。
比k小的k-1个元素构成k的左子树。则左子树有f(k-1)种情况。
比k大的n-k个元素构成k的右子树。则右子树有f(n-k)种情况。
易知,左右子树相互独立,所以f(k)=f(k-1)*f(n-k)。
综上,对于n,结果为k取1,2,3,...,n时,所有f(k)的和。
代码思路:
根据上述思路可以用简单的递归方法快速解决。
现在考虑非递归解法,用数组记录每个f(i)的值,记f(0)=1,f(1)=1。
根据公式:f(k)=f(k-1)*f(n-k),访问数组中的元素。
循环求和,结果更新到数组中。
(PS:此题可用Catalan number快速求解:对于n,答案为1/(n+1)*nC2n。)
class Solution {
public:
/**
*
* @param n int整型
* @return int整型
*/
int numTrees(int n) {
// write code here
if(n<0) return -1;
if(n==0) return 1;
int dp[n+1];
memset(dp,0,sizeof dp);
dp[0] = 1;
dp[1] = 1;
for(int i=2;i<=n;++i) {
for(int j=0;j<i;++j) {
dp[i] += dp[j]*dp[i-j-1];
}
}
return dp[n];
}
};