day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ

题目1:24  两两交换链表中的节点

题目链接:24 两两交换链表中的节点

题意

两两交换链表中相邻的节点,返回交换后链表的头节点

虚拟头节点

注意终止条件,考虑节点的奇偶数,根据奇偶数确定终止条件

day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ_第1张图片

注意定义中间变量,temp  temp1,节点的指向改变时,使用中间变量保存以前指向的节点,以便后续的链表查询操作

day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ_第2张图片

完整操作1

day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ_第3张图片

代码1

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyhead = new ListNode(0);
        dummyhead->next = head;
        ListNode* cur = dummyhead;//头节点交换时,要知道其前一个节点(dummyhead),所以cur=dummyhead
        while(cur->next!=NULL && cur->next->next!=NULL){
            ListNode* temp = cur->next;
            cur->next = cur->next->next;
            ListNode* temp1 = cur->next->next;
            cur->next->next = temp;
            temp->next = temp1;
            cur = cur->next->next;
        }
        return dummyhead->next;  
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

完整操作2(先将上述分析的需要定义的中间变量全部提前定义好)

day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ_第4张图片

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyhead = new ListNode(0);
        dummyhead->next = head;
        ListNode* cur = dummyhead;//头节点交换时,要知道其前一个节点(dummyhead),所以cur=dummyhead
        while(cur->next!=NULL && cur->next->next!=NULL){
            ListNode* temp = cur->next;
            ListNode* temp1 = cur->next->next->next;
            cur->next = cur->next->next;
            cur->next->next = temp;
            temp->next = temp1;
            cur = cur->next->next;
        }
        return dummyhead->next;  
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

题目2:19  删除链表的倒数第N个节点

题目链接:19 删除链表的倒数第N个节点

题意

删除链表中的倒数第n个节点,返回链表的头节点

虚拟头节点

先让fast走n+1步,然后fast和slow再同时移动,这样slow就会到达要删除节点的前一个节点

day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ_第5张图片

伪代码

day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ_第6张图片

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
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!=NULL){
            fast = fast->next;
            n--;
        }
        while(fast!=NULL){
            fast = fast->next;
            slow = slow->next;
        }
        ListNode* tmp = slow->next;//定义临时变量,用于释放内存
        slow->next = slow->next->next;
        delete tmp;
        return dummyhead->next;

    }
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

题目3:链表相交

题目链接:链表相交

题意

找到两个单链表相交的起始节点;如果没有交点,则返回NULL

注意交点不是数值相等,而是指针相等

步骤

①  链表A定义一个curA指针  curA=headA;  链表B定义一个curB指针 curB=headB

② 链表A的长度lenA   链表B的长度lenB  

③  lenA 与 lenB 的差gap

将curA移动gap步  此时curA与curB在相同的位置处(到链表末尾的距离相等)

curA与curB一同移动 若curA==curB 返回curA  否则,一直移动curA和curB

curA==NULL 代表curA与curB还是不相等,则返回NULL

day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ_第7张图片

代码1

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0;
        int lenB = 0;
        while(curA!=NULL){
            curA = curA->next;
            lenA++;
        }
        while(curB!=NULL){
            curB = curB->next;
            lenB++;
        }
        cout< lenA){
            swap(lenA,lenB);
            swap(curA,curB);
        }
        cout<next;
            gap--;
        }
        //这样curA与curB在同一长度处
        while(curA!=NULL && curA!=curB){
            curA=curA->next;
            curB=curB->next;
        }
        if(curA!=NULL){
            return curA;
        }
        else{
            return NULL;
        }



        
    }
};

代码2

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0;
        int lenB = 0;
        while(curA!=NULL){
            curA = curA->next;
            lenA++;
        }
        while(curB!=NULL){
            curB = curB->next;
            lenB++;
        }
        //此时curA  curB已经移动到了NULL位置,将curA curB重新指向head处
        curA = headA;
        curB = headB;
        //求解长度差
        //首先使得A是最长的链表
        if(lenB > lenA){
            swap(lenA,lenB);
            swap(curA,curB);
        }
        int gap = lenA - lenB;
        //将curA移动到与链表B对齐的位置
        while(gap){
            curA = curA->next;
            gap--;
        }
        //这样curA与curB在同一长度处
        while(curA!=NULL){
            if(curA==curB){
                return curA;
            }
            curA=curA->next;
            curB=curB->next;
        }  
        return NULL;
    }
};
  • 时间复杂度:O(n + m)
  • 空间复杂度:O(1)

题目4:142  环形链表Ⅱ

题目链接:142 环形链表Ⅱ

题意

判断链表有无环,有环的话则返回开始入环的第一个节点;无环则返回null

主要分两个步骤:

①判断有环  无环

使用fast  slow两个指针,fast每次走两个节点,slow每次走1个节点,若有环,则fast,slow一定会在环内相遇  因为相对于slow,fast是每次走1个节点靠近slow,所以一定会和slow重合

day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ_第8张图片

②有环的话,返回入环的第一个节点;无环的话,返回null

fast,slow相遇时,fast走过的节点数为x+y+n(y+z),slow走过的节点数为x+y

fast走过的节点数=2*slow走过的节点数   n>=1  

day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ_第9张图片

伪代码

day04 两两交换链表中的节点 删除链表的倒数第N个节点 链表相交 环形链表Ⅱ_第10张图片

代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
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 = fast;
                ListNode* index2 = head;
                while(index1!=index2){
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index1;
            }
        }
        return NULL;
    }
};
  • 时间复杂度: O(n),快慢指针相遇前,慢指针走的次数小于链表长度(没走1圈fast和slow就相遇了),快慢指针相遇后,两个index指针走的次数也小于链表长度,总体为走的次数小于 2n
  • 空间复杂度: O(1)

你可能感兴趣的:(链表,算法,leetcode)