剑指offer第25题(C#)
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
这道题目的主要是能够把逻辑梳理清楚,我采用的的方法是网上流行的解法,将整个链表复制然后再分割返回深拷贝后的复杂链表。借用网友做的三张图
可以很直观的看出原链表插入复制第一步就是将链表中的next复制插入一遍。
接下来就是把random给复制和穿插起来,第二步需要依靠第一步复制之后的链表才能继续复制关系。(代码中我会详细解释)
最后将复制出来的大链表分割开来把后者返回输出。好了大致的逻辑是这样的我们来看看代码实现吧:下面展示一些 内联代码片
。
public RandomListNode Clone(RandomListNode pHead)
{
// write code here
if(pHead==null)
return null;
RandomListNode head = pHead;
RandomListNode head2 = pHead;//这里将头节点复制两遍在后面复制两块逻辑用上
while(pHead!=null)
{
RandomListNode res = new RandomListNode(pHead.label);
res.next = pHead.next;
pHead.next = res;
pHead = res.next;//第一部分的模块链表建议大家参照第一张图片配合食用效果更佳,就是简单的单链表插入操作。
}
while(head!=null)
{
if(head.random!=null)
head.next.random = head.random.next;//原来的节点指向的random赋值到复制之后A’节点的random去
head = head.next.next;//第二部分复制random模块,同样建议大家配合第二张图食用,
//利用第一段代码的基础下把原来的节点指向的random赋值到复制之后A’节点的random去。
}
RandomListNode head3 = head2.next;//head3赋值为复制之后的链表头节点做输出头节点。
RandomListNode result = head3;//从result来开始拼接起来整个深拷贝链表的每个节点。
head = head2;//从重合的大链表头指针开始循环切分
while(head!=null)
{
head.next = head.next.next;//原链表两个两个一切之后缝合。
if(result.next!=null)
result.next = result.next.next;//深拷贝链表两个两个一切之后缝合。
head = head.next;
result = result.next;//循环递增指向下一个两个分链表各自节点。
}
return head3;
}
这道题目主要在于那三张图的逻辑,把三个步骤的逻辑都思考和理清楚了,一个一个步骤实现下去就能解决了,其中并没有涉及太多的语法和链表的方法使用,比较考验大家的逻辑算法能力。