复制链表
题目:已知一链表,每个节点除了有一个指向下一节点的指针外,还有一随机指针指向链表中的任意节点(可能为空,也有可能为自身),请复制一个链表,要求节点的顺序以及节点上的随机指针指向的节点位置和原链表一致。
这个题目有个很巧妙的解法,可以达到O(n)的效率,其中心思想是把原始链表和复制链表先合并为一个有固定顺序的链表,然后给复制链表中每个节点的随机指针复制,最后再打断链表恢复原样。
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 复制链表
{
class Program
{
class Node
{
public object nData;
public Node pNext;
public Node pRandom;
public Node(string data)
{
this.nData = data;
}
public Node()
{
}
}
/// <summary>
/// copy单链表方法2
/// </summary>
/// <param name="Head"></param>
/// <returns></returns>
static Node CopyNodeMethod2(Node Head)
{
if (Head == null)
return null;
Node pNode = Head;
while (pNode != null)
{
Node newNode = new Node();
newNode.nData = pNode.nData + "'";
newNode.pNext = pNode.pNext;
newNode.pRandom = pNode.pRandom;
pNode.pNext = newNode;
pNode = newNode.pNext;
}
PrintList(Head);
// 把新链表的随机指针指向自己的链表节点,看图就明白了
pNode = Head;
while (pNode != null)
{
pNode.pNext.pRandom = pNode.pRandom.pNext;
pNode = pNode.pNext.pNext;
}
// 拆开链表,分成2个
Node NewHead = Head.pNext;
pNode = Head;
Node pNodeNext = Head.pNext;
while (pNode != null)
{
pNode.pNext = pNodeNext.pNext;
if (pNode.pNext != null)
pNodeNext.pNext = pNodeNext.pNext.pNext;
else
pNodeNext.pNext = null;
// 新链表向前走一步
pNodeNext = pNodeNext.pNext;
// 原链表向前走一步
pNode = pNode.pNext;
}
return NewHead;
}
static void PrintList(Node temp)
{
while (temp != null)
{
Console.Write(temp.nData.ToString() + "-->");
temp = temp.pNext;
}
Console.WriteLine("\n");
}
static void Main(string[] args)
{
Node node1 = new Node("1");
Node node2 = new Node("2");
Node node3 = new Node("3");
Node node4 = new Node("4");
node1.pNext = node2;
node1.pRandom = node3;
node2.pNext = node3;
node2.pRandom = node1;
node3.pNext = node4;
node3.pRandom = node2;
node4.pRandom = node3;
Node tempNode = CopyNodeMethod1(node1);
PrintList(tempNode);
Console.ReadKey();
}
}
}