DAY4 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表II

文章介绍了如何在链表中进行两两交换相邻节点的操作,使用虚拟头节点和双指针技巧,以及如何删除链表的倒数第N个节点,包括一次扫描和双指针方法。还讨论了如何检测链表中的环形结构,给出了相应的算法实现。
摘要由CSDN通过智能技术生成

两两交换链表中的节点:

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

对应力扣24题

这题简单,使用虚拟头结点,然后用两个临时指针,一个固定指针就行,画图可以看的很清楚

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
         ListNode* vhead=new ListNode();
         vhead->next=head;
         ListNode* cur=vhead;
         while(cur->next!=NULL&&cur->next->next!=NULL)
         {   ListNode* temp=cur->next; 
             ListNode* temp1=cur->next->next->next;
             cur->next=cur->next->next;
             cur->next->next=temp;
             temp->next=temp1;
             cur=temp;
         }
         return vhead->next;
    }
};

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

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

进阶:你能尝试使用一趟扫描实现吗?

对应力扣19题

说实话,如果支持多次扫描的话,确实很简单,可以手搓,但是扫描一次的话可能有点难

手搓代码,直接先遍历一遍得到链表的大小,然后再删除:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
              int i=0;
              ListNode* vhead=new ListNode();
              vhead->next=head;
              ListNode* flag=vhead;
              if(vhead->next==NULL)return head;
              while(flag->next!=NULL)
              {     i++;
                  flag=flag->next;
              }
              ListNode* flag1=vhead;
              for(int j=0;j<i-n;j++)
              {     flag1=flag1->next;   
              }
                ListNode* temp=flag1->next;
                flag1->next= flag1->next->next;
                delete temp; 
                return vhead->next;
    }
};

巧妙方法使用双指针:

如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了,因为slow要指向被删除的结点,所有应该让fast走n+1步。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
              ListNode* vhead=new ListNode();
              vhead->next=head;
              n++;
              ListNode* fast=vhead;
              ListNode* slow=vhead;
              while(n--&&fast!=NULL)
              {
                  fast=fast->next;
              }
              while(fast!=NULL)
              {
                  fast=fast->next;
                  slow=slow->next;
              }
              ListNode* temp=slow->next;
              slow->next=slow->next->next;
              delete temp;
                return vhead->next;
    }
};

链表相交:

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交:

对应力扣160题

这题解法太妙了,

我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:

此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
           ListNode* flag1=headA;
           ListNode* flag2=headB;
           int len_A=0;
           int len_B=0;
           while(flag1!=NULL)
           {
               len_A++;
               flag1=flag1->next;
           }
           while(flag2!=NULL)
           {
               len_B++;
               flag2=flag2->next;
           }
           flag1=headA;
           flag2=headB;

          if(len_A<len_B)
          {
              swap(len_A,len_B);
              swap(flag1,flag2);
          }

    
              int n=len_A-len_B;
               while(n--)
               {
                   flag1=flag1->next;
               }
               while(flag1&&flag2)
               {
                   if(flag1==flag2)
                   return flag1;
                   flag1=flag1->next;
                   flag2=flag2->next;
               }
               return NULL;
           }
         
    
};

环形链表II:

题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

纯纯数学题,没啥好说的,对应力扣142题。

把环形链表讲清楚! 如何判断环形链表?如何找到环形链表的入口? LeetCode:142.环形链表II_哔哩哔哩_bilibili

这里是讲解。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast=head;
        ListNode *slow=head;
        while(fast!=NULL&&fast->next!=NULL)
        {
            fast=fast->next->next;
            slow=slow->next;
            if(fast==slow)
            {   ListNode *index1=fast;
                ListNode *index2=head;
                while(index1!=index2)
                {  index1=index1->next;
                   index2=index2->next;
                }
                return index1;
            }
        }
        return NULL;
    }
};

哦对了,明天休息

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值