c实现力扣95题(不同的搜索二叉树)

搜索二叉树的特点:

对于所有的节点,他的左子树上所有的节点都比他小,右子树上所有的节点都比他大.

所以就有了中序遍历二叉树会得到一个递增的数组

 

 思路

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;
}

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值