删除链表的第N个节点|栈、双指针

删除链表的倒数第N个节点

类似于删除链表中的第N个节点,但是这里是倒数第N个且不知道链表的长度,如果用删除第N个节点的方法去解决问题的时候需要先知道链表的长度。这就需要遍历一遍链表,然后删除还需要再遍历一遍所以这会增大开销,但不失为一种方法。这里给出两种不需要知道链表长度的解题方法,使用栈和双指针法。

对应题目19. 删除链表的倒数第 N 个结点🐾

首先建议先去菜鸟看看栈的定义和方法C++ Stack。由于栈的特性,可以很好得解决这种倒数问题。先让所有节点压入栈中,随后再弹出\(N\)个节点。此时,栈顶的节点即为要删除节点的前一位。分析复杂度,压栈操作需要将所有节点压入所以时间复杂度为\(O(N)\);同时开辟了一个空间去保存栈,所以空间复杂度也为\(O(N)\)

ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0,head);
        ListNode* p = dummyHead;
        //define a stack as myStack.
        stack<ListNode*> myStack;
        //push all the nodes into myStac.
        while(p != nullptr) {
            myStack.push(p);
            p = p->next;
        }
        //pop those nodes after the number 'n-1' from the end of the list.
        //find the previous node of the one of the number 'n' 
        for(int i = 0;i < n;i ++) {
            myStack.pop();
        }
        //remove the target node.
        ListNode* pre = myStack.top();
        pre->next = pre->next->next;
        return dummyHead->next;
}

双指针

又是老熟人双指针。这次需要使用到快慢指针进行操作。定义一快一慢指针初始都指向虚拟头结点,然后快指针先移动\(N\)位,再将快指针和慢指针同时移动直到快指针指向链表末尾。这是慢指针所指的即为需要删除节点的前一位。分析复杂度,由于需要遍历一遍链表所以时间复杂度为\(O(N)\);空间复杂度为\(O(1)\)

ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0,head);
        // define a fast pointer and a slow pointer.
        // they both point the dummyHead initially.
        ListNode* fast = dummyHead;
        ListNode* slow = dummyHead;
        // move the fast one.
        for(int i = 0;i < n;i++) {
            fast = fast->next;
        }
        // move both them until the end of the list.
        while(fast->next != nullptr) {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next;
        return dummyHead->next;
}
posted on 2023-03-29 12:11  Coeleone  阅读(53)  评论(0)    收藏  举报