Given a linked list, remove the nth node from the end of list and return its head.(Difficulty: Easy)
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.
方法一:遍历了两边链表。
/* 这是我做的第1个方法,实现这个地方相当于遍历了两遍链表
* 第一遍:统计链表有多少个元素
* 第二遍:从头遍历找到需要被删除的元素
* 在第一次实现的时候我是把删除的节点为头结点时做了特殊处理,直接返回head.next
*/
public ListNode removeNthFromEnd1(ListNode head, int n) {
ListNode q = head;
ListNode p = q.next;
int total = 1;// 记录链表中的总元素个数
while (p != null) {
q = p;
p = p.next;
total++;
}
if (n == total) {// 即要删的是头结点
return head.next;
}
// 出while循环的时候q是链表的最后一个元素
p = head;
System.out.println("total = " + total);
for (int i = 1; i < total - n + 1; i++) {
q = p;
p = p.next;// 永远保持q在p的前一个
}
// 出来for循环之后,p是应该被删的元素
System.out.println("被删的元素 " + p.val);
q.next = p.next;
return head;
}</span>
方法二:对方法一做了一点点修改。
</* 加上一个额外的头结点dump,这样在删除的节点是head时不需要再做额外的处理。
*/
public ListNode removeNthFromEnd2(ListNode head, int n) {
ListNode p = head.next;
int total = 1;// 记录链表中的总元素个数
while (p != null) {
p = p.next;
total++;
}
ListNode dump = new ListNode(0);//做为额外的头节点
dump.next = head;
ListNode q = dump;
p = head; //保持q在p的前一个
System.out.println("total = " + total);
for (int i = 1; i < total - n + 1 ; i++) {
q=p;
p = p.next;// 永远保持q在p的前一个
}
// 出来for循环之后,p是应该被删的元素
q.next = p.next;
return dump.next;
}
方法三:最符合题意,让链表只走了一遍。
Step1:加上dump做为额外的头节点,最后返回dump.next;
Step2:先让first走n步;(敢在题目直接让first走n步是因为note中提到输入的n都是合法的)
Step3:再让first和p同时走,这样当first走到链表结尾时,p就是被删除的节点,在走的过程中 节点q永远是p的前一个节点;
Step4:删除p节点。
/*效率最快,只走了一遍链表即可*/
public ListNode removeNthFromEnd3(ListNode head, int n) {
/*Step1:加上dump做为额外的头节点,最后返回dump.next*/
ListNode dump = new ListNode(0);
dump.next = head;
ListNode first = head;
ListNode p = head;
ListNode q = dump;//永远保持q在p的前一个
/*Step2:先让first走n步*/
for(int i = 0;i<n;i++){
first = first.next;
}
/*Step3:再让first和p同时走,这样当first走到链表结尾时,p就是被删除的节点,在走的过程中
* 节点q永远是p的前一个节点*/
while(first!=null){
first = first.next;
q=p;
p=p.next;
}
/*Step4:删除p节点*/
q.next = p.next;
return dump.next;
}
总结:做链表的题目一定要保证不能出现空指针的情况。