19. Remove Nth Node From End of List 删除链表的倒数第 N 个结点


  • 作者: 负雪明烛
  • id: fuxuemingzhu
  • 个人博客:http://fuxuemingzhu.cn/open in new window
  • 个人公众号:负雪明烛
  • 本文关键词:链表, 删除节点,双指针,题解,leetcode, 力扣,Python, C++, Java

@TOC

题目地址:https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/

题目描述

Given a linked list, remove the n-th node from the end of list and return its head.

Example:

Given linked list: 1->2->3->4->5, and n = 2.

After removing the second node from the end, the linked list becomes 1->2->3->5.

Note:

  1. Given n will always be valid.

Follow up:

  • Could you do this in one pass?

题目大意

删除一个单链表的倒数第n个节点。

解题方法

双指针

先来分析一下这个题埋的坑吧。 第一,首先要判断这个n是不是有效,如果n超出链表长度怎么办,还好题目给了n是有效的。 第二,如果要删除头结点怎么办?估计很多人栽在了这个上面。 第三,题目说的是单链表没错,但是是否有环呢?当有环的时候,没有倒数第n个节点,你让我怎么办?很遗憾,题目没有说明这一点,我认为这是题目不严谨的地方。

具体到解法,这个题肯定是使用快慢指针啊,两个之间的距离是n,所以当快指针指向结尾的时候,慢指针正好指向了倒数第n个。因为要删除慢指针的位置,所以需要一个pre指针记录一下前面的那个节点的位置。

由于有可能删除首节点,所以使用哑结点当做新的头可以解决。

Python代码如下:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def removeNthFromEnd(self, head, n):
        """
        :type head: ListNode
        :type n: int
        :rtype: ListNode
        """
        root = ListNode(0)
        root.next = head
        fast, slow, pre = root, root, root
        while n - 1:
            fast = fast.next
            n -= 1
        while fast.next:
            fast = fast.next
            pre = slow
            slow = slow.next
        pre.next = slow.next
        return root.next
        

C++代码如下:

/**
 * 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* dummy = new ListNode(0);
        dummy->next = head;
        ListNode* prev = dummy;
        ListNode* cur = dummy;
        while (n--) {
            cur = cur->next;
        }
        while (cur && cur->next) {
            cur = cur->next;
            prev = prev->next;
        }
        prev->next = prev->next->next;
        return dummy->next;
    }
};

日期

2018 年 6 月 23 日 —— 美好的周末要从刷题开始 2019 年 1 月 10 日 —— 加油 2019 年 9 月 27 日 —— 昨天面快手,竟然是纯刷题