LeetCode 19之Remove Nth Node From End of List的Java题解(三种解法)

题目

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.
解题:

第一种解法:

这种解法是最容易想到的,先遍历一遍链表得到链表的长度,知道长度后就可以定位到要删除的节点

代码:

if(head==null||head.next==null)
			return null;
		int length=0;
		ListNode fakeNode=new ListNode(-1);
		fakeNode.next=head;
		ListNode pre=fakeNode;
		ListNode cur=head;
		//先统计链表长度
		while(cur!=null)
		{
			length++;
			cur=cur.next;
		}
		cur=head;//重新置为指向头节点
		while(cur!=null)
		{
			if(length==n)
			{
				pre.next=cur.next;//删除节点
				break;
			}
			pre=pre.next;
			cur=cur.next;
			length--;
		}
		return fakeNode.next;
第二种解法:

第一种解法需要遍历两遍,效率会显得低一些,常用的思路用空间换时间,我们遍历一遍链表把所有链表都存在一个哈希表中并统计哈希表的长度,知道长度之后也可以很容易定位到需要删除的节点,这时候需要处理要删除的节点为第一个和最后一个的特殊情况。

代码:

if(head==null||head.next==null)
			return null;
		ListNode cur=head;
		Hashtable<Integer, ListNode> ht=new Hashtable<>();
		int length=0;
		//把所有节点存在链表中
		while(cur!=null)
		{
			length++;
			ht.put(length, cur);
			cur=cur.next;
		}
		if(length==n)//链表中第一个节点
		{
			head=head.next;
			
		}
		else if(n==1)//链表中最后一个节点
		{
			ListNode temp=ht.get(length-1);
			temp.next=null;
		}
		else {
			ListNode temp=ht.get(length-n);
			temp.next=temp.next.next;
		}
		return head;
第三种解法:

有没有不使用额外空间又能够只遍历一遍的解法呢?第三种就是这种解法,它利用两个指针。我先说明一些原理:

利用对称性,数组第一个点到倒数第n个点的距离等于数组最后一个点到顺数第n个点的距离,为了删除倒数第n个点我们要找到它前一个点(即倒数第n+1个点) 利用对称性  我们定义两个指针  先让指针1跑到顺数第n+1个点,到了之后,让指针1和指针2同时跑,当指针1跑到最后一个点的时候,根据对称性,指针2也跑到了倒数第n+1个点这个是最重要的思路,除此之外记得处理两个特殊情况,当要删除的节点位于链表第一个和链表最后一个。当n=1时,链表最后一个点,当N等于链表长度时,链表第一个点。

public static ListNode removeNthFromEnd2(ListNode head, int n) {
		if(head==null||head.next==null)
			return null;
		ListNode cur1=head;
		ListNode cur2=head;
		//让指针1跑到顺数第n+1个点
		while(n!=0)
		{
			cur1=cur1.next;
			n--;
			if(cur1.next==null&&n!=0)//判断cur1是不是最后一个点,如果是说明要删除的点是链表的第一个点
			{
				head=head.next;
				return head;
			}
		}
		while(cur1.next!=null)
		{
			cur1=cur1.next;
			cur2=cur2.next;
		}
		//经过上面这个while循环 cur1跑到了最后一个节点 cur2跑到了要删除节点的前一个
		if(n==1)
		{
			cur2.next=null;
		}
		else {
			cur2.next=cur2.next.next;
		}
		return head;
		
		
	}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值