继续学习链表的算法链接

题目描述:删除单链表倒数第 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;
   }

这个感觉比较简单。


好多知识不知道
21 声望0 粉丝

想法,每个人都有,每时每刻。想法并不会一直留在脑中,时间会遗忘一切,有必要整理一些东西,记住那时的你。思维是最美的东西,让不同时间的你,用思维对话。(起高了)