題目:判斷一個鏈表是否是迴文
就是諸如1-2-3-2-1 1-2-3-3-2-1 奇數個或者偶數個這樣的。
方法一:
快慢指針,前半部分放入棧中,快指針到達結尾,慢指針到達中間,然後慢指針繼續後續遍歷,和棧中的彈出來一個個比較。若一旦有不同就return false,都一樣就最後返回true。
方法二:
將鏈表切割爲兩部分,再將某一部分進行inverse反轉鏈表,再對兩個鏈表挨個比較。若一旦有不同就return false,都一樣就最後返回true。
方法一代碼:
public class Solution {
public boolean isPalindrome(ListNode head) {
ListNode fast=head;
ListNode slow=head;
Stack<Integer> stack=new Stack<Integer>();
while(fast!=null && fast.next!=null){
stack.push(slow.val);//入棧
slow=slow.next;//慢指針
fast=fast.next.next;//快指針
}
if(fast!=null){
slow=slow.next;//如果fast指針不是空,證明鏈表個數是奇數個,所以最中間那個數要跳過去(可以實際畫個鏈表走一下)
}
while(slow!=null){//接下來開始比較後半段鏈表和棧中
int val=stack.pop().intValue();//棧裏彈出來,並轉換成intValue值
if(val!=slow.val){//一旦不一樣就返回false
return false;
}
slow=slow.next;//慢指針在後半段一個個往後挪,進行比較
}
return true;
}
}
方法二代碼:
public class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null || head.next==null) return true;
ListNode middle= partition(head);
middle= reverse(middle);
// ListNode middle= reverse(middle);
while(head!=null && middle!=null){//前半截和 反轉後的後半段進行一一比較
if(head.val!=middle.val) return false;
head=head.next;
middle=middle.next;
}
return true;
}
private ListNode partition(ListNode head){//將頭結點爲head的鏈表分成兩段,返回後半段的頭結點P
// ListNode p;
ListNode p=head;
while(p.next!=null && p.next.next!=null){
head=head.next;
p=p.next.next;
}
p=head.next;
head.next=null;
return p;
}
private ListNode reverse(ListNode head){//將頭結點爲head的鏈表反轉,返回反轉後的頭結點pre
if(head==null || head.next==null) return head;
ListNode pre=head;
ListNode cur=head.next;
pre.next=null;//這句不能漏~!! 要把前後關係該斷斷 該連連
ListNode nxt=null;
while(cur!=null){//
nxt=cur.next;
cur.next=pre;
pre=cur;
cur=nxt;
}
return pre;
}
}
參見參考資料3
參考資料:
1、cracking the coding interview / page129 (本書給出了三種方法,遞歸掌握的不好,第三種遞歸方法還木有掌握)
3、leetcode 234: Palindrome Linked List 嗯。。這個叫西施豆腐渣的博主已經深深印在我的腦海裏。。