Java 将二叉树展平为链表

Java 将二叉树展平为链表,java,algorithm,linked-list,binary-tree,Java,Algorithm,Linked List,Binary Tree,您好,我目前正在尝试解决此问题(不幸的是,没有解决方案): 基本上,您希望展平具有指向单个链接列表的next指针和down指针的链接列表 下面是我的想法,如果有任何错误,或者如果您发现任何边缘案例将打破这一点,请纠正我 static class Node { Node next; Node down; int val; Node(int val) { this.val = val; } } static Node flattenLink

您好,我目前正在尝试解决此问题(不幸的是,没有解决方案):

基本上,您希望展平具有指向单个链接列表的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);
}
静态类节点{
节点下一步;
节点向下;
int-val;
节点(int-val){
this.val=val;
}
}
静态节点链接列表(节点头){
队列q=新的LinkedList();
q、 增加(标题);
节点dummyhead=新节点(0);
节点前=dummyhead;
而(!q.isEmpty()){
节点电流=q.poll();
while(当前!=null){
pre.next=新节点(current.val);
pre=pre.next;
if(current.down!=null){
q、 添加(当前。向下);
}
当前=当前。下一步;
}
}
返回dummyhead.next;
}
公共静态void main(字符串[]args){
节点开始=新节点(1);
start.next=新节点(2);
start.next.next=新节点(3);
start.next.next.next=新节点(4);
start.next.down=新节点(5);
start.next.down.down=新节点(8);
start.next.down.next=新节点(6);
start.next.next.next.down=新节点(7);
Node sol=flattLinkedList(开始);
}

我这样做是为了练习面试,不是为了做作业

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

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;
}
1 --- 2 --- 3 ---------------- 4
      |     |
      21    31 --- 32 --- 33 
      |             |
      221          332
                   3332 - 3333
您的函数将返回
12341323233233233233

关于缺点-我会注意到在循环中创建新节点并保持
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;
    }
}
共享O(n)解决方案。这个想法很简单

  • 从当前节点的左侧获取最右边的指针, 指向它的右边,指向父母的右边
  • 然后将当前节点的左指针设置为右指针
解决方案(参考内联注释):


你自己写过单元测试吗?@cricket_007,是的,你认为它对网站上的示例有效,但想确定它是否普遍正确。你认为它有效是什么意思?你们是如何验证的?你们能展示你们当前的单元测试吗?“一个有下一个指针和下一个指针的链表”——这不是叫做二叉树吗?
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;
    }
}
/**
 * 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; 
    }
}