Algorithm:Leetcode 234. 迴文鏈表
https://leetcode-cn.com/problems/palindrome-linked-list/submissions/
請判斷一個鏈表是否爲迴文鏈表。
示例 1:
輸入: 1->2
輸出: false
示例 2:
輸入: 1->2->2->1
輸出: true
進階:
你能否用 O(n) 時間複雜度和 O(1) 空間複雜度解決此題?
解法一:先遍歷一遍,將原鏈表全部反轉得到一個新鏈表;再遍歷一遍,將新舊兩個鏈表逐個比較。時間複雜度和空間複雜度都是O(n)。
解法二:先遍歷一遍求出鏈表長度,計算出鏈表中間節點的位置。然後遍歷前半段,將其反轉。繼續遍歷後半段,將其與反轉後的前半段鏈表逐個比較。時間複雜度是O(n),空間複雜度是O(1)。
解法二優化:用快慢指針尋找中間節點,反轉後半段而不是前半段,因爲反轉前半段還得關心鏈表長度是奇數還是偶數。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
// 解法二優化:用快慢指針尋找中間節點,反轉後半段而不是前半段,因爲反轉前半段還得關心鏈表長度是奇數還是偶數。
public boolean isPalindrome(ListNode head) {
ListNode fast = head;// 快指針每次移動兩步
ListNode slow = head;// 慢指針每次移動一步
for(; fast != null && fast.next != null; fast = fast.next.next, slow = slow.next);
//慢指針指向後半段的起始節點,後半段有可能比前半段多一個節點
ListNode leftStart = head;
ListNode rightStart = reverseOriginalList(slow);
while(leftStart != slow && leftStart.val == rightStart.val) {
leftStart = leftStart.next;
rightStart = rightStart.next;
}
return leftStart == slow;
}
private ListNode reverseOriginalList(ListNode head) {
ListNode p = null;
ListNode q = head;
ListNode r = head == null ? null : head.next;
while(q != null) {
q.next = p;
p = q;
q = r;
r = r == null ? null : r.next;
}
return p;
}
// 解法二:先遍歷一遍求出鏈表長度,計算出鏈表中間節點的位置。然後遍歷前半段,將其反轉。繼續遍歷後半段,將其與反轉後的前半段鏈表逐個比較。
private boolean isPalindromeSolution_2(ListNode head) {
// count O(n)
int size = 0;
ListNode p = head;
while(p != null) {
p = p.next;
size++;
}
// reverse the left half O(n/2)
int half = size / 2;
int i = 0;
p = null;
ListNode q = head;
ListNode r = head == null ? null : head.next;
while(i++ < half) {
q.next = p;
p = q;
q = r;
r = r == null ? null : r.next;
}
// compare O(n/2)
ListNode leftStart = p;
ListNode rightStart = size % 2 == 0 ? q : r;
while(leftStart != null && leftStart.val == rightStart.val) {
leftStart = leftStart.next;
rightStart = rightStart.next;
}
return leftStart == null;
// total O(n) 空間複雜度O(1)
}
// 解法一:將輸入反轉得到一個新的鏈表,逐個比較。時間和空間複雜度都是O(n)
private boolean isPalindromeSolution_1(ListNode head) {
ListNode reverseHead = reverseNewList(head);
while(head != null && head.val == reverseHead.val) {
head = head.next;
reverseHead = reverseHead.next;
}
return head == null;
}
private ListNode reverseNewList(ListNode head) {
ListNode p = null;
while(head != null) {
ListNode node = new ListNode(head.val);
node.next = p;
p = node;
head = head.next;
}
return p;
}
private void print(ListNode head) {
StringBuilder sb = new StringBuilder();
while(head != null) {
sb.append(head.val);
head = head.next;
}
System.out.println(sb.toString());
}
}