代码随想录算法训练营|二叉树内容复习
双指针内容复习
二叉树递归遍历
类似于图论的深搜
首先是二叉树的递归三部曲
-
确定递归函数的参数和初始条件
-
确定递归的终止条件
-
确定单层递归的逻辑
144前序遍历,145后序,94中序,虽然很简单,但是时间长了不写,三个没有一个遍通过的
二叉树层序遍历
再看发现确实还是有很多细节,层序遍历的核心是用队列实现的。队列的类型是TreeNode* 用来存放指针的,但是定义的数组类型是int型的,用来存放二叉树的结点的val
107. 二叉树的层序遍历 II,在层序的基础上加一个reverse库函数对数组进行翻转即可
- 二叉树的右视图 很简单,在层序基础上加一个判断即可
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
vector<int> result;
while (!que.empty()) {
int size = que.size();
while (size--) {
TreeNode* cur = que.front();
// cout << size << endl;
que.pop();
if (size == 0) {
result.push_back(cur->val);
}
if (cur->left != NULL) que.push(cur->left);
if (cur->right != NULL) que.push(cur->right);
}
}
return result;
}
};
637. 二叉树的层平均值 也比较简单,每一层的值相加起来之后除以size即可,需要注意的是数值的类型
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<double> averageOfLevels(TreeNode* root) {
queue<TreeNode*> que;
vector<double> vec;
que.push(root);
while (!que.empty()) {
int size = que.size();
double len = size;
long sum = 0;
while (size--) {
TreeNode* cur = que.front();
que.pop();
sum += cur->val;
if (cur->left != NULL) que.push(cur->left);
if (cur->right != NULL) que.push(cur->right);
}
vec.push_back(sum / len);
}
return vec;
}
};
429. N 叉树的层序遍历 这个是第一次处理N叉树,和二叉树的定义不一样,不过核心的思路没有变,今天写了两个版本的代码。
这个是层序遍历的标准代码,简单易懂,注意就是在每次pop完之后,要及时将pop出来的元素加入到vec中。这里表示的是处理当前结点
点击查看代码
/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> children;
Node() {}
Node(int _val) {
val = _val;
}
Node(int _val, vector<Node*> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
queue<Node*> que;
vector<vector<int>> result;
if(root != NULL) que.push(root);
while (!que.empty()) {
int size = que.size();
vector<int> vec;
while (size--) {
Node* cur = que.front();
que.pop();
vec.push_back(cur->val);
for (int i = 0; i < cur->children.size(); i++) {
if (cur->children.size() > 0) {
que.push(cur->children[i]);
}
}
}
result.push_back(vec);
}
return result;
}
};
写的第二个版本是这样的,刚开始写这个版本的时候有点稀里糊涂的,不过后来一想,这个其实处理的是当前结点的孩子结点,这样就有点麻烦了
点击查看代码
/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> children;
Node() {}
Node(int _val) {
val = _val;
}
Node(int _val, vector<Node*> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
queue<Node*> que;
vector<vector<int>> result;
if(root != NULL) {
que.push(root);
vector<int> vec;
vec.push_back(root->val);
result.push_back(vec);
}
else return result;
while (!que.empty()) {
int size = que.size();
vector<int> vec;
while (size--) {
Node* cur = que.front();
que.pop();
for (int i = 0; i < cur->children.size(); i++) {
if (cur->children.size() > 0) {
que.push(cur->children[i]);
vec.push_back(cur->children[i]->val);
}
}
}
result.push_back(vec);
}
result.pop_back();
return result;
}
};
这两种不同的处理方式让我想到了,之前的105有向图的完全可达性中,对深搜处理的不同讨论,分别是当前结点还有当前结点的下一个结点的两种不同的方式。
515. 在每个树行中找最大值 感觉和上面你的求层平均值差不多
处理当前结点
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> largestValues(TreeNode* root) {
queue<TreeNode*> que;
vector<int> result;
if (root != NULL) que.push(root);
while (!que.empty()) {
int size = que.size();
int m = INT_MIN;
while (size--) {
TreeNode* cur = que.front();
que.pop();
m = max(m, cur->val);
if (cur->left != NULL) que.push(cur->left);
if (cur->right != NULL) que.push(cur->right);
}
result.push_back(m);
}
return result;
}
};
处理下一个结点
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> largestValues(TreeNode* root) {
queue<TreeNode*> que;
vector<int> result;
if (root != NULL) que.push(root);
else return result;
int m = max(INT_MIN, root->val);
while (!que.empty()) {
int size = que.size();
result.push_back(m);
m = INT_MIN;
while (size--) {
TreeNode* cur = que.front();
que.pop();
if (cur->left != NULL) {
que.push(cur->left);
m = max(m, cur->left->val);
}
if (cur->right != NULL) {
que.push(cur->right);
m = max(m, cur->right->val);
}
}
}
return result;
}
};
翻转二叉树
226.翻转二叉树 核心就是要看自己使用的具体是哪种遍历方式,注意中序的翻转顺序比较特殊,导致其应该对左子树进行两次翻转。
中序遍历
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == NULL) return NULL;
invertTree(root->left);
swap(root->left, root->right);
invertTree(root->left);
return root;
}
};
对称二叉树
101. 对称二叉树 这个就是需要同时进行两个子树的比较,还是比较固定的写法,需要用到后序遍历,注意他比较的是左右子树的共同外侧和共同内侧。
二叉树的最大深度
104.二叉树的最大深度 二叉树的深度一般由前序遍历来求,高度一般由后序遍历来求,本题可以用后序来做。其实质也是先算了二叉树的高度,之后高度==深度,所以才求出来深度。
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == NULL) return 0;
int lheight = maxDepth(root->left);
int rheight = maxDepth(root->right);
int result = max(lheight, rheight) + 1;
return result;
}
};
二叉树的最小深度
111. 二叉树的最小深度 二叉树的最小深度同样使用的是后序遍历,计算最小高度,之后再将最小高度转换为最小深度(这一步就是直接等于的关系)。在递归最小高度时,要注意如果出现一棵子树为空,那么此时需要从不空的子树高度上+1
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int minDepth(TreeNode* root) {
if (root == NULL) return 0;
int lheight = minDepth(root->left);
int rheight = minDepth(root->right);
int result;
if (root->left != NULL && root->right == NULL) result = 1 + lheight;
if (root->left == NULL && root->right != NULL) result = 1 + rheight;
if (root->left != NULL && root->right != NULL) result = 1 + min(lheight, rheight);
return result;
}
};
完全二叉树的结点个数
222.完全二叉树的节点个数 首先是用后序遍历,5行代码很简单就过了。
这是普通的二叉树的解法
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int countNodes(TreeNode* root) {
if (root == NULL) return 0;
int lnum = countNodes(root->left);
int rnum = countNodes(root->right);
int result = lnum + rnum + 1;
return result;
}
};
其实这里用完全二叉树的性质还是有点不太好理解的,他有两个终止条件注意
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int countNodes(TreeNode* root) {
//确定递归的终止条件
if (root == NULL) return 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
int lleft = 0;
int lright = 0;
while (left != NULL) {
lleft++;
left = left->left;
}
while (right != NULL) {
lright++;
right = right->right;
}
if (lleft == lright) return (2 << lleft) - 1;
// 确定单层递归的逻辑
int lresult = countNodes(root->left);
int rresult = countNodes(root->right);
return lresult + rresult + 1;
}
};
平衡二叉树
110. 平衡二叉树 再写平衡二叉树的时候,感觉还是有一些地方不太好写,这次从后序遍历开始手搓,但是相比之前的代码,不自觉写了很多
有一个测试用例,不太好搞[1,2,2,3,null,null,3,4,null,null,4],这个画出来是一个根结点是平衡的,但是其他结点就不是平衡的了。一开始还纳闷呢,所以这里就需要有一步操作,就是在递归的时候,一旦发现有某个结点的高度差大于1了,那么就及时进行标注-1,不让他再向上递归返回
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
int getHeight(TreeNode* root) {
if (root == NULL) return 0;
int lheight = getHeight(root->left);
if (lheight == -1) return -1;
int rheight = getHeight(root->right);
if (rheight == -1) return -1;
int result;
if (lheight >= rheight) {
result = lheight - rheight;
} else {
result = rheight - lheight;
}
return result > 1 ? -1 : max(lheight, rheight) + 1;
}
public:
bool isBalanced(TreeNode* root) {
if (root == NULL) return true;
int lheight = getHeight(root->left);
int rheight = getHeight(root->right);
if (lheight == -1 || rheight == -1) {
return false;
}
cout << lheight << ' ' << rheight << endl;
cout << abs(lheight - rheight) << endl;
if (abs(lheight - rheight) <= 1) {
return true;
}
return false;
}
};
二叉树的所有路径
257. 二叉树的所有路径 这个题再写的时候,又不会了,用到了回溯算法。首先是三部曲,确定递归的终止条件这里有点特殊不一样。还有就是再单层递归的逻辑,在每一部分要加上回溯的部分。
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
void traversal(TreeNode* root, vector<string>& result, vector<int> &path) {
// 前序的根结点在这里
path.push_back(root->val);
if (root != NULL && root->left == NULL && root->right == NULL) {
string spath;
for (int i = 0; i < path.size() - 1; i++) {
spath += to_string(path[i]);
spath += "->";
}
spath += to_string(path[path.size() - 1]);
result.push_back(spath);
return;
}
if (root->left) {
traversal(root->left, result, path);
path.pop_back();
}
if (root->right) {
traversal(root->right, result, path);
path.pop_back();
}
}
public:
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
vector<int> path;
if (root == NULL) return result;
traversal(root, result, path);
return result;
}
};
左叶子之和
404. 左叶子之和 本题的递归方式是最特殊的,用int进行递归,另外要注意其只是对左子树进行计数。
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if (root == NULL) return 0;
// 单层递归的逻辑,是先递归左,后递归右
int lsum = sumOfLeftLeaves(root->left);
if (root->left != NULL && root->left->left == NULL && root->left->right == NULL) {
lsum = root->left->val;
}
int rsum = sumOfLeftLeaves(root->right);
int result = lsum + rsum;
return result;
}
};
找树左下角的值
513.找树左下角的值 这个题找最底层,左边第一个即可。因为是递归遍历,是向深处遍历的,所以要不断进行回溯,看路径中是否有大于当前最大深度的结点出现。
点击查看代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
int result;
int maxDepth = INT_MIN;
void traversal(TreeNode* root, int depth) {
if (root != NULL && root->left == 0 && root->right == 0) {
if (depth > maxDepth) {
maxDepth = depth;
result = root->val;
return;
}
}
if (root->left) {
depth++;
traversal(root->left, depth);
depth--;
}
if (root->right) {
depth++;
traversal(root->right, depth);
depth--;
}
}
public:
int findBottomLeftValue(TreeNode* root) {
traversal(root, 1);
return result;
}
};
浙公网安备 33010602011771号