力扣:19-删除链表的倒数第N个结点

题目描述

给你一个链表,删除链表的倒数第 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


进阶:一次扫描实现

来源:力扣(LeetCode)

解题思路 

首先这道题是要删除链表的倒数第n个结点,一种容易想到的方法是,先遍历一下链表获得这个链表的长度,这样我们就可以获得要删除的结点正着数的位置了。我们创建一个新的链表,遍历一下题目所给链表,把遍历到的节点加到新链表中,遍历到要删除的结点时跳过即可,最后返回这个新链表即可。

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* m=new ListNode();//新链表
        ListNode* p=m;
        ListNode* k=head;
        int t=0;//链表长度
        while(k)//遍历链表获得链表长度
        {
            k=k->next;
            t++;
        }
        int w=t-n;//获得要删除的结点正着数的位置
        int j=1;
        while(head)
        {
            if(j==w+1)//遇到删除的节点跳过
            {
                head=head->next;
                j++;
                continue;
            }
            ListNode* q=new ListNode(head->val);
            p->next=q;//将遍历到的结点加入到新链表中
            p=q;
            head=head->next;
            j++;
        }
        return m->next;//返回新链表即可
    }
};

进阶要求我们扫描一次实现,想了半天没想出来,看了题解才知道要用双指针。双指针雀氏是一种非常妙的解法,没遇到这种题还真不好想出来。这道题用双指针就是用了一个前后指针,我们创建两个指针,一个前指针first,一个后指针second,我们让first超过second指针n个结点,那么first指针遍历到链表结尾的时候,second指针刚好就在倒数第n个结点,这样一次遍历是可以实现了。

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* p=new ListNode();
        p->next=head;
        ListNode* first=head;
        ListNode* second=p;
        for(int i=0;i<n;i++)
        {
            first=first->next;
        }
        while(first)
        {
            first=first->next;
            second=second->next;
        }
        second->next=second->next->next;
        return p->next;
    }
};

这道题还有一种解法,就是利用递归,递归也是一个非常好的想法,也很巧妙。按道理讲也是扫描了一次,下面是代码实现,仅供参考

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        int ans=find(head,n);
        if(ans==n)
        return head->next;
        else
        return head;
    }
    int find(ListNode* node,int n)
    {
        if(node==nullptr)
        {
            return 0;
        }
        int res=find(node->next,n);
        if(res==n)
        {
            node->next=node->next->next;
        }
        return res+1;

    }
};

猜你喜欢

转载自blog.csdn.net/qq_52905520/article/details/126593959