[Leetcode][019] Remove Nth Node From End of List (Java)
题目在这里: https://leetcode.com/problems/remove-nth-node-from-end-of-list/
【标签】 Linked List; Two Pointers
【个人分析】
这个题目应该算是Linked List里面的基础题。说它基础不是因为它简单,而是因为它是基石。一些 Linked list中经典方法在这道题里面都有应用。
1. Two Pointers 在 Linked List中: 如果能预先链表知道长度,那题目就简单多了,删掉从头开始的 Len - N就完事了。但是,LinkedList是没有办法预先知道链表长度的,所以需要借助双指针来利用offset来解决。
1.1)设置两个指针,fast 和 slow。
1.2) 让fast先单独走 n 步(这样,fast 和 slow这件就有了固定的差距:n)。
1.3) 然后两个指针一起往前走,当 fast.next = null, 即 fast是链表中最后一个结点时,slow就指在倒数第 n + 1个结点处, 也就是我们想要删除的那个结点前面的那个结点。
1.4) 让slow.next = slow.next.next,这样就成功删除掉了原先的slow.next
2. dummy head的应用: dummy head 就是我们自己新建一个结点,然后让原先的head结点接到这个新建结点的后面。我觉得用dummy head用三个比较明显的好处。
一个是可以尽量减少对原先链表的改变,如果是用head = head.next这样的方法,head会移动,这样就改变了原先的情况,不是很好。
二个好处是方便返回,直接返回dummy.next就可以。
三个是不用对头结点做特除对待,如果删除的结点恰好是头结点,还要为这种情况单独写一些代码,增加了代码量。
总之,如果要求返回新的头结点的链表题目,新建一个dummy head多半是比较好的选择。
1 public class Solution { 2 public ListNode removeNthFromEnd(ListNode head, int n) { 3 if (head == null || n <= 0) { 4 return null; 5 } 6 ListNode dummyHead = new ListNode(-1); 7 dummyHead.next = head; 8 9 ListNode fast = dummyHead; 10 ListNode slow = dummyHead; 11 12 // let fast point go n steps itself 13 for (int i = 0; i < n; i++) { 14 assert(fast != null); 15 fast = fast.next; 16 } 17 18 // fast and slow go together 19 // until fast reaches the end of list 20 while (fast.next != null) { 21 fast = fast.next; 22 slow = slow.next; 23 } 24 25 // now slow should pointing to the node 26 // before which we want to remove 27 slow.next = slow.next.next; 28 29 return dummyHead.next; 30 } 31 }