剑指Offer(数据结构与算法面试题精讲)C++版——day15

题目一:二叉树最低层最左边的值

    题目:如何在一棵二叉树中找出它最低层最左边节点的值?假设二叉树中最少有一个节点。例如,在如图7.5所示的二叉树中最低层最左边一个节点的值是5。
在这里插入图片描述
    这道题就比较方便了,结合前面剑指Offer(数据结构与算法面试题精讲)C++版——day14里面提到的使用层序遍历以及利用qu.size()对每一层进行拆分。这样我们就能够获取每一层的所有节点,只需要在遍历的时候统计该层数据的第一个,用一个变量存储,直到遍历面整个动态队列,最终得到的结果就是最终想要的最后的结果了,得到如下代码:

int getLeftCorner(treeNode * tree) {
	queue<treeNode *> qu;
	treeNode * p;
	int leftCorner=-1;
	if(!tree)return -1;
	qu.push(tree);
	while(!qu.empty()) {
		for(int i=0,size=qu.size(); i<size; ++i) {
			p=qu.front();
			qu.pop();
			if(i==0) {
				leftCorner=p->val;
			}
			if(p->left) {
				qu.push(p->left);
			}
			if(p->right) {
				qu.push(p->right);
			}
		}
	}
	return leftCorner;
}

在这里插入图片描述

题目二:二叉树的右侧视图

    题目:给定一棵二叉树,如果站在该二叉树的右侧,那么从上到下看到的节点构成二叉树的右侧视图。例如,图7.6中二叉树的右侧视图包含节点8、节点10和节点7。请写一个函数返回二叉树的右侧视图节点的值。
在这里插入图片描述
    我们首先要明确右视图的具体含义。根据题目给定的条件以及示例进行分析,所谓二叉树的右视图,指的是当我们从二叉树的右侧进行观察时,所能够看到的节点所构成的序列。从层序遍历的角度来看,在每一层中,最右侧的节点就是我们从右往左看时能够看到的节点,这些节点组成的集合就是二叉树的右视图。
    因此,可以考虑使用层序遍历,从根节点开始,逐层地对节点进行访问。为了准确地获取每一层的最右侧节点,我们可以利用队列这一数据结构来辅助实现层序遍历。在层序遍历的过程中,队列会存储当前层的所有节点。通过获取队列的大小qu.size(),我们能够清晰地知道当前层节点的数量。
    在每一层的遍历中,我们会依次将当前层的节点从队列中取出,并将它们的子节点加入到队列中。在取出当前层节点的过程中,我们会进行计数。当计数达到当前层节点的总数时,说明我们已经遍历到了当前层的最后一个节点,这个节点就是该层的最右侧节点,也就是我们需要记录到右视图结果中的节点。我们将这个节点的值存储下来,然后继续进行下一层的遍历。通过这种方式,可以依次获取每一层的最右侧节点,最终得到的结果就是二叉树的右视图。代码如下:

void getRightView(treeNode * tree,vector<int> &vec) {
	queue<treeNode *> qu;
	treeNode * p;
	if(!tree)return ;
	qu.push(tree);
	while(!qu.empty()) {
		for(int i=0,size=qu.size(); i<size; ++i) {
			p=qu.front();
			qu.pop();
			if(i==size-1){
				vec.push_back(p->val);
			} 
			if(p->left) {
				qu.push(p->left);
			}
			if(p->right) {
				qu.push(p->right);
			}
		}
	}
}

在这里插入图片描述

题目三:二叉树剪枝

    题目:一棵二叉树的所有节点的值要么是0要么是1,请剪除该二叉树中所有节点的值全都是0的子树。例如,在剪除图8.2(a)中二叉树中所有节点值都为0的子树之后的结果如图8.2(b)所示。
在这里插入图片描述
    由题意可知,因为当一个节点本身为0并且其左右子节点都是空的情况下,这个节点需要被裁剪掉,接下来需要分析被删除的这个节点的右侧兄弟节点,如果右侧兄弟节点也需要被删除的话,那么紧接着需要判断删除之后左右兄弟节点的父节点是否需要删除,如果父节点为0,那么由于刚才其左右孩子节点已经被删除过,那么父节点也需要删除。我们分析可以得到,这种扫描过程恰好是后续遍历的扫描过程,因此我们可以站在后序遍历的基础上去检测节点,如果该节点满足了值为0并且左右孩子为空,那么可以直接将这个节点设置为空。于是得到如下代码:

treeNode* clearTree(treeNode * tree) {
	if(tree==nullptr) {
		return nullptr;
	} else {
		tree->left=clearTree(tree->left);
		tree->right=clearTree(tree->right);
		if(!tree->left&&!tree->right&&!tree->val) {
			free(tree);
			tree=nullptr;
		}
	}
	return tree;
}

在这里插入图片描述

附录:源码gitee仓库

    考虑到有些算法需要模拟数据,如果全部放进来代码显得过长,不利于聚焦在算法的核心思路上。于是把所有的代码整理到了开源仓库上,如果想要看详细模拟数据,可在开源仓库自取:【凌空暗羽/剑指offer-C++版手写代码】

    我是【Jerry说前后端】,本系列精心挑选的算法题目全部基于经典的《剑指 Offer(数据结构与算法面试题精讲)》。在如今竞争激烈的技术求职环境下,算法能力已成为前端开发岗位笔试考核的关键要点。通过深入钻研这一系列算法题,大家能够系统地积累算法知识和解题经验。每一道题目的分析与解答过程,都像是一把钥匙,为大家打开一扇通往高效编程思维的大门,帮助大家逐步提升自己在数据结构运用、算法设计与优化等方面的能力。
    无论是即将踏入职场的应届毕业生,还是想要进一步提升自己技术水平的在职开发者,掌握扎实的算法知识都是提升竞争力的有力武器。希望大家能跟随我的步伐,在这个系列中不断学习、不断进步,为即将到来的前端笔试做好充分准备,顺利拿下心仪的工作机会!快来订阅吧,让我们一起开启这段算法学习之旅!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jerry说前后端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值