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

99 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

题目

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

示例 1:

img

输入: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

**进阶:**你能尝试使用一趟扫描实现吗?

解题

解题一:双指针

思路

使用快慢指针,确定链表的长度,从而确定倒数第 N 个数是在 链表的前半部分还是后半部分,然后进行删除操作

代码

/**
 * 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 slow = head;
        ListNode fast = head;
        int len = 1;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            len += 2;
        }
        if (fast.next != null) {
            len++;
        }
        if (n == len) {
            // 删除头节点
            return head.next;
        }
        // 在链表的后半段,或者在链表的前半段
        slow = n > (len / 2) ? head : slow;
        n = n > (len / 2) ? len - n -1: len / 2 - n;
        for (int i = 0; i < n ; i++) {
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return head;
    }
}

总结

性能分析

  • 执行耗时:0 ms,击败了 100.00% 的 Java 用户
  • 内存消耗:39.4 MB,击败了 37.55% 的 Java 用户

解题二:栈

思路

  1. 遍历链表,将所有节点依次入栈
  2. 弹出栈第 N 个,就是要删除的节点的前一个节点
    • 主要注意,可能会删除头节点,这时直接返回头节点的下一个节点即可

代码

import java.util.LinkedList;

/**
 * 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) {
        if (head == null) {
            return null;
        }
        Deque<ListNode> stack = new LinkedList<>();
        ListNode temp = head;
        while (temp != null) {
            stack.push(temp);
            temp = temp.next;
        }
        if (n >= stack.size()) {
            // 删除头节点
            return head.next;
        }
        for (int i = 0; i < n; i++) {
            stack.pop();
        }
        ListNode prev = stack.pop();
        prev.next = prev.next.next;
        return head;
    }
}

总结

性能分析

  • 执行耗时:0 ms,击败了 100.00% 的 Java 用户
  • 内存消耗:39.7 MB,击败了 36.14% 的 Java 用户