LeetCode Unique Binary Search Trees II

本文探讨了根据中序遍历序列构造所有可能的二叉搜索树的方法,并提供了具体的实现代码。此外,还介绍了如何根据给定的先序遍历序列来构建二叉树。

题记:我只看见一棵接一棵的树,却没看见整个森林。

这题搞得蒙呀,刚开没看题意,以为和 按顺序入栈出栈的种类 一样呢,结果题意是:搜索二叉树,中序是123,求先序的可能。想了半天这也不能转化为进栈出栈的问题,有一种解法是求所有的排列,然后对任意排列作为先序判断是够能和按序的中序组成二叉树,再把符合条件的组合构建二叉树,确实很麻烦。再看看,肯定是有更直接的求法,自己没想出来,贴的别人想法。如此干练精湛,佩服的五体投地。如下:

vector<TreeNode *> generate(int beg, int end)
{
    vector<TreeNode* > ret;
    if (beg > end)
    {
        ret.push_back(NULL);
        return ret;
    }
    
    for(int i = beg; i <= end; i++)
    {
        vector<TreeNode* > leftTree = generate(beg, i - 1);
        vector<TreeNode* > rightTree = generate(i + 1, end);
        for(int j = 0; j < leftTree.size(); j++)
            for(int k = 0; k < rightTree.size(); k++)
            {
                TreeNode *node = new TreeNode(i + 1);
                ret.push_back(node);
                node->left = leftTree[j];
                node->right = rightTree[k];              
            }           
    }
    
    return ret;
}

vector<TreeNode *> generateTrees(int n) {
    // Start typing your C/C++ solution below
    // DO NOT write int main() function
    return generate(0, n - 1);
}
下面的代码是,假设题意让求的是按顺序的先根遍历,求符合的二叉树,这个和出栈入栈的题一样,也是按照那个思路做的,如下:

void finn(const int n,int cur,vector<int>&stac,vector<int>&outL,int&count,vector<vector<int> > &ret)
{
	if((int)outL.size ()==n)//终点
	{
		//print(outL);
		ret.push_back(outL);
		count++;
	}
	if(cur!=n+1)//入栈
	{
		//操作
		stac.push_back(cur);
		//进入下层
		finn(n,cur+1,stac,outL,count,ret);
		//恢复
		stac.pop_back ();
	}
	if(!stac.empty())//出栈
	{
		//留底
		int temp=stac[(int)stac.size ()-1];
		//操作
		outL.push_back (temp);
		stac.pop_back ();
		//进入下层
		finn(n,cur,stac,outL,count,ret);
		//恢复
		outL.pop_back ();
		stac.push_back (temp);
	}
}

TreeNode *generateOneTree(vector<int> &preOrder,int preFrom,int preEnd,vector<int> &midOrder,int midFrom,int midEnd)
{
	TreeNode *p=NULL;
	if(preFrom>preEnd||midFrom>midEnd)
		return p;
	if(preFrom==preEnd)
	{
		p = new TreeNode(preOrder[preFrom]);
		return p;
	}
	int midPos=midFrom;
	while(midOrder[midPos]!=preOrder[preFrom])
		midPos++;
	p = new TreeNode(preOrder[preFrom]);
	p->left = generateOneTree(preOrder,preFrom + 1,preFrom + midPos - midFrom,midOrder,midFrom,midPos - 1);
	p->right = generateOneTree(preOrder,preFrom + midPos - midFrom + 1,preEnd,midOrder,midPos + 1,midEnd);
	return p;
}

vector<TreeNode *> generateTrees(int n) {
	vector<TreeNode*> ret;
	if(n==0)
	{
		ret.push_back(NULL);
		return ret;
	}
	vector<int> preOrder;
	vector<int> midOrder;
	for (int i=1;i<=n;i++)
		preOrder.push_back(i);
	
	vector<int> stac;
	vector<int> outL;
	vector<vector<int> >retMidOrger;
	int num=0;
	finn(n,1,stac,outL,num,retMidOrger);

	vector<vector<int> >::iterator iter1=retMidOrger.begin();
	vector<int>::iterator iter2;
	while(iter1!=retMidOrger.end())
	{
		iter2 = iter1->begin();
		midOrder.clear();
		while(iter2!=iter1->end())
		{
			midOrder.push_back(*iter2);
			iter2++;
		}
		TreeNode *p = generateOneTree(preOrder,0,n-1,midOrder,0,n-1);
		ret.push_back(p);
		iter1++;
	}
	return ret;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值