题目:给你二叉树的根结点 root
,请你将它展开为一个单链表:
展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。
根据题目,需要把整个二叉树所有的节点按照前序遍历的方式,全部转为该二叉树的右节点。
前序遍历的顺序是根节点-左节点-右节点。从示例的图中可以看出,要完成二叉树的转变,思路如下:
1、先要把这个大二叉树的左子树(2、3、4)的最右子节点(4)接到左子节点(3)的下面,然后再把(3,4)作为2的右子节点。
2、把这个大二叉树的右子树(5,6)做同样操作,但因为这个右子树本来就符合变化后的要求,所以不需要调整
3、把右子树(5,6)作为左子树(2,3,4)最下层节点(4)的右子树,再把变化后的左子树+右子树(2,3,4,5,6)作为根节点(1)的右子树。
从以上三步可以总结出规律:我们需要一层一层递归输入二叉树的左子树和右子树,先让左右子树都转化为链表格式,再让右子树作为左子树最下层节点的右子树,最后将转化后的左子树+右子树作为输入二叉树根节点的右子树。
代码实现:
1、首先定义递归停止条件,如果输入的二叉树为空,直接返回自身。
public TreeNode114 flatten(TreeNode114 root) {
if (root == null) {
return root;
}
if (root.left == null && root.right == null) {
return root;
}
}
2、获取二叉树的左子树和右子树,因为需要逐层转化直到最底层,所以以递归形式获取左右子树
public TreeNode114 flatten(TreeNode114 root) {
if (root == null) {
return root;
}
if (root.left == null && root.right == null) {
return root;
}
TreeNode114 left = flatten(root.left);
TreeNode114 right = flatten(root.right);
}
3、在获取到最底层后,我们会return最底层的节点(在1中已经定义),然后返回上一层递归
在上一层递归中,让节点原来的右子树作为它原来左子树的右子树形成新的左子树,然后将新的左子树作为该节点的右子树,再把该节点的左子树移除。
public TreeNode114 flatten(TreeNode114 root) {
if (root == null) {
return root;
}
if (root.left == null && root.right == null) {
return root;
}
TreeNode114 left = flatten(root.left);
TreeNode114 right = flatten(root.right);
if (left != null) {
left.right = root.right;
root.right = root.left;
root.left = null;
}
//
}
4、在把右子树(是还没有递归的右子树root.right而不是flatten(root.right))接过来(就是要实现left.right = root.right这一步)前,这个left必须是返回递归转换后的左子树最最下方的节点,才能让递归转换后的右子树接上。
所以不管递归多少层后,最终都要返回最下层节点,然后退回上一层递归,才能把上一层的右子树接过去。所以在最下方加上调用自身到最后会return的值后完整代码如下:
public TreeNode114 flatten(TreeNode114 root) {
if (root == null) {
return root;
}
if (root.left == null && root.right == null) {
return root;
}
TreeNode114 left = flatten(root.left);
TreeNode114 right = flatten(root.right);
if (left != null) {
left.right = root.right;
root.right = root.left;
root.left = null;
}
// System.out.println(right.toString());
return right != null ? right : left;
}