继续学习链表的算法链接
题目描述:删除单链表倒数第 n 个节点,1 <= n <= length,尽量在一次遍历中完成。
分析:看到题目时的第一想法是先遍历一次计算出单链表的长度 length,然后在遍历第二次删除第 length - n + 1 个节点,但是这需要遍历两次。正常的删除第 n 个节点只需要遍历一次就可以,如何只遍历一次找到倒数第 n 个节点呢?可以设置两个指针 p1、p2,首先 p1 和 p2 都指向 head,p2 移动到第 n 个节点,然后 p1 和 p2 同时向后移动,当 p2 移动到末尾时,p1 刚好指向倒数第 n 个节点。因为最后要删除倒数第 n 个节点,所以可以找到倒数第 n + 1 个节点,方便删除节点。这种思想在学校的时候学习过,还是蛮有用的吧,还是可以学到很多东西的,只不过总是找了很多借口。
function Node(val){ //class的定义好像有点没弄好
this.val = val;
this.next = null;
}
function removeNthNodeFromEnd(head, location){
if(head == null) return head;
var pointer1 = head;
var pointer2 = head;
for(var i = 0 ; i < location; i ++ ){
pointer2 = pointer2.next;
if(pointer2==null&&i!=location-1)
return null; //如果根本没有n个元素,就没有倒数第n个元素
}
if(pointer2==null){ //总共就n个元素,那么head就是要删除的那个点,返回下一个节点作为头节点就好了。
return pointer1.next;
}
while(pointer2.next!=null){ //如果条件是pointer2!=null,那么被删除的点就是pointer1,但是这样删不掉。所以应该记录要删除的节点的上一个节点。
pointer2=pointer2.next;
pointer1=pointer1.next;
}
pointer1.next = pointer1.next.next;//
return head;
}
我自己测试了下,测试用例如下,可能构建链表的过程有点傻。
var head = new Node("head");
var current = head,next = null;
for(var i =5 ; i >0 ; i--){
next = new Node(i);
current.next = next;
current = next;
}
function showLinkedNode(head){
if(head==null) console.log("head is "+head);
while(head!=null){
console.log(head.val);
head = head.next;
}
}
showLinkedNode(head);
var result = removeNthNodeFromEnd(head,6);
showLinkedNode(result);
结果是 head 5 4 3 2 1 和 5 4 3 2 1
如果removeNthNodeFromEnd(head,7),返回的是null。
showLinkedNode(head);
var result = removeNthNodeFromEnd(head,3);
showLinkedNode(result);
结果是head 5 4 2 1
还是得自己动手写写,可能以前能懂,但是过了一段时间以后就不懂了,让往日的自己和后面的自己隔着时间对话。人并不总是在进步,每一个时间点的思考以及结论都很有意义。
类似的问题
题目描述:求单链表的中间节点,如果链表的长度为偶数,返回中间两个节点的任意一个,若为奇数,则返回中间节点。
分析:这道题的思路和第 3 题「删除单链表倒数第 n 个节点」很相似。如果要求只能遍历一遍链表的花,也通过两个指针来完成。两个指针从头节点开始,慢指针每次向后移动一步,快指针每次向后移动两步,直到快指针移动到尾节点时,慢指针移动到中间节点。思路很相似,那么三分之一,四分之一,五分之一,或者均分三段,均分四段也是类似的想法。
function findMiddleNode(head){
if(head==null||head.next==null) return head;
var fastPoint = head;
var normalPoint = head;
while(fastPoint!=null&&fastPoint.next!=null){
fastPoint = fastPoint.next.next;
normalPoint = normalPoint.next;
}
return normalPoint;
}
这个感觉比较简单。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。