剑指offer-复杂链表的复制

本文介绍了一种在O(n)时间复杂度内复制复杂链表的方法,该方法无需额外空间,通过三步骤完成复制:首先复制节点并插入原节点后;其次设置复制节点的随机指针;最后将链表分离得到复制后的链表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


    RandomListNode(int label) {
        this.label = label;
    }
}
*/
/*
思路:
在不用辅助空间的情况下实现 O(n)的时间效率。
一个含有 5 个结点的复杂链表。图中实线箭头表示 next 指针,虚线箭头表示 sibling 指针。为简单起见,指向 null 的指针没有画出。


1.:仍然是根据原始链表的每个结点ABCDE创建对应的 A’B'CDE'。把 N’链接在N的后面。图 4.8 的链表经过这一步之后的结构。


2.:设置复制出来的结点的 sibling。假设原始链表上的 N 的 sibling 指向结点 S,那么其对应复制出来的 N’是 N的 pext 指向的结点,同样 S’也是 S 的 next 指向的结点。


3.把这个长链表拆分成两个链表。把奇数位置的结点用 next 链接起来就是原始链表,把偶数位置的结点用 next 链接起来就是复制 出来的链表



public class Solution {
    public RandomListNode copyRandomList(RandomListNode head) {
        if (head == null) {
            return null;
        }
        copyNode(head);
        linkRandomPointer(head);
        return splitList(head);
    }


    //第一步:复制结点,复制的结点放在待复制的结点后,依然组成一个单链表
 
    public void copyNode(RandomListNode head) {
        // 记录当前要被复制的缜
        RandomListNode node = head;
        while (node != null) {
            // 复制一个新的结点
            RandomListNode copyNode = new RandomListNode(node.label);
            // 将结点串接到被复制的结点后,并且依然组成单链表
            copyNode.next = node.next;//A->B  A'->B
            node.next = copyNode;//A->A'
            node = copyNode.next;//不断循环 B
        }
    }
    // 第二步:串接随机指针
    public void linkRandomPointer(RandomListNode head) {
        // 记录当前要被复制的缜
        RandomListNode node = head;
        while (node != null) {
            // 随机指针有指向某个具体的结点
            if (node.random != null) {
                // 串接node被复制结点的随机指针
                node.next.random = node.random.next;//
            }
            // 指向下一个被复制的结点
            node = node.next.next;
        }
    }


    /**
     *第三步: 将链表拆分,还原原来的链表,并且组装拷贝的链表
     * @param head 链表头
     * @return 拷贝的新链表头
     */
    public RandomListNode splitList(RandomListNode head) {
        // 新链表头
        RandomListNode copyHead = head.next;
        // 当前处理的被复制的结点
        RandomListNode node = head;
        // 当前复制的结点
        RandomListNode copy;
        while (node != null){
            // 指向复制结点
            copy = node.next;
            // node.next指向下一个被复制的结点
            node.next = copy.next;


            // 下一个被复制的结点不为null
            if (node.next != null) {
                // copy.next指向下一个复制的结点
                copy.next = node.next.next;
            }


            // node指向下一个要被处理的被复制结点
            node = node.next;
        }
        return copyHead;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值