代码随想录
二叉树的层序遍历要借助队列来实现,队列先进先出,符合一层一层遍历的逻辑,而是用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。层序遍历的一般步骤如下:
(1)初始化。定义一个队列,将根结点放入队列中。
(2)从队首读一个元素,处理该节点,然后将该节点的左右节点分别加入队列中(如果该节点有子节点)。重复这个过程直到队列为空。
按照上述步骤就可以把二叉树的遍历结果放入整个数组中,但是如果需要将每一层的结果分开来,就需要稍作修改。以下图为例,说明二叉树的层序遍历过程。
/**
* 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<vector<int>> levelOrder(TreeNode* root) {
if(root == nullptr) return {};
vector<vector<int>> result;
vector<int> tmp;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
int size = que.size();
tmp.clear();
for(int i=0;i<size;i++)
{
TreeNode* node = que.front();
que.pop();
tmp.push_back(node->val);
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
result.push_back(tmp);
}
return result;
}
};
上面的代码中的while循环中的for循环的作用就是将每一层的结果放入到一个数组中。
/**
* 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<vector<int>> levelOrderBottom(TreeNode* root) {
if(root == nullptr) return {};
vector<vector<int>> result;
vector<int> tmp;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
int size = que.size();
tmp.clear();
for(int i=0;i<size;i++)
{
TreeNode* node = que.front();
que.pop();
tmp.push_back(node->val);
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
result.push_back(tmp);
}
reverse(result.begin(),result.end());
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> rightSideView(TreeNode* root) {
if(root == nullptr) return {};
vector<int> result;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
int size = que.size();
for(int i=0;i<size;i++)
{
TreeNode* node = que.front();
que.pop();
if(i == size-1) //只保存最后一个节点
result.push_back(node->val);
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
}
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<double> averageOfLevels(TreeNode* root) {
if(root == nullptr) return{};
vector<double> result;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
int size = que.size();
double tmp = 0;
for(int i=0;i<size;i++)
{
TreeNode* node = que.front();
que.pop();
tmp += node->val;
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
result.push_back(tmp/size);
}
return result;
}
};
/*
// Definition for a Node.
class Node {
public:
int val;
vector children;
Node() {}
Node(int _val) {
val = _val;
}
Node(int _val, vector _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public:
vector<vector<int>> levelOrder(Node* root) {
if(root == nullptr) return {};
vector<vector<int>> result;
vector<int> tmp;
queue<Node*> que;
que.push(root);
while(!que.empty())
{
int size = que.size();
tmp.clear();
for(int i=0;i<size;i++)
{
Node* node = que.front();
que.pop();
tmp.push_back(node->val);
for(int j=0;j<(node->children).size();j++) //添加子节点
que.push(node->children[j]);
}
result.push_back(tmp);
}
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) {
if(root == nullptr) return {};
vector<int> result;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
int size = que.size();
int max = INT_MIN;
for(int i=0;i<size;i++)
{
TreeNode* node = que.front();
que.pop();
if(node->val > max) max = node->val;
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
result.push_back(max);
}
return result;
}
};
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
if(root == nullptr) return nullptr;
queue<Node*> que;
que.push(root);
while(!que.empty())
{
int size = que.size();
if(size > 1)
{
for(int i=0;i<size-1;i++)
{
Node* node = que.front();
que.pop();
node->next = que.front();
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
que.front()->next = nullptr;
if(que.front()->left != nullptr) que.push(que.front()->left);
if(que.front()->right != nullptr) que.push(que.front()->right);
que.pop();
}
else
{
Node* node = que.front();
node->next = nullptr;
que.pop();
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
}
return root;
}
};
class Solution {
public:
Node* connect(Node* root) {
if(root == nullptr) return nullptr;
queue<Node*> que;
que.push(root);
while(!que.empty())
{
int size = que.size();
if(size > 1)
{
for(int i=0;i<size-1;i++)
{
Node* node = que.front();
que.pop();
node->next = que.front();
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
que.front()->next = nullptr;
if(que.front()->left != nullptr) que.push(que.front()->left);
if(que.front()->right != nullptr) que.push(que.front()->right);
que.pop();
}
else
{
Node* node = que.front();
node->next = nullptr;
que.pop();
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
}
return root;
}
};
上一个题的二叉树是完美二叉树,这个题是一般的二叉树,但在代码实现上没有任何区别,直接复制上一个题的代码就行。
/**
1. Definition for a binary tree node.
2. struct TreeNode {
3. int val;
4. TreeNode *left;
5. TreeNode *right;
6. TreeNode() : val(0), left(nullptr), right(nullptr) {}
7. TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
8. TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
9. };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root == nullptr) return 0;
queue<TreeNode*> que;
int cnt = 0;
que.push(root);
while(!que.empty())
{
int size = que.size();
for(int i=0;i<size;i++)
{
TreeNode* node = que.front();
que.pop();
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
cnt++;
}
return cnt;
}
};
/**
10. Definition for a binary tree node.
11. struct TreeNode {
12. int val;
13. TreeNode *left;
14. TreeNode *right;
15. TreeNode() : val(0), left(nullptr), right(nullptr) {}
16. TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
17. TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
18. };
*/
class Solution {
public:
int minDepth(TreeNode* root) {
if(root == nullptr) return 0;
queue<TreeNode*> que;
int depth = 0;
que.push(root);
while(!que.empty())
{
int size = que.size();
depth++;
for(int i=0;i<size;i++)
{
TreeNode* node = que.front();
que.pop();
if(node != root && node->left == nullptr
&& node->right == nullptr)
return depth;
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
}
return depth;
}
};
从第二层可开始,如果某一个节点既没有左子节点也没有右节点,则该节点就是满足条件的叶子节点。
注意在递归法历里不能使用中序遍历!!!
递归三部曲
第一步,确定递归函数的参数和返回值。这个题的要求是反转每个节点的子节点,因此不需要返回值,参数就是某个节点。
void recursion(TreeNode* node);
第二步,确定递归终止条件。当传入的节点为空时,终止递归。
if(node == nullptr) return;
第三步,确定单层递归逻辑。交换传入节点的两个子节点:
swap(node->left,node->right);
recursion(node->left);
recursion(node->right);
完整代码实现如下:
/**
19. Definition for a binary tree node.
20. struct TreeNode {
21. int val;
22. TreeNode *left;
23. TreeNode *right;
24. TreeNode() : val(0), left(nullptr), right(nullptr) {}
25. TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
26. TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
27. };
*/
class Solution {
public:
void recursion(TreeNode* node)
{
if(node == nullptr) return;
swap(node->left,node->right);
recursion(node->left);
recursion(node->right);
}
TreeNode* invertTree(TreeNode* root) {
recursion(root);
return root;
}
};
上面的代码使用的是前序遍历,后序遍历的代码如下:
/**
28. Definition for a binary tree node.
29. struct TreeNode {
30. int val;
31. TreeNode *left;
32. TreeNode *right;
33. TreeNode() : val(0), left(nullptr), right(nullptr) {}
34. TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
35. TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
36. };
*/
class Solution {
public:
void recursion(TreeNode* node)
{
if(node == nullptr) return;
recursion(node->left);
recursion(node->right);
swap(node->left,node->right);
}
TreeNode* invertTree(TreeNode* root) {
recursion(root);
return root;
}
};
/**
37. Definition for a binary tree node.
38. struct TreeNode {
39. int val;
40. TreeNode *left;
41. TreeNode *right;
42. TreeNode() : val(0), left(nullptr), right(nullptr) {}
43. TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
44. TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
45. };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root == nullptr) return nullptr;
stack<TreeNode*> stk;
stk.push(root);
while(!stk.empty())
{
TreeNode* node = stk.top();
stk.pop();
if(node != nullptr)
{
stk.push(node); //中
stk.push(nullptr);
if(node->left != nullptr)stk.push(node->left); //左
if(node->right != nullptr)stk.push(node->right); //右
}
else
{
node = stk.top();
stk.pop();
swap(node->left,node->right);
}
}
return root;
}
};
上面的代码是前序遍历,中序遍历和后序遍历的做相应修改就可以了。注意,迭代遍历中是可以使用中序遍历的。
/**
46. Definition for a binary tree node.
47. struct TreeNode {
48. int val;
49. TreeNode *left;
50. TreeNode *right;
51. TreeNode() : val(0), left(nullptr), right(nullptr) {}
52. TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
53. TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
54. };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root == nullptr) return nullptr;
queue<TreeNode*> que;
que.push(root);
while(!que.empty())
{
int size = que.size();
for(int i=0;i<size;i++)
{
TreeNode* node = que.front();
que.pop();
swap(node->left,node->right);
if(node->left != nullptr) que.push(node->left);
if(node->right != nullptr) que.push(node->right);
}
}
return root;
}
};
bool compare(TreeNode* node1,TreeNode* node2);
if(node1 == nullptr && node2 != nullptr) return false;
else if(node1 != nullptr && node2 == nullptr) return false;
else if(node1 == nullptr && node2 == nullptr) return true;
else if(node1->val != node2->val) return false;
bool outside = compare(node1->left,node2->right);
bool inside = compare(node1->right,node2->left);
bool isSame = outside && inside;
完整的代码如下:
/**
* 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:
bool compare(TreeNode* node1,TreeNode* node2)
{
if(node1 == nullptr && node2 != nullptr) return false;
else if(node1 != nullptr && node2 == nullptr) return false;
else if(node1 == nullptr && node2 == nullptr) return true;
else if(node1->val != node2->val) return false;
bool outside = compare(node1->left,node2->right);
bool inside = compare(node1->right,node2->left);
bool isSame = outside && inside;
return isSame;
}
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
return compare(root->left,root->right);
}
};
/**
* 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:
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
stack<TreeNode*> stk;
stk.push(root->left);
stk.push(root->right);
while(!stk.empty())
{
TreeNode* node1 = stk.top();
stk.pop();
TreeNode* node2 = stk.top();
stk.pop();
if(node1 == nullptr && node2 == nullptr) continue;
else if(node1 == nullptr && node2 != nullptr) return false;
else if(node1 != nullptr && node2 == nullptr) return false;
stk.push(node1->left);
stk.push(node2->right);
stk.push(node1->right);
stk.push(node2->left);
if(node1->val != node2->val) return false;
}
return true;
}
};
这里不是标准的前序遍历,但是用的是一样的思路。注意下面的语句里用的continue而不能直接返回:
if(node1 == nullptr && node2 == nullptr) continue;
此外要注意压栈顺序,外侧两个节点要一起压栈,内侧的两个节点也如此,这样在弹出两个即节点时才是对应的两个节点。
/**
* 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:
bool isSymmetric(TreeNode* root) {
if(root == nullptr) return true;
queue<TreeNode*> que;
que.push(root->left);
que.push(root->right);
while(!que.empty())
{
TreeNode* node1 = que.front();
que.pop();
TreeNode* node2 = que.front();
que.pop();
if(node1 == nullptr && node2 == nullptr) continue;
else if(node1 == nullptr && node2 != nullptr) return false;
else if(node1 != nullptr && node2 == nullptr) return false;
que.push(node1->left);
que.push(node2->right);
que.push(node1->right);
que.push(node2->left);
if(node1->val != node2->val) return false;
}
return true;
}
};
用队列迭代和用栈迭代基本一致。用栈迭代类似于二叉树的层序遍历,只是入队顺序由原来的从左到右变为从两侧到中间。
今天的内容是二叉树的层序遍历、翻转和对称判断,层序遍历是二叉树遍历的最基本的一种,翻转和对称是二叉树的一个简单应用,从本质上看还是考虑如何遍历二叉树,但这种遍历不是常规的几种遍历,要根据具体的要求来确定遍历顺序,例如翻转这个题,我们只需要将每个节点的两个子节点进行反转就可以了,所以可以用递归遍历(不能使用中序遍历),也可以统一迭代遍历,还可以用层序遍历,方法较多,不限制遍历顺序,但是判断对称性这个题只能从每一层的两侧往里遍历或者从中间往两侧遍历,不能用常规的遍历方法,但也是用常规方法的简单变形,因此掌握二叉树的基本遍历方法很重要!