1、Java面试中的链表题目总结Java面试中的链表题目总结链表是面试中常出现的一类题目,本文用Java实现了面试中常见的链表相关题目。本文主要参考整合重写了轻松搞定面试中的链表题目和 算法大全(1)单链表两篇大作。两篇大神的实现分别是C和C#,因为我更喜欢用Java面试,所以用Java重写了所有实现,并附上自己的一些思考注释。算法大全(1)单链表尚未有一些问题尚未整合进来,很快我会更新本文。接下来还会出关于二叉树的大总结和栈和队列的大总结。因为这些都属于面试中的送分题!必须毫无偏差地拿下。至于像动态规划这些比较“高端”的算法,就只能靠日积月累,而不能像这样临时突击了。java view plai
2、ncopypackageLinkedListSummary;importjava.util.HashMap;importjava.util.Stack;/*轻松搞定面试中的链表题目*算法大全(1)单链表*目录:*1.求单链表中结点的个数:getListLength*2.将单链表反转:reverseList(遍历),reverseListRec(递归)*3.查找单链表中的倒数第K个结点(k0):reGetKthNode*4.查找单链表的中间结点:getMiddleNode*5.从尾到头打印单链表:reversePrintListStack,reversePrintListRec(递归)*6.已知
3、两个单链表pHead1和pHead2各自有序,把它们合并成一个链表依然有序:mergeSortedList,mergeSortedListRec*7.判断一个单链表中是否有环:hasCycle*8.判断两个单链表是否相交:isIntersect*9.求两个单链表相交的第一个节点:getFirstCommonNode*10.已知一个单链表中存在环,求进入环中的第一个节点:getFirstNodeInCycle,getFirstNodeInCycleHashMap*11.给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted:delet
4、e*/publicclassDemopublicstaticvoidmain(Stringargs)Noden1=newNode(1);Noden2=newNode(2);Noden3=newNode(3);Noden4=newNode(4);Noden5=newNode(5);n1.next=n2;n2.next=n3;n3.next=n4;n4.next=n5;printList(n1);System.out.println(getListLength(n1);/Nodehead=reverseList(n1);Nodehead=reverseListRec(n1);printList(h
5、ead);Nodex=reGetKthNode(head,2);System.out.println(x.val);x=getMiddleNode(head);System.out.println(x.val);System.out.println(reversePrintListStack:);reversePrintListStack(head);System.out.println(reversePrintListRec:);reversePrintListRec(head);privatestaticclassNodeintval;Nodenext;publicNode(intval)
6、this.val=val;publicstaticvoidprintList(Nodehead)while(head!=null)System.out.print(head.val+);head=head.next;System.out.println();/求单链表中结点的个数/注意检查链表是否为空。时间复杂度为O(n)publicstaticintgetListLength(Nodehead)/注意头结点为空情况if(head=null)return0;intlen=0;Nodecur=head;while(cur!=null)len+;cur=cur.next;returnlen;/翻转
7、链表(遍历)/从头到尾遍历原链表,每遍历一个结点,/将其摘下放在新链表的最前端。/注意链表为空和只有一个结点的情况。时间复杂度为O(n)publicstaticNodereverseList(Nodehead)/如果链表为空或只有一个节点,无需反转,直接返回原链表表头if(head=null|head.next=null)returnhead;NodereHead=null;/反转后新链表指针Nodecur=head;while(cur!=null)NodepreCur=cur;/用preCur保存住对要处理节点的引用cur=cur.next;/cur更新到下一个节点preCur.next=r
8、eHead;/更新要处理节点的next引用reHead=preCur;/reHead指向要处理节点的前一个节点returnreHead;/翻转递归(递归)/递归的精髓在于你就默认reverseListRec已经成功帮你解决了子问题了!但别去想如何解决的/现在只要处理当前node和子问题之间的关系。最后就能圆满解决整个问题。/*head1-2-3-4head1-|4-3-2/NodereHead=reverseListRec(head.next);reHeadhead.next4-3-2-1/head.next.next=head;reHead4-3-2-1-null/head.next=nul
9、l;reHead*/publicstaticNodereverseListRec(Nodehead)if(head=null|head.next=null)returnhead;NodereHead=reverseListRec(head.next);head.next.next=head;/把head接在reHead串的最后一个后面head.next=null;/防止循环链表returnreHead;/*查找单链表中的倒数第K个结点(k0)*最普遍的方法是,先统计单链表中结点的个数,然后再找到第(n-k)个结点。注意链表为空,k为0,k为1,k大于链表中节点个数时的情况*。时间复杂度为O(n
10、)。代码略。这里主要讲一下另一个思路,这种思路在其他题目中也会有应用。*主要思路就是使用两个指针,先让前面的指针走到正向第k个结点*,这样前后两个指针的距离差是k-1,之后前后两个指针一起向前走,前面的指针走到最后一个结点时,后面指针所指结点就是倒数第k个结点*/publicstaticNodereGetKthNode(Nodehead,intk)/这里k的计数是从1开始,若k为0或链表为空返回nullif(k=0|head=null)returnnull;Nodeq=head;/q在p前面p-qNodep=head;/p在q后面/让q领先p距离kwhile(k1&q!=null)q=q.ne
11、xt;k-;/当节点数小于k,返回nullif(k1|q=null)returnnull;/前后两个指针一起走,直到前面的指针指向最后一个节点while(q.next!=null)p=p.next;q=q.next;/当前面的指针指向最后一个节点时,后面的指针指向倒数k个节点returnp;/查找单链表的中间结点/*此题可应用于上一题类似的思想。也是设置两个指针,只不过这里是,两个指针同时向前走,前面的指针每次走两步,后面的指针每次走一步,*前面的指针走到最后一个结点时,后面的指针所指结点就是中间结点,即第(n/2+1)个结点。注意链表为空,链表结点个数为1和2的情况。时间复杂度O(n*/pu
12、blicstaticNodegetMiddleNode(Nodehead)if(head=null|head.next=null)returnhead;Nodeq=head;/p-qNodep=head;/前面指针每次走两步,直到指向最后一个结点,后面指针每次走一步while(q.next!=null)q=q.next;p=p.next;if(q.next!=null)q=q.next;returnp;/*从尾到头打印单链表*对于这种颠倒顺序的问题,我们应该就会想到栈,后进先出。所以,这一题要么自己使用栈,要么让系统使用栈,也就是递归。注意链表为空的情况*。时间复杂度为O(n)*/public
13、staticvoidreversePrintListStack(Nodehead)Stacks=newStack();Nodecur=head;while(cur!=null)s.push(cur);cur=cur.next;while(!s.empty()cur=s.pop();System.out.print(cur.val+);System.out.println();/*从尾到头打印链表,使用递归(优雅!)*/publicstaticvoidreversePrintListRec(Nodehead)if(head=null)return;elsereversePrintListRec(
14、head.next);System.out.print(head.val+);/*已知两个单链表pHead1和pHead2各自有序,把它们合并成一个链表依然有序*这个类似归并排序。尤其注意两个链表都为空,和其中一个为空时的情况。只需要O(1)的空间。时间复杂度为O(max(len1,len2))*/publicstaticNodemergeSortedList(Nodehead1,Nodehead2)/其中一个链表为空的情况,直接返回另一个链表头,O(1)if(head1=null)returnhead2;if(head2=null)returnhead1;NodemergeHead=null
15、;/先确定下来mergeHead是在哪里if(head1.valhead2.val)mergeHead=head1;mergeHead.next=null;/断开mergeHead和后面的联系head1=head1.next;/跳过已经合并了的元素elsemergeHead=head2;mergeHead.next=null;head2=head2.next;NodemergeCur=mergeHead;while(head1!=null&head2!=null)if(head1.valhead2.val)mergeCur.next=head1;/把找到较小的元素合并到merge中head1=
16、head1.next;/跳过已经合并了的元素mergeCur=mergeCur.next;/找到下一个准备合并的元素mergeCur.next=null;/断开mergeCur和后面的联系elsemergeCur.next=head2;head2=head2.next;mergeCur=mergeCur.next;mergeCur.next=null;/合并剩余的元素if(head1!=null)mergeCur.next=head1;elseif(head2!=null)mergeCur.next=head2;returnmergeHead;/*递归合并两链表(优雅!)*/publicsta
17、ticNodemergeSortedListRec(Nodehead1,Nodehead2)if(head1=null)returnhead2;if(head2=null)returnhead1;NodemergeHead=null;if(head1.valhead2.val)mergeHead=head1;/连接已解决的子问题mergeHead.next=mergeSortedListRec(head1,head2);elsemergeHead=head2;mergeHead.next=mergeSortedListRec(head1,head2);returnmergeHead;/*判断一个单链表中是否有环*这里也是用到两个指针。如果一个链表中有环,也就是说用一个指针去遍历,是永远走不到头的。因此,我们可以用两个指针去遍历,一个指针一次走两步*,一个指针一次走一步,如果有环,两个指针肯定会在环中相遇。时间复杂度为O(n)*/publicstaticbooleanhasCycle(Nodehead)Nodefast=head;/快指针每次前进两步Nodeslow=head;/慢指针每次前进一步while(fast!=null&fast.next!=null)fast=fast.next.next;slow=slow.next;if(fast=slow)/相遇,存在环
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1