Leetcode 19.删除链表的倒数第 N 个结点 remove-nth-node-from-end-of-list(链表,快慢指针变种应用)

题目描述

给定一个链表,删除链表的倒数第n个节点并返回链表的头指针
例如,
   给出的链表为:1->2->3->4->5, n= 2.↵↵   删除了链表的倒数第n个节点之后,链表变为1->2->3->5.
备注:
题目保证n一定是合法的
请尝试只用一步操作完成该功能

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

For example,

   Given linked list:1->2->3->4->5, andn= 2.↵↵   After removing the second node from the end, the linked list becomes1->2->3->5.↵

Note: 
Given n will always be valid.
Try to do this in one pass.

思路:快慢指针变种。只遍历一遍的话,需要考虑怎么把n与size联系起来,那就可以考虑双指针,慢指针需要指向[size-n],需要走size-n,先快指针走n,然后快慢指针同步走,快指针走到末尾,走了size-n步,则慢指针正好指到需要删除的倒数第n个。需要考虑特殊情况,如果指定n=size,则快指针为空,此时只需要删除[0]就可以。
/**
 * 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 *fast=head;
        ListNode *low=head;
        while(n--)
            fast=fast->next;
        if(fast==NULL)
            return head->next;
        while(fast->next!=NULL)
        {
            fast=fast->next;
            low=low->next;
        }
        fast=low->next;
        low->next=fast->next;
        return head;
    }
};

另一种思路:

我们可以拆分成两部分,第一部分为找到倒数n+1节点,第二部分为使用n+1节点删除n节点。

PS:会有总长为1,删除倒数第1个节点的case,因此我们需要构建一个虚拟头节点vhead,以vhead为头查找倒数n+1节点,再删除倒数n节点

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode vhead;
        vhead.next=head;
        ListNode* p=findNthFromEnd(&vhead,n+1);
        p->next=p->next->next;
        return vhead.next;
    }
    ListNode* findNthFromEnd(ListNode* head, int n){
        ListNode* fast=head;
        for(int i=0;i<n;++i){
            fast=fast->next;
        }
        ListNode* slow=head;
        while(fast!=nullptr){
            fast=fast->next;
            slow=slow->next;
        }
        return slow;
    }
};

 

 

posted @ 2020-04-26 23:43  鸭子船长  阅读(161)  评论(0编辑  收藏  举报