时间复杂度:O(n),空间复杂度:O(1)
解题思路
仿照官方题解寻找前驱结点的思路。
可以简单理解为三部曲:
- 找到根结点的右孩子的前驱结点。由于是先序遍历,右孩子的前驱结点就是根结点左孩子的最右结点。所以我们要先判断根结点是否有左孩子,如果有那么就找到左孩子的最右结点(特殊情况是其自身)
- 令刚刚找到的前驱结点的右孩子为根结点的右孩子。
- 根结点左右孩子交换,左孩子置空
AC代码
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func flatten(root *TreeNode) {
p:=root
for p!=nil{
if p.Left!=nil{
pre:=p.Left//右节点的先驱节点
for pre.Right!=nil{
pre=pre.Right
}
pre.Right=p.Right
p.Right=p.Left//根节点的左右节点交换
p.Left=nil//根节点的左结点置空
}
p=p.Right
}
}
感悟
只能想到先序遍历建树的方法,但是空间复杂度为O(n)。看了题解才反应过来原来可以通过找前驱结点的方法原地修改树,这也在提醒我要学会用逆向思维解题。