• C++ 删除链表的倒数第N个结点


    C++ 删除链表的倒数第N个结点

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

    示例 1

    效果图

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

    示例2

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

    示例3

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

    提示:

    • 链表中结点的数目为 sz
    • 1 <= sz <= 30
    • 0 <= Node.val <= 100
    • 1 <= n <= sz

    思路/解法

    方式一

    使用一个vector容器保存当前链表的所有节点即可。

    TIPS:

      在删除结点的时候需要分三种情况进行讨论:

    1. 当删除的结点为最后一个结点时,需要判断当前的结点是一个还是多个。
    2. 当删除的结点为第一个结点时(由于第一种情况已经判断删除最后一个结点且当前总结点为一个的情况,所以这里不需要判断删除一个结点且结点个数为1的情况),直接删除并更新下一个结点即可。
    3. 当删除的结点为普通节点时,直接删除并更新下一结点即可。
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode() : val(0), next(nullptr) {}
     *     ListNode(int x) : val(x), next(nullptr) {}
     *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     * };
     */
    class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) 
        {
            ListNode* node   = head;
            ListNode* temp   = nullptr;
            int       size   = 0;
            bool      status = false;
            std::vector<ListNode*> lists;
            while(node != nullptr)
            {
                lists.push_back(node);
                node = node->next;
            }
            
            size = lists.size();
            if(1 == n)                      //删除最后一个元素
            {
                if(1 == size)
                {
                    delete lists[0];
                    goto Exit;
                }
                else
                {
                    delete lists[size - 1];
                    lists[size - 2]->next = nullptr;
                }
            }
            else if(size == n)              //删除第一个元素
            {
                delete lists[0];
                head = lists[1];
            }
            else
            {
                lists[size - n - 1]->next = lists[size - n + 1];
                delete lists[size - n];
            }
            status = true;
        Exit:
            if(!status)
            {
                head = nullptr;
            }
            return head;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    方式二

    快慢指针,一开始快慢指针都指向head结点。在删除倒数第N个结点时,先让快指针指向第N+1个结点的位置,然后慢指针跟随快指针移动,直至快指针的下一个结点为空即可,此时慢指针指向需要删除的结点的前一个结点。

    TIPS:算法未释放指针指向的动态空间。

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode() : val(0), next(nullptr) {}
     *     ListNode(int x) : val(x), next(nullptr) {}
     *     ListNode(int x, ListNode *next) : val(x), next(next) {}
     * };
     */
    class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) 
        {
            ListNode* quickPtr = head;
            ListNode* slowPtr  = head;
            bool      status   = false;
            int       size     = n;
            while(size)
            {
                quickPtr = quickPtr->next;
                size--;
            }
    
            if(nullptr == quickPtr)                  
            {
                if(1 == n)                              //链表只有一个结点
                {
                    goto Exit;
                }
                else                                    //删除第一个结点
                {
                    head = head->next;
                }
            }
            else
            {
                while(quickPtr->next != nullptr) 
                {
                    quickPtr = quickPtr->next;
                    slowPtr  = slowPtr->next;
                }
    
                slowPtr->next = slowPtr->next->next;    //删除结点
            }
    
           status = true;
        Exit:
            if(!status)
            {
                head = nullptr;
            }
            return head;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
  • 相关阅读:
    探秘Socks5代理在跨界电商、爬虫和游戏领域的应用
    推荐一个AI人工智能技术网站(一键收藏,应有尽有)
    go学习笔记
    腾讯云GPU云服务器计算型和渲染型分别适用于哪些场景?
    【Redis GEO】3、地理位置类型的性能优化及使用限制
    servlet -> spring-mvc -> spring-boot-> spring-security目录
    大道至简,CAN 诊断的本质,脱离cdd 和dbc ,纯手造轮子
    Java多线程开发系列之五:Springboot 中异步请求方法的使用
    VUE3写后台管理(3)
    每日一题——Python实现PAT甲级1132 Cut Integer(举一反三+思想解读+逐步优化)五千字好文
  • 原文地址:https://blog.csdn.net/qq135595696/article/details/126680336