自学内容网 自学内容网

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

解题思路

计算链表长度

一种容易想到的方法是,我们首先从头节点开始对链表进行一次遍历,得到链表的长度 L。随后我们再从头节点开始对链表进行一次遍历,当遍历到第 L−n+1 个节点时,它就是我们需要删除的节点。

为了与题目中的 n 保持一致,节点的编号从 1 开始,头节点为编号 1 的节点。

为了方便删除操作,我们可以从哑节点开始遍历 L−n+1 个节点。当遍历到第 L−n+1 个节点时,它的下一个节点就是我们需要删除的节点,这样我们只需要修改一次指针,就能完成删除操作。

该方式比较传统,下方的第二个方法 比较好。

双指针遍历

采取双重遍历肯定是可以解决问题的,但题目要求我们一次遍历解决问题,那我们的思路得发散一下。

我们可以设想假设设定了双指针 p 和 q 的话,当 q 指向末尾的 NULL,p 与 q 之间相隔的元素个数为 n 时,那么删除掉 p 的下一个指针就完成了要求。

  • 设置虚拟节点 dummyHead 指向 head
  • 设定双指针 p 和 q,初始都指向虚拟节点 dummyHead
  • 移动 q,直到 p 与q 之间相隔的元素个数为 n
  • 同时移动 p 与 q,直到 q 指向的为 NULL
  • 将 p 的下一个节

点指向下下个节点

请添加图片描述

代码

双指针遍历 代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode preNode = new ListNode(-1);
            preNode.next = head;

            ListNode firstNode = preNode;
            ListNode secondNode = firstNode;
            for (int  i = 0; i < n; i++) {
                secondNode = secondNode.next;
            }

            while (secondNode.next != null) {
                firstNode = firstNode.next;
                secondNode = secondNode.next;                
            }
            firstNode.next = firstNode.next.next;

            return preNode.next;
    }
}

原文地址:https://blog.csdn.net/liyunxiangrxm/article/details/140183227

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!