今天让我们来做一些复杂一些的链表面试题。
1.复杂链表的复刻。
typedef struct CN{ //复杂链表的结构体。
int data; //每个节点的数据。
struct CN *pNext; //指向下一个节点。
struct CN *pRandom; //指向随机节点或NULL。
} CN;
CN *Copy(CN *pFirst)
{
CN *pNode=pFirst;
CN *pNewNode;
CN *pOldRandom;
CN *pNewRandom;
CN *pNewFirst=pFirst->pNext;
//1.复制节点放到老节点后边。
for(pNode=pFirst;pNode!=NULL;pNode=pNode->pNext->pNext)
{
pNewNode=(CN *)malloc(sizeof(CN)); //开辟一个空间。
pNewNode->data=pNode->data; //拷贝节点的值。
pNewNode->pRandom=NULL;
pNewNode->pNext=pNode->pNext;
pNode->pNext=pNewNode; //把新节点放在老节点后面。
}
//2.复制pRandom。
for(pNode=pFirst;pNode!=NULL;pNode=pNode->pNext->pNext)
{
pNewNode=pNode->pNext;
pOldRandom=pNode->pRandom;
if(pOldRandom!=NULL)
{
pNewRandom=pOldRandom->pNext;
pNewNode->pRandom=pNewRandom;
}
}
//3.拆链表。
for(pNode=pFirst;pNode!=NULL;pNode=pNode->pNext)
{
pNewNode=pNode->pNext;
pNode->pNext=pNewNode->pNext;
if(pNode->pNext!=NULL)
{
pNewNode->pNext=pNode->pNext->pNext;
}
else{
pNewNode->pNext=NULL;
}
}
return pNewFirst;
}
CN *Buy(int data) //建立复杂链表。
{
CN *pNode=(CN *)malloc(sizeof(CN));
pNode->data=data;
pNode->pNext=NULL;
pNode->pRandom=NULL;
return pNode;
}
void Print(CN *pFirst) //打印各个节点的数据。
{
CN *pNode;
for(pNode=pFirst;pNode!=NULL;pNode=pNode->pNext)
{
printf("[%d, (%p, %d)] ",
pNode->data,
pNode->pRandom,
pNode->pRandom ? pNode->pRandom->data : 0);
}
printf("\n");
}
void test() //测试程序。
{
CN *p1 = Buy(1);
CN *p2 = Buy(2);
CN *p3 = Buy(3);
CN *p4 = Buy(4);
p1->pNext = p2;
p2->pNext = p3;
p3->pNext = p4;
p1->pRandom = p4;
p4->pRandom = p1;
p2->pRandom = p2;
Print(p1);
CN *pNew = Copy(p1);
Print(pNew);
}
2.//判断两个链表是否相交,若相交,求交点。
SListNode *Jiao(SListNode *a1,SListNode *a2)
{
SListNode *n1=a1; //先定义两个指针指向两个链表头。
SListNode *n2=a2;
int z=0; //计数。
int x=0;
while(n1->pNext!=NULL) //求两个链表的尾结点并记下总节点个数。
{
n1=n1->pNext;
z+=1;
}
while(n2->pNext!=NULL)
{
n2=n2->pNext;
x+=1;
}
if(n1!=n2) //如果两个尾结点不同,证明两个链表不相交。
{
printf("Not\n");
return;
}
else{
printf("Yes\n");
if(x==z) //否则当两个链表一样长时。
{
n1=a1; //先让指针回到头指针。
while(n1->pNext!=NULL)
{
if(n1==n2) //循环指针求两个相等时的指针输出即可得到解。
{
return n1;
}
n1=n1->pNext;
}
}
else if(x<z) //如果第一个大,就先让它移到与第二个一样的位置,在进行如上的操作。
{
z=z-x;
n1=a1;
while(z)
{
n1=n1->pNext;
}
while(n1->pNext!=NULL)
{
if(n1==n2)
{
return n1;
}
n1=n1->pNext;
}
}
else if(x>z) //当第二个大时如上操作即可。
{
x=x-z;
n2=a2;
while(x)
{
n2=n2->pNext;
}
while(n2->pNext!=NULL)
{
if(n2==n1)
{
return n2;
}
n2=n2->pNext;
}
}
}
}
这两个题挺复杂的,需要好好琢磨才能掌握。