每日一算法题-删除链表的倒数节点

105 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

一、题目

image.png

struct ListNode {
    int val;
    ListNode *next = nullptr;
    inline ListNode(int x, ListNode* next = nullptr) : val(x), next(next) { }
};

ListNode* removeReverseNode(ListNode* pHead, int n) {

}

int main(int, char**)
{
    ListNode p1(1);
    ListNode p2(2);
    ListNode p3(3);
    ListNode p4(4);
    ListNode p5(5);

    p1.next = &p2;
    p2.next = &p3;
    p3.next = &p4;
    p4.next = &p5;
    p5.next = nullptr;

    ListNode* node = removeReverseNode(&p1, 2);
    cout << node->val << endl;

    return 0;
}

二、分析

根据题意可知

难点一:
需要获取倒数第n个节点
因为是单向链表,所以不能直接从右往左数,
此时就需要有两个节点,一个节点先跑n步,
然后两个节点同时一步一步的跑,跑得快的节点跑到终点,
此时跑得慢的节点就刚好指向需要的节点。

由于是单向链表,删除节点又需要此节点的父节点,
所以在两个节点一起跑的时候还得记录跑得慢的父节点。

三、模拟

  1. 创建两个遍历节点 节点一 跑得快A
    节点二 跑得慢B

  2. 跑得快先跑 n减一
    跑得快A 走一步
    只要n不等于0就继续

  3. 两个节点一起跑
    跑的快A 走一步
    跑得慢B 走一步
    只要跑的快A没到终点就继续

  4. 删除节点

四、实现

ListNode* removeReverseNode(ListNode* pHead, int n) {
    ListNode* rabbit = pHead;
    ListNode* tortoise = pHead;
    ListNode* tortoiseParent = nullptr;

    while(n){
        --n;
        rabbit = rabbit->next;
    }
    while(rabbit){
        rabbit = rabbit->next;
        tortoiseParent = tortoise;
        tortoise = tortoise->next;
    }
    if(tortoiseParent){
        tortoiseParent->next = tortoise->next;
    }
    return tortoise;
}

五、结言

利用操场跑步原理,解题的思路就很明显了,而关键的点就在于如何获取倒数的节点,我们通过生活中平移测距的方法来解决问题,这道题就变得非常简答了

创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!