Java 实现复杂链表的复制

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head

代码

    static class ListNode {
        int val;
        ListNode next;
        ListNode other;

        public ListNode(int val) {
            this.val = val;
        }

        @Override
        public String toString() {
            return "ListNode{" +
                    "val=" + val +
                    ", next=" + (next == null ? "null" : next.val) +
                    ", other=" + (other == null ? "null" : other.val) +
                    "}";
        }
    }

    /**
     * 复制
     * 原链表为a->b->c
     * 复制后为a->a1->b->b1->c->c1
     * @param head
     */
    private static void copy(ListNode head) {
        ListNode listNode = head;
        while (listNode != null) {
            // 根据当前节点的内容创建新的节点
            ListNode copy = new ListNode(listNode.val);
            copy.next = listNode.next;

            // 将新节点作为当前节点的next节点,而新节点的next指向了当前节点的原next节点
            // 原来是a->b,选择则是a->a1->b
            listNode.next = copy;
            // 指向下一节点,重复上述操作
            listNode = copy.next;
        }
    }

    /**
     * 设置other节点
     * @param head
     */
    private static void setOther(ListNode head) {
        ListNode listNode = head;
        // listNode是原链表节点,copy是对应的复制节点,同时移动指针遍历
        while (listNode != null) {
            // 当前节点下一节点为其复制节点
            ListNode copy = listNode.next;

            // 当前节点的other节点不为null时,复制节点的other应为源节点other节点的next节点
            // a -> a1 -> b -> b1    a1是a的复制节点,b1是b的复制节点
            // |          ↑          a.other是b,b.next节点是b1(由第一步复制保证的)
            // |_ _ _ _ _ |          所以a1的other节点是a.other即b的next,也就是a.other.next
            if (listNode.other != null) {
                copy.other = listNode.other.next;
            }
            // 当前节点指向其复制节点的下一节点,即源节点的原next节点,重复上述操作
            listNode = copy.next;
        }
    }

    /**
     * 断开与原链表的连接
     * @param head
     * @return
     */
    private static ListNode disConnect(ListNode head) {
        ListNode listNode = head;
        ListNode copyHead = null;
        ListNode copyNode = null;
        if (listNode != null) {
            // 复制链表的头节点就是目前链表头节点的next节点(即其复制节点)
            copyHead = listNode.next;
            // 用于遍历复制链表
            copyNode = listNode.next;
            // 当前链表的原始链表节点的next指向原始next(此时是其复制节点的next)
            listNode.next = copyNode.next;
            // 移动当前链表的指针,此时为复制链表的头节点
            listNode = listNode.next;
        }

        while (listNode != null) {
            // 复制链表节点的next改为当前节点的next
            // a -> a1 -> b -> b1,变回 a1 -> b1
            copyNode.next = listNode.next;
            // 移动复制链表的指针
            copyNode = copyNode.next;

            // 将原始链表中的节点的next指向原始next(此时是其复制节点的next)
            // a -> a1 -> b -> b1,变回 a -> b
            listNode.next = copyNode.next;
            // 移动当前链表的指针,此时遍历的是原始链表
            listNode = listNode.next;
        }

        return copyHead;
    }

    public static ListNode cloneNode(ListNode head) {
        if (head == null) {
            return null;
        }
        copy(head);
        setOther(head);
        return disConnect(head);
    }

    public static void main(String[] args) {
        ListNode root = bulidList();
        ListNode copy = cloneNode(root);
        while (root != null) {
            System.out.println(root.toString());
            root = root.next;
        }
        while (copy != null) {
            System.out.println(copy.toString());
            copy = copy.next;
        }
    }

    private static ListNode bulidList() {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(4);
        ListNode node5 = new ListNode(5);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;

        node1.other = node3;
        node4.other = node1;
        return node1;
    }

猜你喜欢

转载自blog.csdn.net/zl18310999566/article/details/80171395