《剑指offer》系列 复杂链表的复制(Java)

链接

牛客: 复杂链表的复制

题目描述

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

思路

这题目应该算是这本书最难得几个题目之一了,基本上不看题解的话很难想到这种思路,而且这种题目我觉得只能多做题接触吧,其实没啥意思。
具体思路可见 java 复杂链表的复制

大致分为三点:

  • 1、遍历链表,复制每个结点,如复制结点A得到A1,将结点A1插到结点A后面;
  • 2、重新遍历链表,复制老结点的随机指针给新结点,如A1.random = A.random.next;
  • 3、拆分链表,将链表拆分为原链表和复制后的链表。

代码

/*
public class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;

    RandomListNode(int label) {
        this.label = label;
    }
}
*/
public class Solution {
    //第一步 在原链表每个结点后面分别复制创建新的结点
    public static void cloneNodes(RandomListNode pHead) {
        RandomListNode pNode = pHead;
        while (pNode != null) {
            RandomListNode pCloned = new RandomListNode(0);
            pCloned.label = pNode.label;
            pCloned.next = pNode.next;
            pCloned.random = null;

            pNode.next = pCloned;
            pNode = pCloned.next;
        }
    }

    //第二步 根据旧链表的兄弟结点 初始化新链表的兄弟结点
    public static void connectRandom(RandomListNode pHead) {
        RandomListNode pNode = pHead;
        while (pNode != null) {
            RandomListNode pCloned = pNode.next;
            if (pNode.random != null) {
                pCloned.random = pNode.random.next;
            }
            pNode = pCloned.next;
        }
    }

    //第三步 从旧链表拆分得到新的结点
    public static RandomListNode reconnectNode(RandomListNode pHead) {
        RandomListNode pNode = pHead;
        RandomListNode pClonedHead = null;
        RandomListNode pClonedNode = null;

        if (pNode != null) {
            pClonedHead = pClonedNode = pNode.next;
            pNode.next = pClonedNode.next;
            pNode = pNode.next;
        }

        while (pNode != null) {
            pClonedNode.next = pNode.next;
            pClonedNode = pClonedNode.next;
            pNode.next = pClonedNode.next;
            pNode = pNode.next;
        }
        return pClonedHead;
    }

    //分为三个步骤
    //第一步 在原链表每个结点后面分别复制创建新的结点
    //第二步 根据旧链表的兄弟结点 初始化新链表的兄弟结点
    //第三步 从旧链表拆分得到新的结点
    public static RandomListNode Clone(RandomListNode pHead) {
        cloneNodes(pHead);
        connectRandom(pHead);
        return reconnectNode(pHead);
    }
}

你可能感兴趣的:(剑指offer)