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 步。遇到这种问题,可以在纸上画出来分析一下,可以很快得出答案。

  • 相关阅读:
    How to install VXDIAG Honda, Toyota and JLR SDD software
    16% off MPPS V16 ECU tuning tool for EDC15 EDC16 EDC17
    Cummins INSITE locked and ask for verification code
    How to use BMW Multi Tool 7.3 to replace lost key for BMW X1
    Bleed Brake Master Cylinder with Intelligent Tester IT2
    Porsche Piwis Tester II “No VCI has been detected”,how to do?
    Creader VIII VS. Creader VII+
    How to solve GM MDI cannot complete the installation
    汽车OBD2诊断程序开发 (原文转载,思路很清晰!)
    汽车节温器单片机开发思路
  • 原文地址:https://www.cnblogs.com/flix/p/13096109.html
Copyright © 2011-2022 走看看