Bootstrap

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

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

leetcode题目链接
思路:遍历链表,进行两两交换的操作。

注意的点:

  1. 遍历的点指在哪里(必须指在两两交换的前一个节点)
  2. 遍历终止的条件是什么
  3. 两两操作的逻辑
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *dummyhead = new ListNode(0);
        dummyhead->next = head;
        
        ListNode *tmp = head;
        ListNode *prev = dummyhead;
        while (tmp && tmp->next) {
            ListNode *next = tmp->next->next;
            tmp->next->next = tmp;
            prev->next = tmp->next;
            tmp->next = next;
            prev = tmp;
            tmp = next;
        }
        return dummyhead->next;
    }
};

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

leetcode题目链接
定义一个快指针和一个慢指针,快指针比慢指针快n步,然后当快指针的next指向NULL时,也就是慢指针指向要被删除的元素的前一个。进行删除操作即可。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyhead = new ListNode(0);
        dummyhead->next = head;
        ListNode* fast = dummyhead;
        ListNode* slow = dummyhead;
        for (int i = 0; i < n; ++i) {
            fast = fast->next;
        }
        while (fast->next) {
            fast = fast->next;
            slow = slow->next;
        }
        ListNode *deleted = slow->next;
        slow->next = deleted->next;
        delete(deleted);
        return dummyhead->next;
    }
};

面试题 02.07. 链表相交

leetcode题目链接
求出两个链表的长度,一个指针指向短的链表头节点,另一个指向长链表+两链表长度差的节点,然后判断指针是否相同。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int len1 = 0, len2 = 0;
        ListNode *n1 = headA;
        ListNode *n2 = headB;

        while (n1) {
            len1++;
            n1 = n1->next;
        }

        while (n2) {
            len2++;
            n2 = n2->next;
        }

        n1 = headA;
        n2 = headB;
        if (len1 > len2) {
            int tmp = len1;
            len1 = len2;
            len2 = tmp;
            ListNode *tmpn = n1;
            n1 = n2;
            n2 = tmpn;
        }
        int distance = len2 - len1;
        while (distance--) {
            n2 = n2->next;
        }
        while (n1) {
            if (n1 == n2)
                return n1;
            n1 = n1->next;
            n2 = n2->next;
        }
        return NULL;
    }
};

142.环形链表II

leetcode题目链接
怎么判断链表是否有环形呢?设置一个快指针,一个慢指针,快指针每次走两步,慢指针每次走一步,如果两个指针会相遇,那么存在环形链表。

怎么找到环形链表入口呢?具体证明过程不写了,操作过程如下:

  1. 同样是快慢指针,记录下两指针相遇的节点。
  2. 定义另一个指针从头节点开始,一个从相遇节点开始,都是一步一步走,相遇的地方就是环形链表入口。
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head;
        ListNode *slow = head;
        while (fast && fast->next) {
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) {
                ListNode *intersection = fast;
                ListNode *tmp = head;
                while (intersection != tmp) {
                    intersection = intersection->next;
                    tmp = tmp->next;
                }
                return intersection;
            }
        }
        return NULL;
    }
};

总结

虚拟链表使用场景一般是头节点情况需要单独处理的情况,也就是插入、删除节点的场景。

;