2.2.7 Remove Nth Node From End of List

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
修改后:通过OJ

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值