删除链表的倒数第 N 个结点——LeetCode

 方法一:

用遍历链表,用数组保存每一个节点,因为数组的特性,所以达到目的很简单:

    public ListNode removeNthFromEnd(ListNode head, int n) {
        List<ListNode> list = new ArrayList<>();
        while (head != null) {
            list.add(head);
            head = head.next;
        }

        if (list.size() == 1) {
            return null;
        }

        if (n == 1) { // 最后一个
            ListNode listNode = list.get(list.size() - n - 1);
            listNode.next = null;
        } else if (n == list.size()) { // 第一个
            return list.get(1);
        } else {
            ListNode listNodePre = list.get(list.size() - n - 1);
            ListNode listNodePro = list.get(list.size() - n + 1);
            listNodePre.next = listNodePro;
        }

        return list.get(0);
    }

方法二:

遍历计算链表的长度,注意: 在获取链表长度时遍历,如果直接用head遍历,head会直接指向链表尾,这样后面再用的时候,head就不是指向头节点了,然后就知道要删除哪一个节点了,这里有一个删除节点时的窍门:

创建一个新的节点,放在头节点前,这样做就能够做到删除节点时判断的统一性,当删除的是头节点的时候就不用专门去处理了。

这个窍门处理还是有点秀的:

    public ListNode removeNthFromEnd(ListNode head, int n) {
        int length = 0;
        ListNode temp = head;
        while (temp != null){
            length ++;
            temp = temp.next;
        }
        ListNode first = new ListNode();
        first.next = head;

        ListNode cur = first; // 为什么从first开始
        for (int i = 1; i < length + 1 - n ; i++) { // length + 1因为加了first节点,如果不加1会造成错误,后面加了1,如果还从第0个开始会产生错乱,所以要从1开始,正好head也是第二个元素
            cur = cur.next; //i = 1的时候 cur = cur.next 现在的cur正好指向head,在i=1的时候已经是 cur.next了,相当于加一了 (这就是操作指针的时候需要注意的)
        }//这样做相当于加上first节点后,在遍历时撇过了first,逻辑上没有问题

        //现在curt正好是要删除的那个元素的前一个元素
        cur.next = cur.next.next;
        ListNode ans = first.next;
        return ans;
    }

方法三:

快慢指针,前后指针正好相差n个

    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode first = new ListNode();
        first.next = head;
        ListNode preNode = head; // 注意🌟🌟🌟
        ListNode proNode = first;
        int index = 0;

        while (preNode != null){
            preNode = preNode.next;
            index++;
            if (index > n){
                proNode = proNode.next;
            }
        }

        proNode.next = proNode.next.next;

        return first.next;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值