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

学习文章链接:代码随想录


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

题目链接:24. 两两交换链表中的节点
思路:画图缕清思路。虚拟头节点指针指向第二个节点,第二个节点指针指向第一个节点,第一个节点指向第三个节点。如此循环。
需要注意的点:两节点交换过后要把第二个节点指针指向第三个节点,考虑cur->next->next为非NULL时,也要考虑cur->next非NULL,不然会报错。
方法1:使用虚拟头节点

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

方法2:不使用虚拟头节点

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

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

题目链接:19.删除链表的倒数第N个节点
思路:使用双指针,快指针走n步,然后快慢指针一起走,直到快指针指向尾部,此时慢指针指的即为需要删除的节点。然而要想删除这个节点,slow应该走到前面一个节点停止,然后再将停下的这个节点的指针指向要删除的节点后的节点。
需要注意的点:快指针应该多走一步。
方法1:使用虚拟头节点

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

方法2:不适用虚拟头节点

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* slowindex=head;
        ListNode* fastindex=head;
        for(int i=0;i<n;i++){
            fastindex=fastindex->next;
        }//画图可知,当快指针走n步走到NULL的时候,说明需要删掉第一个节点,否则的话再走一步
        if(fastindex==NULL){
            head=head->next;
            return head;
        }
        else{
            fastindex=fastindex->next;
        }
        while(fastindex!=NULL){
            slowindex=slowindex->next;
            fastindex=fastindex->next;
        }
        ListNode* temp=slowindex->next;
        slowindex->next=slowindex->next->next;
        delete temp;
        return head;
    }
};

三、面试题 02.07. 链表相交

题目链接:面试题 02.07. 链表相交
思路:将两个链表的末端对齐,较长链表先走到两个链表差值的位置,然后同时移动两个链表上的指针,当两个指针相等时,返回这个值,否则返回null;

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *curA=headA;
        ListNode *curB=headB;
        int lengthA=0;
        int lengthB=0;
        while(curA!=NULL){
            curA=curA->next;
            lengthA++;
        }
        while(curB!=NULL){
            curB=curB->next;
            lengthB++;
        }
        curA = headA;
        curB = headB;
        if(lengthA>=lengthB){
            int index=lengthA-lengthB;
           while(index--){
                curA=curA->next;
            }
        }
        else{
            int index=lengthB-lengthA;
            while(index--){
                curB=curB->next;
            }
        }
         while (curA != NULL && curB != NULL ) {
            if (curA == curB) {
                return curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return NULL; 
    }
};

四、142.环形链表II

题目链接:142.环形链表II

1. 环形链表的原理

1.1 判断是否是环形链表

使用快慢指针,快指针每次走两步,慢指针每次走一步。当链表不是循环链表时,fast一定会先走到NULL,所以只需要判断fast->next是否为NULL就OK。当链表为循环链表时,fast一定先进入环内,当slow进入环内的时候,fast和slow都在环内移动,相对于slow来说,fast每次都移动一步,因此fast和slow一定会在某处相遇,此时跳出循环,判断循环节点。

1.2 判断环形链表的循环节点

考虑从头节点到循环节点的长度x。画图列出式子,然后分类讨论。具体思路参考

2. 环形链表的代码实现

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 *cur=head;
                while(cur!=fast){
                    cur=cur->next;
                    fast=fast->next;
                }
                return cur;
            }
            
        }
        return NULL;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值