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

1.题目描述

题目链接:19删除链表的倒数第 N 个结点

2.题解

i.暴力解法:

        获取要删除的元素的位置(正数的位置,可由数学关系得到),用一个指针遍历到该元素的前一位删除即可。

ii.双指针法:

        由上图可以发现,当要删除倒数第n个元素时,将fast移到正数第n个元素位置,再同时将slow和fast一起向后移直到fast移到最后一个元素则slow就指向了目标元素。

然而要执行删除操作需要slow指向目标元素的前一位(这样删除更方便),因此fast在一开始移动时应该多移一位,则这样slow就少移一位(即最终位置会在目标元素的前一位)。

最后删除操作就是slow的next指向目标元素的next即可。

3.代码示例

i.暴力解法

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        int length=getLength(head);//获取链表的长度
        int loctaion=length-n;//指要删的元素的位置
        ListNode index=new ListNode();
        index=head;
        //将指针不断向后遍历直到移到目标元素的前一位
        for(int i=0;i<loctaion-1;i++){
            index=index.next;
        }
        //若要删的是第一个元素,则直接将head向后移一位后返回即可
        if(head!=null&&loctaion==0){
            head=head.next;
            return head;
        }
        //删除操作
        if(index.next!=null&&index.next.next!=null)
            index.next=index.next.next;
        else
            index.next=null;
        return head;
    }
    //新定义的获取链表长度的方法
    public int getLength(ListNode head){
        ListNode listnode=new ListNode();
        listnode=head;
        int len=0;
        while(listnode!=null){
            listnode=listnode.next;
            len++;
        }
        return len;
    } 
}

 ii.双指针法

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode virtuaNode=new ListNode(0);//定义一个虚拟指针
        ListNode fast=new ListNode();
        ListNode slow=new ListNode();
        virtuaNode.next=head;
        fast=virtuaNode;
        slow=virtuaNode;
        //fast指针向后移动n位
        for(int i=0;i<n;i++){
            fast=fast.next;
        }
        //slow和fast指针一起向后移动直到fast指到最后一个元苏
        while(fast.next!=null){
            fast=fast.next;
            slow=slow.next;
        }
            slow.next=slow.next.next;//删除操作
        return virtuaNode.next;
    } 
}

4.问题总结

i.关于虚拟指针的作用

        可以省略头节点为空的情况的判断。

ii.双指针法最后的返回值应该时虚拟节点的next

        如果n=1,若返回head则最后会返回head指向的节点,而没有实现删除操作,而引入虚拟节点后,可以对虚拟节点进行删除操作:将虚拟节点的next指向head的next,最后输出虚拟节点的next则就得到删除第一个元素的链表了。这也间接体现了虚拟节点的好处。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值