试解leetcode算法题--删除链表的倒数第N个节点

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

示例:给定一个链表: 1->2->3->4->5, 和 n = 2。当删除了倒数第二个节点后,链表变为 1->2->3->5.

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

/** 后台定义了这样的链表,在之后可以直接使用。 * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */

<原题链接>
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
<理明思路>
删除倒数第n个数也即是删除正数第N-n+1(N是链表的总长度)个数,按照这个思路,我们可以先算出链表的长度,然后将指针定位到要删除结点的前一个结点,只需让其将要删除的结点所指向的结点作为新结点(就是前一个点直接指向下下个结点,然后free掉要删除的结点)即可。
<样例代码>
ps:被注释掉的代码的用途是为了更快速准确地排除 调试时的各种bug,不影响程序正常运行,也不影响最终结果。

#include<iostream>
#include<stdlib.h>
using namespace std;
/* 这里为方便调试并且能够在编译器下让程序正常运行,定义了与一个题目中一样的全局变量。
    struct ListNode {
       int val;
       ListNode *next;
       ListNode(int x) : val(x), next(NULL) {}
    };
*/
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(n<1) exit(0);        /* case1:n的取值错误。 */
        ListNode *p,*q;
        int length = 1;
        q=NULL;
        p=head;

        while(p->next!=NULL)
        {
            length++;                //得到链表长度。
            p=p->next;
        }
//      cout<<"length="<<length<<endl;

        if(n>length) exit(1);  /* case2:n取值大于链表长度。 */

        p=head;                 //回到表头。
        if(length==1)           /* case3:如果链表只有1个结点,依据之前的if,只需删除该节点即可。 */
            return NULL;

        if(length-n==0 && length!=1)                //如果要删除第一个结点(倒数最后一个)
        {
            head=p->next;
/* 输出调试用:
        p=head;
        cout<<"新链表为:";
        while(p->next!=NULL)
        {
            cout<<p->val<<" ";
            p=p->next;
        }
        cout<<p->val<<" ";
        cout<<endl; 
*/
            return head;
        }
        for(int i=1;i<length-n+1;i++)
        {
            q=p;                        //将当前p赋给q.
            p=p->next;                  //p指向下一个结点.
        }
//      cout<<"p->val="<<p->val<<endl;
//      cout<<"q->val="<<q->val<<endl;
        q->next=p->next;
        free(p);
/* 输出调试用:
        p=head;
        cout<<"新链表为:";
        while(p->next!=NULL)
        {
            cout<<p->val<<" ";
            p=p->next;
        }
        cout<<p->val<<" ";
        cout<<endl;  
*/
        return head;
    }
};

另附调试结果用的main函数示例(参考用,通过修改第 6 行和第 28 行的数值来得到不同的运行结果):

int main()
{
    struct ListNode *head,*p,*q;
    head=NULL;
    q=NULL;
    for(int i=1;i<=4;i++)
    {
        p=(struct ListNode*)malloc(sizeof(struct ListNode));
        p->val = i;
        p->next=NULL;
        if(head==NULL) head=p;
        else
            q->next=p;
        q=p;
    }
/*输出调试用
    p=head;
    cout<<"原链表为:";
        while(p->next!=NULL)
        {
            cout<<p->val<<" ";
            p=p->next;
        }
        cout<<p->val<<" ";
        cout<<endl;
*/
    Solution slu;
    slu.removeNthFromEnd(head,2);
    return 0;
}

ps:刚刚自学了链表,这道题算是现学现用吧,代码写起来还是有些生疏呢。。。。

点赞