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.
Note:
Given n will always be valid.
Try to do this in one pass.
题目目标:将单链表中倒数第n个元素删除。要求时间复杂度O(n),且尽量只扫描一次链表。
题目分析:要知道链表最末位的元素才知道倒数第n个是啥啊,所以扫到末位元素已经占据了O(n)的复杂度。为了不再一次扫链表,所以删除操作只能在O(1)时间内完成。在这里我引入一个长度为n+1的缓冲区(这里的n代表是倒数第n个元素),来保存扫描过程中最后出现的n+1个链表节点,可以把这段缓冲看作是循环链表,因为我就是这么做的。
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode temp=head;
ListNode[] nodepointer=new ListNode[n+1]; //构建缓冲区,要删除倒数第n个元素,必须找到倒数第n+1个才行,所以缓冲大小是n+1
int i=0;
for(i=0;temp!=null;i++){
//遍历链表,并将链表元素循环存入缓冲区
nodepointer[i%(n+1)]=temp;
temp=temp.next;
}
if(i-n-1<0)return nodepointer[(i-n)%(n+1)].next;
//在遍历完成后i会指向链表末位元素的后一位,即链表最大元素为5的话,i也会变成5(i是从0开始,元素是从1开始).所以如果删除的是首个元素的话(i-n-1<0),就不用进行链表拼接了,直接返回第二个元素的引用即可,否则进行链表拼接
else {
temp=nodepointer[(i-n-1)%(n+1)];
temp.next=temp.next.next;
return head;
}
}
}
import java.util.Arrays;
import java.util.Scanner;
/**
* @author DELL
*
*/
public class Main{
public static void main(String[] args){
/*Scanner in=new Scanner(System.in);
String target=in.nextLine();*/
ListNode listnode=new ListNode(1),temp=null;
temp=listnode;
for(int i=2;i<=5;i++){
temp.next=new ListNode(i);
temp=temp.next;
}
temp.next=null;
long startTime=System.currentTimeMillis();
Solution find=new Solution();
temp=find.removeNthFromEnd(listnode,2);
long endTime=System.currentTimeMillis();
long excTime=(long)(endTime-startTime);
System.out.println("执行时间:"+excTime+"ms");
for(int i=0;temp!=null;i++){
System.out.println(temp.val);
temp=temp.next;
}
}
}