最新【数据结构与算法】详解 “清华大学(考研)OJ题,2024年最新大数据开发常用面试题

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取


📌导航小助手📌

💡本章重点

  • 二叉树的层序遍历
  • 二叉树重要面试OJ题
  • 🔥算法思想

**🍞一.**广度优先遍历

**🥐Ⅰ.**层序遍历

💡广度优先遍历: 对于二叉树来说又称为层序遍历

  • 即访问顺序不同与先序中序后序遍历【这三种遍历统称为:深度优先遍历】要递归访问完一个分支后才返回再递归访问剩下的分支
  • 层序遍历就是一层一层的遍历树的结点,遍历完一层后,才遍历下一层,直至遍历完整棵树

特别注意:

  • 对于广度优先遍历,我们一般借助队列的数据结构去实现
    【对于>队列<的知识有遗忘的,可以点击跳转食用哟~】
  • 在遍历完后,切记对队列所申请的空间进行释放,以防止 内存泄露的情况

➡️实现方式:

  • 1️⃣先将第一层的树的结点入队列
  • 2️⃣当队列不为NULL时,可以借助队列FIFO(先进先出)原则,进行对已经入队列的树的结点依次读取(达到访问结点的效果)并删除在队列中已经访问过的结点
  • 3️⃣在上述删除某个结点的同时,将此结点的孩子结点插入队列中(即相当于同时对下一层进行处理,以达到访问完这一层后,可以继续访问孩子节点所在的层)
  • 4️⃣重复上述步骤,直至队列NULL,代表整棵树已完全遍历

动图示例:

在这里插入图片描述

👉代码实现:

1️⃣实现队列的数据结构:

typedef int QDataType;
typedef struct QueueNode
{
	struct QueueNode\* next;
	QDataType data;
    
}QNode;

typedef struct Queue
{
	//int size;
	QNode\* head;
	QNode\* tail;
}Queue;

void QueueInit(Queue\* pq);
void QueueDestroy(Queue\* pq);
void QueuePush(Queue\* pq, QDataType x);
void QueuePop(Queue\* pq);
QDataType QueueFront(Queue\* pq);
QDataType QueueBack(Queue\* pq);
bool QueueEmpty(Queue\* pq);
int QueueSize(Queue\* pq);

void QueueInit(Queue\* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}

void QueueDestroy(Queue\* pq)
{
	assert(pq);
	QNode\* cur = pq->head;
	while (cur)
	{
		QNode\* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->head = pq->tail = NULL;
}

void QueuePush(Queue\* pq, QDataType x)
{
	assert(pq);
	QNode\* newnode = (QNode\*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;

	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}

void QueuePop(Queue\* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode\* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
}

QDataType QueueFront(Queue\* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->head->data;
}

QDataType QueueBack(Queue\* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->tail->data;
}

bool QueueEmpty(Queue\* pq)
{
	assert(pq);
	return pq->head == NULL;
}

int QueueSize(Queue\* pq)
{
	assert(pq);
	QNode\* cur = pq->head;
	int size = 0;
	while (cur)
	{
		++size;
		cur = cur->next;
	}

	return size;
}


2️⃣实现层序遍历:

void TreeLevelOrder(BTNode\* root)
{
	Queue q;
	QueueInit(&q);

	if (root)
	{
		QueuePush(&q, root);
	}

	while (!QueueEmpty(&q))
	{
		BTNode\* front = QueueFront(&q);
		
		QueuePop(&q);

		printf("%d ", front->data);

		if (front->left != NULL)
		{
			QueuePush(&q, front->left);
		}

		if (front->right != NULL)
		{
			QueuePush(&q, front->right);
		}
	}
	QueueDestroy(&q);
}

**🥯Ⅱ.**总结

✨综上:就是层序遍历啦~

➡️相信大家对新的遍历方式有不一样的看法了吧🧡


**🍞二.**二叉树重要面试OJ题

🔥秒杀模板

秒杀口诀:

  • 左右子树之间的逻辑关系➕树的遍历方式

❓忘记的同学可以>点击<前往回顾呀

✊让我们用题目来实际运用分析吧~


🏷️ 二叉树的前序遍历【难度:简单】

🔍题目传送门:

牛客网:BM23. 二叉树的前序遍历

🌐更多同类题型,不同算法思想学习,可点击>网站跳转<呀😉

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

  • 示例 1:

在这里插入图片描述

输入:root = [1,null,2,3]
输出:[1,2,3]

  • 示例 2:
输入:root = []
输出:[]

  • 示例 3:
输入:root = [1]
输出:[1]

💡解题关键:

  • 我们需要知道前序遍历的遍历方式
  • 本题就可以运用我们的秒杀技巧

特别注意:

  • 本题中我们需要将前序遍历得到的结点存入数组中,我们便需要提前得知此数组需要开辟多大的空间【即需要知道树的结点个数

👉秒杀分析:

  • 计算树的结点个数时,整棵树(分为根节点左子树右子树)来看就是:

左子树总的结点个数 + 右子树总的结点个数 + 1(根节点)

  • 所以逻辑关系为:+

👆综上:

  • 秒杀口诀为:+后序遍历
  • 本质:利用递归的性质,先计算左子树总的结点个数,再计算右子树总的结点个数,最终返回的是左子树右子树总的结点个数的和 + 1(根节点自身个数)

动图示例:

在这里插入图片描述

👉代码实现:

int treeSize(struct TreeNode\* root)
{
	return root == NULL ? 0 : treeSize(root->left) + treeSize(root->right) + 1;
}

void preorder(struct TreeNode\* root, int\*arr, int\* i)
{
	//前序遍历
	if (root == NULL)
	{
		return;
	}

	arr[(\*i)++] = root->val;

	preorder(root->left, arr, i);
	preorder(root->right, arr, i);
}

int\* preorderTraversal(struct TreeNode\* root, int\* returnSize) 
{
	\*returnSize = treeSize(root);

	int\* arr = (int\*)malloc(sizeof(int)\*(\*returnSize));

	int i = 0;
	preorder(root, arr, &i);

	return arr;
}

➡️补充:

  • 我们需要带着自己开辟的数组数组下标进行前序遍历,因为需要将遍历得到的结点存入数组中
  • 所以每一次下标的改变都需要让不同的递归栈帧知道,所以下标需要传的是地址(否则如果传的是下标的临时拷贝,那数组内的结点之间就会造成覆盖)

🏷️ 另一棵树的子树【难度:简单】

🔍题目传送门:

Leetcode:572. 另一棵树的子树

给你两棵二叉树 rootsubRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树

示例 1:

在这里插入图片描述

输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

示例 2:

在这里插入图片描述

输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false

💡解题关键:

  • 遍历主树的每一个结点,让每一个结点当作根节点时,去判断此时的根节点的树是否与子树相同
  • 此时我们便可以复用 检查两棵树是否相同的代码进行判断

👉秒杀分析:

  • 因为需要遍历主树的每一个结点,让其每一个结点当根节点时的树去与子树判断是否相同
  • 所以我们对主树采取前序遍历【即这样遍历下,我们可以快速且从上往下全面的判断是否为子树】,若为其余遍历方式,则可能一开始就错过导致程序做了一些无用功
  • 又因为只要主树里一旦找到为子树的情况,就无需继续找子树了,所以逻辑关系为||【即主树的某个结点为树时是子树的情况,返回true,逻辑关系||遇上true就可以直接停止寻找】

➡️做题思路:

  • 前序遍历遍历主树每一个结点,让每一个结点当作根节点去作树,与需要判断的子树判断两棵树是否相同
  • 一旦找到,就返回true,停止寻找

动图示例:

在这里插入图片描述

👉代码实现:

bool isSameTree(struct TreeNode\* p, struct TreeNode\* q)
{
	//1.树都为NULL的时候 -- 相等
	//2.比较比到 NULL 的时候 == 前面都比完了,那就相等
	if (p == NULL && q == NULL)
	{
		return true;
	}

	//判断p树和q树结构是否相同
	if (p == NULL || q == NULL)
	{
		return false;
	}

	//结构相同,再去判断值
	if (p->val != q->val)
	{
		return false;
	}

	return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}


bool isSubtree(struct TreeNode\* root, struct TreeNode\* subRoot) 
{
	//遍历root这棵树的每个结点,每个结点做子树根 ,去跟subRoot比较

	if (root == NULL)
	{
		return false;
	}

	if (isSameTree(root, subRoot))
	{
		return true;
	}

	return isSubtree(root->left, subRoot)|| isSubtree(root->right, subRoot);
}


🏷️ 平衡二叉树【难度:简单】

🔍题目传送门:

Leetcode:110. 平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树

本题中,一棵高度平衡二叉树定义为:

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

ubRoot)|| isSubtree(root->right, subRoot);
}




---


### 🏷️ 平衡二叉树【难度:简单】


🔍**题目传送门:**




| [Leetcode:110. 平衡二叉树](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb) |
| --- |


给定一个二叉树,判断它是否是高度平衡的二叉树


本题中,一棵高度平衡二叉树定义为:



> 


[外链图片转存中...(img-WKmeR3dm-1715501834839)]
[外链图片转存中...(img-1UPjg9Xg-1715501834839)]
[外链图片转存中...(img-Pp7Kd8Na-1715501834839)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值