LeetCode 19. Remove Nth Node From End of List

106 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情

LeetCode 19. Remove Nth Node From End of List

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

示例 1:

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

示例 2:

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

示例 3:

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

 

提示:

  • 链表中结点的数目为 sz
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz C++ 代码 /**
  • Definition for singly-linked list.
  • struct ListNode {
  • int val;
    
  • ListNode *next;
    
  • ListNode(int x) : val(x), next(NULL) {}
    
  • };

进阶: 你能尝试使用一趟扫描实现吗?

算法1

(两次遍历) 第一次遍历求出链表长度。
第二次遍历删掉指定结点。
注意删除头结点的特殊情况。
时间复杂度
遍历两次链表,故空间复杂度为 O(L)。
空间复杂度
仅需要定义常数个指针变量,故空间复杂度为 O(1)。

ac代码
class Solution {
public:
   ListNode* removeNthFromEnd(ListNode* head, int n) {
       int len = 0;
       for (ListNode *cur = head; cur != NULL; cur = cur -> next)
           len++;
       if (len == n)
           return head -> next;
       int cnt = 0;
       for (ListNode *cur = head; cur != NULL; cur = cur -> next) {
           cnt++;
           if (cnt == len - n) {
               cur -> next = cur -> next -> next;
               break;
           }
       }
       return head;
   }
};

算法2

(一次遍历)
在头部之前添加保护结点。
设置两个指针 first 和 second,均指向保护结点。
first 指针先向后移动 n+1 个结点。
然后 first 和 second 指针同时向后移动,直到 first 指针指向空,此时 second 结点指向的下一个结点需要删除。
解释:始终保持两个指针之间间隔 n 个结点,在 first 到达终点时,second 的下一个结点就是从结尾数第 n个 结点。
时间复杂度 遍历两次链表,故空间复杂度为 O(L)。 空间复杂度 仅需要定义常数个指针变量,故空间复杂度为 O(1)。

ac 代码:
/**
 * 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) {
        ListNode* ext_head = new ListNode(0);
        ext_head -> next = head;

        ListNode* first = ext_head;
        ListNode* second = ext_head;

        for (int i = 0; i <= n; i++)
            first = first -> next;

        while (first != NULL) {
            first = first -> next;
            second = second -> next;
        }
        second -> next = second -> next -> next;

        return ext_head -> next;
    }
};