牛客网剑指offer树题目总结(共17道)
1、二叉树的前、中、后序遍历(递归和非递归)
#include<iostream>
#include<string>
#include<vector>
#include<stack>
using namespace std;
struct TreeNode{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x):val(x),left(NULL),right(NULL){};
};
//前序遍历,递归
void preOrder(TreeNode *root, vector<int> &s){
if (root == NULL) return;
s.push_back(root->val);
if (root->left) preOrder(root->left, s);
if (root->right) preOrder(root->right, s);
}
//前序遍历,非递归
void preOrder1(TreeNode *root, vector<int> &s){
stack <TreeNode *> st;
st.push(root);
while (!st.empty()){
TreeNode *t = st.top();
s.push_back(t->val);
st.pop();
if (t->right!=NULL) st.push(t->right);
if (t->left!=NULL) st.push(t->left);
}
}
//中序遍历,递归
void inOrder(TreeNode *root, vector<int> &s){
if (root == NULL) return;
if (root->left) inOrder(root->left, s);
s.push_back(root->val);
if (root->right) inOrder(root->right, s);
}
//中序遍历,非递归
void inOrder1(TreeNode *root, vector<int> &s){
stack<TreeNode *> st;
while (!st.empty() || root != NULL){
if (root == NULL){
TreeNode *t = st.top();
st.pop();
s.push_back(t->val);
root = t->right;
}
else{
st.push(root);
root = root->left;
}
}
}
//后序遍历,递归
void postOrder(TreeNode *root, vector<int> &s){
if (root == NULL) return;
if (root->left) postOrder(root->left, s);
if (root->right) postOrder(root->right, s);
s.push_back(root->val);
}
//后序遍历,非递归
void postOrder1(TreeNode *root, vector<int> &s){
stack<TreeNode *> st;
stack<TreeNode*> res;
st.push(root);
while (!st.empty()){
TreeNode * t = st.top();
st.pop();
res.push(t);
if (t->left != NULL) st.push(t->left);
if (t->right != NULL) st.push(t->right);
}
while (!res.empty()){
s.push_back(res.top()->val);
res.pop();
}
}
int main(){
TreeNode *A = new TreeNode(1);
TreeNode *B = new TreeNode(2);
TreeNode *C = new TreeNode(3);
A->left = B;
A->right = C;
vector<int> s;
postOrder1(A, s);
for (int i = 0; i < s.size(); i++)
cout << s[i] << " ";
cout << endl;
}
2、判断一个树是不是平衡二叉树(剑指39)
class Solution {
public:
bool IsBalanced_Solution(TreeNode* pRoot) {
return GetDepth(pRoot)!=-1;
}
int GetDepth(TreeNode *pRoot){
if(pRoot==NULL) return 0;
int left=GetDepth(pRoot->left);
if(left==-1) return -1;
int right=GetDepth(pRoot->right);
if(right==-1) return -1;
if(abs(left-right)>1) return -1;
return 1+max(left,right);
}
};
3、二叉搜索树的第k个结点(剑指62,类似leetcode230)
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
int index=0;
TreeNode* KthNode(TreeNode* pRoot, int k)
{
if(pRoot==NULL) return NULL;
TreeNode *node=KthNode(pRoot->left,k);
if(node!=NULL) return node;
index++;
if(index==k) return pRoot;
node=KthNode(pRoot->right,k);
if(node!=NULL) return node;
}
};
4、根据前序和中序遍历结果重建二叉树(剑指4,同leetcode105)
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
if(pre.empty()||vin.empty()||pre.size()!=vin.size()) return NULL;
else return reConstruct(pre,vin,0,0,vin.size()-1);
}
TreeNode* reConstruct(vector<int> pre,vector<int> vin,int pstr,int vstr,int vend){
if(vstr>vend) return NULL;
TreeNode *root=new TreeNode(pre[pstr]);
for(int i=vstr;i<=vend;i++){
if(vin[i]==pre[pstr]){
root->left=reConstruct(pre,vin,pstr+1,vstr,i-1);
root->right=reConstruct(pre,vin,pstr+i-vstr+1,i+1,vend);
break;
}
}
return root;
}
};
5、把二叉树打印多行(剑指60,同leetcode102)
从上到下按层打印二叉树,同层结点从左到右输出,每一层输出一行。
/*
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>> ans;
if(pRoot==NULL) return ans;
queue<TreeNode*> q;
q.push(pRoot);
while(!q.empty()){
vector<int> temp;
int n=q.size();
for(int i=0;i<n;i++){
TreeNode *t=q.front();
temp.push_back(t->val);
q.pop();
if(t->left!=NULL) q.push(t->left);
if(t->right!=NULL) q.push(t->right);
}
ans.push_back(temp);
}
return ans;
}
};
6、按照之字形打印二叉树(剑指59)
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
/*
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>> ans;
if(pRoot==NULL) return ans;
stack<TreeNode *> s1;
stack<TreeNode *> s2;
s1.push(pRoot);
while(!s1.empty()||!s2.empty()){
vector<int> temp1;
while(!s1.empty()){
TreeNode * t=s1.top();
temp1.push_back(t->val);
s1.pop();
if(t->left!=NULL) s2.push(t->left);
if(t->right!=NULL) s2.push(t->right);
}
if(!temp1.empty()) ans.push_back(temp1);
vector<int> temp2;
while(!s2.empty()){
TreeNode * t=s2.top();
temp2.push_back(t->val);
s2.pop();
if(t->right!=NULL) s1.push(t->right);
if(t->left!=NULL) s1.push(t->left);
}
if(!temp2.empty()) ans.push_back(temp2);
}
return ans;
}
};
7、对称的二叉树(剑指58,同leetcode101)
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
/*
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)
{
if(pRoot==NULL) return true;
else return judge(pRoot->left,pRoot->right);
}
bool judge(TreeNode* pNode1,TreeNode* pNode2){
if(pNode1==NULL&&pNode2==NULL) return true;
else if(pNode1!=NULL&&pNode2==NULL) return false;
else if(pNode1==NULL&&pNode2!=NULL) return false;
else return pNode1->val==pNode2->val&&judge(pNode1->left,pNode2->right)&&judge(pNode1->right,pNode2->left);
}
};
8、二叉树的下一个结点(剑指57)
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
/*
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!=NULL){
TreeLinkNode * node=pNode->right;
while(node->left!=NULL) node=node->left;
return node;
}
else{
if(pNode->next!=NULL){
TreeLinkNode * parent=pNode->next;
TreeLinkNode * cur=pNode;
while(parent!=NULL&&cparent->right==cur){
cur=parent;
parent=parent->next;
}
return parent;
}
else return NULL;
}
}
};
9、二叉树的深度(简单、剑指38)
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
int TreeDepth(TreeNode* pRoot)
{
if(pRoot==NULL) return 0;
else return 1+max(TreeDepth(pRoot->left),TreeDepth(pRoot->right));
}
};
10、二叉搜索树与双向链表(剑指26)
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(pRootOfTree==NULL) return NULL;
TreeNode* pre=NULL;
CovertHelp(pRootOfTree,pre);
TreeNode* res=pRootOfTree;
while(res->left)
res=res->left;
return res;
}
void CovertHelp(TreeNode* cur,TreeNode* &pre){
if(cur==NULL) return;
CovertHelp(cur->left,pre);
cur->left=pre;
if(pre) pre->right=cur;
pre=cur;
CovertHelp(cur->right,pre);
}
};
11、二叉树中和为某一值的路径(剑指24)
输入一颗二叉树的根节点和一个整数,按字典序打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
/*
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>> ans;
vector<int> temp;
void find(TreeNode *node,int p){
temp.push_back(node->val);
if(!node->left&&!node->right&&node->val==p){
ans.push_back(temp);
}
else{
if(node->left) find(node->left,p-node->val);
if(node->right) find(node->right,p-node->val);
}
temp.pop_back();
}
vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
if(root) find(root,expectNumber);
return ans;
}
};
12、二叉搜索树的后续遍历序列(剑指23)
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。
class Solution {
public:
bool judge(vector<int> sequence,int l,int r){
if(l>=r) return true;
int temp=sequence[r];
int j=r;
while(j>=l&&sequence[j]>=temp) j--;
for(int i=j;i>=l;i--){
if(sequence[i]>temp) return false;
}
return judge(sequence,l,j)&&judge(sequence,j+1,r-1);
}
bool VerifySquenceOfBST(vector<int> sequence) {
if(sequence.empty()) return false;
return judge(sequence,0,sequence.size()-1);
}
};
13、从上到下打印二叉树(剑指22)
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int> ans;
if(root==NULL) return ans;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
TreeNode * t=q.front();
ans.push_back(t->val);
q.pop();
if(t->left!=NULL) q.push(t->left);
if(t->right!=NULL) q.push(t->right);
}
return ans;
}
};
14、二叉树的镜像(剑指18)
操作给定的二叉树,将其变换为源二叉树的镜像。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
void Mirror(TreeNode *pRoot) {
if(pRoot==NULL) return;
if(pRoot->left==NULL&&pRoot->right==NULL) return;
TreeNode * temp=pRoot->left;
pRoot->left=pRoot->right;
pRoot->right=temp;
if(pRoot->left )Mirror(pRoot->left);
if(pRoot->right) Mirror(pRoot->right);
}
};
15、树的子结构(剑指17)
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot1==NULL||pRoot2==NULL) return false;
else return isSubTree(pRoot1,pRoot2)||isSubTree(pRoot1->right,pRoot2)||isSubTree(pRoot1->left,pRoot2);
}
bool isSubTree(TreeNode* pRoot1,TreeNode* pRoot2){
if(pRoot2==NULL) return true;
if(pRoot1==NULL) return false;
if(pRoot1->val==pRoot2->val){
return isSubTree(pRoot1->left,pRoot2->left)&&isSubTree(pRoot1->right,pRoot2->right);
}
else return false;
}
};
16、重建二叉树(剑指4)
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
if(pre.empty()||vin.empty()||pre.size()!=vin.size()) return NULL;
return reConstruct(pre,vin,0,0,vin.size()-1);
}
TreeNode * reConstruct(vector<int> pre,vector<int> vin,int pstr,int vstr,int vend){
if(vstr>vend) return NULL;
TreeNode * root=new TreeNode(pre[pstr]);
for(int i=vstr;i<=vend;i++){
if(pre[pstr]==vin[i]){
root->left=reConstruct(pre,vin,pstr+1,vstr,i-1);
root->right=reConstruct(pre,vin,pstr+i-vstr+1,i+1,vend);
break;
}
}
return root;
}
};
17、序列化二叉树(剑指61)
请实现两个函数,分别用来序列化和反序列化二叉树。
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过某种符号表示空节点(#),以!表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己的函数来解析回这个二叉树。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
*/
class Solution {
public:
char* Serialize(TreeNode *root) {
if(root==NULL) return NULL;
string s;
Serialize(root,s);
int i;
char *res=new char[s.length()+1];
for(i=0;i<s.length();i++){
res[i]=s[i];
}
res[i]=' ';
return res;
}
void Serialize(TreeNode *root,string &str){
if(root==NULL){
str+='#';
return;
}
string s=to_string(root->val);
str+=s;
str+=',';
Serialize(root->left,str);
Serialize(root->right,str);
}
TreeNode* Deserialize(char *str) {
if(str==NULL) return NULL;
TreeNode *ret = Deserialize(&str);
return ret;
}
TreeNode* Deserialize(char **str){
if(**str=='#'){
++(*str);
return NULL;
}
int num = 0;
while(**str != ' ' && **str != ','){
num = num*10 + ((**str) - '0');
++(*str);
}
TreeNode *root = new TreeNode(num);
if(**str == ' ')
return root;
else
(*str)++;
root->left = Deserialize(str);
root->right = Deserialize(str);
return root;
}
};