## 算法记录Day 4 | 链表part02

91 阅读4分钟

算法记录Day 4 | 链表part01

LeetCode 24-两两交换链表中的节点

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

输入: head = [1,2,3,4]
输出: [2,1,4,3]

题目链接:leetcode.cn/problems/sw…

题解
class Solution {
   public:
    ListNode *swapPairs(ListNode *head) {
        if (head == nullptr || head->next == nullptr) {
            return head;
        }
        ListNode *dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode *cur = dummyHead;
        while (cur->next != nullptr && cur->next->next != nullptr) {
            ListNode *temp = cur->next;
            ListNode *temp2 = cur->next->next->next;

            cur->next = cur->next->next;
            cur->next->next = temp;
            cur->next->next->next = temp2;

            cur = cur->next->next;
        }

        return dummyHead->next;
    }
};
解题思路

借助一个虚拟头结点,这里的边界需要保证链表长度大于1的情况才需要交换,因此需要处理链表长度和剩下链表结点数量小于等于1。接下来就是使用临时变量存储需要交换的结点,然后更新cur结点指向的指针,先更新后一个结点,再更新前一个结点。

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

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

题目链接:leetcode.cn/problems/re…

输入: head = [1,2,3,4,5], n = 2
输出: [1,2,3,5]
题解
class Solution {
   public:
    ListNode *removeNthFromEnd(ListNode *head, int n) {
        if (head == nullptr) {
            return head;
        }
        ListNode *dummyNode = new ListNode(0);
        dummyNode->next = head;
        ListNode *fast = dummyNode, *slow = dummyNode;
        while (n--) {
            fast = fast->next;
        }
        while (fast->next != nullptr) {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next;
        return dummyNode->next;
    }
};
解题思路

先前进n步,再用快慢指针的思想,当快指针走到最后一个结点,那么慢指针指向的下一个结点就是要被移除的。

LeetCode 面试题02.07.链表相交

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

题目链接:leetcode.cn/problems/in…

输入: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出: Intersected at '8'
解释: 相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
题解
class Solution {
   public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *h1 = headA, *h2 = headB;
        while (h1 != h2) {
            if (h1 != nullptr) {
                h1 = h1->next;
            } else {
                h1 = headB;
            }

            if (h2 != nullptr) {
                h2 = h2->next;
            } else {
                h2 = headA;
            }
        }
        return h1;
    }
};
解题思路

当较短的链表走到末尾,就从另一个链表继续遍历,如果有相交的结点就会相遇,如果两个链表没有相交,最终会h1 = h2 = nullptr。

LeetCode 142-环形链表II

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 *如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。 不允许修改链表。

题目链接:leetcode.cn/problems/in…

输入: head = [3,2,0,-4], pos = 1
输出: 返回索引为 1 的链表节点
解释: 链表中有一个环,其尾部连接到第二个节点。
题解
class Solution {
   public:
    ListNode *detectCycle(ListNode *head) {
        if (head == nullptr) {
            return head;
        }
        ListNode *fast = head, *slow = head;
        while (fast != nullptr && fast->next != nullptr) {
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) {
                break;
            }
        }
        if (fast == nullptr || fast->next == nullptr) {
            return nullptr;
        }
        slow = head;
        while (slow != fast) {
            fast = fast->next;
            slow = slow->next;
        }

        return fast;
    }
};
解题思路

使用快慢指针,如果存在环那么它们一定会相遇。那么如何找到环的入口?从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是环形入口的节点。