当前位置:   article > 正文

【算法刷题】链表笔试题解析(1)

【算法刷题】链表笔试题解析(1)

 

一、链表分割

题目描述:

链接:链表分割

d908ed776515446ba1ee0ca64e55793b.png

题目分析:

        这题直接处理并不好做,我们可以构建前后两个链表,将小于x值的结点放在链表a内,将其它结点放在链表b内,这样将原链表遍历完后,原链表就自然地分成了两部分,最后将两个链表拼接起来就行了。

如果你以为这题到这里就完了,那这题就不会被分在“较难题”里了

        做算法题,我们一定要细心,要考虑好程序可能会面临的所有情况,仔细梳理一下,你会发现这道题主要会有四种情况:

1、给定链表为空

2、链表中的值有大于x的,也有小于x的

3、链表中所有结点的值都大于x

4、链表中所有节点的值都小于x

这时问题就很明显了,我们之前的思路只能处理第二种情况,遇到其它情况的时候就会出现问题。

比如在第三种情况下,由于没有小于x的结点,所以链表a的头尾指针都不能指向具体的结点,这时如果再通过a链表的尾节点指向b链表的方式链接,就会出现空指针异常导致程序出错了

因此我们还需要分别处理其它三种情况:

1、因为链表为空,所以不需要处理,直接返回头结点即可

3、此时a链表的头指针应该为空,只需要返回b链表的头结点即可

4、此时b链表为空,正常让a的尾结点指向b的头,直接返回头结点即可

注意:二三种情况时需要将b的尾结点的后驱结点置空,这样才能构建一个正常的单链表


代码实现:

  1. public class Partition {
  2. public ListNode partition(ListNode pHead, int x) {
  3. // write code here
  4. if(pHead==null){
  5. return pHead;
  6. }
  7. ListNode as=null;
  8. ListNode ae=null;
  9. ListNode bs=null;
  10. ListNode be=null;
  11. ListNode cur=pHead;
  12. while(cur != null){
  13. if(cur.val<x){
  14. if(as==null){
  15. as=cur;
  16. ae=cur;
  17. }else{
  18. ae.next=cur;
  19. ae=ae.next;
  20. }
  21. }else{
  22. if(bs==null){
  23. bs=cur;
  24. be=cur;
  25. }else{
  26. be.next=cur;
  27. be=be.next;
  28. }
  29. }
  30. cur=cur.next;
  31. }
  32. if(as==null){
  33. be.next=null;
  34. return bs;
  35. }
  36. ae.next=bs;
  37. if(bs!=null){
  38. be.next=null;
  39. }
  40. return as;
  41. }
  42. }

二、链表的回文结构

题目描述:

链接:链表的文结构

da5cea59b7bc46d2923b22b02920ddaf.png

题目分析:

有些人看到这题的第一想法可能是遍历一遍链表,将链表中的值都存在一个数组中,然后用数组的处理方法来判断是否回文,从而大大简化题目难度。

这的确是一个不错的思路,但你有没有发现题目还有以下要求:

时间复杂度为O(n),额外空间复杂度为O(1)的算法

如果你不知道什么是时间复杂度和空间复杂度的话,可以看看博主的这篇文章:博客链接

很明显,数组的空间复杂度是O(N),不符合题目要求,出题者明显不想让你用这么粗暴的方式解题

这里博主提供一个简单的思路:

我们可以先将链表反转,然后判断两个链表相应位置上的值是否相等即可

 

代码实现:

  1. public class PalindromeList {
  2. public boolean chkPalindrome(ListNode A) {
  3. // write code here
  4. if(A==null||A.next==null){
  5. return true;
  6. }
  7. ListNode cur1=A.next;
  8. ListNode cur2=A.next;
  9. ListNode head=A;
  10. head.next=null;
  11. while(cur1!=null){
  12. cur2=cur1.next;
  13. cur1.next=head;
  14. head=cur1;
  15. cur1=cur2;
  16. }
  17. while(A!=null){
  18. if(A.val!=head.val){
  19. return false;
  20. }
  21. A=A.next;
  22. head=head.next;
  23. }
  24. return true;
  25. }
  26. }

三、链表的中间节点

题目描述:

链接: 链表的中间节点

52df901407e04f78afeb34a52a34d5b9.png

题目分析:

我们可以用快慢指针的方法,定义一个快指针fast每次走两步,再定义一个慢指针每次走一步,这样在快指针遍历完链表时,慢指针就正好位于中间位置了

注意:链表的长度可能是奇数也可能是偶数,当结点数为奇数时,fast是走不到最后一个的,如果强行每次都走两步的话最后会出现空指针异常,不过仔细观察你会发现,当fast走到倒数第二位时,slow就刚好位于中间结点了,因此我们只要改变一下循环退出条件即可

代码实现:

  1. class Solution {
  2. public ListNode middleNode(ListNode head) {
  3. ListNode cur1=head;
  4. ListNode cur2=head;
  5. while(cur1 !=null&&cur1.next!=null){
  6. cur1=cur1.next.next;
  7. cur2=cur2.next;
  8. }
  9. return cur2;
  10. }
  11. }

 

四、相交节点

题目描述:

链接:相交节点

d5e2d95c48bd4b1aa612c11944789f5c.png

 

题目分析:

        如果两个链表等长的情况下,这题就非常简单了,只需要同时让指针a、b分别从两个链表的头结点出发,判断是否有结点相等即可,但显然,两个链表的长度未必是相等的。

        这时我们可以先让指针a、b分别遍历两个链表,直到有一个链表被遍历完后,这时长链表指针与长链表尾结点的距离正好是两个链表长度的差值,这时再令一指针x指向长链表的头结点,再一次让之前没遍历完的指针y与新指针x进行遍历,直到老指针y指向长链表的尾结点,这时x与长链表的尾结点的距离正好等于短链表的长度,接着就可以用处理两个等长链表的方式来处理了


代码实现:

  1. public class Solution {
  2. if(headA==null&&headB==null)return null;
  3. ListNode cur1=headA;
  4. ListNode cur2=headB;
  5. while(cur1!=null&&cur2!=null){
  6. cur1=cur1.next;
  7. cur2=cur2.next;
  8. }
  9. if(cur1==null){
  10. cur1=headB;
  11. }else{
  12. cur2=headA;
  13. }
  14. while(cur1!=null&&cur2!=null){
  15. cur1=cur1.next;
  16. cur2=cur2.next;
  17. }
  18. if(cur1==null){
  19. cur1=headB;
  20. }else{
  21. cur2=headA;
  22. }
  23. while(cur1!=null&&cur2!=null){
  24. if(cur1==cur2){
  25. return cur1;
  26. }
  27. cur1=cur1.next;
  28. cur2=cur2.next;
  29. }
  30. return null;
  31. }

 

 

五、返回倒数第k个节点

题目描述:

链接:返回倒数第k个节点

ba9d2323bd824f7f842222b741a418a8.png

题目分析:

我们可以定义两个指针,先让指针1遍历链表,同时记录指针走过的步数s,当s=k时,开始让指针2从头结点开始遍历链表,当指针1指向链表的尾结点时,指针2所指向的结点就是倒数第k个结点了

注意:可能出现k值大于链表长度或k值小于零的情况,

当k<0时,题目显然是无解的,直接return-1即可

当k大于链表长度时,我们可以通过记录指针1走过的步数s的大小来判断,如果指针1遍历完链表时,s任小于k,就说明k值超过了链表的长度,直接return -1即可


代码实现:

  1. public class Solution {
  2. public int kthToLast(ListNode head, int k) {
  3. if (k < 0) {
  4. return -1;
  5. }
  6. ListNode cur1=head;
  7. ListNode cur2=head;
  8. int s=0;
  9. while(cur1!=null){
  10. cur1=cur1.next;
  11. if(s==k){
  12. cur2=cur2.next;
  13. }else{
  14. s++;
  15. }
  16. }
  17. if(s<k){
  18. return -1;
  19. }else{
  20. return cur2.val;
  21. }
  22. }
  23. }

 

总结

那么本篇文章就到此为止了,如果觉得这篇文章对你有帮助的话,可以点一下关注和点赞来支持作者哦。作者还是一个萌新,如果有什么讲的不对的地方欢迎在评论区指出,希望能够和你们一起进步✊

6d1311864a3f47b8a5ba9bb8a3f457cc.png

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/417695
推荐阅读
相关标签
  

闽ICP备14008679号