1. 二叉树的锯齿形层次遍历
给出一棵二叉树,返回其节点值的锯齿形层次遍历(先从左往右,下一层再从右往左,层与层之间交替进行)
样例
样例 1:
输入:{1,2,3}
输出:[[1],[3,2]]
解释:
1
/ \
2 3
它将被序列化为 {1,2,3}
样例 2:
输入:{3,9,20,#,#,15,7}
输出:[[3],[20,9],[15,7]]
解释:
3
/ \
9 20
/ \
15 7
它将被序列化为 {3,9,20,#,#,15,7}
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: A Tree
* @return: A list of lists of integer include the zigzag level order traversal of
its nodes' values.
*/
deque<TreeNode*> d;//
vector<vector<int>> zigzagLevelOrder(TreeNode * root) {
// write your code here
vector<vector<int>> res;
if(root == NULL)
return res;
d.push_back(root);
int index = 0;
while(!d.empty())
{
int t = d.size();
vector<int> vt;
if(index%2 == 0)
{
for (int i = 0; i < t; i++)
{
/* code */
TreeNode * oushu = d.front();
vt.push_back(oushu->val);
d.pop_front();
if(oushu->left)
d.push_back(oushu->left);
if(oushu->right)
d.push_back(oushu->right);
}
}
else
{
for (int i = 0; i < t; i++)
{
/* code */
TreeNode * jishu = d.back();
vt.push_back(jishu->val);
d.pop_back();
if(jishu->right)
d.push_front(jishu->right);
if(jishu->left)
d.push_front(jishu->left);
}
}
index++;
res.push_back(vt);
}
return res;
}
};
前序遍历
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
vector<int> res;
/**
* @param root: A Tree
* @return: Preorder in ArrayList which contains node values.
*/
vector<int> preorderTraversal(TreeNode * root) {
// write your code here
//Preorder(root);
PreorderNoCur(root);
return res;
}
//非递归遍历
void PreorderNoCur(TreeNode *root)
{
if(!root)
return ;
std::stack<TreeNode*> s ;
s.push(root);
while(!s.empty())
{
TreeNode *t = s.top();
s.pop();
res.push_back(t->val);
if(t->right)
s.push(t->right);
if(t->left)
s.push(t->left);
}
}
} ;
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
vector<int> res;
/**
* @param root: A Tree
* @return: Inorder in ArrayList which contains node values.
*/
vector<int> inorderTraversal(TreeNode * root) {
// write your code here
InorderNocur(root);
return res;
}
void Inorder(TreeNode *root)
{
if(root)
{
Inorder(root->left);
res.push_back(root->val);
Inorder(root->right);
}
}
//非递归遍历
void InorderNocur(TreeNode *root)
{
std::stack<TreeNode*> stk ;
if(root)
{
TreeNode *head = root;
while(!stk.empty() ||head)
{
while(head)//一直往左边走
{
stk.push(head);
head = head->left;
}
if(!stk.empty())
{
head = stk.top();
res.push_back(head->val);
stk.pop();
head = head->right;
}
}
}
}
};
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
vector<int> res;
/**
* @param root: A Tree
* @return: Postorder in ArrayList which contains node values.
*/
vector<int> postorderTraversal(TreeNode * root) {
// write your code here
//二叉树的遍历 非递归遍历
if(!root)
return res;
std::stack<TreeNode *> stk;
TreeNode *head = root, *pLast = NULL;
while(head)
{
stk.push(head);
head = head->left;
}//一直朝着左边走
while(!stk.empty())
{
TreeNode *r = stk.top();
stk.pop();
if(r->right == NULL || r->right == pLast)//标记是否被访问过
{
//因为两次经过同一个节点,需要标记是否被访问
res.push_back(r->val);
pLast = r;
}//记录最近访问的节点
else
{
stk.push(r);
r = r->right;
while(r)
{
stk.push(r);
r = r->left;
}
}
}
return res;
}
};
设计一个算法,并编写代码来序列化和反序列化二叉树。将树写入一个文件被称为“序列化”,读取文件后重建同
样的二叉树被称为“反序列化”。
如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列化为一个字符串,并且可以将字符
串反序列化为原来的树结构。
样例
样例 1:
输入:{3,9,20,#,#,15,7}
输出:{3,9,20,#,#,15,7}
解释:
二叉树 {3,9,20,#,#,15,7},表示如下的树结构:
3
/ \
9 20
/ \
15 7
它将被序列化为 {3,9,20,#,#,15,7}
样例 2:
输入:{1,2,3}
输出:{1,2,3}
解释:
二叉树 {1,2,3},表示如下的树结构:
1
/ \
2 3
它将被序列化为 {1,2,3}
我们的数据是进行 BFS 遍历得到的。当你测试结果 Wrong Answer 时,你可以作为输入调试你的代码。
你可以采用其他的方法进行序列化和反序列化。
注意事项
对二进制树进行反序列化或序列化的方式没有限制,LintCode 将您的 serialize 输出作为 deserialize 的
输入,它不会检查序列化的结果。
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* This method will be invoked first, you should design your own algorithm
* to serialize a binary tree which denote by a root node to a string which
* can be easily deserialized by your own "deserialize" method later.
*/
//按照满二叉树的特征遍历二叉树
string serialize(TreeNode * root) {
// write your code here
preOrderA(root);
return toString();
}
std::vector<string>res;
//std::stack<TreeNode*> stk;
void preOrderA(TreeNode* root)
{
if(root == NULL)
{
res.push_back("#");
return;
}
else
{
res.push_back(to_string(root->val));
preOrderA(root->left);
preOrderA(root->right);
}
}
TreeNode * preOrderB(vector<string> arr, int &i)
{
if(arr[i] == "#")
{
i++;//这个非常重要
return NULL;
}
else
{
TreeNode * root = new TreeNode(stoi(arr[i]));
i++;//注意这里每次遍历都会导致数组下标的变化
root->left = preOrderB(arr, i);
root->right = preOrderB(arr, i);
return root;
}
}
string toString()
{
string str = "";
for (int i = 0; i < res.size(); i++) {
/* code */
str += res[i] +"?";
}//最后一个位置多一个问号?
return str;
}
/**
* This method will be invoked second, the argument data is what exactly
* you serialized at method "serialize", that means the data is not given by
* system, it's given by your own serialize method. So the format of data is
* designed by yourself, and deserialize it here as you serialize it in
* "serialize" method.
*/
TreeNode * deserialize(string &data)
{
// write your code here
vector<string> ret = splitString(data);
int i = 0;
return preOrderB(ret,i);
}
vector<string> splitString(string &data)
{
vector<string> ret;
string :: size_type pos1 = 0, pos2 = 0;
while(data.find("?",pos1) != string::npos)
{
pos2 = data.find("?", pos1);
ret.push_back((data.substr(pos1, pos2 - pos1)));
pos1 = pos2 + 1;
}
if(pos1 != data.size())
{
ret.push_back((data.substr(pos1)));
}
return ret;
}
};
在二叉树中找到一个节点的后继节点
【题目】 现在有一种新的二叉树节点类型如下:
public class Node { public int value; public Node left; public Node right; public Node parent;
public Node(int data) { this.value = data; }
}
该结构比普通二叉树节点结构多了一个指向父节点的parent指针。假 设有一 棵Node类型的节点组成的二叉树,
树中每个节点的parent指针 都正确地指向 自己的父节点,头节点的parent指向null。只给一个在 二叉树中的
某个节点 node,请实现返回node的后继节点的函数。在二 叉树的中序遍历的序列中, node的下一个节点叫作
node的后继节点。
class Solution
{
public:
TreeNode *res = NULL;
TreeNode * findSuccessor(TreeNode *p)
{
if (p == NULL)
return res;
TreeNode *q = p;
if(q->right)
{
q = q->right;
while (q->left)
{
q = q->left;
}
res = q;
return res;
}
else
{
proccess( p);
}
return res;
}
void proccess(TreeNode *p)
{
TreeNode *q = p;
TreeNode *parent = q->parent;
while (parent!= NULL && parent->left != q)
{
q = q->parent;
parent = q->parent;
}
res = parent;
}
};
二叉搜索树的后继节点
class Solution{
public:
/*
* @param root: The root of the BST.
* @param p: You need find the successor node of p.
* @return: Successor of p.
*/
TreeNode * inorderSuccessor(TreeNode * root, TreeNode * p) {
// write your code here
if(p == NULL)
return NULL;
inorder(root);
int index = 0;
int aim = p->val;
for (int i = 0; i <res.size(); i++)
{
/* code */
if(aim == res[i]->val)
{
index = i+1;
// cout << index <<endl;
break;
}
}
if (index == res.size()) {
return NULL;
}
else
return res[index];
}
std::vector<TreeNode*> res ;
void inorder(TreeNode *root)
{
if(root == NULL)
return;
inorder(root->left);
res.push_back(root);
inorder(root->right);
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution{
public:
/*
* @param root: The root of the BST.
* @param p: You need find the successor node of p.
* @return: Successor of p.
*/
TreeNode *res = NULL;
TreeNode * inorderSuccessor(TreeNode * root, TreeNode * p) {
// write your code here
if(p == NULL)
return NULL;
find(root, p);
return res;
}
void find(TreeNode *root,TreeNode *p)
{
if(p->right)//要在子节点中寻找
{
TreeNode * pp = p->right;
while(pp->left)
{
pp = pp->left;
}
res = pp;
return;
}
else
{//要在父节点中寻找
proccess(root, p);
}
}
void proccess(TreeNode * root, TreeNode *p)
{
if(root == NULL)
{
return ;
}
if(root->val > p->val)//遍历左子树
{
res = root;//找到离p节点最近的比p的val值大的节点
proccess(root->left, p);
}
else if(root->val < p->val)
{
proccess(root->right, p);
}
else
{
return ;
}
}
};
折纸问题
题目
请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折
痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上
到下依次是下折痕,下折痕和上折痕。给定一个输入参数N,代表纸条都从下边向上方连续对折N次,请从上到下打
印所有折痕的方向。例如 :
N = 1时,打印 : down
N = 2时,打印 : down down up
解析
可以用一张纸条自己折一下,会发现:
第一次折的时候,只有一条折痕,往里凸的,记为1down。
第二次折的时候,发现1down的上方为往里凸,记为2down,而下方为往外凸,记为2up。
第三次折的时候,发现2dowm的上方往里凸,记为3down,2down的下方往外凸,记为3up; 而2up的上方往里凸,
记为3down,2up的下方往外凸,记为3up;
从上面折痕可以发现新的折痕的上面总是为down,下面总是为up,所以我们可以构造出一颗二叉树,具体看下图
所以当前结点左子树总是down(true),右子树为up(false),所以我们只要按照中序遍历这颗二叉树就解决问题
了。
class PaperFloding {//相当于中序遍历
public:
//打印的所有折痕方向的函数
void printAllFolds(int N){
printProcess(1,N,true);// 根节点的是down(第一次折的时候是往下的(往里凸))
}
void printProcess(int i, int N, bool down) {
if(i > N){ //终止条件(相当于结点为null)
return;
}
printProcess(i+1, N, true);// 相当于往左子树跑(因为左子树永远是down(下))
string s = down? "down " :"up ";
cout << s;
printProcess(i+1, N, false); //往右子树跑
}
void mains() {
int N = 4;
printAllFolds(N);
}
};