leetcode题19. 删除链表的倒数第 N 个结点

94 阅读1分钟

leetcode地址: leetcode.cn/problems/re…

原题描述:

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

进阶:一次循环完成

解题思路:

方法1:

多次循环法,第一次循环知道链表的长度,根据链表长度第二次循环就能找到链表的位置,再进行相应操作。 这个太简单了不做实现,我也没这么做。

方法2:

额外数据结构法,第一次循环将链表放入ArrayList结构,这样就能规避掉第二次循环找到这个节点的操作,而是通过arraylist取下标来获取,然后注意处理好边界条件即可。

代码如下:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ArrayList<ListNode> list = new ArrayList<>();
        ListNode temp = head;
        while(temp!=null){
            list.add(temp);
            temp = temp.next;
        }
        int size = list.size();//size=6 n=2 index=4 实际第五 倒数第二
        int index = size - n;
        ListNode node = list.get(index);
        ListNode next = node.next;
        if(index-1>=0){
            ListNode pre = list.get(index-1);
            pre.next = next;
        }else{
            head = next;
        }
        return head;
    }
}

方法3:

快慢指针,定义一个快指针一个慢指针,快指针先走n,然后快慢一起走,这样快走到null的时候,慢走到需要删除的节点。省略了o(n)的空间消耗。不过这样处理指针转换会麻烦一点,具体请看以下代码:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode index1 = head;
        ListNode index2 = head;
        ListNode pre = head;
        for(int i = 0;i<n;i++){
            index1 = index1.next;
        }
        for(int i = 0;index1!=null;i++){
            index1 = index1.next;
            index2 = index2.next;
            if(i!=0){
                pre = pre.next;
            }
        }
        ListNode node = index2;
        ListNode next = node.next;
        if(pre!=node){
            pre.next = next;
        }else{
            head = next;
        }
        return head;
    }
}

请大家着重理解最后的if判断,为什么是pre!=node,而不是pre!=head;