對於單鏈表來說,判斷回文最簡單的方法就是遍歷鏈表,將鏈表中的元素復制到數組中,然后對數組進行判斷是否是回文數組,但是這不符合O(1)的空間復雜度。
由於空間復雜度的要求,需要就地操作鏈表,不能開辟多余的空間來進行處理,因此引入快慢指針來進行操作。
快慢指針: slow 和 fast,每次slow指針前進一步,fast指針前進兩步,當遇到指針為空時說明遍歷鏈表完成,此時也就可以找到鏈表的中心位置。
注意,由於鏈表的長度可能是奇數也可能是偶數,因此應該做一個判斷。
找到鏈表的中心后,把鏈表的后半部分進行就地逆轉,就地逆轉是采用頭插法即可。
后半部分逆轉完成后,將鏈表的前半部分和后半部分一次比較,即可判斷是否是回文。
實現代碼如下:
鏈表類定義:
class ListNode { int val; ListNode next; ListNode(int x) { val = x; } }
鏈表就地反轉:
public static ListNode reverseList(ListNode head){ ListNode ptr = head, ptr2 = head; ListNode fast = head.next; while(fast!=null){ //頭插法 ptr = fast.next; fast.next = head; head = fast; fast = ptr; } //反轉完成后將原頭指針的next設置為null ptr2.next = null; return head; }
判斷鏈表是否是回文:
1 public static boolean isPalindrome(ListNode head){ 2 if(head==null || head.next==null){ 3 return true; 4 } 5 //建立快慢指針,尋找鏈表中心 6 ListNode slow = head; 7 ListNode fast = head; 8 while(fast!=null && fast.next!=null){ 9 slow = slow.next; 10 fast = fast.next.next; 11 } 12 13 if(fast == null){ 14 //偶數個元素(進行鏈表反轉) 15 ListNode ptr = slow, ptr2 = slow; 16 ListNode fast1 = slow.next; 17 while(fast1!=null){ 18 ptr = fast1.next; 19 fast1.next = slow; 20 slow = fast1; 21 fast1 = ptr; 22 } 23 ptr2.next = null; 24 }else{ 25 //奇數個元素(進行鏈表反轉) 26 ListNode ptr = slow.next,ptr2 = slow.next; 27 ListNode fast1 = slow.next.next; 28 while(fast1 != null){ 29 ptr = fast1.next; 30 fast1.next = slow.next; 31 slow.next = fast1; 32 fast1 = ptr; 33 } 34 ptr2.next = null; 35 slow = slow.next; 36 } 37 38 while(slow!=null){ 39 if(head.val!=slow.val) 40 return false; 41 slow = slow.next; 42 head = head.next; 43 } 44 return true; 45 } 46 47 }