代码随想录算法训练营第四天 | 24. 两两交换链表中的节点 、 19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

24. 两两交换链表中的节点

题目链接/文章讲解/视频讲解: 代码随想录

 解题思路

本题考查的是链表的基础操作,但在操作过程中我们画图分析时会发现有时会丢失节点的引用,因此要记录可能会丢失的节点,另外比较重要的就是循环条件要如何写,分为偶数和奇数节点的情况,但我们应要先判断cur->next,否则会发生空指针引用的错误

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
          ListNode* dummyHead = new ListNode(0,head);
          ListNode* cur = dummyHead;     //虚拟头节点
          while(cur->next!=nullptr && cur->next->next !=nullptr)
          {
              ListNode* temp = cur->next;      
              ListNode* temp1 = cur->next->next->next;    //两个临时变量,用于记录节点
              cur->next = cur->next->next;
              cur->next->next = temp;
              temp->next = temp1;
              cur = cur->next->next;     //节点交换的过程
          }
          head = dummyHead->next;
          delete dummyHead;
          return head;
    }
};

这里使用两张卡哥的图来表示一下过程

 

 

19.删除链表的倒数第N个节点

题目链接/文章讲解/视频讲解:代码随想录

解题思路

利用双指针的思路,让快指针先走n步,然后快慢指针同时移动,这样就可以找到倒数第N个节点(快指针指向空,慢指针指向倒数第N个),但由于我们需要删掉这个节点,因此要找到这个节点的前一个节点,只需要让快指针走N+1步即可

 

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
         ListNode* dummyHead = new ListNode(0,head);
         ListNode* fast = dummyHead;
         ListNode* slow = dummyHead;
         n++;   //让快指针多移动一次,因为我们要操作删除节点的上一个节点
         while(n--&&fast!=nullptr)
         {
            fast = fast->next;
         }     //快指针先移动,帮助慢指针寻找到删除节点的上一个节点
         while(fast!=nullptr)
         {
            fast = fast->next;
            slow = slow->next;   //同时移动
         }
         ListNode* temp  = slow->next;
         slow->next = temp ->next;
         delete temp;
         head = dummyHead->next;
         delete dummyHead;
         return head;   //删除操作
    }
};

记得清除内存即可 

142.环形链表II

题目链接/文章讲解/视频讲解:代码随想录

解题思路

 判断是否有环?

利用快慢指针的思想,让快指针一次走两步,慢指针一次走一步,那这样如果有环的话,那么他们必定在环内相遇,如果没有环,那么不会相遇

 

快指针是以一步一步去逼近慢指针的,因此必定会相遇

 如果有环,那么如何知道环的入口处呢?

利用卡哥的思路 

 

动画演示

 

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
           ListNode* fast =head;
           ListNode* slow = head;     //定义快慢指针
           while(fast!=nullptr && fast->next!=nullptr)    //避免对空指针的操作
           {
                  fast = fast->next->next;
                  slow=slow->next;        //快指针一次走两个,慢指针一次走一个
                  if(fast == slow)     //当相遇时代表有环
                  {
                     ListNode* index1 = head;
                     ListNode* index2 = fast;      //在相遇节点分别定义两个指针求出入口
                     while(index1!=index2)
                     {
                             index1=index1->next;
                             index2 = index2->next;    //让他们分别往后移动即可找到入口
                     }
                     return index1;
                  }
           }
           return nullptr;   //没找到入口则返回空
    }
};
  • 时间复杂度: O(n),快慢指针相遇前,指针走的次数小于链表长度,快慢指针相遇后,两个index指针走的次数也小于链表长度,总体为走的次数小于 2n
  • 空间复杂度: O(1)

 面试题 02.07. 链表相交

题目链接/文章讲解:代码随想录

解题思路

 关键在于如何让两个链表同时开始比较,求出两个链表长度,并将长的链表指针移动他们之间的距离即可,利用代码随想录的图理解一下,注意不能对空指针的判断,同时注意值相同,并不代表节点相交,只有地址相同,才是相交节点

 

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
           ListNode* curA = headA;
           ListNode* curB = headB;
           int lenA=0,lenB=0;
           while(curA!=NULL)
           {
              curA=curA->next;
              lenA++;
           }
           while(curB!=NULL)
           {
            curB = curB->next;
            lenB++; 
           }    //求两个链表长度
           curA = headA;
           curB = headB;   //两个指针回到头节点
           if(lenA<lenB)
           {
            swap(lenA,lenB);
            swap(curA,curB);    //以A为长链表
           }
           int gap = lenA-lenB;
           while(gap--&&curA!=NULL)
           {
               curA = curA->next;    //移动curA指针和curB指针对齐
           }
           while(curA!=NULL && curB!=NULL)
           {
                 if(curA==curB)
                    return curA;     //开始比较,如果地址相同则返回相交节点
                else
                {
                    curA=curA->next;
                    curB=curB->next;   //否则判断下一个
                }
           }
           return NULL;   //如果没有则返回NULL
    }
};
  • 时间复杂度:O(n + m)
  • 空间复杂度:O(1)

收获

今天的收获最大的主要是环形链表,让我茅厕顿开,同时链表相交和删除倒数N节点,都是让一个指针先移动,链表相交则是对齐后进行比较,同时比较重要的一个就是对于空指针引用的判断,其次是可以利用index进行while的判断,在面试题中是自己计算出来进行对齐的,马上进入哈希表环节啦,是我不熟悉的领域,继续加油

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值