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

  • 题目

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

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

代码随想录第四天|24.两两交换链表中的节点、19、删除链表的倒数第N个节点、面试题02.07.链表相交、142环形链表②_第1张图片

 利用虚拟头结点进行操作。

代码随想录第四天|24.两两交换链表中的节点、19、删除链表的倒数第N个节点、面试题02.07.链表相交、142环形链表②_第2张图片

得到:

代码随想录第四天|24.两两交换链表中的节点、19、删除链表的倒数第N个节点、面试题02.07.链表相交、142环形链表②_第3张图片

代码:

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

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

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

代码随想录第四天|24.两两交换链表中的节点、19、删除链表的倒数第N个节点、面试题02.07.链表相交、142环形链表②_第4张图片

 首先设置虚拟节点,方便处理删除实际头结点的逻辑。

利用双指针原理,设置一个快指针,一个慢指针,两指针之间相差n步或n+1步,随后两者同时移动,直至fast指向NULL的前一个或NULL。

最后删除slow指向的下一个节点。

代码随想录第四天|24.两两交换链表中的节点、19、删除链表的倒数第N个节点、面试题02.07.链表相交、142环形链表②_第5张图片

代码随想录第四天|24.两两交换链表中的节点、19、删除链表的倒数第N个节点、面试题02.07.链表相交、142环形链表②_第6张图片

代码随想录第四天|24.两两交换链表中的节点、19、删除链表的倒数第N个节点、面试题02.07.链表相交、142环形链表②_第7张图片 

代码随想录第四天|24.两两交换链表中的节点、19、删除链表的倒数第N个节点、面试题02.07.链表相交、142环形链表②_第8张图片 

 代码:

//走n步
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* virtualNode=new ListNode(0);
        virtualNode->next=head;
        ListNode* fast=virtualNode;
        ListNode* slow=virtualNode;
        while(n--) {
            fast=fast->next;
        }
        while(fast->next!=nullptr) {
            fast=fast->next;
            slow=slow->next;
        }
        ListNode* cur=slow->next;
        slow->next=slow->next->next;
        delete(cur);
        return virtualNode->next;
    }
};
//走n+1步
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* slow = dummyHead;
        ListNode* fast = dummyHead;
        while(n-- && fast != NULL) {
            fast = fast->next;
        }
        fast = fast->next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
        while (fast != NULL) {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next; 
        
        // ListNode *tmp = slow->next;  C++释放内存的逻辑
        // slow->next = tmp->next;
        // delete nth;
        
        return dummyHead->next;
    }
};

面试题 02.07链表相交

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

代码随想录第四天|24.两两交换链表中的节点、19、删除链表的倒数第N个节点、面试题02.07.链表相交、142环形链表②_第9张图片

首先可求出两链表长度,并求出差值,让相对长的链表移动到与另一链表末尾对齐的位置。

比较两指针是否相同,相同则找到交点,不同则将两指针向后移。

若都不满足则退出返回空指针。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int numA=0;
        int numB=0;
        ListNode* curA=headA;
        ListNode* curB=headB;
        while(curA!=NULL) {
            curA=curA->next;
            numA++;
        }
        while(curB!=NULL) {
            curB=curB->next;
            numB++;
        }
        curA=headA;
        curB=headB;
        int gap=abs(numA-numB);
        if(numB>numA) {
            swap(numA,numB);
            swap(curA,curB);
        }
        while(gap--) {
            curA=curA->next;
        }
        while(curA!=NULL) {
            if(curA==curB) return curA;
            curA=curA->next;
            curB=curB->next;
        }
        return NULL;
    }
};

142.环形链表

 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

 首先需要判断链表是否有环,分别定义fast和slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次只移动一个节点,若两指针在途中相遇说明链表有环。

接下来需要找到环的入口。

代码随想录第四天|24.两两交换链表中的节点、19、删除链表的倒数第N个节点、面试题02.07.链表相交、142环形链表②_第10张图片

相遇时,slow走x+y,fast走x+y+n(y+z) ,fast走的是slow的二倍,故(x+y)*2=x+y+n(y+z)         —>x+y=n(y+z) —>x=(n-1)(y+z)+z。当n=1时,x=z,表明,从头节点出发一指针,相遇节点出发一指针,两者相遇的节点即为环入口节点。当n!=1时,表明fast在转n圈之后与slow相遇,同样为n=1时的情形。

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

 

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