方法一,空间复杂度为O(n),但是可读性最高
按先根遍历把节点放在列表里,然后遍历列表,连接节点
class Solution {
List<TreeNode> nodes = new ArrayList<>();
public void flatten(TreeNode root) {
preorderTraversal(root);
for (int i = 1; i < nodes.size(); i++) {
TreeNode pre = nodes.get(i - 1), cur = nodes.get(i);
pre.right = cur;
pre.left = null;
}
}
private void preorderTraversal(TreeNode root) {
if (root != null) {
nodes.add(root);
preorderTraversal(root.left);
preorderTraversal(root.right);
}
}
}
方法二,三指针遍历拼接
如果把二叉树展开为链表的话,根据先根遍历,根->左->右,左子树应该拼接在根节点的右边,右子树应该拼接在左子树的最右节点的右边,如下图,2应该接在1的右边,5应该接在4的右边,如此遍历下去
所以需要三个指针(注意防止空指针发生)
curr: 指向根节点,负责迭代
next: curr的左指针,负责寻找左子树
predecessor: 寻找左子树的最右节点
public void flatten(TreeNode root) {
TreeNode curr = root;
TreeNode next = null;
TreeNode predecessor = null;
while (curr != null) {
if (curr.left != null) {
next = curr.left;
predecessor = next;
while (predecessor.right != null) {
predecessor = predecessor.right;
}
predecessor.right = curr.right;
curr.right = next;
curr.left = null;
}
curr = curr.right;
}
}