【LeetCode】P95 不同的二叉搜索树 II(未完结)

P95 不同的二叉搜索树 II

题目链接:95. 不同的二叉搜索树 II.

题目描述

给定一个整数 n,生成所有由 1 … n 为节点所组成的二叉搜索树 。

示例:

输入:3
输出:
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]
解释:
以上的输出对应以下 5 种不同结构的二叉搜索树:
1         3     3      2      1\       /     /      / \      3     2     1      1   3      2/     /       \                 2     1         2                 3

二叉树结点的定义:

struct TreeNode {
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(): val(0),left(nullptr),right(nullptr) {}
	TreeNode(int x): val(x),left(nullptr),right(nullptr) {}
	TreeNode(int x,TreeNode* left,TreeNode* right): val(x),left(left),right(right) {}
};

题解

方法一:递归

思路

二叉搜索树或者是一颗空树,或者是具有下列性质的二叉树:

  • 每个结点都有一个作为搜索依据的关键码(key),所有结点的关键码互不相同。
  • 左子树(如果存在)上的所有结点的关键码都小于根结点的关键码。
  • 右子树(如果存在)上的所有结点的关键码都大于根结点的关键码。
  • 左子树和右子树也是二叉搜索树。

当我们在构建关键码序列为 [ b e g i n , e n d ] [begin,end] [begin,end] (为了方便,这里将 [ b e g i n , e n d ] [begin,end] [begin,end] 表示为序列 b e g i n 、 b e g i n + 1... e n d begin、begin+1...end beginbegin+1...end,下同)的所有二叉搜索树时,先对根结点的值 r o o t V a l rootVal rootVal 进行枚举 ( r o o t V a l = b e g i n 、 b e g i n + 1... e n d ) (rootVal=begin、begin+1 ... end) rootVal=beginbegin+1...end,由二叉搜索树的定义知,若根结点的值为 r o o t V a l rootVal rootVal,那么其左子树为关键码序列为 [ b e g i n , r o o t V a l − 1 ] [begin,rootVal-1] [begin,rootVal1],其右子树的关键码序列为 [ r o o t V a l + 1 , e n d ] [rootVal+1,end] [rootVal+1,end],这样就将 构建关键码序列为 [ b e g i n , e n d ] [begin,end] [begin,end] 的所有二叉搜索树问题 转换为 构建关键码序列为 [ b e g i n , r o o t V a l − 1 ] [begin,rootVal-1] [begin,rootVal1] 的所有二叉搜索树和构建关键码序列为 [ r o o t V a l + 1 , e n d ] [rootVal+1,end] [rootVal+1,end] 的所有二叉搜索树 两个子问题,然后可以同样对上面的两个子问题再次重复上面的操作(即枚举根结点,使用左子树的关键码序列构建所有二叉搜索树,使用右子树的关键码序列构建所有二叉搜索树),这样我们就自然会想到使用递归来求解。

枚举根结点的值为 r o o t V a l rootVal rootVal,当构建出关键码序列为 [ b e g i n , r o o t V a l − 1 ] [begin,rootVal-1] [begin,rootVal1] 的所有二叉搜索树(记为 l e f t S u b T r e e leftSubTree leftSubTree 集合)和关键码序列为 [ r o o t V a l + 1 , e n d ] [rootVal+1,end] [rootVal+1,end] 的所有二叉搜索树(记为 r i g h t S u b T r e e rightSubTree rightSubTree 集合),然后在 l e f t S u b T r e e leftSubTree leftSubTree r i g h t S u b T r e e rightSubTree rightSubTree 集合中各取一个元素,这两个元素分别作为根结点的左子树与右子树。

递归的终止条件
b e g i n > e n d begin>end begin>end 时递归终止,返回一个集合,这个集合中的元素为一个空指针。

递归的入口
求解由 1 … n 为节点所组成的所有二叉搜索树问题,就是构建关键码序列为 [ 1 , n ] [1,n] [1,n] 的所有二叉搜索树。

算法

class Solution {
public:
	vector<TreeNode*> generateTrees(int begin,int end){
		if(begin>end){
			return vector<TreeNode*>(1,nullptr);
		}
		vector<TreeNode*> allTrees;
		for(int rootVal=begin;rootVal<=end;++rootVal){
			vector<TreeNode*> leftSubTree=generateTrees(begin,rootVal-1);
			vector<TreeNode*> rightSubTree=generateTrees(rootVal+1,end);
			for(int left=0;left<leftSubTree.size();++left){
				for(int right=0;right<rightSubTree.size();++right){
					TreeNode* rootNode=new TreeNode(rootVal);
					rootNode->left=leftSubTree[left];
					rootNode->right=rightSubTree[right];
					allTrees.push_back(rootNode);
				}
			}
		}
		return allTrees;
	}

	vector<TreeNode*> generateTrees(int n) {
		if(!n){
			return vector<TreeNode*>();
		}
		return generateTrees(1,n);
	}
};

复杂度分析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值