5/10, Tree,修改结构


Flatten Binary Tree to Linked List

很符合递归思想的写法,美中不足是每次都要把左子树遍历一遍好去找尾端节点,如果整个树左子树体积非常大而右子树很小的话,时间复杂度会很高。最差的情况是,整个树是一个只有左边的链表,时间复杂度可以达到 O(n^2),而且用递归还要花费栈空间。

public class Solution {
    public void flatten(TreeNode root) {
        if(root == null) return;

        flatten(root.left);
        flatten(root.right);

        TreeNode left = root.left;
        TreeNode right = root.right;

        root.left = null;
        root.right = left;
        while(root.right != null){
            root = root.right;
        }
        root.right = right;
    }
}

于是这题有特别赞的O(n)时间O(1)空间写法,还是利用 Morris 遍历。

Morris 遍历的特点是寻找左子树中能沿着右边走最长的节点,并且利用这个节点做文章;这题是把 right 指针直接指向 root 的右节点了,相当于每次缩进去【root.left -> 左子树最长向右路径】这段到右子树上,如此反复。因此省去了最坏情况下重复遍历寻找链表尾的过程。

public class Solution {
    public void flatten(TreeNode root) {
        TreeNode cur = root;
        while(cur != null){
            if(cur.left == null){
                cur = cur.right;
            } else {
                TreeNode prev = cur.left;
                while(prev.right != null){
                    prev = prev.right;
                }
                prev.right = cur.right;
                cur.right = cur.left;
                cur.left = null;
            }
        }
    }
}

Reverse LinkedList

链表经典水题,把它放在这是因为它和下一题真的很像,只是维度上更单一而已。

public class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        while(head != null){
            ListNode temp = head.next;
            head.next = prev;
            prev = head;
            head = temp;
        }
        return prev;
    }
}

Binary Tree Upside Down

这题与其说是 Tree 类题目,不如说更像 LinkedList... 因为有很多的存 temp 和改动 reference ptr 的过程,尤其是迭代版,活脱一个反转列表。

  • 迭代版
public TreeNode upsideDownBinaryTree(TreeNode root) {
    TreeNode curr = root;
    TreeNode temp = null;
    TreeNode prev = null;

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

        prev = curr;
        curr = next;
    }
    return prev;
}
  • 递归版
public TreeNode upsideDownBinaryTree(TreeNode root) {
    if(root == null || root.left == null) {
        return root;
    }

    TreeNode newRoot = upsideDownBinaryTree(root.left);
    root.left.left = root.right;   // node 2 left children
    root.left.right = root;         // node 2 right children
    root.left = null;
    root.right = null;
    return newRoot;
}

(FB) BST to doubly linked-list

LC 论坛的讨论帖http://articles.leetcode.com/convert-binary-search-tree-bst-to/

递归

思路 :http://www.geeksforgeeks.org/convert-given-binary-tree-doubly-linked-list-set-3/

  • 完全就是 in - order 的递归结构,左-中-右

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

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

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

时间复杂度 O(n).

private static class TreeNode{
        int val;
        TreeNode left,right;
        public TreeNode(int val){
            this.val = val;
        }
    }

    static TreeNode prev;
    static TreeNode head;

    // In-order
    public static void convert(TreeNode root){
        if(root == null) return;

        convert(root.left);

        if(prev == null){
            head = root;
        } else {
            root.left = prev;
            prev.right = root;
        }
        prev = root;

        convert(root.right);

    }

    public static void main(String[] args){

        TreeNode node1 = new TreeNode(1);
        TreeNode node2 = new TreeNode(2);
        TreeNode node3 = new TreeNode(3);
        TreeNode node4 = new TreeNode(4);
        TreeNode node5 = new TreeNode(5);
        TreeNode node6 = new TreeNode(6);
        TreeNode node7 = new TreeNode(7);
        TreeNode node8 = new TreeNode(8);
        TreeNode node9 = new TreeNode(9);
        TreeNode node10 = new TreeNode(10);

        node2.left = node1;
        node2.right = node3;
        node4.left = node2;
        node4.right = node5;
        node6.left = node4;
        node6.right = node9;
        node9.left = node8;
        node8.left = node7;
        node9.right = node10;

        convert(node6);

        while(head != null){
            System.out.print(" " + head.val);
            head = head.right;
        }
    }

迭代(Stack)

  • In-order 跑一遍,每次 pop 出来的时候,我们就有 root 了;

  • 然后拼接的逻辑处理和递归的方法完全一样,这次连全局变量都不用,简单直接~

时间O(n),空间 O(log n)

  // In-order
    public static TreeNode convert(TreeNode root){
        if(root == null) return null;

        TreeNode prev = null;
        TreeNode head = null;

        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while(!stack.isEmpty() || cur != null){
            while(cur != null){
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode node = stack.pop();

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

            prev = node;
            cur = node.right;
        }
        return head;
    }

    public static void main(String[] args){

        TreeNode node1 = new TreeNode(1);
        TreeNode node2 = new TreeNode(2);
        TreeNode node3 = new TreeNode(3);
        TreeNode node4 = new TreeNode(4);
        TreeNode node5 = new TreeNode(5);
        TreeNode node6 = new TreeNode(6);
        TreeNode node7 = new TreeNode(7);
        TreeNode node8 = new TreeNode(8);
        TreeNode node9 = new TreeNode(9);
        TreeNode node10 = new TreeNode(10);

        node2.left = node1;
        node2.right = node3;
        node4.left = node2;
        node4.right = node5;
        node6.left = node4;
        node6.right = node9;
        node9.left = node8;
        node8.left = node7;
        node9.right = node10;

        TreeNode head = convert(node6);

        while(head != null){
            System.out.print(" " + head.val);
            head = head.right;
        }
    }

Convert DLL back to BST

http://algorithms.tutorialhorizon.com/convert-a-sorted-doubly-linked-list-to-balanced-bst/

核心在递归node两边, head节点总指向当前root节点

    static Node headc = firstnode;
    //convert double link list back to tree
    //http://algorithms.tutorialhorizon.com/convert-a-sorted-doubly-linked-list-to-balanced-bst/
    private static Node convertback(int size) {
        // TODO Auto-generated method stub
        if(size<=0)
            return null;
        Node left = convertback(size/2);
        Node root = headc;
        root.left = left;
        headc = headc.right;
        Node right = convertback(size-(size)/2-1);
        root.right = right;
        return root;
    }

Add One Row to Tree

d==1特殊处理,否则到d-2层,添加children,将原children设为孙子。

public TreeNode addOneRow(TreeNode root, int v, int d) {
        if (d == 1) {
            TreeNode newroot = new TreeNode(v);
            newroot.left = root;
            return newroot;
        }
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        for (int i = 0; i < d-2; i++) {
            int size = queue.size();
            for (int j = 0; j < size; j++) {
                TreeNode t = queue.poll();
                if (t.left != null) queue.add(t.left);
                if (t.right != null) queue.add(t.right);
            }
        }
        while (!queue.isEmpty()) {
            TreeNode t = queue.poll();
            TreeNode tmp = t.left;
            t.left = new TreeNode(v);
            t.left.left = tmp;
            tmp = t.right;
            t.right = new TreeNode(v);
            t.right.right = tmp;
        }
        return root;
    }
public TreeNode addOneRow(TreeNode root, int v, int d) {
        if (d < 2) {
            TreeNode newroot = new TreeNode(v);
            if (d == 0) newroot.right = root;
            else newroot.left = root;
            return newroot;
        }
        if (root == null) return null;
        root.left = addOneRow(root.left, v, d == 2 ? 1 : d-1);
        root.right = addOneRow(root.right, v, d == 2 ? 0 : d-1);
        return root;
    }

results matching ""

    No results matching ""