剑指offer -- 树

二叉树的下一个结点 - trick

题目描述

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

参考:https://www.nowcoder.com/questionTerminal/9023a0c988684a53960365b889ceaf5e?f=discussion
来源:牛客网
 

思路:首先知道中序遍历的规则是:左根右,然后作图

剑指offer -- 树_第1张图片

结合图,我们可发现分成两大类:1、有右子树的,那么下个结点就是右子树最左边的点;(eg:D,B,E,A,C,G) 2、没有右子树的,也可以分成两类,a)是父节点左孩子(eg:N,I,L) ,那么父节点就是下一个节点 ; b)是父节点的右孩子(eg:H,J,K,M)找他的父节点的父节点的父节点...直到当前结点是其父节点的左孩子位置。如果没有eg:M,那么他就是尾节点。

#include
#include
using namespace std;
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)
	{
		TreeLinkNode* proot;
		if (pNode == NULL)return NULL;

		if (pNode->right != NULL) {
			proot=pNode->right;
			while (proot->left != NULL) {
				proot = proot->left;
			}
			return proot;
		}
		else {
			proot = pNode->next;
			while (proot != NULL) {

				if (proot->left == pNode) {
					return proot;
				}
				pNode = proot;
				proot = proot->next;
			}
			
		}
	}
};

对称的二叉树

题目描述

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

#include
#include
using namespace std;

struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};

class Solution {
public:
	bool dfs(TreeNode*r1, TreeNode*r2) {

		if (r1 == NULL && r2 == NULL)return true;
		else if (r1 == NULL && r2 != NULL)return false;
		else if (r2 == NULL && r1 != NULL)return false;
		else
			return r1->val == r2->val&&dfs(r1->left, r2->right) && dfs(r1->right, r2->left);

	}
	bool isSymmetrical(TreeNode* pRoot)
	{
		if (pRoot == NULL)return true;
		else return dfs(pRoot->left, pRoot->right);
	}

};

 把二叉树打印成多行  -- dfs / bfs

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

mycode:

#include
#include
#include
#include
using namespace std;

struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};

class Solution {
public:
	vector > Print(TreeNode* pRoot) {
		vector >res;
		if (pRoot == NULL)return res;
		unordered_map level;
		queueq;
		
		level[pRoot] = 0;
		q.push(pRoot);
		while (!q.empty()) {
			TreeNode* w = q.front();
			q.pop();
			int index = level[w];
			if (index >= res.size()) {
				res.push_back(vector());
			}
			res[index].push_back(w->val);
			if (w->left != NULL) {
				level[w->left] = level[w] + 1;
				q.push(w->left);
			}
			if (w->right != NULL) {
				level[w->right] = level[w] + 1;
				q.push(w->right);
			}
		}
		
		return res;
		
	}

};

bfs:https://www.nowcoder.com/questionTerminal/445c44d982d04483b04a54f298796288?f=discussion



class Solution {
public:
        vector > Print(TreeNode* pRoot) {
            vector > vec;
            if(pRoot == NULL) return vec;
 
            queue q;
            q.push(pRoot);
 
            while(!q.empty())
            {
                int lo = 0, hi = q.size();
                vector c;
                while(lo++ < hi)
                {
                    TreeNode *t = q.front();
                    q.pop();
                    c.push_back(t->val);
                    if(t->left) q.push(t->left);
                    if(t->right) q.push(t->right);
                }
                vec.push_back(c);
            }
            return vec;
        }
};

dfs:



public class Solution {
    ArrayList > Print(TreeNode pRoot) {
        ArrayList> list = new ArrayList<>();
        depth(pRoot, 1, list);
        return list;
    }
     
    private void depth(TreeNode root, int depth, ArrayList> list) {
        if(root == null) return;
        if(depth > list.size())
            list.add(new ArrayList());
        list.get(depth -1).add(root.val);
         
        depth(root.left, depth + 1, list);
        depth(root.right, depth + 1, list);
    }
}

序列化二叉树 -trick

请实现两个函数,分别用来序列化和反序列化二叉树

链接:https://www.nowcoder.com/questionTerminal/cf7e25aa97c04cc1a68c8f040e71fb84?f=discussion
来源:牛客网
 

/*

 1. 对于序列化:使用前序遍历,递归的将二叉树的值转化为字符,并且在每次二叉树的结点

不为空时,在转化val所得的字符之后添加一个' , '作为分割。对于空节点则以 '#' 代替。

 2. 对于反序列化:按照前序顺序,递归的使用字符串中的字符创建一个二叉树(特别注意:

在递归时,递归函数的参数一定要是char ** ,这样才能保证每次递归后指向字符串的指针会

随着递归的进行而移动!!!)

*/

#include
#include
#include
#include
#include
using namespace std;


struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};

class Solution {
public:

	void serialize(TreeNode * root, string &res) {
		if (root == NULL) {
			res += "#,";
			return;
		}
		
		res += to_string(root->val);
		res += ",";
		serialize(root->left, res);
		serialize(root->right, res);
	}
	char* Serialize(TreeNode *root) {
		string res;
		serialize(root, res);
		int n = res.size();
		char *a = new char[res.length()];
		for (int i = 0; i < res.size()-1; i++)
		{
			a[i] = res[i];
		}
		a[n - 1] = '\0';
		return a;
	}
	TreeNode* deserialize(string &s) {
		int i = 0;
		string cur;
		TreeNode* root = NULL;
		while (ileft = deserialize(s);
				root->right = deserialize(s);
			}
			else {
				root->left = NULL;
				root->right = NULL;
			}
			
		}
		return root;
	}
	TreeNode* Deserialize(char *str) {
		string s = str;
		return deserialize(s);
	}
};

int main() {

	Solution sol;
	sol.Deserialize("3,1,#,5,#,#,2,#,#");
}

 

你可能感兴趣的:(OJ)