leetcode 19 Remove Nth Node From End of List

Remove Nth Node From End of List
Total Accepted: 74559 Total Submissions: 274808 Difficulty: Easy

Given a linked list, remove the nth node from the end of list and return its head.

For example,

Given linked list: 1->2->3->4->5, and n = 2.

After removing the second node from the end, the linked list becomes 1->2->3->5.

Note:
Given n will always be valid.
Try to do this in one pass.

因为这道题要求尽量只通过一次遍历就求出结果,这样的问题是这是单向链表,在我们到达最后链表尾端之前,我们都不知道我们距离末尾还有多远,这样一来一个最直接的想法就是我们可以先遍历一遍链表得到链表的长度,这样用长度减去指定的n,就知道这个要删除的节点是正着数的第几个,然后再沿着链表去找到这个节点并删除它。但这样的问题就是如果发现要删除的节点是正着数的最后一个,那么我们要删除它, 实际上要在遍历一遍链表,算法总共就遍历了两次链表,这就不符合题目要求,虽然还是能通过测试。

那怎样才能做到只遍历一次呢,我们的问题是当我们走到链表末端时,我们知道要倒退几个节点,但是回不去。要解决这个问题,我们可以使用两个指针,第一个指针在前面走,第二个指针在它后面距离它n个位置跟着它走,当第一个指针到达最后一个节点时,第二个指针正好在倒数第n+1个节点,这个时候正好进行删除操作,值得注意的是如果第二个指针正好在倒数第n个节点,那么没法进行删除操作。

另外,如果要删除的是第一个节点,那么需要特殊的处理,即直接更新head指针到head->next,即让它指向第二个节点即可。

下面是完整代码

#include <iostream>
using namespace std;

struct ListNode 
{
     int val;
     struct ListNode *next;
};

struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{
    struct ListNode *f, *s;
    f = head;
    s = head;
    while(n > 0)
    {
        f = f->next;
        n--;
    }
    if(f == NULL)
    {
        return head->next;
    }
    while(f->next != NULL)
    {
        f = f->next;
        s = s->next;
    }

    s->next = s->next->next;

    return head;
}

int main()
{
    int inputSize;
    cout<<"Input the size of input:\n";
    cin>>inputSize;

    ListNode* head = NULL;
    ListNode** p;
    p = &head;

    for(int i = 0; i < inputSize; i++)
    {
        if((*p) != NULL)
        {
            (*p)->next = (ListNode*)malloc(sizeof(ListNode));
            cin>>(*p)->next->val;
            (*p)->next->next = NULL;
        }
        else
        {
            (*p) = (ListNode*)malloc(sizeof(ListNode));
            cin>>(*p)->val;
            (*p)->next = NULL;
        }

        p = &((*p)->next);
    }

    cout<<"\nInput which index to delete\n";
    int n;
    cin>>n;

    ListNode* nhead = removeNthFromEnd(head, n);

    for(int i = 0; i < inputSize - 1; i++)
    {
        cout<<nhead->val<<" ";
        nhead = nhead->next;
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值