将链接列表展平为单个链接列表

时间:2017-07-08 22:43:17

标签: java algorithm

你好我现在正试图解决这个问题(不幸的是,没有解决办法):

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

基本上,您希望将具有下一个指针和向下指针的链接列表展平为单个链接列表。

以下是我提出的问题,如果出现任何问题或者发现任何可能导致此问题的边缘情况,请纠正我。

   class Node{
      Node next;
      Node down;
      int val;
      Node(int val){
        this.val = val;
      }
   }
    class test{
        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我这样做是为了练习面试,而不是做作业。

3 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:0)

如果我理解您的方法正确,那么您的功能将逐层压扁一棵树。考虑以下结构

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

您的函数将返回1 2 3 4 21 22 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 22 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;
    }
}

答案 2 :(得分:0)

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

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

解决方案(请参阅嵌入式注释):

/**
 * 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; 
    }
}