好久都没刷leetcode的啦!这个周末终于有属于自己的时间了,就来做一下题吧~
首先,我的思路是比较直接的,利用递归的思想,先修改当前结点的左子树,记录下当前结点的左子树的最右下结点,再修改当前结点的右子树,将最右下结点与当前结点的左结点链接起来就可以了。
具体代码:
TreeNode* leaf;
TreeNode *dfs(TreeNode* rt)
{
if(rt==NULL)
{
return rt;
}
else
{
leaf=rt;
TreeNode* left=dfs(rt->left);
leaf->right=rt->right;
TreeNode* right=dfs(rt->right);
if(left==NULL&&right==NULL)// is leaf
{
//cout<<"leaf is :"<<leaf->val<<endl;
return rt;
}
if(right==NULL)
{
rt->right=left;
rt->left=NULL;
}
else
{
if(rt->left)
{
rt->right=left;
rt->left=NULL;
}
}
return rt;
}
}
AC后,看下了运行时间并不理想,就到讨论区看了下,发现大神的思想还是需要我膜拜的~
大神的思想:采用了后序遍历树的方法,遍历当前结点的右子树,左子树,使当前结点的右子树链接上之前保存的pre。这样简洁的思路是需要我自己学习的~
具体代码:
private TreeNode prev = null;
public void flatten(TreeNode root) {
if (root == null)
return;
flatten(root.right);
flatten(root.left);
root.right = prev;
root.left = null;
prev = root;
}
在讨论区还看到了另一种方法,大致的思想跟我自己的思想差不多,是非递归的。将当前结点的左子树上的结点的最右下结点与当前结点的左孩子结点链接,然后将整个左子树移到右子树上。再取当前结点的右孩子结点,成为下一个被处理的结点。
具体代码:
class Solution {
public:
void flatten(TreeNode *root) {
TreeNode*now = root;
while (now)
{
if(now->left)
{
//Find current node's prenode that links to current node's right subtree
TreeNode* pre = now->left;
while(pre->right)
{
pre = pre->right;
}
pre->right = now->right;
//Use current node's left subtree to replace its right subtree(original right
//subtree is already linked by current node's prenode
now->right = now->left;
now->left = NULL;
}
now = now->right;
}
}
};