解法一:基于分解子问题思维模式的递归
flatten 函数的定义如下:
给 flatten 函数输入一个节点 root,那么以 root 为根的二叉树就会被拉平为一条链表。
如何利用这个定义来完成算法?你想想怎么把以 root 为根的二叉树拉平为一条链表?
很简单,流程如下:
- 将
root的左子树和右子树拉平。 - 将拉平后的左子树接到
root的下方, 然后将拉平后的右子树接到现在右子树的下方。
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func flatten(root *TreeNode) {
if root == nil{
return
}
// 先展开左右子树
flatten(root.Left)
flatten(root.Right)
flatLeft := root.Left
flatRight := root.Right
// 将拉平后的左子树接到当前节点的右边
root.Left = nil
root.Right = flatLeft
// 将原先的右子树接到当前右子树(即拉平后的原左子树)的后面
p := root
for p.Right != nil{
p = p.Right
}
p.Right = flatRight
}
解法二:基于遍历思维模式的递归(dfs, 链表头插法)
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func flatten(root *TreeNode) {
var head *TreeNode
traverse(root, &head)
}
func traverse(root *TreeNode, head **TreeNode){
if root == nil{
return
}
traverse(root.Right, head)
traverse(root.Left, head)
root.Left = nil
root.Right = *head
*head = root
}
也可以写成函数包函数
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func flatten(root *TreeNode) {
var head *TreeNode
var dfs func(*TreeNode)
dfs = func(node *TreeNode) {
if node == nil {
return
}
dfs(node.Right)
dfs(node.Left)
node.Left = nil
node.Right = head // 头插法,相当于链表的 node.Next = head
head = node // 现在链表头节点是 node
}
dfs(root)
}