19. 删除链表的倒数第 N 个结点

目录

19.删除链表的倒数第N个节点

题目

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

输入: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)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解-暴力

要删除链表中的某个节点,需要知道其前一个节点。对于头节点来说,其没有前一个节点,因此,需定义虚拟头节点dummy

链表的第x个节点,就必然需要遍历。
第一遍遍历知道整个链表的长度,把倒数的节点转换成正数的第x个节点
第二遍遍历删除倒数第n个节点

ListNode dummy = new ListNode(); //增加一个无数据的节点,统一边界节点操作
dummy.next = head;
int count = 1;
while(head.next!=null){
	head = head.next;
	count++;
}
n = count - n + 1;//删除从头到尾的第n个
count = 1;
ListNode pre = dummy;
head = dummy.next;
for(;count!=n;count++){
	pre=head;
	head = head.next;
}//找到了要删除的元素
//进行删除
pre.next = head.next;
return dummy.next;

题解-哈希表

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

第二遍遍历主要是去找需要删除的元素,那么如果我们使用哈希表在第一次遍历的时候就把位置信息记录下来,那么就不需要再遍历去找了。

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(); 
        dummy.next = head;
        HashMap<Integer,ListNode> map = new HashMap<>();
        int count = 0;
        map.put(count,dummy);
        while(head!=null){
            count++;
            map.put(count,head);
	        head = head.next;
        }
        //计算删除的元素位置
        n = count-n+1;
        //获取要删除的元素前一个元素,与当前元素
        ListNode pre = map.get(n-1);
        head = map.get(n);    
        pre.next = head.next;
        return dummy.next;
    }
}

题解-双指针

之前的链表题使用了双指针,这里我们考虑一下双指针,双指针适合用于划分区间,距离等。

需要遍历一遍的主要原因时找到链表的长度,也就是需要遍历到最后一个节点后面,通过最后一个节点的后面再去定位倒数的节点。那么这里我们用一个指针指向最后,一个指针指向需要删除的节点前一个节点就可以了。

这里要删除的是链表中倒数第2个节点,slow指向需要删除的节点的前一个节点。
那如何确定好slow指向的位置?当指针fast指向null时,它与指针slow之间相差2个节点,刚好是n=2。

先让fast走n+1步,然后再一起走

class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode dummyHead = new ListNode(0);
    dummyHead.next = head;

    // 慢指针初始指向虚拟头结点
    ListNode slow = dummyHead;
    // 快指针初始指向虚拟头结点
    ListNode fast = dummyHead;

    // 快指针先向前移动n+1步
    for(int i = 0; i <= n; i++) {
        fast = fast.next;
    }

    // 快慢指针同时向前移动,直到快指针指向null
    while (fast!=null){
        fast = fast.next;
        slow = slow.next;
    }

    // 慢指针的下一个节点即待删除节点
    ListNode delNode = slow.next;
    // 慢指针的后继指针指向待删除节点的下一个节点
    // 这样就将待删除节点删除了
    slow.next = delNode.next;
    delNode.next = null;
    return dummyHead.next;
}

}

上一篇:java web-01-servlet


下一篇:Filter实战——实现非法字符的过滤