题目:重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路:利用递归,将前序遍历的第一个节点做根节点,
将中序遍历由根节点分开,又分别作为左子树与右子树的中序遍历
还可以提高的地方:以根节点将vector分开时还可以简化。
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
if(pre.size() == 0)
{
return NULL;
}
vector<int> left_pre,right_pre,left_vin,right_vin;
TreeNode* head = new TreeNode(pre[0]);
int root = 0;
//找到根节点
for(int i = 0; i < pre.size(); i++)
{
if(pre[0] == vin[i])
{
root = i;
break;
}
}
for(int i = 0; i < root; i++)
{
left_vin.push_back(vin[i]);
left_pre.push_back(pre[i + 1]);//第一个节点为根节点
}
for(int i = root +1; i < pre.size(); i++)
{
right_vin.push_back(vin[i]);
right_pre.push_back(pre[i]);
}
head->left = reConstructBinaryTree(left_pre, left_vin);
head->right = reConstructBinaryTree(right_pre, right_vin);
return head;
}
};
题目:树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
解题思路:运用递归方法。这个题目需要两次递归,一次对pRoot1递归,pRoot1每一个节点都需要与pRoot2相比,都相等才相等。还有一次是需要将每个pRoot1的节点当做根节点与pRoot2相比,再把他们的每个节点相比。
需要思考的问题:|| 与 &&的用法,即所谓的短路原理。
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot2 == NULL || pRoot1 == NULL)
{
return false;
}
else
{
return tree(pRoot1, pRoot2) || HasSubtree(pRoot1->left, pRoot2) ||HasSubtree(pRoot1->right, pRoot2);
}
}
bool tree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot1 == NULL && pRoot2 != NULL)
{
return false;
}
if(pRoot2 == NULL)
{
return true;
}
if(pRoot1->val != pRoot2->val)
{
return false;
}
return tree(pRoot1->left, pRoot2->left) && tree(pRoot1->right, pRoot2->right);
}
};
题目:二叉树的镜像
操作给定的二叉树,将其变换为源二叉树的镜像。
解题思路:递归的将每个节点的左右子树交换。
可以思考的问题:如果这个函数有返回值,这个函数体还可以怎么写。
class Solution {
public:
void Mirror(TreeNode *pRoot) {
if(pRoot == NULL)
{
return;
}
TreeNode* Node = pRoot->left;
pRoot->left = pRoot->right;
pRoot->right = Node;
Mirror(pRoot->right);
Mirror(pRoot->left);
}
};
题目:二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
解题思路:用递归方法。以最后一个元素为判断标志,将数组分为两段,如果分开的
这两段数组里的元素都是比最后一个元素大或者小,则分别将这两段数组再继续分开。
还可以提高的地方:以最后一个元素分开数组时,还可以怎么优化!
bool VerifySquenceOfBST(vector<int> sequence) {
if (sequence.size() == NULL)
{
return false;
}
else
{
return judgeBTS(sequence, 0, sequence.size() - 1);
}
}
bool judgeBTS(vector<int> ivec, int start, int end)
{
if(start >= end)
{
return true;
}
int flog = 0;
for(int i = start; ivec[i] < ivec[end]; ++i)
{
flog = i;
if(i >= end - 1)
break;
}
for(int i = flog + 1; i < end; ++i)
{
if(ivec[i] < ivec[end])
return false;
}
return judgeBTS(ivec, start, flog) && judgeBTS(ivec, flog + 1, end - 1);
}
题目:从上往下打印二叉树
从上往下打印出二叉树的每个节点,同层节点从左至右打印
思路:利用队列先进先出的特点,进行遍历。
还可以提高的地方:优化代码
vector<int> PrintFromTopToBottom(TreeNode* root) {
queue <TreeNode*> queTree;
vector<int> ivec;
if (root == NULL)
return ivec;
ivec.push_back(root->val);
queTree.push(root);
while (!queTree.empty())
{
TreeNode* Node = queTree.front();
if (Node->left != NULL)
{
queTree.push(Node->left);
ivec.push_back(Node->left->val);
}
if (Node->right != NULL)
{
queTree.push(Node->right);
ivec.push_back(Node->right->val);
}
queTree.pop();
}
return ivec;
题目:二叉树中和为某一值得路径
输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
思路:??
class Solution {
public:
vector<vector<int> > FindPath(TreeNode* root,int expectNumber) {
vector<vector<int> > ivec1;
vector<int> ivec2;
if(root)
Sum(root, expectNumber, ivec1, ivec2);
return ivec1;
}
void Sum(TreeNode* root, int sum, vector<vector<int> > &ivec1, vector<int> &ivec2)
{
ivec2.push_back(root->val);
if(root->left == NULL && root->right == NULL)
{
if(sum == root->val)
ivec1.push_back(ivec2);
}
if(root->left)
{
Sum(root->left, sum-root->val, ivec1, ivec2);
}
if(root->right)
{
Sum(root->right, sum-root->val, ivec1, ivec2);
}
ivec2.pop_back();
}
};
题目:二叉树的下一个结点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
解题思路:1.如果该节点的右子树不为空,找到以该节点为根的最左节点
2.如果该节点的右子树为空,判断该节点是否为父节点的左节点,是则返回父节点;否则,返回该节点中的父节点作为第一个左子树的父节点。
提高:代码可以更精简。
class Solution {
public:
TreeLinkNode* GetNext(TreeLinkNode* pNode)
{
TreeLinkNode* root;
TreeLinkNode* rNode;
rNode = pNode;
if(pNode == NULL)
{
return NULL;
}
if(rNode->right != NULL) //找右子树最左边的节点
{
root = pNode->right;
rNode = root->left;
while(rNode != NULL)
{
root = rNode;
rNode = rNode->left;
}
return root;
}
else
{
root = rNode->next;
while(root != NULL)
{
if(root->left == rNode)
{
return root;
}
else
{
rNode = root;
root = root->next;
}
}
}
return NULL;
}
};
题目:对称的二叉树
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
思路:利用递归的思想
class Solution {
public:
bool isSymmetrical(TreeNode* pRoot)
{
TreeNode* root;
TreeNode* rNode;
root = pRoot;
rNode = pRoot;
if(pRoot == NULL)
return true;
return same(root, rNode);
}
bool same(TreeNode* root, TreeNode* rNode)
{
if(root == NULL && rNode == NULL)
return true;
if(root == NULL || rNode == NULL)
return false;
if(root->val != rNode->val)
return false;
return same(root->left, rNode->right) && same(root->right, rNode->left);
}
};
题目:按之字形顺序打印二叉树
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
思路:这道题目实际是层次遍历的变形,利用队列,按行进行题目要求的操作
提高:代码优化
class Solution {
public:
vector<vector<int> > Print(TreeNode* pRoot) {
vector<vector<int> > ivect;
deque<TreeNode* > Tdeq;
if(pRoot == NULL)
return ivect;
Tdeq.push_back(pRoot);
TreeNode* temp = NULL;
int Number = 1;
int odd = 1;
vector<int> ive;
while(!Tdeq.empty())
{
for(int i = 0; i < Number; ++i)
{
if(odd % 2 == 1)
{
temp = Tdeq.back();
Tdeq.pop_back();
ive.push_back(temp->val);
if(temp->left != NULL)
Tdeq.push_front(temp->left);
if(temp->right != NULL)
Tdeq.push_front(temp->right);
}
else
{
temp = Tdeq.front();
Tdeq.pop_front();
ive.push_back(temp->val);
if(temp->right != NULL)
Tdeq.push_back(temp->right);
if(temp->left != NULL)
Tdeq.push_back(temp->left);
}
}
Number = Tdeq.size();
odd++;
ivect.push_back(ive);
ive.clear();
}
return ivect;
}
};
题目:二叉搜索树的第k个结点
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
思路:利用中序遍历的思想,中序遍历得到的第k个结点就是题目要求的节点。
提高:代码优化
//中序遍历,得到第k个结点
class Solution {
public:
int i = 0;
TreeNode* KthNode(TreeNode* pRoot, int k)
{
if(k == 0)
{
return NULL;
}
if(pRoot == NULL)
{
++i;
return pRoot;
}
TreeNode* Node = KthNode(pRoot->left, k);
if(Node == NULL)
{
Node = pRoot;
}
if(k == i)
{
return Node;
}
Node = KthNode(pRoot->right, k);
if(k == i)
{
return Node;
}
return Node;
}
};
题目:序列化二叉树
请实现两个函数,分别用来序列化和反序列化二叉树
思路:
题目:二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。