第四天|24. 两两交换链表中的节点 19.删除链表的倒数第N个节点 面试题 02.07. 链表相交 142.环形链表II

第四天|24. 两两交换链表中的节点 19.删除链表的倒数第N个节点 面试题 02.07. 链表相交 142.环形链表II

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

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

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

笔记

当前操作的是cur->nextcur->next->next这两个元素的更换。为什么这样做:因为调换时候会涉及到前一个元素,如果使用cur为当前遍历的值,会出现无法找到前一个节点的情况。

注意循环条件while(cur->next!=nullptr&&cur->next->next!=nullptr)

1.同时要cur->next!=nullptrcur->next->next!=nullptr,前者是奇数情况,后者是偶数情况;

2.cur->next!=nullptr要在cur->next->next!=nullptr之前,因为如果cur->next==nullptr,会导致cur->next->next!=nullptr这一判断语句非法操作

具体操作流程画图即可

实操出现问题

没有把dummyhead 指向原链表head

代码/比较

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyhead=new ListNode(0);//虚拟头节点
        ListNode* cur=dummyhead;//现在遍历的是cur->next和cur->next->next
        dummyhead->next=head;
        while(cur->next!=nullptr&&cur->next->next!=nullptr)
        {
            ListNode* temp=cur->next;
            ListNode* temp1=cur->next->next->next;
            cur->next=cur->next->next;
            temp->next->next=temp;
            temp->next=temp1;
            cur=temp;

        }
        return dummyhead->next;

    }
};

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

19.删除链表的倒数第N个节点 | 代码随想录

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

笔记:

设计删除的链表操作一定要处理的是cur->next

fast要提前出发n+1次。

实操出现问题:

delete时候直接删除了链表内部元素,注意用tmp

代码/比较:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
    ListNode* dummyhead=new ListNode(0);//虚拟头节点
    dummyhead->next=head;//
    ListNode* fast=dummyhead;
    ListNode* slow=dummyhead;//注意:结束时应该指向被删除的节点之前
    n++;
    while(n--&&fast!=nullptr)
    {
        fast=fast->next;
    }
    while(fast!=nullptr)//双指针同时向后移动,让slow结束时指向被删除节点之前
    {
        fast=fast->next;
        slow=slow->next;
    }
    //删除slow->next
    ListNode* tmp=slow->next;
    slow->next=slow->next->next;
    delete tmp;
    return dummyhead->next;

    }
};

面试题 02.07. 链表相交

笔记

面试题 02.07. 链表相交 | 代码随想录

为什么要先找到差值?让两个链表处于同一个起点?:因为处于同一个起点后,两个链表后面的位置应该是一摸一样的

步骤如下:

1.找到两个链表各自的长度

2.让长的那个链表cura往前移动,保持到和短的那个链表相同的长度

3.遍历,知道两个指针相等,如果最后都没有相等,则没有相交

实操出现的问题

思路清晰没啥问题

代码/对比

我自己的:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //获取两个链表的长度 
        int lenA=0;
        int lenB=0;
        ListNode* cura=headA;
        ListNode* curb=headB;
        while(cura!=NULL)
        {
            cura=cura->next;
            lenA++;
        }
        cura=headA;
        while(curb!=NULL)
        {
            curb=curb->next;
            lenB++;
        }
        curb=headB;
        //找到更大的那个长度
        if(lenA>lenB)//A更长
        {
            //让A的cura往前跑
            int sub=lenA-lenB;
            while(sub--)
            {
                cura=cura->next;
            }
            //对比指针即可
            while(cura!=NULL&&curb!=NULL)
            {
                if(cura==curb)
                {
                    return cura;
                }
                cura=cura->next;
                curb=curb->next;
            }
            return NULL;
        }
        else//B更长
        {
            //让B的curb往前跑
            int sub=lenB-lenA;
            while(sub--)
            {
                curb=curb->next;
            }
            //对比指针即可
            while(cura!=NULL&&curb!=NULL)
            {
                if(cura==curb)
                {
                    return cura;
                }
                cura=cura->next;
                curb=curb->next;
            }
            return NULL;
        }
        
    }
};

太蠢了,可以直接交换两个链表的关键信息保持A链表的长度最长

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != NULL) { // 求链表A的长度
            lenA++;
            curA = curA->next;
        }
        while (curB != NULL) { // 求链表B的长度
            lenB++;
            curB = curB->next;
        }
        curA = headA;
        curB = headB;
        // 让curA为最长链表的头,lenA为其长度
        if (lenB > lenA) {
            swap (lenA, lenB);
            swap (curA, curB);
        }
        // 求长度差
        int gap = lenA - lenB;
        // 让curA和curB在同一起点上(末尾位置对齐)
        while (gap--) {
            curA = curA->next;
        }
        // 遍历curA 和 curB,遇到相同则直接返回
        while (curA != NULL) {
            if (curA == curB) {
                return curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
    }
};

142.环形链表II

142.环形链表II | 代码随想录

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

笔记:

1.怎么判断有没有环:

快慢指针,一个走两步一个走一步.为什么不用担心快指针跳过慢指针:因为快指针相对于慢指针就是一步一步在前进,一定不会错过

2.怎么找到环开始的点?

为什么慢指针一定在第一圈和快指针相遇:展开画图可知慢指针走那一圈快指针一定走到他前面去;

通过公式推导知:两个指针分别从相遇点和head出发一定在环的起点相遇(无论那个从相遇点在环里走了多少圈)

实操出现的问题:

再把逻辑分析清楚

代码/对比:

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=head;
                ListNode* index2=fast;
                while(index1!=index2)
                {
                    index1=index1->next;
                    index2=index2->next;
                }
                return index1;
            }
        }
        return NULL;
        
    }
};
posted @ 2026-01-19 10:20  欧尼酱ovo  阅读(1)  评论(0)    收藏  举报