数据结构 || 二叉树面试题(部分题目)

【二叉树面试题】
1.【判断两个二叉树是否相等】
//接口
bool isSameTree(struct TreeNode* p,struct TreeNode *q)

解题思路

首先考虑到如果两棵树都为空,则两棵树是相等的;如果两者中的一个为空,另外一个不为空,则两棵树肯定不相等。若两者都不为空,则需要将两颗二叉树分别分成三部分:1.根结点,2.左子树,3.右子树。然后按照递归的思想一直递推下去。

//利用递归的思想,先判断根的情况,再判断左右子树的情况
bool isSameTree(struct TreeNode* p,struct TreeNode *q){
    if(p==NULL&&q==NULL){
        return true;
    }
    if(p==NULL||q==NULL){
        return false;
    }
    return p->_data==q->_data
        &&isSameTree(p->left,q->left)
        &&isSameTree(p->right,q->right);
}
2.【判断对称树】
//接口
bool isMirror(struct TreeNode *p, struct TreeNode *q)

解题思路

  • 利用递推的思想,将所传的两个结点先进行检查。
  • 而后在确保两个结点的值相等的情况下,判断一个根节点的左孩子与另一个根结点的右孩子的情况继而判断这个根节点的右孩子和另外一个根节点的左孩子的情况。

在这里插入图片描述

代码实现

bool isMirror(struct TreeNode *p, struct TreeNode *q){
    if(p==NULL&&q==NULL){
         return true;
    }
    if(p==NULL||q==NULL){
        return false;
    }
    return p->val==q->val
        &&isMirror(p->left,q->right)
        &&isMirror(q->left,p->right);
}
3.【判断一棵树是否为另外一棵树的子树】

接口

bool isSymmetric(struct TreeNode* root)

解题思路

判断是否是子树
1)前序遍历(查找父树上节点的值和子树上结点的值相等的第一个节点,当所要查找的父树上结点的值和子树上根结点的值相等时再判断各自子树的情况)
2)判断两棵树是否相同
3)对于返回值的处理是难点

在这里插入图片描述

代码实现

//当子树的根结点的值和父树上对应的值相等时,判断两者对应的子树是否相等
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
	if (p == NULL && q == NULL) {
		return true;
	}

	if (p == NULL || q == NULL) {
		return false;
	}

	// 递推
	return p->val == q->val
		&& isSameTree(p->left, q->left)
		&& isSameTree(p->right, q->right);
}
//先序遍历,在父树上找与子树根节点值相等的结点
bool preorderTraversal(struct TreeNode *root, struct TreeNode *t) {
	if (root == NULL) {
		return false;
	}
	// 根
	if (root->val == t->val && isSameTree(root, t)) {
		return true;
	}
	// 左子树
	bool left = preorderTraversal(root->left, t);
	if (left == true) {
		return true;
	}
	// 右子树
	bool right = preorderTraversal(root->right, t);
	return right;
}
//该问题所对应的接口
bool isSubtree(struct TreeNode* s, struct TreeNode* t) {
	if (t == NULL) {
		return true;
	}
	return preorderTraversal(s, t);
}
4.【求一棵二叉树的最大深度】

接口

int maxDepth(TreeNode* root)

解题思路

拿到一颗二叉树,需要确定其根结点的左右子树高度,取两者中高度较高的那一个,再加上树根的高度就是该树的高度

代码实现

int maxDepth(TreeNode* root){
    if(root==NULL){
        return 0;
    }
   int left= MaxDepth(root->left);
   int right=MaxDepth(root->right);
    return (left>right?left:right)+1;
}
5.【判断平衡二叉树】

判断依据:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

接口

bool isBalanced(struct TreeNode* root);

解题思路

首先要判断所传的树是否为空树,是空树就为真,不是空树就对根节点的左右子树进行必要的判断。如果都满足则求出左右子树的高度,然后判断根结点对应的左右子树的高度差,并判断高度差满足的条件

代码实现

  • c语言版

int getHeight(struct TreeNode *root) {
	if (root == NULL) {
		return 0;
	}

	int left = getHeight(root->left);
	int right = getHeight(root->right);

	return (left>right?left:right) + 1;
}

bool isBalanced(struct TreeNode* root) {
	if (root == NULL) {
		return true;
	}
    //处理左子树
	bool is_left_balance = isBalanced(root->left);
	if (is_left_balance == false) {
		return false;
	}
     //处理右子树
	bool is_right_balance = isBalanced(root->right);
	if (is_right_balance == false) {
		return false;
	}
    //求左子树的高度
	int left_height = getHeight(root->left);
    //求右子树的高度 
	int right_height = getHeight(root->right);
	int diff = left_height - right_height;
	if (diff >= -1 && diff <= 1) {
		return true;
	}
	else {
		return false;
	}
}


  • c++版
class Solution {
public:
    bool isBalanced(struct TreeNode* root) {
	if (root == NULL) {
		return true;
	}
    //处理左子树
	bool is_left_balance = isBalanced(root->left);
	if (is_left_balance == false) {
		return false;
	}
     //处理右子树
	bool is_right_balance = isBalanced(root->right);
	if (is_right_balance == false) {
		return false;
	}
    //求左子树的高度
	int left_height = getHeight(root->left);
    //求右子树的高度 
	int right_height = getHeight(root->right);
	int diff = left_height - right_height;
	if (diff >= -1 && diff <= 1) {
		return true;
	}
	else {
		return false;
	}
}
    int getHeight(struct TreeNode *root) {
	if (root == NULL) {
		return 0;
	}

	int left = getHeight(root->left);
	int right = getHeight(root->right);

	return (left>right?left:right) + 1;
}

};
6.【完全二叉树的判断】

判定依据

在层序遍历二叉树的过程中如果没有遍历完所有结点之前就遇到了空结点的话,就说明该树不是完全二叉树

解题思路

解题思路大致与层序遍历的相同,不同之处在于。判断二叉树的结点情况的时候两次判断了队列是否为空的情况,第一次遇到空结点就跳出循环,第二次判断队列是否为空

接口

bool BinaryTreeComplete(TreeNode* root);

代码实现

bool BinaryTreeComplete(TreeNode* root){
    if(root == NULL){
        return true;
    }
    std::queue<TreeNode *>  qu;
    qu.push(root);
    while(!qu.empty()){
        TreeNode *front=qu.front();
        qu.pop();
        if(front==NULL){
            break;
        }
            qu.push(root->left);
            qu.push(root->right);
    }
    //检查队列中是否还有其他元素
    while(!qu.empty()){
        TreeNode *node=qu.front();
        qu.pop();
        if(node != NULL){
            return  false;
        }
    }
    return true;
}
【二叉树的前序|中序|后序的非递归实现,自己用栈来实现】

栈(用来存放结点地址)

1.【前序遍历】
void PreorderTraversalNor(TreeNode *root)
{
	TreeNode *cur = root;	// 遍历结点的指针
	TreeNode *top;	// 返回栈顶数据的指针
	TreeNode *last = NULL;
    
	std::stack<TreeNode *>	st;

	while (!st.empty() || cur != NULL) {
		while (cur != NULL) {
			// 第一次访问结点:cur
			printf("%c ", cur->val);
			st.push(cur);
			cur = cur->left;
		}

		top = st.top();	// 从栈里取出栈顶元素
		st.pop();

		if (top->right == NULL) {
			// 既是第二次访问,也是第三次访问
			cur = top->right;
			st.pop();
			last = top;
		}
		else {
			if (top->right != last) {
				// 第二次访问
				cur = top->right;
			}
			else {
				// 第三次访问
				st.pop();
				last = top;
			}
		}
	}
}

方法二

void PreorderTraversalNor2(TreeNode *root)
{
	TreeNode *cur = root;	// 遍历结点的指针
	TreeNode *top;	// 返回栈顶数据的指针

	// std:: 命名空间
	// <> 模板,表示栈里存的数据类型是 TreeNode *
	std::stack<TreeNode *>	st;

	while (!st.empty() || cur != NULL) {
		while (cur != NULL) {
			// 第一次访问结点:cur
			printf("%c ", cur->val);
			st.push(cur);
			cur = cur->left;
		}

		top = st.top();	// 从栈里取出栈顶元素
		st.pop();
		cur = top->right;
	}
}
2.【中序遍历】
void InorderTraversalNor(TreeNode *root)
{
	TreeNode *cur = root;	// 遍历结点的指针
	TreeNode *top;	// 返回栈顶数据的指针
	TreeNode *last = NULL;

	// std:: 命名空间
	// <> 模板,表示栈里存的数据类型是 TreeNode *
	std::stack<TreeNode *>	st;

	while (!st.empty() || cur != NULL) {
		while (cur != NULL) {
			// 第一次访问结点:cur
			st.push(cur);
			cur = cur->left;
		}
		top = st.top();	// 从栈里取出栈顶元素
		if (top->right == NULL) {
			// 既是第二次访问,也是第三次访问
			printf("%c ", top->val);
			cur = top->right;
			st.pop();
			last = top;
		}
		else {
			if (top->right != last) {
				// 第二次访问
				printf("%c ", top->val);
				cur = top->right;
			}
			else {
				// 第三次访问
				st.pop();
				last = top;
			}
		}
	}
}

方法二

//方法二
void InorderTraversalNor2(TreeNode *root)
{
	TreeNode *cur = root;	// 遍历结点的指针
	TreeNode *top;	// 返回栈顶数据的指针

	// std:: 命名空间
	// <> 模板,表示栈里存的数据类型是 TreeNode *
	std::stack<TreeNode *>	st;

	while (!st.empty() || cur != NULL) {
		while (cur != NULL) {
			// 第一次访问结点:cur
			st.push(cur);
			cur = cur->left;
		}
		top = st.top();	// 从栈里取出栈顶元素
		// 既是第二次访问,也是第三次访问
		printf("%c ", top->val);
		cur = top->right;
		st.pop();
	}
}
3.【后序遍历】
void PostorderTraversalNor(TreeNode *root)
{
	TreeNode *cur = root;	// 遍历结点的指针
	TreeNode *top;	// 返回栈顶数据的指针
	TreeNode *last = NULL;

	// std:: 命名空间
	// <> 模板,表示栈里存的数据类型是 TreeNode *
	std::stack<TreeNode *>	st;

	while (!st.empty() || cur != NULL) {
		while (cur != NULL) {
			// 第一次访问结点:cur
			st.push(cur);
			cur = cur->left;
		}
		top = st.top();	// 从栈里取出栈顶元素
		if (top->right == NULL) {
			// 既是第二次访问,也是第三次访问
			printf("%c ", top->val);
			cur = top->right;
			st.pop();
			last = top;
		}
		else {
			if (top->right != last) {
				// 第二次访问
				cur = top->right;
			}
			else {
				// 第三次访问
				printf("%c ", top->val);
				st.pop();
				last = top;
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值