训练营第四天|142、环形链表Ⅱ 24、两两交换链表中的节点

总结:第二次做这个题目,刚开始还没想起来思路,思考了一会想到了一个大概思路,但是没弄清楚其中的等式关系,没思考出来。方法:利用当双指针的方法,当快慢指针相等之后再将快指针归位到头指针,这时候再以相等的速度往前走,则会在入口处相遇。

细节注意:当快慢指针初始化的时候如果没有都初始化为头指针的话,则会导致后面的等式不成立进而导致最终结果不正确。

在其中犯过的错误:快慢指针初始化的时候并没有都初始化为头指针而是快指针已经先走两步,而接下来又用快指针是否与慢指针相等的条件进行判断导致一直无法进入循环,这个小错误虽然很明显但是写的时候还看了很久才看出来。

代码:

class Solution {
public:

    ListNode *detectCycle(ListNode *head) {
        auto fast = head;
        auto slow = head;

        while( fast != nullptr && fast->next != nullptr )
        {
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow)
            {
                auto index1 = head;
                auto index2 = slow;
                while(index1 != index2)
                {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2;
            }
        }
        return nullptr;

两两交换链表中的节点

总结:个人感觉和另一道以k个节点为一组反转链表中节点的题目有点异曲同工之妙,此题关键要解决的问题:1、找到每组交换之前的头节点 。2、使每组交换之后链接起来。

代码:

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        auto phead = new ListNode(0);
        phead->next = head;
        auto cur = phead;
        while(cur->next != nullptr && cur->next->next != nullptr)
        {
            auto temp = cur->next;
            auto temp1 = cur->next->next->next;

            cur->next = cur->next->next;
            cur->next->next = temp;
            cur->next->next->next = temp1;

            cur = cur->next->next;

        }
        return phead->next;
    }
};

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

总结:此题为了避免若要删除头节点而不方便处理后续节点的情况需设置一个虚拟头节点,再巧妙利用双指针,利用好倒数的数字n,当快慢指针之间相隔n个节点且快指针已经到达null的时候,慢指针则刚好是倒数第N个节点的前一个节点。其中需要注意因为设置了一个虚拟头节点,所以快指针需要在原有的基础上再向前走一步。

代码:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(head == nullptr)
        return nullptr;
        auto dummy = new ListNode(0);
        dummy->next = head;

        auto fast = dummy;
        auto slow = dummy;
        while(n--)
        {
            fast = fast->next;
        }
        fast = fast->next;
        while(fast != nullptr)
        {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next;
        return dummy->next;
    }
};

链表相接

总结:此题需要注意的点在,如果两个指针分别从两处出发,因为他们有共同的部分,所以如果他们分别在遍历完自身的节点之后设置为另一个链表的头指针再次开始遍历的话他们就会在相交处相等。

代码

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        auto p1 = headA;
		auto p2 = headB;

		while (p1 != p2) 
		{
			p1=(p1 == NULL)?headB:p1->next;
			p2=(p2 == NULL)?headA:p2->next;
		}
		return p1;
    }
};

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