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

posted @ 2020-06-11 21:11  Flix  阅读(172)  评论(0编辑  收藏  举报