原题:#234_回文链表
- 解法一:利用数组
- 使用遍历把节点的值放置在新开辟的数组中。
- 使用头尾指针,分别向中间靠近,过程中比较两个指针所指的值是否相等(注意是比较数组指针所指的值,而不是数组指针)
public boolean isPalindrome(ListNode head) {
List<Integer> vals = new ArrayList<>();
// Convert LinkedList into ArrayList.
ListNode currentNode = head;
while (currentNode != null) {
vals.add(currentNode.val);
currentNode = currentNode.next;
}
// Use two-pointer technique to check for palindrome.
int front = 0;
int back = vals.size() - 1;
while (front < back) {
// Note that we must use ! .equals instead of !=
// because we are comparing Integer, not int.
if (!vals.get(front).equals(vals.get(back))) {
return false;
}
front++;
back--;
}
return true;
}
- 时间复杂度:O(n)
- 空间复杂度:O(n)
- 解法二:快慢指针+翻转链表
- 步骤
- 找到第一部分的尾节点
- 翻转后半部分节点
- 判断是否为回文
- 恢复链表
- 返回结果
- 快慢指针同时出发,快指针比慢指针快一倍,当快指针到达链表尾部时,慢指针到达链表中部
- 若链表节点数为奇数,则中点视为前半段的节点
- 步骤
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null) return true;
ListNode firstHalfEnd = endOfFirstHalf(head); //找到第一部分的尾结点
ListNode secondHalfStart = reverseList(firstHalfEnd.next); //翻转第二部分链表
//判断是否为回文链表
ListNode p1 = head;
ListNode p2 = secondHalfStart;
boolean result = true;
while (result && p2 != null) {
if (p1.val != p2.val) result = false;
p1 = p1.next;
p2 = p2.next;
}
// 恢复原链表的结构
firstHalfEnd.next = reverseList(secondHalfStart);
return result;
}
// 翻转链表
private ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
//找到第一部分的尾节点
private ListNode endOfFirstHalf(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)