二叉树的下一个结点
/*
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;
TreeLinkNode*temp=NULL,*temp1=NULL;
if (pNode->right != NULL)
{
temp = pNode->right;
while (temp->left != NULL)
{
temp = temp->left;
}
return temp;
}
else if(pNode->next!=NULL)//因为给的可能是根节点,所以这里要判断下。
{
temp= pNode->next,temp1 = pNode;
while (temp != NULL&&temp->left != temp1)//注意判断条件
{
temp1 = temp;
temp = temp->next;
}
}
return temp;
}
};
思路
注意这个题给了父节点的信息,所以不需要给二叉树的根节点信息,而当前节点可能是二叉树中的任一结点;分两种情况讨论:
- 有右子树,则返回右子树的最左节点;
- 没有右子树:
- 没有父节点,返回NULL
- 有父节点,是该父节点的左儿子,则返回父节点;
- 有父节点,但是不是该父节点的左儿子,一直向上找,要注意判断条件:while (temp != NULL&&temp->left != temp1)
对称的二叉树
/*
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;
return symmetrical(pRoot->left,pRoot->right);
}
bool symmetrical(TreeNode*left, TreeNode*right)
{
if ((!left) && (!right)) return true;
if (!(left)||!(right))return false;
return (left->val == right->val) && (symmetrical(left->left, right->right) && symmetrical(left->right, right->left));
}//左子树的左子树个右子树的右子树对称;左子树的右子树和右子树的左子树对称;
};
按Z字型顺序打印二叉树
/*
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) {
int depth = 0;
vector<vector<int> > result;
if (pRoot == NULL)return result;
vector<TreeNode*>a;
a.push_back(pRoot);
print_level(a, depth, result);
return result;
}
void print_level(vector<TreeNode*>a,int depth, vector<vector<int> >&result)
{
if (a.size() == 0)return;
vector<int>level;
vector<TreeNode*> temp;
if (depth % 2 == 0)
{
for (int i = 0; i < a.size(); i++)
{
level.push_back(a[i]->val);//从前往后打印
//用新的vector<TreeNode*> temp来存下一层的指针
if (a[i]->left != NULL)temp.push_back(a[i]->left);
if (a[i]->right != NULL)temp.push_back(a[i]->right);
}
}
else
{
for (int i = a.size()-1; i>=0; i--)//从后往前打印
{
level.push_back(a[i]->val);
}
for (int i = 0; i < a.size(); i++)//用新的vector<TreeNode*> temp来存下一层的指针
{
if (a[i]->left != NULL)temp.push_back(a[i]->left);
if (a[i]->right != NULL)temp.push_back(a[i]->right);
}
}
depth++;
result.push_back(level);//打印当前层结果
print_level(temp,depth,result);//迭代调用
}
};
思路
按BFS的思路,但不同的是每一层迭代调用都用新的vector<TreeNode*> temp来存下一层的指针;
把二叉树打印成多行
/*
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) {
int depth = 0;
vector<vector<int> > result;
if (pRoot == NULL)return result;
vector<TreeNode*>a;
a.push_back(pRoot);
print_level1(a, depth, result);
return result;
}
void print_level1(vector<TreeNode*>a, int depth, vector<vector<int> >&result)
{
if (a.size() == 0)return;
vector<int>level;
vector<TreeNode*> temp;
for (int i = 0; i < a.size(); i++)
{
level.push_back(a[i]->val);
if (a[i]->left != NULL)temp.push_back(a[i]->left);
if (a[i]->right != NULL)temp.push_back(a[i]->right);
}
result.push_back(level);
depth++;
print_level1(temp, depth, result);
}
};
比上一题简单,稍微改下就好了;
序列化二叉树
char* Serialize(TreeNode *root) {
if (root == NULL)return NULL;
string str;
getSerialize(root, str);
char *ret = new char[str.length() + 1];
int i;
for (i = 0; i < str.length(); i++) {
ret[i] = str[i];
}
ret[i] = '\0';
return ret;
//char*a= (char*)str.c_str() ;
//return a;
}
void getSerialize(TreeNode*root, string& str)
{
if (root == NULL)
{
str += '#';
return;
}
str += to_string(root->val);
str += ',';
getSerialize(root->left, str);
getSerialize(root->right, str);
}
TreeNode* Deserialize(char *str) {
if (str == NULL)
return NULL;
TreeNode *ret = Deserialize(&str);
return ret;
}
TreeNode* Deserialize(char **str) {
TreeNode*root;
if (**str == '#') {
++(*str);
return NULL;
}
int num = 0;
while ((**str)!='\0'&&(**str)!=',')
{
num = num * 10 + ((**str) - '0');
++(*str);
}
root = new TreeNode(num);
if (**str == '\0')return root;
++(*str);
root->left = Deserialize(str);
root->right = Deserialize(str);
return root;
}
参考:
链接:
https://www.nowcoder.com/questionTerminal/cf7e25aa97c04cc1a68c8f040e71fb84
来源:牛客网
/* ``1. 对于序列化:使用前序遍历,递归的将二叉树的值转化为字符,并且在每次二叉树的结点 不为空时,在转化val所得的字符之后添加一个' , '作为分割。对于空节点则以 '#' 代替。 ``2. 对于反序列化:按照前序顺序,递归的使用字符串中的字符创建一个二叉树(特别注意: 在递归时,递归函数的参数一定要是char ** ,这样才能保证每次递归后指向字符串的指针会 随着递归的进行而移动!!!) */
二叉搜索树的第k个节点
/*
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||k<1)return NULL;//边界
vector<TreeNode*>a;
midNode(pRoot, a);
if (k >a.size())return NULL;//边界
return a[k-1];
}
void midNode(TreeNode*p, vector<TreeNode*>&a)
{
if (p == NULL)return;
midNode(p->left, a);
a.push_back(p);
midNode(p->right, a);
}
};
思路
先得到中序遍历序列,然后直直接返回第k个节点就可以了。注意边界条件的处理
数据流中的中位数
priority_queue<int, vector<int>, less<int> > p;
priority_queue<int, vector<int>, greater<int> > q;
void Insert(int num) {
if (p.empty() || num <= p.top()) p.push(num);//如果是奇数个的话,p要比q多一个元素
else q.push(num);
if (p.size() == q.size() + 2) q.push(p.top()), p.pop();//保持两个堆的数据个数最多差一个,p.top()返回的是最大值,因为是<操作符,越大的优先级越高
if (p.size() + 1 == q.size()) p.push(q.top()), q.pop();//q.top()返回的是最小值,越小的优先级越高
}
double GetMedian() {
return p.size() == q.size() ? (p.top() + q.top()) / 2.0 : p.top();
}
思路
这个题我只想到了排序的方法,优先队列的方法:大顶堆和小顶堆写起来还是很简单的。
数组插入进去然后再排序,这种情况插入时间效率是O(n),找中位数时间效率是O(1)。
排序的链表,两种时间复杂度和上面是一样的。
二叉搜索树,首先说一下平均的时间效率,插入的时间效率是O(logn),找中位数的时间效率是O(logn)。然而当插入的时间顺序是排好序的数组的时候,二叉树就退化成了一个数组,插入时间效率是O(n),找中位数的时间效率是O(n)。
AVL树,插入的时间效率是O(logn),找中位数的时间效率是O(1)。
大顶堆和小顶堆。插入的时间效率是O(logn),找中位数的时间效率是O(1)。
——————— 本文来自 will_duan 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/willduan1/article/details/53392940?utm_source=copy