1.反转二叉树
题目链接:. - 力扣(LeetCode)
讲解链接:代码随想录 (programmercarl.com)
视频链接:听说一位巨佬面Google被拒了,因为没写出翻转二叉树 | LeetCode:226.翻转二叉树_哔哩哔哩_bilibili
本题的基本思想是依次遍历所有结点,然后一一交换每个结点的左右子树。
但是不是所有遍历方法都可以,中序遍历会让左子树被交换两次。
涉及到遍历就有三种方法实现:递归、迭代和层序。
递归法:
首先确定三要素:
1.返回值与参数:本题每次递归不需要输出,因此返回值是空。参数是树结点指针。
2.终止条件:在遇到空节点时中止。
3.单层循环的逻辑:只要简单交换左右结点即可,可以使用swap()函数实现。
迭代法:
与遍历的代码类似,使用栈来实现。每次交换完左右孩子再将其入栈。
层序遍历:
同样与遍历类似,使用队列实现。每次交换完左右还在再将其入队。
代码如下:
// 递归法(前序)
void invert(TreeNode* root){
if (root == nullptr)
return;
swap(root->left, root->right);
invert(root->left);
invert(root->right);
}
TreeNode* invertTree(TreeNode* root) {
invert(root);
return root;
}
// 迭代法(前序)
TreeNode* invertTree1(TreeNode* root) {
if (root == nullptr) return root;
stack<TreeNode*> st;
st.push(root);
while (!st.empty()){
TreeNode* cur = st.top();
st.pop();
swap(cur->left, cur->right);
if (cur->right) st.push(cur->right);
if (cur->left) st.push(cur->left);
}
return root;
}
// 层序遍历
TreeNode* invertTree2(TreeNode* root) {
if (root == nullptr) return root;
queue<TreeNode*> que;
que.push(root);
while (!que.empty()){
TreeNode* cur = que.front();
que.pop();
swap(cur->left, cur->right);
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
return root;
}
2.对称二叉树
题目链接:. - 力扣(LeetCode)
讲解链接:代码随想录 (programmercarl.com)
视频链接:新学期要从学习二叉树开始! | LeetCode:101. 对称二叉树_哔哩哔哩_bilibili
本题要确定好对称的比较逻辑:外侧与外侧比(左结点的左孩子和右结点的右孩子比),内侧与内侧比(左结点的右孩子和右结点的左孩子比)。
递归法:
三要素
1.返回值与参数:本题每次递归需要返回左右子树是否对称,返回值为bool。需要传入左右子树比较,参数为两个数结点指针。
2.终止条件:本题终止条件较多,就是什么情况下可以判断已经不对称了。有以下几种情况:左空右不空、左不空右空、左右数值不相等,这些情况确定已经不对称了,可以返回false。而左右都为空可以确定是对称的,返回true。最后只剩下左右数值相等的情况,因为还要判断子树的情况。
3.单层逻辑:单层逻辑仅需判断左右数值相等的情况。根据比较逻辑依次对:左结点的左子树和右结点的右子树、左结点的右子树和右结点的左子树。只有当他们都对称时,才返回true。否则返回false。
代码如下:
bool compare(TreeNode* A, TreeNode* B){
if (A == nullptr && B != nullptr) return false;
else if (A != nullptr && B == nullptr) return false;
else if (A == nullptr && B == nullptr) return true;
else if(A->val != B->val) return false;
else{
bool com1 = compare(A->left, B->right);
bool com2 = compare(A->right, B->left);
return com1 && com2;
}
}
bool isSymmetric(TreeNode* root) {
if (root == nullptr) return true;
return compare(root->left,root->right);
}
3.最大深度
题目链接:. - 力扣(LeetCode)
讲解链接:代码随想录 (programmercarl.com)
视频链接:二叉树的高度和深度有啥区别?究竟用什么遍历顺序?很多录友搞不懂 | LeetCode:104.二叉树的最大深度_哔哩哔哩_bilibili
深度是某一结点到根结点的路径长度,最大深度就是最远的叶子结点到根结点的路径长度,也就是二叉树根结点的高度。而求高度要使用后序遍历(求深度不知道最远的叶子结点在哪,求高度可以从根节点开始,所以求高度代替深度)。
递归法:
三要素
1.返回值与参数:需要返回子树的高度,返回值为int。参数为树结点指针。
2.终止条件:遇到空节点停止,返回0;
3.单层逻辑:后序遍历,先处理左右子树高度。然后取最大值+1为该树的高度。
层序遍历:
求深度是层序遍历的拿手绝活,每遍历一层让深度+1即可。
代码如下:
// 递归
int getDepth(TreeNode* root){
if (root == nullptr)
return 0;
int leftDepth = getDepth1(root->left);
int rightDepth = getDepth1(root->right);
int Depth = 1 + max(leftDepth, rightDepth);
return Depth;
}
int maxDepth(TreeNode* root){
return getDepth1(root);
}
// 层序
int maxDepth(TreeNode* root){
if (root == nullptr) return 0;
queue<TreeNode*> que;
que.push(root);
int depth = 0;
while (!que.empty()){
int size = que.size();
while (size--){
TreeNode* cur = que.front();
que.pop();
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
depth++;
}
return depth;
}
4.最小深度
题目链接:. - 力扣(LeetCode)
讲解链接:代码随想录 (programmercarl.com)
视频链接:看起来好像做过,一写就错! | LeetCode:111.二叉树的最小深度_哔哩哔哩_bilibili
本题看起来与最大深度相似,但是要注意最小深度指的是叶子结点的最小深度(最大深度一定是叶子节点处,所以不用额外注意),即该结点左右孩子为空。
递归法:
三要素
1.返回值与参数:每次递归要返回树的最小深度,返回值为int。参数为树结点指针。
2.终止条件:遇到空节点终止。
3.单层逻辑:求深度时要注意他是否是叶子结点,不能简单取左右子树的最小值。如果该结点只有右子树,最小深度就是右子树最小深度+1,反之就是左子树最小深度+1。如果左右子树都存在,再取他们的最小值。
层序遍历:
同样是层序遍历的绝活,只要在队列中碰到左右孩子都为空的结点时返回当前深度即可。
代码如下:
// 递归法
int getDepth(TreeNode* root){
if (root == nullptr)
return 0;
if (root->left == nullptr && root->right != nullptr)
return 1 + getDepth2(root->right);
else if (root->left != nullptr && root->right == nullptr)
return 1 + getDepth2(root->left);
else
return 1 + min(getDepth2(root->left), getDepth2(root->right));
}
int minDepth1(TreeNode* root){
return getDepth2(root);
}
// 层序遍历
int minDepth(TreeNode* root){
if (root == nullptr) return 0;
queue<TreeNode*> que;
que.push(root);
int depth = 1;
while (!que.empty()){
int size = que.size();
while (size--){
TreeNode* cur = que.front();
que.pop();
if (cur->left == nullptr && cur->right == nullptr)
return depth;
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
depth++;
}
return depth;
}