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

题目

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

示例

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

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

说明:给定的 n 保证是有效的。

题目来源

分析

这道题的关键点就在链表的长度不知道,所以链表的长度尤为重要,最简单的方法就是,先遍历一遍链表,知道了长度之后再设定计数变量去遍历,就可以找到要删除的节点。

但仔细想想,没有办法只遍历一次了吗?当然可以,我们借鉴之前做过的链表中间节点的经验,可以这样设定一个指针先出发,再设一个指针慢出发,慢多少,就慢n+1拍,这样快指针结束遍历,慢指针此时就在倒数第n个节点的前一个节点,这样就可以将其残忍地删除。可一切都没有结束,如果n为表长的时候,快指针遍历完毕了,慢指针还在第一个节点,怎么办?此时要删除的就是第一个节点,把第一个节点的下一个节点返回就行了。

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

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

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

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

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

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

代码实现

/**

*C语言

*/

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


struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    struct ListNode *front = head;
    struct ListNode *rear = head;

    //遍历链表
    while( front != NULL )
    {
        //计数结束的条件
        if( n < 0 )
        {
            rear = rear->next;
        }
        n--;
        front = front->next;
    }
    //当n是表长的情况下,返回头结点的下一个即可。
    if( n==0 )
    {
        return head->next;
    }

    struct ListNode *temp = rear->next;
    rear->next = rear->next->next; 
    free(temp);

    return head;
}