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

题目:

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

示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.

当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:

给定的 n 保证是有效的。

进阶:

你能尝试使用一趟扫描实现吗?

解答:

自己的解答:

ListNode* removeNthFromEnd(ListNode* head, int n) 
{
    if (n <= 0)
        return head;

    ListNode* tmp = head;
    int num = 0;
    while (tmp != nullptr)
    {
        num++;
        tmp = tmp->next;
    }

    if (n == num)
        return head->next;

    ListNode* headTmp = head;
    ListNode* pre;
    int deleteK = num - n;
    int idx = 0;
    while (idx < deleteK)
    {
        pre = headTmp;
        headTmp = headTmp->next;
        idx++;
    }

    pre->next = headTmp->next;
    delete headTmp;
    return head;
}

答案里用双指针:

  由于我们需要找到倒数第 n 个节点,因此我们可以使用两个指针 first 和 second 同时对链表进行遍历,并且first 比second 超前 n 个节点。当first 遍历到链表的末尾时,second 就恰好处于倒数第 n 个节点。

  具体地,初始时first 和 second 均指向头节点。我们首先使用first 对链表进行遍历,遍历的次数为 n。此时,first 和 second 之间间隔了 n−1 个节点,即first 比second 超前了n 个节点。

  在这之后,我们同时使用first 和 second 对链表进行遍历。当 first 遍历到链表的末尾(即 first 为空指针)时,second 恰好指向倒数第 n 个节点。

根据该思路编写代码如下:

ListNode* removeNthFromEnd2(ListNode* head, int n)
{
    if (n == 0)
        return head;

    ListNode* tmp = head;
    int num = 0;
    while (tmp != nullptr)
    {
        num++;
        tmp = tmp->next;
    }

    if (n == num)
        return head->next;

    ListNode* first = head;
    ListNode* second = head;

    int idx = 0;
    while (idx < n)
    {
        first = first->next;
        idx++;
    }

    while (first->next != nullptr)
    {
        first = first->next;
        second = second->next;
    }

    first = second;
    second = second->next;
    first->next = second->next;
    delete second;

    return head;
}

  看了题解的答案,并没有统计链表元素的个数,解答的代码如下:

 示意图如下图所示:

 图片来源:

https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/

原文地址:https://www.cnblogs.com/zyk1113/p/13984247.html