剑指Offer(25):复杂链表的复制

一、题目描述

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


二、解题思路

1)复制复杂链表。把复制结点跟在原结点后面,而不直接创建新的链表;
2)设置复制出来的结点的random。因为原结点与复制结点是前后对应关系,所以原结点的random的后一个结点即为复制结点的random;
3)拆分链表。

例如:
链表:1 -> 2 -> 3 -> 4 -> 5 -> 6
随机指针:2 -> 5,3 -> 6
在每个结点后链接复制结点
链表:1 -> 1* -> 2 -> 2* -> 3 -> 3* -> 4 -> 4* -> 5 -> 5* -> 6 -> 6*
随机指针:2 -> 5,3 -> 6
链接复制结点的random结点,即链接原结点的random结点的后一个结点
链表:1 -> 1* -> 2 -> 2* -> 3 -> 3* -> 4 -> 4* -> 5 -> 5* -> 6 -> 6*
随机指针:2 -> 5,2* -> 5*,3 -> 6,3* -> 6*
拆分链表
原始链表:1 -> 2 -> 3 -> 4 -> 5 -> 6
随机指针:2 -> 5,3 -> 6
复制链表:1* -> 2* -> 3* -> 4* -> 5* -> 6*
随机指针:2* -> 5*,3* -> 6*


三、编程实现

public class Solution {
    public RandomListNode Clone(RandomListNode pHead) {
        if (pHead == null) {
            return null;
        }
        // 当前指针指向原链表头
        RandomListNode currentNode = pHead;
        // 在每个结点后链接一个它的复制结点
        while (currentNode != null) {
            // 创建复制结点
            RandomListNode cloneNode = new RandomListNode(currentNode.label);
            // 定义当前结点的后一个结点
            RandomListNode nextNode = currentNode.next;
            // 将复制结点链接到当前结点的后面
            currentNode.next = cloneNode;
            // 将原先的后一个结点链接到复制节点后面
            cloneNode.next = nextNode;
            // 将指针移动到下一个结点
            currentNode = nextNode;
        }
        // 将当前指针重新指向原链表头
        currentNode = pHead;
        while (currentNode != null) {
            // 判断当前结点是否存在随机指针,如果存在,则将当前结点的下一个结点(即复制结点)的随机指针
            // 指向当前结点的随机结点的后一个结点(即随机指针的复制结点)
            currentNode.next.random = currentNode.random == null ? null : currentNode.random.next;
            // 将指针移动到下下个结点(因为下一个是复制结点)
            currentNode = currentNode.next.next;
        }
        // 将当前指针重新指向原链表头
        currentNode = pHead;
        // 定义复制链表的表头为原链表头的下一个结点
        RandomListNode pCloneHead = pHead.next;
        while (currentNode != null) {
            // 定义复制链表的指针指向的结点为当前指针指向结点的后一个
            RandomListNode cloneNode = currentNode.next;
            // 将当前复制结点的后一个结点(即原本链表的后一个结点)重新链接回当前结点
            currentNode.next = cloneNode.next;
            // 链接复制结点的下下个结点
            cloneNode.next = cloneNode.next == null ? null : cloneNode.next.next;
            // 将指针移动到后一个结点(因为复制结点已从链表中断出)
            currentNode = currentNode.next;
        }
        return pCloneHead;
    }
}

猜你喜欢

转载自blog.csdn.net/Fan0628/article/details/88964874
今日推荐