改变tree的结构

2016-12-10 Bobst

  • 维护一个prev node
  • 观察以什么order来traversal

Flatten Binary Tree to Linked List

         1
        / \
       2   5
      / \   \
     3   4   6


       1
        \
         2
          \
           3
            \
             4
              \
               5
                \
                 6

这题的本质是什么?

pre-order + 维护prev节点

public void flatten(TreeNode root) {
    List<TreeNode> prev = new ArrayList<>();
    prev.add(null);
    dfs(root, prev);
}

public void dfs(TreeNode root, List<TreeNode> prev) {
    if(root == null) {
        return;
    }

    // pre-order
    if(prev.get(0) != null) {
        prev.get(0).left = null;
        prev.get(0).right = root;
    }

    prev.set(0, root);

    TreeNode right = root.right;
    // 因为改变的是前置节点的右孩子
    dfs(root.left, prev);
    dfs(right, prev);
}

Binary Tree Upside Down

        1
       / \
      2   3
     / \
    4   5
        ||
        \/
       4
      / \
     5   2
        / \
       3   1

其实就是把一个节点的左孩子变成变成父节点,右孩子变成左孩子的左孩子。

是一个类似于in-order

递归版做法:

public TreeNode upsideDownBinaryTree(TreeNode root) {
    // 从最左节点的父节点开始处理
    if(root == null || root.left == null) {
        return root;
    }

    // cache了往左那条path上的所有节点
    TreeNode newRoot = upsideDownBinaryTree(root.left);

    root.left.left = root.right;
    root.left.right = root;
    root.left = null;
    root.right = null;

    return newRoot;
}

迭代:

顺着最左边的一条path 走下去就可以了

public TreeNode upsideDownBinaryTree(TreeNode root) {
    TreeNode curr = root;
    TreeNode prev = null, temp = null;

    while(curr != null) {
        TreeNode next = curr.left;
        curr.left = temp;
        temp = curr.right;
        curr.right = prev;

        prev = curr;
        curr = next;
    }

    return prev;
}

BST to doubly linked list (FB)

in - order 的递归结构,左-中-右

核心在于 “中” 这步上,如何正确做好 “拼接” 工作

我们需要存一个全局变量 prev 用于保存 "左子树的最后一个节点",在每步上,和 root 做双向拼接; prev 初始化为 null;

额外用于遍历 LinkedList 还需要存下 head ; 在 prev 为 null 的时候 root 就代表着最左面的节点,设一下就好,之后就不用管了。

时间复杂度O(n)

static TreeNode prev = null;
static TreeNode head;

public static void convert(TreeNode root) {
    if(root == null) return;

    // in-order
    convert(root.left);

    // reach the most-left node
    if(prev == null) {
        head = root;
    } else {
        root.left = prev;
        prev.right = root;
    }

    prev = root;

    convert(root.right);
}

迭代的做法

因为是in-order, 所以用stack来做,其他基本和递归是一样的,用prev node和当前的节点进行拼接,然后更新prev node

public TreeNode convert(TreeNode root) {
    if(root == null) {
        return null;
    }

    LinkedList<TreeNode> stack = new LinkedList<>();
    TreeNode prev = null, head = null;

    TreeNode cur = root;

    while(!stack.isEmpty() || cur != null) {
        while(cur.left != null) {
            stack.push(cur.left);
            cur = cur.left;
        }

        TreeNode node = stack.pop();

        if(prev == null) {
            head = node;
        } else {
            node.prev = prev;
            prev.next = node;
        }

        prev = node;
        if(node.right != null) {
            cur = node.right;
        }
    }

    return head;
}

results matching ""

    No results matching ""