【牛客剑指offer】数据结构——树——简单

JZ55 二叉树的深度

代码

/*
    int TreeDepth(TreeNode* pRoot) {
		if(pRoot==NULL){
			return 0;
		}
		int lDeep=TreeDepth(pRoot->left);
		int rDeep=TreeDepth(pRoot->right);
		return max(lDeep+1,rDeep+1);

    }

get

思路:
递归
树的深度=左右子树深度的较大值+1
沿着树的左右节点向下遍历,直至空节点时,空节点的深度为0

JZ27 二叉树的镜像

代码

    TreeNode* Mirror(TreeNode* pRoot) {
        // write code here
        if(pRoot==nullptr){
            return nullptr;
        }

        TreeNode* lchild=Mirror(pRoot->left);
        TreeNode* rchild=Mirror(pRoot->right);

        pRoot->left=rchild;
        pRoot->right=lchild;

        return pRoot;
    }

get

思路:
递归遍历左右子树、左右孩子节点
遍历到最底层的空节点时,返回空
递归处理左右子树,并保存左右子节点,用于后续交换左右孩子
交换左右孩子完成镜像

JZ32从上往下打印二叉树

代码

    vector<int> PrintFromTopToBottom(TreeNode* root) {
		vector<int> res;
		if(root==nullptr){
			return res;
		}
		queue<TreeNode*> q;				//借助队列实现层次遍历
		q.push(root);					//根入队列
		TreeNode* cur;
		while(!q.empty()){				//队列非空,处理队首元素
			cur=q.front();
			q.pop();
			res.push_back(cur->val);	//队首元素的值纳入结果数组
			if(cur->left!=nullptr){		//有左右孩子,孩子入队
				q.push(cur->left);
			}
			if(cur->right!=nullptr){
				q.push(cur->right);
			}
		}
		return res;
    }

get

二叉树为空时,直接返回空的结果——注意返回类型
有题目可得要使用层序遍历。往往通过队列来实现层序遍历。
初始化队列:根节点入队。
当队列不空时,进行层序遍历。处理队首元素,将其val值纳入结果数组,并弹出队首元素。
若队首节点有左右孩子,则左右孩子纳入队列,待后续处理。

JZ82二叉树中和为某一值的路径

代码

    bool hasPathSum(TreeNode* root, int sum) {
        // write code here
        if(root== NULL){
            return false;
        }
        if(root->left==NULL && root->right==NULL && sum==root->val){
            return true;
        }
        return (hasPathSum(root->right, sum-root->val) ||
        hasPathSum(root->left, sum-root->val));
    }

get

判断路径为某一值——每次经过路径中的一层节点,目标值减去当前节点的val,在当前节点的子树中寻找 // 子树路径值= =结果 // 的路径。
由此可使用递归的方法处理。
当处理到空节点时,返回false。
当处理到叶子节点,且当前sum= = 当前val时,表示这样的路径是存在的,返回true。
若上述两情况均不满足,递归处理当前节点的左右子树。
在处理子树时,目标sum为当前sum减去当前节点的val,只需在子树中找到路径为结果值的路径即可。

JZ79判断是不是平衡二叉树

代码

    int deep(TreeNode* root) {
        if (root == NULL) {
            return 0;
        }
        int left = deep(root->left);
        int right = deep(root->right);
        return max(left + 1, right + 1);
    }

    bool IsBalanced_Solution(TreeNode* pRoot) {
        if(pRoot == NULL){
            return true;
        }
        int left = deep(pRoot->left);
        int right = deep(pRoot->right);
        if(abs(left-right)>1){
            return false;
        }
        return (IsBalanced_Solution(pRoot->left) && IsBalanced_Solution(pRoot->right));
    }

get

思路:
获取树的深度的函数deep()
判断树是不是二叉树,所有结点的左右子树深度相差为0或1.
空节点左右子树高度均为0,是平衡二叉树。
非空节点,获取左右子树的高度,若高度差绝对值大于1,则不是平衡二叉树。
若满足左右子树高度差为0或1,则继续判断子树是否满足平衡二叉树,若左右子树均为平衡二叉树,且左右子树的高度差为0或1,则该节点为根节点的树为平衡二叉树。
——在判断左右子树是否为平衡二叉树中,用到了递归处理。

JZ28对称的二叉树

代码

    //判断是否为镜像的子树
    bool isMirror(TreeNode* root1, TreeNode* root2){
        //都为空,镜像
        if(root1==NULL && root2==NULL){
            return true;
        }
        //只有一个节点为空。或两节点的val不同
        if((root1==NULL&&root2!=NULL) || (root1!=NULL&&root2==NULL)
        ||(root1->val!=root2->val)){
            return false;
        }
        //当前根节点满足镜像,处理其子树
        return (isMirror(root1->left,root2->right)&&isMirror(root1->right,root2->left));
    }

    bool isSymmetrical(TreeNode* pRoot) {
        return isMirror(pRoot,pRoot);
    }

get

联系镜像二叉树。
镜像的二叉树,两棵树左右对称。 某节点的左子树与对称位置的右子树镜像。
对称的二叉树,根节点的左右子树镜像。

参考up 香辣鸡排蛋包饭 的图示:
up:香辣鸡排蛋包饭

问题可推演为,判断一棵树是否沿根节点镜像。
镜像——树A的左侧与树B的右侧镜像、对称。
一棵树对称——左右子树镜像——同一棵树的左侧与右侧镜像。
判断镜像的函数的两个参数均为根节点即可。

判断镜像:
空树,镜像。
只有一个为空树,或当前处理的树的两个根节点val值不同,不镜像。
两者均非空,且val值相同,继续处理其子树。
判断镜像,对子树的处理为 树A的左侧与树B的右侧。树A的右侧与树B的左侧。

JZ68二叉搜索树的最近公共祖先

代码

    int lowestCommonAncestor(TreeNode* root, int p, int q) {
        // write code here
        while (root) {
            if (root->val < p && root-> val < q) {
                root = root->right;
            }
            else if (root->val > p && root-> val > q) {
                root = root->left;
            }
            else{
                return root->val;
            }
        }
        return -1;
    }

get

思路:
讲解视频
二叉搜索树有序
当p、q均大于或均小于root时,两者在root的同一侧,则root可下移到对应侧的孩子节点,继续判断。
当p、q一大一小时,两者在root的两侧,则root即为其最近公共祖先

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值