「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战」。
题目
链接:leetcode-cn.com/problems/fl…
给你二叉树的根结点 root ,请你将它展开为一个单链表:
- 展开后的单链表应该同样使用
TreeNode,其中right子指针指向链表中下一个结点,而左子指针始终为null。 - 展开后的单链表应该与二叉树 先序遍历 顺序相同。
示例 1:
**输入:**root = [1,2,5,3,4,null,6] 输出:[1,null,2,null,3,null,4,null,5,null,6]
示例 2:
**输入:**root = [] 输出:[]
示例 3:
**输入:**root = [0] 输出:[0]
提示:
- 树中结点数在范围
[0, 2000]内 -100 <= Node.val <= 100
**进阶:**你可以使用原地算法(O(1) 额外空间)展开这棵树吗?
思路
利用递归的思想。假设递归函数treeToList能将节点p转换为单链表,那就再次利用treeToList将p的左子树、右子树都转换成单链表,再让p的右指针指向其左子树单链表,左子树单链表的右指针指向右子树单链表。因此,我们需要知道左子树最后一个元素,因此就引入了last变量,在递归函数treeToList需要时刻“维护”last。又因为在递归函数中会改变指针指向,因此需要使用left,right变量保留当前节点p的左右指针。
我犯的一个错误: 当我将leftLast,和rightLast当做指针传入进treeToList时,最后得到的值都为null。这是因为在js中,实参与形参存储的都是指向同一的地址,在函数内部只该变量形参的指向地址,实参的指向地址没有变化。所以这里需要通过函数的返回值来获取它们。
代码
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {void} Do not return anything, modify root in-place instead.
*/
var flatten = function(root) {
treeToList(root)
return;
function treeToList(p){
if(!p){
return;
}
// 值得注意的是,当我将leftLast,和rightLast当做指针传入进treeToList时,最后得到的值为null。
// 这是因为在js中,实参与形参存储的都是指向同一的地址,在函数内部只该变量形参的指向地址,实参的指向地址没有变化。
// 所以这里通过函数的返回值来获取它们。
let leftLast = null, rightLast = null;
let left = p.left, right = p.right;
if(left==null && right==null){
last = p;
}
if(left){
leftLast = treeToList(left);
p.right = left;
p.left = null;
last = leftLast;
}
if(right){
rightLast = treeToList(right);
last = rightLast;
// 如果节点p只有右子树,没有左子树,就不用改变任何结构,它本身就满足题上要求。
if(leftLast){
leftLast.right = right;
leftLast.left = null;
}
}
return last;
}
};