zoukankan      html  css  js  c++  java
  • 【LeetCode-链表】删除链表的倒数第N个节点

    题目描述

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

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

    说明:
    给定的 n 保证是有效的。
    进阶:
    你能尝试使用一趟扫描实现吗?
    题目链接https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/

    思路1

    链表倒数第 n 个节点就是正数的第 len-n 个节点,其中 len 为链表长度。所以,先遍历链表一遍求长度 len,然后在遍历到链表的第 len-n 个节点前执行删除操作。需要注意的是,由于删除的可能是链表的第一个节点,所以需要使用一个新的链表头(哑结点)指向原来的链表。代码如下:

    /**
     * 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==nullptr) return nullptr;
    
            int len = getLen(head);
            ListNode* dummyHead = new ListNode(0);
            dummyHead->next = head;
            ListNode* curNode = dummyHead;
            for(int i=0; i<len-n; i++){ // 循环 len-n 次,得到原链表中第 len-n-1 个节点(编号从 1 开始)
                curNode = curNode->next;
            }
            curNode->next = curNode->next->next;
    
            return dummyHead->next;
        }
    
        int getLen(ListNode* head){
            int len = 0;
            while(head!=nullptr){
                len++;
                head = head->next;
            }
            return len;
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    思路2

    使用两个指针 p1, p2. p1 和 p2 初始都指向哑结点 dummyHead,然后 p2 先走 n 步,然后 p1 和 p2 共同往后走,当 p2->next==nullptr 时停止移动两个指针,此时 p1->next 就是倒数第 n 个节点。代码如下:

    /**
     * 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==nullptr) return nullptr;
    
            ListNode* dummyHead = new ListNode(0);
            dummyHead->next = head;
            ListNode* p1 = dummyHead;
            ListNode* p2 = dummyHead;
            for(int i=0; i<n; i++) p2 = p2->next;
            while(p2->next!=nullptr){
                p1 = p1->next;
                p2 = p2->next;
            }
            p1->next = p1->next->next;
            return dummyHead->next;
            
        }
    };
    
    • 时间复杂度:O(n)
    • 空间复杂度:O(1)

    总结

    这个问题的难点在于不好确定应该移动几步,例如思路 2 中,p2 是先移动 n 步,还是 n-1 步或者 n+1 步。遇到这种问题,可以在纸上画出来分析一下,可以很快得出答案。

  • 相关阅读:
    Delphi 的字符及字符串[4] 字符串、字符指针与字符数组
    Delphi 的字符及字符串[5] 字符串与 Windows API
    WinAPI: FindWindow、FindWindowEx 查找窗口
    java LookAndFeel 美化 Substance使用
    持久化和对象关系映射ORM技术
    java 更换皮肤问题Cannot refer to a nonfinal variable inside an inner class defined in a different method
    java Swing可视化开发工具
    php ORM 持久层框架与简单代码实现
    生成Substance皮肤Menu项的代码
    三层架构实现
  • 原文地址:https://www.cnblogs.com/flix/p/13096109.html
Copyright © 2011-2022 走看看