LCR 027. 回文链表

88 阅读2分钟

解题思路
1快慢指针同时遍历单链表。快指针一下走两步,慢指针一下走一步。
2当快指针走到结尾时,即慢指针走到中间。
3若此时从中间往两端走,则可比较是否为回文。执行时间因为根据链表的量级而变化而变化,而先后遍历链表为一次,故时间复杂度为O(n)。
4下面思考如何判断快指针走到结尾。当快指针再链表倒数第二个节点时,快指针前进,则此时快指针指向null。此种情况之下,快指针不能再前进了。所以当fast&&fast.next(区别于快指针落到最后一个节点时不能再前进了)为真时才能前进。
5慢指针走到中间时,想要往回走,就要在来的路上边走边更改next指向。保存慢指针下一步该到的位置,更改完当前位置下的next为保存的pre之后,慢指针直接跳到next。
6当跳出第一个while之后,要区分链表长度为奇数还是偶数。当遍历结束时,fast指针为真时,此链表为奇数。反之为偶数。当链表为奇数时,一个指针从此时的pre往反方向走,另一个要从当前slow指针的next指针开始走。
7注意一点当链表只有一个节点时不会进while,所以需要单独讨论。

    // 回文字符串-链表实现

    //1.用类去实现链表的结构

    class Node{
      constructor(val){
         this.val = val;
         this.next = null;
      }
    }

    /*
     用数组作为入参,单链表作为返回值
    */
   const arrayToLinkNode = (arr)=>{
      // 需要一个移动指针
      // 还需要一个头指针-最后返回这个头指针
      let head = new Node(arr[0]);
      let cur = head;
      for(let i = 1; i < arr.length; i++){
         cur.next = new Node(arr[i]);
         cur = cur.next;
      }

      return head;


   }

   console.log('--arrayToLinkNode', arrayToLinkNode([1,2,3,4,5]))

   // 回文链表

   // 慢指针和快指针一起走,慢指针尾插法进行反转,快指针用来判断走到尾了结束掉慢指针的尾插行为
   // 最后将慢指针的值和后半部分的指针的值进行逐个对比

   const isPalindrome = (head)=>{
      let fast = head;
      let slow = head;
      let pre = null;
      let next = null;
      // 这个判断条件,当fast和fast.next
      while(fast&&fast.next){
         fast = fast.next.next;
         next = slow.next;
         slow.next = pre;
         pre = slow;
         slow = next;
      }

      if(fast){
         slow = slow.next;
      }

      while(pre){
         if(pre.val !== slow.val){
             return false;
         }
         pre = pre.next;
         slow = slow.next;
      }

      return true;
   }

   console.log('--',isPalindrome(arrayToLinkNode([1,2,3,4,5])))