搜索与回溯算法-目录
面试题32 - I. 从上到下打印二叉树
描述
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
例如:
输入:
给定二叉树:
[3,9,20,null,null,15,7],
~~~~ ~ 3
~~~~ / ~~~~ \
~~~~ 9 ~ 20
~~~~ ~~~~~ / \
~~~~ ~ 15 ~ 7
输出:[3,9,20,15,7]
~~
条件:节点总数 <= 1000
思路
从头结点开始层次遍历二叉树,用一个队列存储每一个不为null的节点,每一层的子节点存在当前层节点的后面,先进先出,用数组(使用vector动态数组,不用考虑数值个数)存储每个不为null节点的数值。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> levelOrder(TreeNode* root) {
vector<int> tree;
queue<TreeNode*> q;
if(root==NULL) return {};
q.push(root);
while(!q.empty()){
TreeNode* p=q.front();//取队列树头节点
if(p->left!=NULL) q.push(p->left);
if(p->right!=NULL) q.push(p->right);//将此节点的左右不为空的子树放到队列里
q.pop();
tree.push_back(p->val);
}
return tree;
}
};
/*
执行用时:0ms;
内存消耗:11.9.
*/
搜索与回溯算法-目录
剑指 Offer 32 - II. 从上到下打印二叉树 II
描述
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:
给定二叉树:
[3,9,20,null,null,15,7],
~~~~ ~ 3
~~~~ / ~~~~ \
~~~~ 9 ~ 20
~~~~ ~~~~~ / \
~~~~ ~ 15 ~ 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
思路
整体思路同上一题,不过在每一层遍历的时候多了一层循环,在上一层遍历结束时,记录当前队列数量(当前层个数),再新建一个单层的数组用来存储当前层的数值,一层循环结束后,将该数组存入需要输出的数组。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> tree;
vector<int> brant;
if(root==NULL)
return {};
queue<TreeNode*>q;
q.push(root);
while(!q.empty()){
TreeNode* p;
int x=q.size();
brant.clear();
for(int i=0;i<x;i++){
p=q.front();
if(p->left!=NULL) q.push(p->left);
if(p->right!=NULL) q.push(p->right);
q.pop();
brant.push_back(p->val);
}
tree.push_back(brant);
}
return tree;
}
};
/*
执行用时:8ms;
内存消耗:12.3。
*/
搜索与回溯算法-目录
剑指 Offer 32 - III. 从上到下打印二叉树 III
描述
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
例如:
给定二叉树:
[3,9,20,null,null,15,7],
~~~~ ~ 3
~~~~ / ~~~~ \
~~~~ 9 ~ 20
~~~~ ~~~~~ / \
~~~~ ~ 15 ~ 7
返回其层次遍历结果:
[
[3],
[20,9],
[15,7]
]
思路
整体思路依旧跟上一题一致,唯一的区别在于我用了一个变量记录层数,从0开始记录,当遍历的层数为奇数时,就用一个栈做辅助实现当前层数组的倒序,再将当前层倒序后的数组收入结果数组。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> tree;
vector<int> brant;
if(root==NULL)
return {};
queue<TreeNode*>q;
q.push(root);
int y=0;
while(!q.empty()){
TreeNode* p;
int x=q.size();
brant.clear();
for(int i=0;i<x;i++){
p=q.front();
if(p->left!=NULL) q.push(p->left);
if(p->right!=NULL) q.push(p->right);
q.pop();
brant.push_back(p->val);
}
if(y%2==1){
stack<int>brant2;
for(int i=0;i<x;i++){
brant2.push(brant[i]);
}
brant.clear();
for(int i=0;i<x;i++){
brant.push_back(brant2.top());
brant2.pop();
}
}
tree.push_back(brant);
y++;
}
return tree;
}
};
/*
执行用时:4ms;
内存消耗:12.7MB。
*/
搜索与回溯算法-目录
剑指 Offer 26. 树的子结构
描述
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
例如:
给定的树 A:
~~~~ ~ 3
~~~~ / ~~~~ \
~~~~ 4 ~ 5
~~~~ / \
~~ 1 ~ 2
给定的树 B:
~~~~ 4
~~~~ /
~~ 1 ~
返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。
~~
示例 1:
输入:A = [1,2,3], B = [3,1]
输出:false
示例 2:
输入:A = [3,4,5,1,2], B = [4,1]
输出:true
限制:0 <= 节点个数 <= 10000
思路
核心思想是利用两次循环。
第一次是遍历A树的节点,用B树的头结点与其比较,找到符合要求的子树头结点。采用递归的手段,父节点不符合,就看子节点符不符合,只要有一个符合即可。
待找到后,进行第二次循环,这次的循环是比较B的结构是否在A当中,也用递归的手段,若是头结点值相等,就再判断左孩子以及右孩子的结构相不相等(看B树有没有孩子,有则比较,没有就默认这部分相等)。第二个循环也单独写了个函数调用。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
//当输入的树的头结点跟大树某个结点值相等,判断子树结构是否相等
bool issame(TreeNode* A,TreeNode* B)
{
if(B==NULL) return true;//子树遍历结束,前面元素都相等
if(A==NULL) return false;//大树遍历结束,子树还没结束,子树超数
if(A->val!=B->val)//有元素不相等,则不是
return false;
return issame(A->left,B->left)&&issame(A->right,B->right);
}
bool isSubStructure(TreeNode* A, TreeNode* B) //判断子树是否存在
{
if(A==NULL||B==NULL)//都是空树不存在
return false;
else if(A->val==B->val&&issame(A,B))//当头结点相等且子树结构相等
return true;
//头结点不相等时,去找大树的子节点
return isSubStructure(A->left,B)||isSubStructure(A->right,B);
}
};
/*
执行用时:28ms;
消耗内存:32.9MB。
*/
搜索与回溯算法-目录
剑指 Offer 27. 二叉树的镜像
描述
请完成一个函数,输入一个二叉树,该函数输出它的镜像。
例如输入:
~~~~ ~ 4
~~~~ / ~~~~ \
~~~ 2 ~~~ 7
~~ / \ ~~~ / \
~ 1 3 ~ 6 9
镜像输出:
~~~~ ~ 4
~~~~ / ~~~~ \
~~~ 7 ~~~ 2
~~ / \ ~~~ / \
~ 9 6 ~ 3 1
**示例 **:
输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]
限制:0 <= 节点个数 <= 1000
思路
利用递归函数,直接修改二叉树,调换每个节点的左右节点,同时调换的还是镜像过的左右节点。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
if(root==NULL)
return root;
TreeNode* p=root->left;
root->left=mirrorTree(root->right);
root->right=mirrorTree(p);
return root;
}
};
/*
执行用时:0ms;
内存消耗:9MB。
*/
搜索与回溯算法-目录
剑指 Offer 28. 对称的二叉树
描述
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
~~~~ ~ 1
~~~~ / ~~~~ \
~~~ 2 ~~~ 2
~~ / \ ~~~ / \
~ 3 4 ~ 4 3
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
~~~~ ~ 1
~~~~ / ~~~~ \
~~~ 2 ~~~ 2
~~~~ \ ~~~~ \
~~~~ 3 ~~~~ 3
示例 1:
输入:root = [1,2,2,3,4,4,3]
输出:true
示例 2:
输入:root = [1,2,2,null,3,null,3]
输出:false
限制:0 <= 节点个数 <= 1000
思路
首先分析一下对称树的样子。
空树或者只有一层的话,一定是对称树;
从二层往下,每层必须满足左右对称,如果把null的位置填充为一个默认值(我用的-99),然后参考打印二叉树的做法,把每一层存到一个数组里,数组大小一定是偶数,再设置一个判断该数组元素是否左右对称的函数,每遍历一层就判断一次,一旦不对称,则不是对称二叉树,若每一层都左右对称,则该树是对称二叉树。
代码
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool isdui(vector<int> link){
int x=link.size()/2;
for(int i=0;i<x;i++){
if(link[i]!=link[2*x-1-i])
return false;
}
return true;
}
bool isSymmetric(TreeNode* root)
{
if(root==NULL) return true;//空树一定为对称
if(root->left==NULL&&root->right==NULL) return true;//只有头结点
if(root->left==NULL||root->right==NULL) return false;//有一边没有
if(root->left->val!=root->right->val) return false;//第二层两个不一样一定不对称
//从第三行开始,一行一行看是否对称,有缺失就补全,我用的-99
vector<int> brant;
queue<TreeNode*>q;
q.push(root->left);
q.push(root->right);
while(!q.empty())
{
TreeNode* p;
int y=q.size();
brant.clear();
for(int i=0;i<y;i++)
{
p=q.front();
if(p->left!=NULL){
q.push(p->left);
brant.push_back(p->left->val);
}
else
brant.push_back(-99);
if(p->right!=NULL){
q.push(p->right);
brant.push_back(p->right->val);
}
else
brant.push_back(-99);
q.pop();
}
if(!isdui(brant)) return false;
}
return true;
}
};
/*
执行用时:4ms;
内存消耗:16.2MB。
*/