剑指向offer之二叉树

33.二叉搜索树的后序遍历
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
思路:先把这个树当搜索二叉树,并对其进行判定 在后续遍历中最后一个数字时树的根节点的值
          数组中前面的数字可以分成两部分:
    第一部分是左子树节点的值,它比根节点的值小
    第二部分是右子树节点的值,它比根节点的值大

bool VerifySquenceOfBST(int sequence[],int length)
{
	if(sequence==NULL||length<=0)
		return false;
	
	int root=sequence[length-1];
	
	//在二叉搜索树中左子树节点的值小于根节点的值
	int i=0;
	for(;i<length-1;++i)
	{
		if(sequence[i]>root)
		break;
	} 
	
	//在二叉搜索树中右子树节点的值小于根节点的值
	int j=i;
	for(;i<length-1;++j)
	{
		if(sequence[i]<root)
		return false;
	} 
	
	//判断左子树是不是二叉搜索树
	bool left=true;
	if(i>0)
	left= VerifySquenceOfBST(sequence,i);
	
	bool right=true;
	if(i<length-1)
    	right=VerifySquenceOfBST(sequence+i,length-i-1);
	
	return (left&&right);
} 

 

34.二叉树中和为某一值的路径
题目:输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
思路:当前序遍历的方式访问到某一节点时,我们把该节点添加到路径上,并累加该节点的值
          如果该节点为叶节点,并且路径中的节点值的和刚好等于输入的整数,则符合当前路径要求并打印出来。
          如果该节点不是叶节点,则继续访问它的子节点。

注意:当访问结束后,递归函数会自动回到它的父节点。因此我们在函数退出之前要在路径上删除当前节点并减去当前节点的值

void FindPath(BinaryTreeNode*pRoot,int expectedSum){
	if(pRoot==nullptr)
		return;
		
	std::vector<int> path;
	int currentSum=0;
	FindPath(pRoot,expectedSum,path,currentSum);
}

void FindPath(BinaryTreeNode*pRoot,int expectedSum,std::vector<int>& path,int currentSum){
	
	currentSum+=pRoot->val;
	path.push_back(pRoot->val);
	
	//如果是叶节点,并且路径上节点值的和等于输入的值
	//则打印出这条路径
	bool isLeaf=pRoot->left==nullptr&&pRoot->right==nullptr;
	if(currentSum==expectedSum&&isLeaf){
		printf("A path is found:");
		std::vector<int>::iterator==path.begin();
		for(;iter!=path.end();++iter)
			printf("%d\t",*iter);
		printf("\n");
	} 
	//如果不是叶节点,则遍历它的子节点
	if(pRoot->left!=nullptr)
		FindPath(pRoot->left,expectedSum,path,currentSum);
	if(pRoot->right!=nullptr)
		FindPath(pRoot->right,expectedSum,path,currentSum);
		
	//在返回父节点之前,在路径上删除当前节点
	path.pop_back(); 
}

 

55.二叉树的深度
题目:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
思路:1.如果一棵树只有一个节点那么它的深度为1
          2.如果根节点只有左子树而没有右子树,深度为左子树的深度+1
          3.反之,深度为右子树的深度加1
          4.如果左右子树都存在,深度为左右子树最大的深度加1

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    int TreeDepth(TreeNode* pRoot)
    {
        if(pRoot==nullptr)
            return 0;
        int left=TreeDepth(pRoot->left);
        int right=TreeDepth(pRoot->right);
        
        return (left>right)?(left+1):(right+1);
    }
};

 

平衡二叉树
题目:输入一棵二叉树,判断该二叉树是否是平衡二叉树。
平衡二叉树:某二叉树中任意节点的左右子树的深度相差不超过1
思路:第一种办法:在遍历每个节点时调用函数TreeDepth得到它左右子树深度,如果左右子树深度不超过1,是平衡二叉树
          第二种办法:采用后续遍历二叉树的每个节点,那么在遍历到一个节点之前我们就已经遍历了它的左右子树
        只要在遍历每个节点的时候记录它的深度,我们就可以一边遍历一遍判断每个节点是不是平衡的


//第一种虽然简单  但是效率不高
int TreeDepth(TreeNode*pRoot)
{
	if(pRoot==nullptr)
	    return 0;
	    
	int left=TreeDepth(pRoot->left);
	int right=TreeDepth(pRoot->right);
	
	return (left>right)?(left+1):(right+1);
}

bool IsBalanced(TreeNode*pNode)
{
	if(pRoot==nullptr)
		return true;
		
	int left=TreeDepth(pRoot->left);
	int right=TreeDepth(pRoot->right);
	int diff=left-right;
	if(diff>1||diff<-1)
		return false;
		
	return  IsBalanced(pRoot->left)&&IsBalanced(pRoot->right);
}
//第二中比较便利的方法
class Solution {
public:
    bool IsBalanced_Solution(TreeNode* pRoot) {
        int depth=0;
        return IsBalanced(pRoot,&depth);
    }
    bool IsBalanced(TreeNode*pRoot,int *pDepth)
    {
        if(pRoot==nullptr)
        {
            *pDepth=0;
            return true;
        }
        
        int left,right;
        if(IsBalanced(pRoot->left,&left)&&IsBalanced(pRoot->right,&right))
        {
            int diff=left-right;
            if(diff<=1&&diff>=-1)
            {
                *pDepth=1+(left>right?left:right);
                return true;
            }
        }
        return false;
    }
};

 

28.对称二叉树
题目:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的
思路:由于是对称二叉树 即根左右和根右左遍历得到的结果一样
注意:当树里面的值都一样时 需要把每个节点的nullptr也考虑进去

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
   bool isSymmetrical(TreeNode* pRoot)
    {
        return isSymmetrical(pRoot1,pRoot2);
    }
    bool isSymmetrical(TreeNode* pRoot1,TreeNode* pRoot2)
    {
        if(pRoot1==nullptr&&pRoot2==nullptr)
            return true;
        if(pRoot1==nullptr||pRoot2==nullptr)
            return false;
        if(pRoot1->val!=pRoot2->val)
            return false;
        return isSymmetrical(pRoot1->left,pRoot2->right)&& isSymmetrical(pRoot1->right,pRoot2->left);
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值