Link: https://oj.leetcode.com/problems/remove-nth-node-from-end-of-list/
Given a linked list, remove the nth node from the end of list and return its head.
For example,
Given linked list: 1->2->3->4->5, and n = 2. After removing the second node from the end, the linked list becomes 1->2->3->5.
Note:
Given n will always be valid.
Try to do this in one pass.
我的思路:
Approach I: two passes
第一遍:
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//two passes solution
//get list length
ListNode node = head;
int len = 1;
while(node.next != null){
len++;
node = node.next;
}
node = head;
for(int i = 1; i < len - n; i++){
node = node.next;
}
node.next = node.next.next;
return head;
}
}
出错:
Runtime Error Message: | Line 26: java.lang.NullPointerException |
Last executed input: | {1}, 1 |
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//two passes solution
//get list length
ListNode node = head;
int len = 1;
while(node.next != null){
len++;
node = node.next;
}
ListNode dummy = new ListNode(-1);
dummy.next = head;
node = dummy ;
for(int i = 0; i < len - n; i++){
node = node.next;
}
node.next = node.next.next;
return dummy.next;
}
}
Approach II: One Pass
第一遍:
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//one passes : two pointers
ListNode slow = head;
ListNode fast = head;
//move fast n steps ahead of slow
for(int i = 0; i < n; i++){
fast = fast.next;
}
if(fast == null){//there are <=n nodes
return null;
}
//move fast and slow together
while(fast.next != null){
slow = slow.next;
fast = fast.next;
}
slow.next = fast;
return head;
}
}
Note: 这个解法是CC150 2.2 Find the kth to last element (but here we need not to find it, but remove it).
错误:
Input: | {1,2}, 1 |
Output: | {1,2} |
Expected: | {1} |
第二遍:把slow.next = fast 改成slow.next = slow.next.next;
因为如果链表是:1->2->3->4->5->6->7, n = 4, 即我们要删除节点4, 那么slow = 3时, slow.next应该指向slow.next.next = 5,而不是fast = 7
错误:
Input: | {1,2}, 2 |
Output: | {} |
Expected: | {2} |
说明必须要加dummy node
第三遍:
Approach I: use dummy nodes, then don't need to specialize for the above error (delete 2 in {1, 2})
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode slow = dummy;
ListNode fast = dummy;
for(int i = 0; i < n; i++){
if(fast == null) return null;
fast = fast.next;
}
if(fast == null) return null;
while(fast.next != null){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
Approach II: Don't use dummy nodes. Then need to specialize for the case (to delete the nth node in a length = n list)
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p1 = head;
ListNode p2 = head;
for(int i = 0; i < n; i++){
if(p2 == null) return null; //note the order of this if and p2=p2.next
p2 = p2.next;
}
//if there are n nodes in the list, we need to remove the head
if(p2 == null){
head = head.next;
return head;
}
while(p2.next != null){
p1 = p1.next;
p2 = p2.next;
}
p1.next = p1.next.next;
return head;
}
}
Time: O(list length), Space: O(1)
相关题目:
CC150 2.2 Find the kth to last element (but here we need not to find it, but remove it).
这一题,for 循环是 i < n-1 而不是i < n.