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

24.两两交换链表的节点

力扣题目链接

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

代码随想录算法训练营第四天 | 24.两两交换链表的节点、19.删除链表的倒数第N个节点、142.环形链表II_第1张图片

代码实现

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* tmp1, *tmp2;
        ListNode* dhead = new ListNode(0,head);
        ListNode* cur = dhead;

        while(cur->next&&cur->next->next)
        {
            tmp1 = cur->next;
            tmp2 = cur->next->next->next;
            cur->next = cur->next->next;
            cur->next->next = tmp1;
            cur->next->next->next = tmp2;
            
            cur = cur->next->next;
        }
        return dhead->next;
    }
};

感悟

为什么需要虚拟头结点:会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。 

以第一次循环举例,为什么需要保存第一个和第三个节点:因为要将第二个改为新的头节点,同时会改变该节点的next。

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

力扣题目链接

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

代码随想录算法训练营第四天 | 24.两两交换链表的节点、19.删除链表的倒数第N个节点、142.环形链表II_第2张图片

 思路

运用快慢指针,如果要求倒数第n个,那么先让fast指针走n次,然后fast,slow指针一起走,最终slow指针停下的地方就是倒数第n个节点

代码实现

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(head->next== nullptr) return nullptr;
        ListNode* dhead = new ListNode(0,head);
        ListNode* fast = dhead;
        ListNode* slow = dhead;
        while(n--)
        {
            fast = fast->next;
        }
        while(fast->next)
        {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next;
        return dhead->next;
    }
};

面试题02.07链表相交

力扣题目链接

代码随想录算法训练营第四天 | 24.两两交换链表的节点、19.删除链表的倒数第N个节点、142.环形链表II_第3张图片

 思路

设链表A长度为a,链表B长度为b,设置两个指针pa,pb分别等于headA,headB。

让pa走一遍链表A,再走一遍链表B,那么走过的长度是a+b,让 pb走一遍链表B,再走一遍链表A,那么走过的长度就是b+a,此时可以理解为两个链表末尾对齐,然后就可以找到相同节点。

代码实现

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA== nullptr||headB== nullptr)
            return nullptr;
        ListNode* pa = headA, *pb = headB;
        while(pa!=pb)
        {
            pa = pa==nullptr?headB:pa->next;
            pb = pb== nullptr?headA:pb->next;
        }
        return pa;
    }
};

142.环形链表II

力扣题目链接

代码随想录算法训练营第四天 | 24.两两交换链表的节点、19.删除链表的倒数第N个节点、142.环形链表II_第4张图片

思路

设环之前的长度为a,环的长度为b。

使用快慢指针,fast,slow指针第一次相遇时f = 2s,f = s+nb。

推导出f = 2nb,s=nb。

此时应该,让fast重新回到头节点,然后fast,slow同时走,第二次相遇时,fast,slow走的长度都是a,所以两个指针此时在环的头相遇。

代码实现

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

你可能感兴趣的:(链表,数据结构)