19. 删除链表的倒数第 N 个结点(剑指 Offer 22. 链表中倒数第k个节点 && 剑指 Offer II 021. 删除链表的倒数第 n 个结点)
题目:

思路:
【1】本质上简单点的就是先扫描一次得到对应的个数,然后第二次扫描的时候,进行删除。
【2】基于上面这种在特殊情况下,又可以变为双指针,因为删除的N是必须不大于链表个数的,所以先一个指针先跑,但是在最差的情况,其实和双循环的效率是一样的,但是最优情况比双循环要少不少次数的扫描。
【3】基于进阶,如果只是针对链表只进行一次扫描,可以考虑扫描后将节点存入辅助中间中再拿出来进行处理。
【4】本质上上面这些其实都是可以算是用到多个循环,但是看怎么理解吧,只用一个循环的话大概率是处理不了的。本身说的一次扫描这个东西的概念就比较模糊。
代码展示:
使用辅助空间完成进阶的要求:
//时间0 ms击败100% //内存39.5 MB击败66.74% //时间复杂度:O(L),其中 L 是链表的长度。 //空间复杂度:O(L),其中 L 是链表的长度。主要为栈的开销。 /** * 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 dummy = new ListNode(0, head); Deque<ListNode> stack = new LinkedList<ListNode>(); ListNode cur = dummy; while (cur != null) { stack.push(cur); cur = cur.next; } for (int i = 0; i < n; ++i) { stack.pop(); } ListNode prev = stack.peek(); prev.next = prev.next.next; ListNode ans = dummy.next; return ans; } }
双循环的做法:
//时间0 ms击败100% //内存39.8 MB击败34.10% //时间复杂度:O(L),其中 L 是链表的长度。 //空间复杂度:O(1)。 /** * 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 temp = head; int length = 0; while (temp != null) { length++; temp = temp.next; } ListNode dummy = new ListNode(0, head); ListNode cur = dummy; for (int i = 1; i < length - n + 1; i++) { cur = cur.next; } cur.next = cur.next.next; return dummy.next; } }
双指针的做法【双指针其实可以看做是双循环的特殊版本】:
//时间0 ms击败100% //内存39.3 MB击败96.28% //时间复杂度:O(L),其中 L 是链表的长度。 //空间复杂度:O(1)。 /** * 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 dummy = new ListNode(0, head); ListNode first = head; ListNode second = dummy; for (int i = 0; i < n; ++i) { first = first.next; } while (first != null) { first = first.next; second = second.next; } second.next = second.next.next; ListNode ans = dummy.next; return ans; } }

浙公网安备 33010602011771号