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

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

题目链接/文章讲解/视频讲解:力扣24. 两两交换链表中的节点

代码实现: 

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* cur = dummyHead;
        while(cur->next != NULL && cur->next->next != NULL)
        {
            ListNode* tmp = cur->next;  //临时存储变量的tmp要在循环内定义
            ListNode* tmp1 = cur->next->next->next;
            cur->next = cur->next->next;
            cur->next->next = tmp;
            tmp->next = tmp1;
            cur = cur->next->next;  //cur移动两位,准备下一轮交换
        }
        return dummyHead->next;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

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

题目链接/文章讲解/视频讲解:力扣 19.删除链表的倒数第N个节点

思考:关键在于如何用双指针来找到倒数第n个节点

代码实现: 

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
        {
            fast = fast->next;
        }
        while(fast != NULL)
        {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next;
        return dummyHead->next;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

三、面试题 02.07. 链表相交

题目链接/文章讲解/视频讲解:力扣 面试题 02.07. 链表相交

思考:

1.交点不是数值相等,而是指针相等

2.较长链表前面的部分一定不是目标节点,利用这点通过两个链表的长度差来解题。

代码实现: 

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != NULL) // 求链表A的长度
        { 
            lenA++;
            curA = curA->next;
        }
        while (curB != NULL) // 求链表B的长度
        { 
            lenB++;
            curB = curB->next;
        }
        curA = headA;
        curB = headB;
        // 让curA为最长链表的头,lenA为其长度
        if (lenB > lenA) 
        {
            swap (lenA, lenB);
            swap (curA, curB);
        }
        // 求长度差
        int gap = lenA - lenB;
        // 让curA和curB在同一起点上(末尾位置对齐)
        while (gap--) 
        {
            curA = curA->next;
        }
        // 遍历curA 和 curB,遇到相同则直接返回
        while (curA != NULL) 
        {
            if (curA == curB) 
            {
                return curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
    }
};
  • 时间复杂度:O(n + m)
  • 空间复杂度:O(1)

四、142.环形链表II

思考:这道题第一次做可能想不到解体方法,它不仅考察对链表的操作,而且还需要一些数学运算

主要考察的知识点:

  • 判断链表是否环:快慢指针法
  • 如果有环,如何找到这个环的入口:数学运算

代码实现:

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 = head;
            ListNode* index2 = fast;
            while(index1 != index2)
            {
                index1 = index1->next;
                index2 = index2->next;
            }
            return index1;
        }
        }
        
        return NULL;
    }
};
  • 时间复杂度: O(n),快慢指针相遇前,指针走的次数小于链表长度,快慢指针相遇后,两个index指针走的次数也小于链表长度,总体为走的次数小于 2n
  • 空间复杂度: O(1)

你可能感兴趣的:(算法)