链表面试题 解法总结

从尾打印链表

1 用递归的方法,如果当前节点不为空,继续调打印函数传过去的参数下一个节点。

If(PNode)

{

  Print_list(PNode->PNext);

  Printf(%d->,PNode->data);

}


2 删除一个非头节点的非尾节点(不能遍历链表)

  用代替法,把当前节点的下一个节点的值赋值给当前节点,在delete掉当前节点的下一个节点。


3在无头单链表的一个非头节点前插入一个节点。

 在当前节点后先把这个节点插入,再交换一个节点的值


4 单链表实现约瑟夫环

PNode Josephcirclr(PNode Phead, SIZE_t M)

它的主要思想是报数当为第M个节点是删除它,继续报数,返回最后一个节点。

{

   pNode Cur=Phead;

   PNode DelNode;

   Size_t count;

   While(Cur!=Cur->Pnext)

  {

     Count=M;

     While(--M)  // M-- M 次,--MM-1次,因为第一个节点也算故走M-1次。

     {

        pCur=PCur->PNext;

     }

     DelNode=PCur->PNext;

     PCur->PNext=DelNode->PNext;

     PCur->data=DelNode->data;

     Free(DelNode);

   }

   Return PCur;

}


5 单链表排序 (冒泡)

 传一个参数为(PHead)

 定义3个指针,PTail ,PCur,PNext.

PTail为尾随指针它为NULL,

当外部while(PHead!=PTail)控制冒泡次数,内部while(PNext!=PTail)控制排序次数,进去首先给PCur=Phead,PNext=Phead->PNext,然后进入内部while进行冒泡。

内部while,在走完一次冒泡后。PCur值为最后一个节点的值把它赋给PTailPTail=PCur.

最终尾随指针走向head.


6找到中间节点

定义俩个指针一个为fast一个为low.fast2步,low走一步。

While(fast&&fast->Next) fast=fast->Next->Next; low=low->Next.  出了whilelow为中间节点


7找到 倒数第K个节点

定义俩个指针,fast先走第K步,low再走,当fast走到NULLlow为倒数第K个节点。

While(K--) { if(k==0)return ; fast=fast->Next;}while(fast){low=low->Next,fast=fast->Next;} return low;

K-- 对应fast , - -k对应fast->Pnext判断条件不同

 

8 逆制 单链表

方法1 .  3指针法

 Pre PCur pnext ,pre记录当前节点的前一个节点,当前节点Next指向pre,这样我们就完成了逆制,但是如果没有Next就会丢失链表,故这就是Next的意义了


 2 递归

Node* rev (Node*PHead)

{

Node * PCur =PHead;

Node * Ppre =PHead;

static Node* ptemp =PHead;

static Node * ret =NULL;

if (NULL == PCur->_PNext)

{

ret = PCur;

}

if (PCur->_PNext)

{

Ppre = PCur;

PCur = PCur->_PNext;

rev(PCur);

PCur->_PNext = Ppre;

}

if (ptemp == Ppre)

{

Ppre->_PNext = NULL;

return ret;

}                                   // 递归

}

 

3 头插法不创建新节点

Node * _rev_2(Node*PHead)

{

assert(PHead);

Node *pre =PHead;

Node * PCur = pre->_PNext;

Node* NewHead =NULL;

while (PCur)

{

pre->_PNext = NewHead;  // ppre插入在新链表的头节点之前

NewHead = pre;    // 头节点指向新的节点。

pre->_PNext = PCur;

PCur = PCur->_PNext;

}

pre->_PNext = NewHead;   // 出while时 , PCur 指向 NULL ,ppre 指向最后一个节点故需处理最后一个节点在循环外

NewHead = pre;

return NewHead;

}


9 链表是否有交点,有的话返回交点。

  如果有交点 那么最后一个节点肯定相同,因为相交意味着有一个相同的节点,那么这个节点之后的所有Next的节点都相同,故相交 最后一个节点都相同。

 那么做法第一步遍历链表的同时 定义size_1 size_2 来一边遍历链表,一边记住链表大小。

那么遍历完 得到俩链表的大小和最后一个节点。

第二步 看最后一个节点是否相同,如果相同的话那么一定相交。

相交后。 定义一个变量来记录他们的差值 gap,  while(gap - -)来使长的链表一直向后走,

直到俩链表长度相同,得到新的一个长链表的节点,从这个节点开始俩链表长度相同。那么

我们开始从这个节点再次遍历 俩链表, 直到俩节点相同,找到交点。


10 链表是否带环,10(2)带环 环的长度,103)求入口点

 10(1) 定义一个快指针 一次走2步 慢 指针一次走1步 ,那么如有环快指针必定入环,等慢指针走进环,快指针必定在慢指针走完环一圈内追上慢指针。故可判断有环。

注意while(fast && fast->Next) 因为fast=fast->next->next, 故得保住fastfast->next不为空。


10(2) 环的长度很简单,由第一小问 返回的 是相遇的节点,定义个临时变量PNode= meetNode;那么while(PNode->Next!=meetNode)PNode走一圈遍历边即可,应注意count应初始化为1, 如果初始化为0,相遇点没有算到里面


103) 第一种方法 定义俩个指针 一个为PH一个为PMPM从相遇点走 ,PH从头节点走,俩个每次都走一步当俩相遇的时候为入口点.因为设环长度为r ,入口点到 头节点为L,入口点到相遇点为X .  由快慢指针相遇得到存在2(L+X)=n*r+(L+x)式子存在,得到L=n*r-x,L=(n-1)r+r-x 。那么举个列子当n=1时(n至少等于1,因为快指针至少在走一圈后追上慢指针),L=r-x.它表示从相遇点走r-x就定于LL刚好为入口点到头节点距离,那么当一个从头开始走一个从相遇点开始走,当它们相遇时,PH=PM那个节点就是入口点。所以该公式L=(n-1)r+(r-x)代表,L这段距离等于n-1圈的长度加上r-x的长度,所以从PM开始每次走一步,从PH的开始每次走一步,只要相遇了,PM肯定是走了n-1圈加上r-x,而从相遇点走r-x后的该点必定是相遇点。

即具体代码就是,PM=meetNode,PH=Phead,while(PH!=PM)PM=PM->Next,PH=PH->Next



11  链表是否相交(可能带环),相交求交点 

俩个链表都不带环




俩个链表都带环




俩个链表一个带一个不带 对于这种情况直接return NULL因为只要相交必定俩个都带或者俩个都不带

  思路:

  1先定义俩个fast和俩个low,遍历边。

  2遍历完后可根据if ((fast == NULL || fast->_PNext == NULL) && (fast2 == NULL || fast2->_PNext == NULL))判断出俩个都不带环

对于不带环的,就定义俩个变量为PH,PH2,代表链表长度,分别变量链表到末尾,如何俩个末尾节点不相等那么俩链表肯定不相交returnNULL,如何相等的话,求gap

为俩长度的差,然后长的链表一直while(gap!=0) p=p->next,gap--; 这样向后走到俩链表长短都一样了,再同时遍历俩链表直到节点相同那么它就是入口点

3 if ((fast != NULL&&fast->_PNext!=NULL)&&(fast2 != NULL&&fast2->_PNext!=NULL))代表俩个都带环,那么先找到环的入口点Enter,Enter2,并记录头节点到入口点的

距离为PH1,PH2。先看入口点是否相等,相等代表有交点,不相等返回NULL。如果那距离一个等于0,就把该链表头结点返回去,代表该链表自成一环,那么又相交,交点肯定为该自成一环的头结点。否则俩个PH都大于0,那么计算出gap,长的走到gap为0时,俩链表相等了长度,再遍历相同节点,找到后返回即可。

4 进不去 2,3的代表一个有环,一个没环就返回NULL.


                                                     第3条分支,俩个都带环相交时的几种情景


12  复杂链表的复制,有random的链表如何复制。 即 该节点有3个字段,一个为值一个为Next指针,一个为random指针。

1 给每个节点后面都new一个 当前节点的副本,边复制边把他们连接起来。

2 给随机域赋值,则新节点的random就等于老节点随即域的random->Next.

3 把俩个链表拆分。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值