搜索二叉树的特点:
对于所有的节点,他的左子树上所有的节点都比他小,右子树上所有的节点都比他大.
所以就有了中序遍历二叉树会得到一个递增的数组
思路
1.首先:建立的是搜索二叉树,所以给定一个数组必定能建且唯一的建一个二叉树,或者数组不满足条件,建不了二叉树
2.所以利用给定的的n里找到0~n内所有的组合数组 举例如图
这里面有一个不符合建立搜索二叉树的组合,所以只能返回五个符合条件的二叉树
符合搜索二叉树数组的特点是从数组的任意一个数字出发,如果后面的数字都比这个数字大,(可以作为这个节点的右子树) 或者都比这个数字小(可以作为这个数字的左子树) 或者前面一部分比这个数字小(做左子树),后面一部分比这个数字大(做右子树)
不符合的数组的特征,有一个数字后面的数字先比他大,后面一部分又比他小,例如2,3,1.
假设当前来到2位置,3比2大,1比2小,
所以不满足条件.因为搜索二叉树要满足左子树所有的节点比自己小,右子树所有的节点都比自己大
1.如果2,3,1要满足条件需要先建右子树再建左子树,首先函数不允许,函数定义的是先建左,再建右.即使建好了,建成的树和2,1,3建成的树一样,所以这个组合不满足条件
3.找到这些组合后分别把数组传进另一个接口建树
typedef struct TreeNode Node;
Node*Make(int x)
{
Node*make=(Node*)malloc(sizeof(Node));
make->val=x;
make->left=NULL;
make->right=NULL;
return make;
}
void swap(int *x,int*y)
{
int tmp=*x;
*x=*y;
*y=tmp;
}
Node* func2(int *arr1,int l,int r)
{
if(l>r)
{
return NULL;
}
Node*root=Make(arr1[l]);
int j=l;
for(;j<=r;j++)
{
if(arr1[j]>arr1[l])
{
break;
}
}
// int jj=j;
// for(;jj<=r;jj++)
// {
// if(arr1[jj]<arr1[l])
// { //之前考虑在建树的时候判断这个数组是否能建成一棵树,
// return NULL; //如果在这里返回,会返回一个空,这个节点之前建的节点销毁不了,整条路销毁不掉,所以不满足
// }
// }
root->left=func2(arr1,l+1,j-1);
root->right=func2(arr1,j,r);
return root;
}
void func1(int *arr,Node**res1,int n,int i,int *size) //生成各种组合的数组
{
if(i==n) //递归结束
{
for(int x=0;x<n-1;x++) //选择生成的数组是不是满足条件
{
int flag=0;
for(int y=x+1;y<n;y++)
{
if(arr[y]>arr[x])
{
flag=1;
}
if(flag==1&&arr[y]<arr[x])
{
return; //如果生成的数组不满足条件直接返回
}
}
}
int *arr1=(int*)malloc(sizeof(int)*n); //如果满足建树的条件就建树
for(int i=0;i<n;i++)
{
arr1[i]=arr[i];
}
Node*ll=func2(arr1,0,n-1); //建树的接口
if(ll)
{
res1[(*size)++]=ll;
}
return;
}
for(int j=i;j<n;j++)
{
swap(&arr[j],&arr[i]);
func1(arr,res1,n,i+1,size);
swap(&arr[j],&arr[i]);
}
}
struct TreeNode** generateTrees(int n, int* returnSize){
//先将所有数字全排列,找合适的数组传进另一个接口
//递归建树
Node**res1=(Node**)malloc(sizeof(Node*)*10000);//存放树的指针
int *arr=(int*)malloc(sizeof(int)*n);
for(int i=0;i<n;i++) //利用前n个数字封装一个数组
{
arr[i]=i+1;
}
*returnSize=0;
func1(arr,res1,n,0,returnSize);
return res1;
}