目录
层序遍历
一个打十个!
102 二叉树的层序遍历
/**
* 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) {
vector<vector<int>> result;
if(root==nullptr) return result;
queue<TreeNode*> q;
q.push(root);
while(q.empty()==0){
int size=q.size();
vector<int> each;
while(size--){
TreeNode* t=q.front();
each.push_back(t->val);
q.pop();
if(t->left!=nullptr) q.push(t->left);
if(t->right!=nullptr) q.push(t->right);
}
result.push_back(each);
}
return result;
}
};
107. 二叉树的层序遍历II
具体思路就是在上一题的基础上把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<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>> result;
if(root==nullptr) return result;
queue<TreeNode*> q;
q.push(root);
while(q.empty()==0){
int size=q.size();
vector<int> each;
while(size--){
TreeNode* t=q.front();
each.push_back(t->val);
q.pop();
if(t->left!=nullptr) q.push(t->left);
if(t->right!=nullptr) q.push(t->right);
}
result.push_back(each);
}
int n=result.size();//数组个数
int left=0,right=n-1;
while(left<right){
vector<int> p=result[left];
result[left]=result[right];
result[right]=p;
++left;
--right;
}
return result;
}
};
199 二叉树的右视图
也是层序遍历,返回遍历后的每一层的最后一个元素
/**
* 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) {
vector<int> result;
if (root == nullptr)
return result;
queue<TreeNode*> q;
q.push(root);
while (q.empty() != 1) {
int size=q.size();
int rightest;
while(size--){
TreeNode* t=q.front();
rightest=t->val;
q.pop();
if(t->left != nullptr) q.push(t->left);
if(t->right != nullptr) q.push(t->right);
}
result.push_back(rightest);
}
return result;
}
};
其实我这里没写判断目前元素是否为该层最后一个元素的语句。我只是在每层内进行遍历的时候,每次都将当前元素的val存入rightest变量,不停覆盖,直到最后一个元素结束后跳出当前层的循环,此时rightest没有被覆盖,就直接是当前层的最后一个元素,此时直接存入result数组即可。
637.二叉树的层平均值
注意两个点:第一个是在计算每层之和的时候需要使用Long int不然会溢出。
第二个是在最后求均值的时候,定义了一个double型变量,但是不能直接把sum/n赋值给此变量,不然得到的还是Int型数,应该先把总和赋给double型变量,然后用这个double来除以n求平均值,得到的才能是double。
/**
* 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) {
vector<double> result;
if(root==nullptr) return result;
queue <TreeNode*> q;
q.push(root);
while(q.empty()==0){
int size=q.size();
int n=size;
long int sum=0;
while(size--){
TreeNode* t=q.front();
sum+= t->val;
q.pop();
if(t->left!=nullptr) q.push(t->left);
if(t->right!=nullptr) q.push(t->right);
}
double each =sum;
each=each/n;
result.push_back(each);
}
return result;
}
};
429. N 叉树的层序遍历
和二叉树层序遍历也没有啥不同
/*
// 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) {
vector<vector<int>> result;
if(root==nullptr) return result;
queue<Node*> q;
q.push(root);
while(q.empty()==0){
int size=q.size();
vector<int> each;
while(size--){
Node* t=q.front();
each.push_back(t->val);
q.pop();
vector<Node*> ch=t->children;
int n=ch.size();
for(int i=0;i<n;++i){
q.push(ch[i]);
}
}
result.push_back(each);
}
return result;
}
};
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) {
vector<int> result;
if(root==nullptr) return result;
queue <TreeNode*> myQue;
myQue.push(root);
while(myQue.empty()==0){
int size=myQue.size();
int M=INT_MIN;
while(size--){
TreeNode* t=myQue.front();
M=max(M,t->val);
myQue.pop();
if(t->left) myQue.push(t->left);
if(t->right) myQue.push(t->right);
}
result.push_back(M);
}
return result;
}
};
116. 填充每个节点的下一个右侧节点指针
/*
// 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==NULL) return root;
queue<Node*> myque;
myque.push(root);
while(myque.empty()==0){
int size=myque.size();
Node* prev;
Node* curr;
for(int i=0;i<size;++i){
if(i==0){
prev=myque.front();
myque.pop();
if(prev->left) myque.push(prev->left);
if(prev->right) myque.push(prev->right);
}
else{
curr=myque.front();
myque.pop();
if(curr->left) myque.push(curr->left);
if(curr->right) myque.push(curr->right);
prev->next=curr;
prev=curr;
}
}
prev->next=NULL;
}
return root;
}
};
相比正常的层序遍历方法有一点点绕,因为要考虑是否为本层第一个节点。之前在每层遍历的时候我喜欢直接用while(size–),这里用for循环会更容易判断是否为本层第一个节点。
117. 填充每个节点的下一个右侧节点指针 II
和上一道题一模一样的代码。。。完全没区别直接复制粘贴也能AC。
略了。
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) {
int result=0;
if(root==nullptr) return result;
queue<TreeNode*> myque;
myque.push(root);
while(myque.empty()==0){
int size=myque.size();
result++;
while(size--){
TreeNode* t=myque.front();
myque.pop();
if(t->left)
myque.push(t->left);
if(t->right)
myque.push(t->right);
}
}
return result;
}
};
111. 二叉树的最小深度
/**
* 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) {
int result=0;
if(root==nullptr) return result;
queue<TreeNode*> myque;
myque.push(root);
while(myque.empty()==0){
int size=myque.size();
result++;
while(size--){
TreeNode* t=myque.front();
if(t->left==nullptr && t->right==nullptr) return result;
myque.pop();
if(t->left) myque.push(t->left);
if(t->right) myque.push(t->right);
}
}
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==nullptr) return root;
queue<TreeNode*> myque;
myque.push(root);
while(myque.empty()==0){
int size=myque.size();
while(size--){
TreeNode* t=myque.front();
myque.pop();
TreeNode* help=t->left;
t->left=t->right;
t->right=help;
if(t->left) myque.push(t->left);
if(t->right) myque.push(t->right);
}
}
return root;
}
};
可以AC。
看了题解:
这道题使用前序后序遍历也可以,(中序遍历不可以因为会把某些节点翻转两次),层序遍历也可以实现
二叉树解题的大忌就是自己稀里糊涂的过了(因为这道题相对简单),但是也不知道自己是怎么遍历的。
再试试深度优先遍历的非递归和递归方法来实现这道题:
递归方法的前序遍历:
/**
* 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) {
process(root);
return root;
}
void process(TreeNode* root){
if(root==nullptr) return;
TreeNode* t=root->left;
root->left=root->right;
root->right=t;
process(root->left);
process(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:
TreeNode* invertTree(TreeNode* root) {
if(root==nullptr) return root;
stack<TreeNode*> myst;
myst.push(root);
while(myst.empty()==0){
TreeNode* t=myst.top();
myst.pop();
TreeNode* a=t->left;
t->left=t->right;
t->right=a;
if(t->right) myst.push(t->right);
if(t->left) myst.push(t->left);
}
return root;
}
};
odk, 下一题
101 对称二叉树
没什么思路。。
看题解:
其实本质是看头节点下面左右节点的二叉树是否为对方的翻转版本。
写一个递归分别遍历两个二叉树,遍历的时候比较左树外侧和右树外侧,左树内侧和右树内侧的节点是否相等即可
/**
* 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) {
bool result=true;
if(root==nullptr) return result;
process(root->right,root->left,result);
return result;
}
void process(TreeNode* right, TreeNode* left, bool& result){
if(left==nullptr && right==nullptr) return;
if(left==nullptr && right!=nullptr) {
result=false;
return;
}
if(right==nullptr&& left!=nullptr){
result=false;
return;
}
if(right->val != left->val){
result=false;
return;
}
process(right->right,left->left,result);
process(left->right,right->left,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:
bool isSymmetric(TreeNode* root) {
//bool result;
if(root==nullptr) return true;
if(root->left==nullptr && root->right!=nullptr) return false;
if(root->right==nullptr && root->left != nullptr) return false;
if(root->left==nullptr&& root->right==nullptr) return true;
queue<TreeNode*> myque;
myque.push(root->left);
myque.push(root->right);
while(myque.empty()==0){
int size=myque.size();
if(size%2) return false;
for(int i=0;i<size;++i){
TreeNode* a=myque.front();
myque.pop();
TreeNode* b=myque.front();
myque.pop();
++i;
if(a==nullptr&&b!=nullptr) return false;
if(a!=nullptr&&b==nullptr) return false;
if(a==nullptr&&b==nullptr) continue;
if(a->val !=b->val) return false;
myque.push(a->left);
myque.push(b->right);
myque.push(a->right);
myque.push(b->left);
}
}
return true;
}
};
用队列,把左右子树对应的节点依次存入队列,一次弹出两个进行比对,而且是按层比对,但跟层序遍历入队列的顺序不太相同。
DAY17的内容完事,看了一下对二叉树的周末小结:
“
在实现迭代法的过程中,有同学问了:递归与迭代究竟谁优谁劣呢?
从时间复杂度上其实迭代法和递归法差不多(在不考虑函数调用开销和函数调用产生的堆栈开销),但是空间复杂度上,递归开销会大一些,因为递归需要系统堆栈存参数返回值等等。
递归更容易让程序员理解,但收敛不好,容易栈溢出。
这么说吧,递归是方便了程序员,难为了机器(各种保存参数,各种进栈出栈)。
在实际项目开发的过程中我们是要尽量避免递归!因为项目代码参数、调用关系都比较复杂,不容易控制递归深度,甚至会栈溢出。
”
over!