32.迴文鏈表

題目:請判斷一個鏈表是否爲迴文鏈表。

解析:
1.利用棧求解

①首先遍歷鏈表獲取鏈表的長度len;
②根據鏈表的長度,將鏈表的前半部分壓入棧,將後半部分依次與彈棧的元素比較看是否一致,一致則爲迴文鏈表;
③這裏注意的是鏈表的後半部分的開始位置(鏈表長度的奇偶)。

public boolean isPalindrome1(ListNode head) {
   if (head == null) return true;
   if (head.next == null) return true;//鏈表只有一個的時候
   int len = 0;
   ListNode first = head;
   //鏈表的長度
   while (head != null){
    head = head.next;
    len++;
   }
  //前半部分壓入棧
   Stack<Integer> stack = new Stack<Integer>();
   int mid = len/2;
   if (len%2 == 0){
    while ((mid--)!=0){
     stack.push(first.val);
     first = first.next;
    }
    //注意區分mid--和--mid時遍歷停止時的first指向的結點
    //鏈表長度是偶數,此時first表示鏈表後半部分的開始
   }else{
    while ((mid--)!=0){
     stack.push(first.val);
     first = first.next;
    }
    first = first.next;
   //鏈表長度是奇數,此時first表示鏈表後半部分的開始
   }
   //後半部分與棧中元素比較
   while (first!=null){
    if (first.val != stack.pop())
     return false;
    first = first.next;
   }
   return true;
  }

2.雙指針—鏈表反轉
①定義兩個指針p1和p2,開始同時指向頭結點;
②指針p1和p2同時移動,p1移動一個節點,p2移動兩個結點,當p2移動到鏈表的末尾無法在移動時,此時p1剛好指向鏈表的中間結點;
例:
1->2->2->1 p1停留在第一個結點2上
1->2->3->2->1 p1停留在結點3上
③進行反轉p1後面的部分鏈表操作;
④比較前半部分的鏈表和反轉的後半部分鏈表。(從上述例中明顯可以看出,不區分鏈表的奇偶)

public boolean isPalindrome2(ListNode head) {
   if (head == null) return true;
   if (head.next == null) return true;
   ListNode p1 = head, p2 = head;
   
   //利用快慢指針,將p1移動到鏈表的中間部分
   while (p2.next != null && p2.next.next != null){
    p1 = p1.next;
    p2 = p2.next.next;
   }
   //反轉此時p1之後的鏈表
   //不用考慮鏈表的奇偶
   ListNode pre = null, curnode = null, tmpnode = p1.next;
   while (tmpnode != null){
    curnode = tmpnode.next;
    tmpnode.next = pre;
    pre = tmpnode;
    tmpnode = curnode;
   }
   p1.next = pre;//接上反轉後的鏈表
   //比較前半部分和反轉後的部分是否一致
   while(pre != null){
    if (head.val != pre.val)
     return false;
    head = head.next;
    pre = pre.next;
   }
   return true;
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章