【问题标题】:Flattening a Binary Tree to a Linked List将二叉树展平为链表
【发布时间】:2017-12-12 23:14:36
【问题描述】:

您好,我目前正在尝试解决这个问题(很遗憾,没有解决方案):

http://blog.gainlo.co/index.php/2016/06/12/flatten-a-linked-list/

基本上,您希望将具有 next 指针和 down 指针指向单链表的链表展平。

以下是我想出的,如果有任何错误或发现任何会破坏这一点的边缘情况,请纠正我。

static class Node {
    Node next;
    Node down;
    int val;
    Node(int val) {
        this.val = val;
    }
}

static Node flattenLinkedList(Node head) {
    Queue<Node> q = new LinkedList<>();
    q.add(head);
    Node dummyhead = new Node(0);
    Node pre = dummyhead;
    while (!q.isEmpty()) {
        Node current = q.poll();
        while (current != null) {
            pre.next = new Node(current.val);
            pre = pre.next;
            if (current.down != null) {
                q.add(current.down);
            }
            current = current.next;
        }
    }
    return dummyhead.next;
}

public static void main(String[] args) {
    Node start = new Node(1);
    start.next = new Node(2);
    start.next.next = new Node(3);
    start.next.next.next = new Node(4);
    start.next.down = new Node(5);
    start.next.down.down = new Node(8);
    start.next.down.next = new Node(6);
    start.next.next.next.down = new Node(7);

    Node sol = flattenLinkedList(start);
}

P.S 我这样做是为了练习面试,而不是为了家庭作业。

【问题讨论】:

  • 你自己写过单元测试吗?
  • @cricket_007,是的,认为它适用于网站上的示例,但想确定它是否普遍正确。
  • 认为它有效是什么意思?您是如何验证的?
  • 你能展示你当前的单元测试吗?
  • “一个有下一个指针和下指针的链表”——这不是叫二叉树吗?

标签: java algorithm linked-list binary-tree


【解决方案1】:
public static Node flatten(Node n) {
    if (n==null) return n;

    Node p = n;

    while (p!=null) {
        if (p.down != null)  {
            Node pn = p.next;
            p.next = flatten(p.down);
            while (p.next!=null) {
                p = p.next;
            }
            p.next = pn;
        }
        p = p.next;
    }

    return n;
}

【讨论】:

    【解决方案2】:

    如果我理解您的方法正确,您的函数将逐层展平树。考虑以下结构

    1 --- 2 --- 3 ---------------- 4
          |     |
          21    31 --- 32 --- 33 
          |             |
          221          332
                       3332 - 3333
    

    您的函数将返回 1 2 3 4 21 31 32 33 221 332 3332 3333

    关于缺点 - 我会注意到在循环中创建新节点并保留 dummyhead。您可以将功能简化为

    static void flatten(Node n) {
        Queue<Node> q = new LinkedList<>();
        while (n != null) {
            if (n.down != null) {
                q.add(n.down);
            }
            if (n.next == null) {
                n.next = q.poll();
            }
            n = n.next;
        }
    }
    

    我还建议查看深度优先方法,它将上面的结构扁平化为1 2 21 221 3 31 32 332 3332 3333 33 4

    static void flatten(Node node) {
        Stack<Node> stack = new Stack<>();
        while (node != null) {
            if (node.down != null) {
                if (node.next != null) {
                    stack.push(node.next);
                }
                node.next = node.down;
            } else if (node.next == null && !stack.empty()) {
                node.next = stack.pop();
            }
            node = node.next;
        }
    }
    

    【讨论】:

      【解决方案3】:

      共享 O(n) 解决方案。这个想法很简单。

      • 从当前节点的左边获取最右边的指针, 并将它的右指针指向父母的右边。
      • 然后设置当前节点的左为右指针。

      解决方案(参考内联cmets):

      /**
       * Definition for a binary tree node.
       * public class TreeNode {
       *     int val;
       *     TreeNode left;
       *     TreeNode right;
       *     TreeNode() {}
       *     TreeNode(int val) { this.val = val; }
       *     TreeNode(int val, TreeNode left, TreeNode right) {
       *         this.val = val;
       *         this.left = left;
       *         this.right = right;
       *     }
       * }
       */
      class Solution {
          public void flatten(TreeNode root) {
              if (root == null) {
                  return;
              }
              TreeNode newr = new TreeNode(-1);
              newr = root;
              dfs(root);
              root = newr;
          }
          
          TreeNode dfs(TreeNode node) {
              
              TreeNode left = null;
              if(node.left != null) {
                 left = dfs(node.left);
              }
              
              TreeNode right = null;
              if(node.right != null) {
                 right = dfs(node.right);
              }
               
              // Before this, refer to the comment in the return line
              if (left != null) {
                  // Point the right pointer of the right most node, of the left
                  // side of the parent, to the parent's right node.
                  left.right = node.right;
                  node.right = node.left;
              }
      
              // Do remember to clear the left node of the current node.
              node.left = null;
              
              // Try to return the rightmost node, so that when we 
              // reach the parent, and the if the "right" node returned here
              // happens to be at the left side of the parent, then we  can point 
              // it's right pointer to the parent's right node.
      
              return right != null ? right : left != null ? left : node; 
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-08
        • 1970-01-01
        • 2015-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-14
        相关资源
        最近更新 更多