• LeetCode 19——删除链表的倒数第 N 个节点


    1. 题目

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

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

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

    进阶:
    你能尝试使用一趟扫描实现吗?

    2. 思路

    • 定义两个指针 p1、p2,刚开始两个指针都指向头结点。如果要删除倒数第 N 个结点,我们就让 p2 先前进 N-1 步,这时候 p2 后面的节点个数为 K,那我们要删除的结点也就是位于 p1 后面的第 K 个结点

    • 如下图所示,假设我们要删除倒数第 3 个结点,p2 前进 2 步后指向第三个结点。

    1.png

    • p2 后面还有 1 个结点,而我们要删除的结点也就是位于 p1 后面的第 1 个结点——结点 2。

    2.png

    • 一种特殊情况是要删除倒数第 4 个结点,也就是第 1 个结点。这时候,我们只需要让 head 指向第 2 个结点即可。

    3.png

    • 其他情况下,在 p2 指针到达指定位置后。我们先让 p2 指针后移一个位置,然后再同时让 p1 和 p2 向后移动。当 p2 指向最后一个结点时,p1 就指向了待删除节点的前一个结点,此时让 p1 指向 p1 后面的第 2 个结点即可删除指定的结点。

    • 以下为删除倒数第 1 个结点的过程。

    4.png

    5.png

    • 当然,不要忘了释放删除结点的内存
    • 代码如下
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) {
            
            if (head == NULL)
            {
                return head;
            }
    
            else
            {
                int i = 1;
                ListNode *p1 = head, *p2 = head, *temp = NULL;
                
                while (i != n) // p2 指针前进 n-1 步
                {
                    i++;
                    p2 = p2->next;
                }
                
                if (p2->next == NULL) // 删除第一个结点的情况
                {
                    temp = head;
                    head = head->next; // head 指向第 2 个结点
                }
                else
                {
                    p2 = p2->next; // p2 指针先前进 1 步
                
                    while(p2->next)  // p1、p2 指针同步向后移动
                    {
                        p2 = p2->next;
                        p1 = p1->next;
                    }
    
                    temp = p1->next;
                    p1->next = p1->next->next; // p1 指向其后面的第 2 个结点
                }
                
                delete(temp); // 释放结点内存
                
            }   
                
            return head;
                
        }
            
    };
    
    

    获取更多精彩,请关注「seniusen」!
    seniusen

  • 相关阅读:
    《C#多线程编程实战》2.7 CountDownEvent
    《C#多线程编程实战》2.6 ManualResetEventSlim
    《C#多线程编程实战》2.5 AutoResetEvent
    《C#多线程编程实战》2.4 SemaphoreSlim
    ConcurrentDictionary与Dictionary 替换
    vs2017 代码格式化 文档排版 编辑 设置文档的格式
    面试笔记
    way.js
    SQL Server 2008 技巧快捷键
    CentOS下Docker与.netcore(四)之 三剑客之一Docker-machine+jenkins简单自动化部署
  • 原文地址:https://www.cnblogs.com/seniusen/p/9823412.html
Copyright © 2020-2023  润新知