题目描述:
Given a binary tree, flatten it to a linked list in-place.
For example,
Given
1 / \ 2 5 / \ \ 3 4 6
The flattened tree should look like:
1 \ 2 \ 3 \ 4 \ 5 \ 6
If you notice carefully in the flattened tree, each node's right child points to the next node of a pre-order traversal.
对于这样的题目,二叉树与链表之间的关系是很微妙的,遇到了很多的关于二叉树转换为链表的方式,那么就对上面的这个题做一些简单的介绍。
Trail 1 : 根据Hint可以知道,只要我们弄清楚了先序遍历时各个节点的访问顺序,将其保存为一个队列,在先序遍历完成之后,直接使用这些节点的right指针将它们串联起来即可。
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void flatten(TreeNode *root) {
if(root == NULL)return;
TreeNode *temp = root;
stack<TreeNode *> myStack;
queue<TreeNode *> myQueue;
while(temp || (!(myStack.empty())))
{
while(temp)
{
myQueue.push(temp);
myStack.push(temp);
temp = temp->left;
}
temp = myStack.top();
myStack.pop();
temp = temp->right;
}
TreeNode *temp2 = NULL;
while(!myQueue.empty())
{
temp = myQueue.front();
myQueue.pop();
if(!myQueue.empty())
temp2 = myQueue.front();
temp->right = temp2;
//temp = temp2;
}
}
};
出现超时错误,虽然我老是觉得它的时间复杂度并没有很高,可是在很小的例子上也会超时。
Trail 2 :涉及到树的问题,很多时候我们会想到递归,刚刚拿到题我想到的也是递归,可是代码老是调不对,我就使用了上面的Trial 1, 结果超时了,因此还是转战到了递归的方式。
首先,root指向左子树flatten之后的链表,然后再链接到右子树flatten之后的链表,由于左右子树也还是二叉树,因此只需要对左右子树分别递归调用即可。
class Solution {
public:
void flatten(TreeNode *root) {
if(root == NULL)return;
TreeNode *tempL = NULL, *tempR = NULL;
tempL = root->left;
tempR = root->right;
root->left = NULL;
flatten(tempL);
root->right = tempL;
TreeNode *pre = root;
while(tempL)
{
pre = tempL;
tempL = tempL->right;
}
flatten(tempR);
if(pre) pre->right = tempR;
}
};
上述关键部分是在找到root节点连接到左子树之后的最终的节点的位置。
总结:递归依旧是我的一个弱点,思想很明白,可是代码对于我来说却是很难的。