剑指offer46

380 阅读1分钟

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

解题思路分析

分三步,此题就很好的解答出来了:

  • 首先从第一个节点开始,将每一个节点都复制一遍,并且将复制的节点链在被复制的节点后面
  • 然后从原链表的第一个节点开始,让每个节点的复制节点的特殊指针指向该节点的特殊指针指向的节点的复制节点
  • 最后,将链表拆分成两个链表,就大功告成

代码实现

public ListNode clone(ListNode head) {
    if (head == null) {
        return null;
    }
    copyNode(head);
    copyPointer(head);
    return split(head);
}

//第一步:复制节点
private void copyNode(ListNode head) {
    ListNode cur = head;
    while (cur != null) {
        ListNode temp = new ListNode(head.label);
        temp.next = cur.next;
        cur.next = temp;
        cur = temp.next;
    }
}

//第二步:复制特殊指针
private void copyPointer(ListNode head) {
    ListNode cur = head;
    ListNode clone = head.next;
    while (cur != null) {
        if (cur.random != null) {
            clone.random = cur.random.next;
        }
        cur = clone.next;
        clone = cur.next;
    }
}

//第三步:拆分链表
private ListNode split(ListNode head) {
    ListNode cloneHead = head.next;
    ListNode cur = head;
    ListNode node = cloneHead;
    while (node != null) {
        ListNode temp = node.next;
        cur.next = temp;
        node.next = temp == null ? null : temp.next;
        cur = cur.next;
        node = node.next;
    }
    return cloneHead;
}