LeetCode 24两两交换链表中的节点 19删除链表的倒数第N个节点 160(面试题02.07)链表相交 142环形链表II | 代码随想录25期训练营day4

LeetCode 24 两两交换链表中的节点 2023.10.28

  • 题目链接
  • 代码随想录讲解[链接]
    LeetCode 24两两交换链表中的节点 19删除链表的倒数第N个节点 160(面试题02.07)链表相交 142环形链表II | 代码随想录25期训练营day4_第1张图片
  • 题意:输入某一链表,将相邻奇数位与偶数位的节点指向相反,最后如果剩下奇数位节点不进行操作
  • 方法:可以采用循环也可以采用递归,类似,首先创建临时节点存储将可能丢失的节点;然后对前后奇偶节点操作,注意条件小心空指针和无限循环
class Solution {
public:
    //创建相邻奇偶节点指向相反的swap函数,包含递归
    ListNode* swapnext(ListNode* pre, ListNode* cur)
    {
        // 判断前面节点和当前遍历节点都不为空时操作,
        //否则(前一节点不为空当前节点为空,即走到了链表最后)直接返回前面节点
        if(pre != nullptr && cur !=nullptr)
        {
            //创建临时节点用于存储当前节点的后两个节点,用于递归
            ListNode *temp0 = cur->next;
            ListNode *temp1 = nullptr;
            //小心temp0为空,所以必须判断,合理则存储当前节点的后第二个节点
            if(temp0 != nullptr && temp0->next != nullptr)
                temp1 = temp0->next;
            //开始操作,当前节点指向前面的一个节点
            cur->next = pre;
            //前面的节点指向下一组遍历后的第一个节点
            //最后一次递归如果为temp0不为空,temp1为空,则会返回temp0
            pre->next = swapnext(temp0, temp1);
            //然后返回操作后在前面的节点
            return cur;
        }
        //(前一节点不为空当前节点为空,即走到了链表最后)直接返回前面节点
        else
        {
            return pre;
        }
    }

    ListNode* swapPairs(ListNode* head) {
        //判断节点是否为空,如果为空则返回,否则调用head->next会报错,因为没有空间
        if(head == nullptr)
            return head;
        //链表不为空时调用递归函数操作
        return swapnext(head, head->next);
    }
};

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

  • 题目链接
  • 代码随想录讲解[链接]
    LeetCode 24两两交换链表中的节点 19删除链表的倒数第N个节点 160(面试题02.07)链表相交 142环形链表II | 代码随想录25期训练营day4_第2张图片
  • 题意:输入一个链表,要求删除倒数第n个节点
  • 方法:采用双指针方法,先使前指针不动,后指针向后移动n步,那么后指针与前指针间相差n+1个节点,然后前后指针一起后移,当后指针指向Null时,前指针指向倒数第n+1个节点,那么令前指针的next节点指向倒数第n-1个节点,即完成题目要求
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //首先判断链表是否为空及所去除元素索引是否合理
        if(n <= 0 || head == nullptr)
            return head;
        //创建虚头节点且指向头结点
        ListNode *virhead = new ListNode();
        virhead->next = head;
        //创建前后指针,初始时当前指针指向虚头节点,后节点指向下一个节点相差1
        //这里为什么相差1,考虑了多1是要被删掉的那一个
        ListNode *cur = virhead;
        ListNode *back = virhead->next;
        
        //取倒数第n个,就先让前后指针相差n+1个,
        while (n--)
        {
            //进行一次次操作,让back与cur相差n+1
            if(back != nullptr)
                back = back->next;
            //下面说明要去除的位置不合理,没有该节点
            else
                return virhead->next;
        }
        //cur和back保持相差n+1个节点一起后移
        //最后back节点变null,cur为倒是第n+1个节点
        while (back != nullptr)
        {
            cur = cur->next;
            back = back->next;
        }
        //用于存储倒数第n个节点,最后删除空间
        ListNode *temp = cur->next;
        //倒数第n+1个节点指向倒是第n-1个节点
        cur->next = cur->next->next;
        //删除占用的空间,并使指针指向空指针
        delete temp;
        temp = nullptr;
        //返回头节点
        return virhead->next;
    }
};

LeetCode 160(面试题02.07) 链表相交 2023.10.28

  • 题目链接

  • 代码随想录讲解[链接]
    LeetCode 24两两交换链表中的节点 19删除链表的倒数第N个节点 160(面试题02.07)链表相交 142环形链表II | 代码随想录25期训练营day4_第3张图片

  • 题意:输入两个链表,寻找这两个链表相交的节点,相交是指两个链表从某一节点开始所有节点都相同,后面的节个点数也相同!(不能通过节点值判断,值相等节点不一定相等)

  • 方法:使两个链表的遍历指针同时走到对应链表的一定位置,该位置后面的节点数是相同的,从该位置开始一起遍历查找是否为相同节点,相同则得到答案,没找到最后输出NULL

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //首先判断两个链表是否合理,某一为空则返回NULL
        if(headA == nullptr || headB == nullptr)
            return NULL;
        //分别创建两链表用于遍历的指针,初始化指向头结点
        ListNode *curA = headA;
        ListNode *curB = headB;
        //创建变量用于计数两个链表中的节点数,由于指向了头结点所以默认值为1
        int size_A = 1;
        int size_B = 1;
        //分别遍历得到两个链表的节点数
        while (curA->next != nullptr)
        {
            size_A++;
            curA = curA->next;
        }
        while (curB->next != nullptr)
        {
            size_B++;
            curB = curB->next;
        }
        //统计之后让遍历指针指向头结点
        curA = headA;
        curB = headB;
        //判断两链表节点差,用于让更长的链表走到与短链表一起走的位置
        int size_delta = abs(size_A-size_B);
        //使长链表指针先走到与短链表节点数相同的位置
        while (size_delta--)
        {
            if(size_A > size_B)
                curA = curA->next;
            else if(size_A < size_B)
                curB = curB->next;
        }
        //用于计数,剩下要遍历的节点数
        int min_size = (size_A < size_B ? size_A : size_B);
        //开始遍历,如果节点相同则返回该节点,不同则往后更新再遍历
        while (min_size--)
        {
            if(curA == curB)
                return curA;
            curA = curA->next;
            curB = curB->next;
        }
        //没找到相同的则返回NULL
        return NULL;
    }
};

LeetCode 142 环形链表II 2023.10.28

  • 题目链接
  • 代码随想录讲解[链接]
    LeetCode 24两两交换链表中的节点 19删除链表的倒数第N个节点 160(面试题02.07)链表相交 142环形链表II | 代码随想录25期训练营day4_第4张图片
  • 题意:输入一个链表,要求求出在该链表有环形时,环形的第一个节点(不一定是头结点)
  • 方法:双(快慢)指针法,快、慢指针同时从头结点出发,如果链表有环,一定快指针与慢指针能相遇(快指针走过的节点是慢指针走过节点的二倍),但是相遇的节点位置不一定是环形第一个节点,属于数学问题,建议先看卡哥视频[链接]
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        //判断输入链表是否为空或只有一个元素,否则不成环
        if(head == nullptr || head->next == nullptr)
            return NULL;
        //创建快慢指针初始指向头节点
        ListNode *slow = head;
        ListNode *fast = head;
        //开始走,首先保证快指针的下一个节点和下两个节点都不为空,因为其一次走两步
        //快指针能满足条件的话慢指针一定满足,所以不用考虑慢指针
        while (fast->next != nullptr && fast->next->next != nullptr)
        {
            slow = slow->next;
            fast = fast->next->next;
            //当快慢指针相遇时,进行求解环形第一个节点
            if(slow == fast)
            {
                //令慢指针指向头结点,与快指针同步遍历
                //下一次相遇的节点一定是环形第一个节点
                slow = head;
                while (slow != fast)
                {
                    slow = slow->next;
                    fast = fast->next;
                }
                //返回相遇的节点
                return slow;
            }
        }
        //没有相遇则返回空
        return NULL;
    }
};

你可能感兴趣的:(LeetCode刷题,代码随想录训练营,leetcode,链表,数据结构,算法)