方法一
- 将右子树接到左子树的最右节点
- 左子树接到原右子树的位置
- 原左子树的位置变为nil
- 解决新右子树根节点
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
var pre *TreeNode
func flatten(root *TreeNode) {
pre = nil
dfs(root)
}
func dfs(root *TreeNode){
if root == nil {
return
}
dfs(root.Right)
dfs(root.Left)
root.Right = pre
root.Left = nil
pre = root
}
方法二
题目其实就是将二叉树通过右指针,组成一个链表。
我们知道题目给定的遍历顺序其实就是先序遍历的顺序,所以我们能不能利用先序遍历的代码,每遍历一个节点,就将上一个节点的右指针更新为当前节点。先序遍历的顺序是 1 2 3 4 5 6。
遍历到 2,把 1 的右指针指向 2。1 -> 2 3 4 5 6。
遍历到 3,把 2 的右指针指向 3。1 -> 2 -> 3 4 5 6。
... ...
一直进行下去似乎就解决了这个问题。但现实是残酷的,原因就是我们把 1 的右指针指向 2,那么 1 的原本的右孩子就丢失了,也就是 5 就找不到了。
解决方法的话,我们可以逆过来进行。
我们依次遍历 6 5 4 3 2 1,然后每遍历一个节点就将当前节点的右指针更新为上一个节点。
遍历到 5,把 5 的右指针指向 6。6 <- 5 4 3 2 1。
遍历到 4,把 4 的右指针指向 5。6 <- 5 <- 4 3 2 1。
... ...
遍历方法 :
- 处理当前右节点
- 处理当前左节点
- 处理当前节点(记录当前节点)
var pre *TreeNode
func flatten(root *TreeNode) {
pre = nil
dfs(root)
}
func dfs(root *TreeNode){
if root == nil {
return
}
dfs(root.Right)
dfs(root.Left)
root.Right = pre
root.Left = nil
pre = root
}
便利方法:
如果直接使用前序遍历,必须记录返回值,当前的左子树有右节点返回右节点,没有则返回左节点,都没有则返回自身。
func flatten(root *TreeNode) {
if root == nil{
return
}
dfs(root)
return
}
func dfs (root *TreeNode) *TreeNode {
var x,y *TreeNode
if root.Left == nil && root.Right == nil {
return root
}
if root.Left != nil && root.Right != nil{
x = dfs(root.Left)
y = dfs(root.Right)
x.Right = root.Right
root.Right = root.Left
root.Left = nil
}
if root.Left == nil{
y = dfs(root.Right)
}
if root.Right == nil{
y = dfs(root.Left)
root.Right = root.Left
root.Left = nil
}
return y
}