leetcode复盘:19. 删除链表的倒数第N个节点

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

方法一:两重遍历(链表的遍历和删除)

(1)链表的遍历:利用临时节点一次遍历链表中的每一个节点,判断节点中的指针域是否为NULL,否则继续向后遍历;向后遍历过程为指向当前节点的指针,赋值为指向下一个节点的地址,即当前节点中的指针域;

(2)链表(a->b->c)删除节点b:删除节点b,只需要使节点a的指针域指向节点c即可,则该链表中不存在节点b;b的内存如何释放?节点内部动态申请的内存需要手动释放,简单数据结构由系统自动处理;

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{
    //二重遍历
    int lenAll = 0;
    struct ListNode *nodeTemp = head;
    //求链表长度
    while (nodeTemp != NULL) {
        lenAll++;
        nodeTemp = nodeTemp->next;
    }
    //异常情况
    if (lenAll == n) {
        return head->next;
    }
    //删除链表指定位置
    nodeTemp = head;
    //链表遍历到指定位置:被删除节点的前一个节点
    for (int i = 0; i < (lenAll - n -1); i++) {
        nodeTemp = nodeTemp->next;
    }
    //删除节点:复杂结构需要手动提前释放内存
    nodeTemp->next = nodeTemp->next->next;
    return head;
}

方法二:单次遍历(双指针法,滑动窗口)

(1)保证low和high的距离固定为n,则当high指向尾节点时,low就为倒数第n个节点
(2)删除节点的操作,需要指向被删除节点的上一个节点

struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{
    struct ListNode *low = head;
    struct ListNode *high = head;
    //将high前移n个节点 (删除节点时,需要保证low指在被删除的前一个节点)
    for (int i = 0; i < n - 1; i++) {
        high = high->next;
    }
    //high已经为尾节点,则被删除的肯定为第一个节点
    if (high->next == NULL) {
        return head->next;
    }
    //同时移动low,high,直到high为倒数第二个节点,因为只有这样,low才会指向被删除节点的前一个节点
    while (high->next->next != NULL) {
        low = low->next;
        high = high->next;
    }
    //删除low后面的一个节点
    low->next = low->next->next;
    return head;
}

运行结果

原文地址:https://www.cnblogs.com/HZL2017/p/13252599.html