《代码随想录》学习笔记---删除链表倒数第n个节点

一、题目

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

示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]


示例 2:
输入:head = [1], n = 1
输出:[]

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list

二、思路及解法

书上直接给出了快慢指针法,对于这一类窗口问题快慢指针确实是最优的,但是我首先想到的笨办法倒也能做对,简单说一下

1.硬反转

删除倒数嘛,整个反转删除正数第n个,然后再转回去就好了(正好上一节是反转)

方法很简单粗暴,没什么技术含量,直接上代码

ListNode* reverse(ListNode* head)
{
    ListNode* tmp;
    ListNode* pre = nullptr, * cur = head;
    while (cur != nullptr)
    {
        tmp = cur->next;
        cur->next = pre;
        pre = cur;
        cur = tmp;
    }
    return pre;
}
ListNode* removeNthFromEnd(ListNode* head, int n) 
{
    head = reverse(head);
    ListNode* illus_head = new ListNode(0);
    illus_head->next = head;
    ListNode* cur = illus_head;
    while (--n)
    {
        cur = cur->next;
    }
    ListNode* temp = cur->next;
    cur->next = cur->next->next;
    delete temp;
    illus_head->next = reverse(illus_head->next);
    return illus_head->next;
}

2.快慢指针法

用两个指针,因为要删倒数第n个,所以需要确定距尾节点n个位置的节点。而删除操作要求我们确定其父节点位置,所以正好用两个指针卡出一个长度为n的区间

当然,删除还是要加个虚拟头,方便处理

先让fast指针跑出n个位置,然后两个一起跑,直到fast跑到尾节点,此时slow就对应目标节点的父节点。

完整代码如下

ListNode* fastslow(ListNode* head, int n)
    {
        ListNode* pre, * cur;
        ListNode* dhead = new ListNode(0);
        dhead->next = head;
        cur = pre = dhead;
        while (n--&&cur!=nullptr)
        {
            cur = cur->next;
        }
        while (cur->next!= nullptr)
        {
            cur = cur->next;
            pre = pre->next;
        }
        ListNode* tmp;
        tmp = pre->next;
        pre->next = pre->next->next;
        delete tmp;
        tmp = nullptr;
        return dhead->next;
    }

3.注意事项

上述两个方法都有一个小雷区,即返回值的选择。我最开始写的时候直接返回的是head,但两种方法都错在了同一个case,即head = [1], n = 1

如果采用虚拟头,根据上述方法删除过后,这一case中的head已经被释放掉了(delete tmp),再返回就不知道返回了个什么东西。所以安全保险的方法是直接用illus_head->next做返回值,在上述特殊情况中,这个值一定是null

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值