把二叉树打印成多行
题目描述
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
实现思路
BFS即可,树的题目切记刚开始要判断顶点是否为空。
具体实现
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
vector<vector<int> > Print(TreeNode* pRoot) {
vector<vector<int> > res;
if(pRoot==NULL) return res;
queue<TreeNode* > q;
q.push(pRoot);
int j=0;
while(!q.empty()){
vector<int> temp;
int sz = q.size();
for(int i=0;i<sz;i++){
TreeNode* cur = q.front();
temp.push_back(cur->val);
if(cur->left) q.push(cur->left);
if(cur->right) q.push(cur->right);
q.pop();
}
res.push_back(temp);
}
return res;
}
};
对称的二叉树
题目描述
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
实现思路
若是镜像的话,从根节点的左子树和右子树出发,不断对比左子树的左子结点和右子树的右子节点,递归调用即可。
具体实现
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
return f(pRoot,pRoot);
}
bool f(TreeNode* root1, TreeNode* root2){
if(root1==NULL && root2==NULL)
return true;
if(root1==NULL||root2==NULL)
return false;
if(root1->val!=root2->val)
return false;
return f(root1->left,root2->right)&&f(root1->right,root2->left);
}
};
二叉树的下一个结点
题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
实现思路
根据中序遍历的性质,只要有以下几点规律:
- 若该结点存在右子结点的,只需从它的右子节点出发不断向下找他的左子结点。
- 此外,若该结点不是根结点:
- 若是左子节点,返回其父结点。
- 若是右子节点,同等判断条件判断其父结点的下一个结点
- 若是根节点,返回NULL
具体实现
/*
struct TreeLinkNode {
int val;
struct TreeLinkNode *left;
struct TreeLinkNode *right;
struct TreeLinkNode *next;
TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
}
};
*/
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
if(pNode==NULL) return NULL;
if(pNode->right){
TreeLinkNode* pright=pNode->right;
while(pright->left){
pright=pright->left;
}
return pright;
}
while(pNode->next!=NULL){
TreeLinkNode* proot=pNode->next;
if(proot->left==pNode)
return proot;
pNode = pNode->next;
}
return NULL;
}
};
数据流中的中位数
题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
实现思路
刚开始打算用一个优先队列来做(最佳解是用两个,但我实在理解不来),不过看了他的样例是反复调用GetMedian,故作废,只能改用数组存储,每添加一个元素就排序(十分辣鸡的做法)。
具体实现
class Solution {
vector<int> q;
public:
void Insert(int num)
{
q.push_back(num);
sort(q.begin(),q.end());
}
double GetMedian()
{
int median = q.size()/2;
if(q.size()%2!=0){
return q[median];
}
else{
return (q[median]+q[median-1])/2.0;
}
return 0;
}
};
二叉搜索树的第k个结点
题目描述
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
实现思路
中序遍历二叉搜索树可以得到一从小到大排序的序列,用栈来模拟这一过程,出栈顺序为中序遍历。
具体实现
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
TreeNode* KthNode(TreeNode* pRoot, int k)
{
if(pRoot==NULL) return NULL;
stack<TreeNode* > s;
TreeNode* cur = pRoot;
while(!s.empty()||cur!=NULL){
if(cur!=NULL){
s.push(cur);
cur=cur->left;
}
else{
cur = s.top();
s.pop();
if(--k==0) return cur;
cur = cur->right;
}
}
return NULL;
}
};
按之字形顺序打印二叉树
题目描述
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
实现思路
其实同二叉树的层次遍历一样,用队列辅助即可,只不过多了一个判定条件当为奇数层时将序列反转。
但这是一种会被骂的做法,我也只做了这种会被骂的解法。最优解是用两个栈来模拟奇数层和偶数层。
假定初始为偶数层,下一层即为奇数层,将根的左子结点、右子节点依次压入栈中。下下一次循环时,弹出的顺序即为从右到左。然后按弹出的顺序按右子结点、左子节点的顺序压入另一个栈中,在下一次循环遍历该栈时弹出顺序即为从左到右。
具体实现(我的垃圾做法)
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
vector<vector<int> > Print(TreeNode* pRoot) {
vector<vector<int> > res;
queue<TreeNode* > q;
if(pRoot==NULL)
return res;
q.push(pRoot);
int sign = 1;
while(!q.empty()){
vector<int> temp;
int sz = q.size();
for(int i=0;i<sz;i++){
TreeNode* cur = q.front();
q.pop();
if(cur->left) q.push(cur->left);
if(cur->right) q.push(cur->right);
temp.push_back(cur->val);
}
if(sign==1)
res.push_back(temp);
else{
reverse(temp.begin(),temp.end());
res.push_back(temp);
}
sign=-sign;
}
return res;
}
};