20210421力扣第19题:删除链表的倒数第n个节点

1.题目

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

进阶:你能尝试使用一趟扫描实现吗?

在这里插入图片描述

	输入:head = [1,2,3,4,5], n = 2
	输出:[1,2,3,5]

	输入:head = [1], n = 1
	输出:[]

输入:head = [1,2], n = 1
输出:[1]

2.想法

  • 首先想到获取到这个链表的长度,再用长度减去第n个数就好了

但是这个只让遍历一次,在以前学习的数据结构书中,我就遇到过这个题,当时这道题还只是一个疑问题,问能不能之遍历一次完成删除倒数第n个节点,第一次回答的是不能,后来又改成,如果知道长度就可以,现在想想当时遇到这个问题,还是缺乏思考。

  • 我看了下提示,说是使用双指针,这样自己还是少了点头绪,直到看了评论
  • 评论说到快慢指针的问题,快指针比慢 指针 快 n步,这样就清楚了

使用while循环判断是否为空写下去

2.1 遇到的问题

  • 在学习数据结构的时候,有个头结点,头结点类似是个虚的,专门指向第一个结点也是用的
  • 我在做题时候,把这个虚头结点和 题目中的头结点搞混了,导致做题最后的slow.next.next指向是空指针,出错。
  • 最后有一次看了评论,发现题中 的head就是第一个有数据的结点,我们需要的是那个虚的头结点。这样,就明白了了自己有的地方错误了;

2.1.1自己开始写遇到的问题

  1. 思考:双指针算不算走了两次?

    我在看评论的时候,看到了一个c++题解,我用了他的思想,但是还是有问题,但是不知道怎么解决。
    我把这个问题记录下来。
    代码:
    
/**
 * 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 fast =head;
	ListNode slow = head;
	for(int i = 0 ; i < n ; i ++)
	{
		fast=fast.next;
	}
	while(fast.next!=null)
	{
		fast=fast.next;
		slow=slow.next;
	}
		slow.next =slow.next.next;
		return head;
    }
 }

上面这个代码 ,看起来没什么问题,但是在测试案例:

	[1,2]
	2
	[1]
	1

这样就会空指针异常,我尝试去增加if语句来拦截这样的错误,但始终没有解决

我觉得这是我没有把头结点问题解决好。
我就尝试着把上面的代码改进:

/**
 * 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 realhead = new ListNode(0,head);
    	ListNode fast =realhead;
	    ListNode slow = realhead;
	for(int i = 0 ; i < n ; i ++)
	{
		fast=fast.next;
	}
    if(fast==null)
    {
        for(int j = 0 ; j < n-1;j++)
        {
            slow =slow.next;
        }
        return realhead;
    }
	while(fast.next!=null)
	{
		fast=fast.next;
		slow=slow.next;
	}
		slow.next =slow.next.next;
		return realhead.next;
	}
}
  • 先让fast走,害怕出现走到末尾,加一个if判断,那if里面的就是fast走到最后的那种情况,这样的话,我们需要再循环一下slow,让slow少走一步,就行了,最后返回。
  • 果然问题还是出现在头结点上。

2.2改进后代码

现在来写一下代码,虽然代码看起来不难,但是我自己写的时候,老出错。提示空指针异常。这也是头指针没搞清楚的原因。

/**
 * 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 realHead = new ListNode(0,head);//说明realHead.next = head; 值为0,值为什么无所谓,起到指向头的位置就行
		//定义快慢指针
		ListNode fast = realHead;
		ListNode slow = realHead;
		int i = 0 ;
		while(fast.next!= null)
		{
			if(i<n)//先让fast到第n个位置
			{
				i++;
				fast = fast.next;
				continue;
			}
			//两个指针在一起走
			slow = slow.next;
			fast = fast.next;
		}
		
		//出了while循环就算fast走完了  这样slow就走到了倒数第n的前驱
		slow.next = slow.next.next;
		return realHead.next;
	}
}

3.总结

自己在写的时候,遇到的问题都在2.1之中了,写这个博客先把2.2都写完了后,又返回去思考了2.1.1的问题,没想到,加了头结点后果然解决了,但是这样似乎没有遍历一次,双指针应该算是遍历一次,本题考的是数据结构中的题,不难,自己在数据结构中遇到过,虽然知道思想,写的时候还是差了点水平,本题的关键是他给的头结点让我觉得是那个虚的头结点,我反而出错了,审题也是关键。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值