代码随想录算法训练营第四天|链表part2

相关链接

24. 两两交换链表中的节点 - 力扣(LeetCode)

视频讲解:帮你把链表细节学清楚! | LeetCode:24. 两两交换链表中的节点_哔哩哔哩_bilibili

19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)

视频讲解:链表遍历学清楚! | LeetCode:19.删除链表倒数第N个节点_哔哩哔哩_bilibili

面试题 02.07. 链表相交 - 力扣(LeetCode)

暂无视频讲解

142. 环形链表 II - 力扣(LeetCode)

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

两两交换链表中的节点

解题思路

定义一个虚拟头结点便于统一操作,这道题一定要画图便于直观理解,否则很容易思路混乱。

遇到的难题&总结

1)自己重新模拟过程的时候,指针的指向混乱,还是需要画图。

2)临时结点的作用是便于之前指针的定位。

3)循环终止条件的判断。

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

删除链表的倒数第N个结点

解题思路(独立写的版本,1.0版本,代码较为啰嗦)

首先遍历链表求出总数,删除倒数第N个结点其实就是删除第(总数-N)个结点,接着删除结点就是链表的基础操作。

AC代码

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        int size=0;
        ListNode* vhead=new ListNode(0);
        vhead->next=head;
        ListNode* cur=vhead;
        ListNode* tmp=cur->next;
        while(cur->next!=NULL)
        {
            size++;
            cur=cur->next;
        }
        int k=size-n;
        cur=vhead;
        while(k--)
        {
            cur=cur->next;
            tmp=cur->next;
        }
        ListNode* de=cur->next;
        cur->next=tmp->next;
        delete de;
        return vhead->next;
    }
};

双指针解法的解题思路

如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。这里定义虚拟头节点便于操作,我们让fast先移动n+1步,这样慢指针指向的就是要删除的结点的前一个结点,之后便于进行删除操作。

AC代码

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

遇到的困难&总结

1)代码在执行过程中报错,虚拟头结点需要与原链表进行相连!!!

2)不懂的时候多画图

链表相交

解题思路

就是求两个链表交点节点的指针交点不是数值相等,而是指针相等。分别计算出两个链表的长度,求出两个链表长度的差值,然后让h1移动使得两个链表的末尾对齐,接着就可以比较h1和h2是否相同,如果不相同,同时向后移动h1和h2,如果遇到h1== h2,则找到交点,否则循环退出返回空指针。

AC代码

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
      ListNode* h1=headA;
      ListNode* h2=headB;
      int lenA=0,lenB=0;
      while(h1!=NULL)
      {
          lenA++;
          h1=h1->next;
      }
      while(h2!=NULL)
      {
          lenB++;
          h2=h2->next;
      }
      h1=headA;
      h2=headB;
      if(lenB>lenA)
      {
          swap(lenA,lenB);
          swap(h1,h2);
      }
      int gap=lenA-lenB;
      while(gap--)
      {
          h1=h1->next;
      }
      while(h1!=NULL)
      {
          if(h1==h2)
          return h1;
          h1=h1->next;
          h2=h2->next;
      }
      return NULL;
    }
};

遇到的困难

1)起初不理解链表相交的含义,以为是数值相等。

2)计算链表长度的时候,循环终止条件判断错误,误以为是h1->next!=NULL(这么低级的错误,我晕)

3)swap函数理解不够透彻

环形链表

AC代码

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(slow==fast)
            {
                ListNode* index1=fast;
                ListNode* index2=head;
                while(index1!=index2)
                {
                    index1=index1->next;
                    index2=index2->next;
                }
                return index1;
            }
        }
        return NULL;
    }
};

总结

最重要的就是判断是否有环以及环的入口,视频真的讲解的很详细,一些疑难点讲解的很详细。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值