Narcissus's blog Stay Follish, Stay Hungry

二叉树

2018-07-28
Narcissus

二叉树的下一个结点

/*
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


上一篇 1.Two Sum

Comments

Content